package com.ouxuan.oxface.device; import android.content.Context; import android.os.Handler; import android.os.Looper; import com.ouxuan.oxface.data.DeviceSelectDataManager; import com.ouxuan.oxface.network.NetworkConfig; import com.ouxuan.oxface.network.api.PadApiService; import com.ouxuan.oxface.network.model.ApiResponse; import com.ouxuan.oxface.utils.LogManager; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; /** * AB门控制器 * 负责AB门的开门控制逻辑和配置参数管理 * * @author AI Assistant * @version 1.0 * @date 2024/09/11 */ public class GateABController { private static final String TAG = "GateABController"; // 单例实例 private static volatile GateABController instance; // 上下文和配置管理器 private Context context; private DeviceSelectDataManager deviceDataManager; // 配置同步相关 private Handler syncHandler; private ExecutorService executorService; private GateABConfig currentConfig; private static final long SYNC_INTERVAL = 60000; // 1分钟同步一次 // 继电器控制器和UDP控制器 private RelayController relayController; private OxUDP udpController; // UDP门禁控制器 // 485通信控制器 private Ox485 ox485; // 网络API服务 private PadApiService acControlApiService; /** * AB门状态类 * 记录AB门的开关状态,用于触发门禁不可用弹窗 */ public static class GateABState { public boolean gateAOpen = false; // A门是否开启 public boolean gateBOpen = false; // B门是否开启 public boolean udpConnected = true; // UDP连接状态 public long lastUpdateTime = 0; // 最后更新时间 public String errorMessage = ""; // 错误信息 /** * 检查是否需要触发门禁不可用弹窗 * @return true表示需要触发弹窗 */ public boolean shouldShowUnavailableDialog() { return gateAOpen || gateBOpen || !udpConnected; } /** * 获取不可用原因描述 * @return 不可用原因 */ public String getUnavailableReason() { if (gateAOpen && gateBOpen) { return "检测到A门和B门都开启,请先关闭所有门"; } else if (gateAOpen) { return "检测到A门开启,请先关闭A门"; } else if (gateBOpen) { return "检测到B门开启,请先关闭B门"; } else if (!udpConnected) { return "无法检测到AB门状态,请检查门禁电磁锁或网络状态"; } return "门禁状态异常"; } @Override public String toString() { return "GateABState{" + "gateAOpen=" + gateAOpen + ", gateBOpen=" + gateBOpen + ", udpConnected=" + udpConnected + ", lastUpdateTime=" + lastUpdateTime + ", errorMessage='" + errorMessage + '\'' + '}'; } } /** * AB门状态监听器接口 */ public interface GateABStateListener { void onGateStateChanged(GateABState state); } // AB门状态实例和监听器 private GateABState currentGateState; private GateABStateListener gateStateListener; /** * AB门配置类 * 对应uniapp中的state参数 */ public static class GateABConfig { // AB门基础配置 public boolean gateAbEnable = false; // AB门禁开关 public boolean gateOpenEnable = false; // 核销结束开启门禁 public boolean gateAbEnter01Enable = false; // 进场门内大于0或者1人都开门 public boolean gateAbAlwaysCheck = false; // 首页AB门状态是否一直轮询 public boolean gateAbGpio = true; // 是否使用gpio控制AB门 public boolean gateAbUdp = false; // 门禁UDP模式开关 public boolean gateOpenReset = false; // 开门状态全部返回为close public boolean gateEnterOpenEnable = false; // 进场:离线识别后直接开门 public boolean isAutoDetect = false; // 是否开启靠近自动检测 public boolean gateAbTestOn = false; // 是否在主页显示测试开关 public boolean faceDetecting = false; // 人脸检测状态 public boolean gateAbClose = false; // AB门关闭状态 public boolean livingControl = true; // 是否开启活体检测 public boolean gateAbNoVoiceAfterOrderCheck = false; // 进场核销开门后,5s内不再提示 // 检测相关配置 public float gateAbCameraScore = 0.3f; // 摄像头评分阈值 public int gateAbPeopleDetectType = 1; // 人数检测类型 1:baidu 2:aliyun人数 3:aliyun人体 public int gateACLoseTime = 2; // A门关闭时间,单位秒 public boolean gateCameraDetectHardLevel = false; // 人数检测严格判定开关 public int gateCameraConfigIndex = 0; // 摄像头配置索引 public boolean gateCamera485OXOn = false; // 是否开启485_OX // 轮询和检测状态 public boolean gateCheckLoopOn = false; // 门禁检测循环开关 public boolean gateAbAlwaysCheckUserEnter = false; // AB门状态轮询结果检测用户进场 public Integer gateAbPeopleCount = null; // AB门内人数 public boolean gateLoopCountPeopleLock = false; // 循环检测人数锁定状态 public Integer gateLoopCountPeopleTimes = null; // 循环检测次数 @Override public String toString() { return "GateABConfig{" + "gateAbEnable=" + gateAbEnable + ", gateOpenEnable=" + gateOpenEnable + ", gateAbGpio=" + gateAbGpio + ", gateAbUdp=" + gateAbUdp + ", gateEnterOpenEnable=" + gateEnterOpenEnable + "}"; } } /** * 门禁控制回调接口 */ public interface GateControlCallback { void onSuccess(String message); void onError(String errorMessage); } private GateABController() { syncHandler = new Handler(Looper.getMainLooper()); executorService = Executors.newSingleThreadExecutor(); relayController = RelayController.getInstance(); udpController = OxUDP.getInstance(); ox485 = Ox485.getInstance(); currentConfig = new GateABConfig(); currentGateState = new GateABState(); // 初始化门状态 // 初始化中控网络服务 initializeACControlService(); } /** * 获取GateABController单例实例 * @return GateABController实例 */ public static GateABController getInstance() { if (instance == null) { synchronized (GateABController.class) { if (instance == null) { instance = new GateABController(); } } } return instance; } /** * 初始化中控网络服务 */ private void initializeACControlService() { try { Retrofit retrofit = new Retrofit.Builder() .baseUrl(NetworkConfig.AC_CONTROL_BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); acControlApiService = retrofit.create(PadApiService.class); LogManager.logInfo(TAG, "中控网络服务初始化成功"); } catch (Exception e) { LogManager.logError(TAG, "中控网络服务初始化失败", e); } } /** * 初始化GateAB控制器 * @param context 上下文 */ public void initialize(Context context) { this.context = context; this.deviceDataManager = DeviceSelectDataManager.getInstance(context); // 初始化485通信模块 ox485.initialize(context); // 初始化UDP控制器 if (udpController != null) { udpController.initUDP(context); // 设置UDP状态监听器 setupUDPStateListener(); LogManager.logInfo(TAG, "UDP控制器初始化完成"); } // 启动配置同步 startConfigSync(); LogManager.logInfo(TAG, "GateABController初始化完成"); } /** * 开启AB门 * 参考JavaScript实现的openGateAB函数 * @param callback 开门结果回调 */ public void openGateAB(GateControlCallback callback) { LogManager.logInfo(TAG, "开始执行AB门开门操作"); executorService.execute(new Runnable() { @Override public void run() { try { // 先获取AB门总状态 boolean gateAbClose = getGateAbClose(); LogManager.logInfo(TAG, "执行开门...gate_open_enable:" + currentConfig.gateOpenEnable + " gate_ab_close: " + gateAbClose); // 检查开门使能配置(可选检查,根据需要启用) // if (!currentConfig.gateOpenEnable) { // notifyCallback(callback, false, "开门失败,请先开启AB门离场逻辑"); // return; // } // 检查AB门是否关闭(可选检查,根据需要启用) // if (!gateAbClose) { // notifyCallback(callback, false, "开门失败,请先关闭AB门-1"); // return; // } // 实时查询1次AB门状态, 防止AB门用户作弊 if (getGateAbEnable()) { String gateStatus = getGateABState(); // 获取AB门状态 LogManager.logInfo(TAG, "开门-门状态查询:" + gateStatus + " gpio:" + getGateAbGpio()); if (!"close".equals(gateStatus)) { notifyCallback(callback, false, gateStatus + "开门失败,请先关闭AB门-2"); return; } } // 设置门禁重置状态 setGateOpenReset(); // 优先判定继电器开门 if (getGateAbGpio()) { openDoorGpio(); notifyCallback(callback, true, "执行继电器开门"); return; } // 次选判定UDP中控开门 if (getGateAbUdp()) { openDoorUdp(); notifyCallback(callback, true, "PAD执行开门"); return; } // 非AB门模式,不执行中控开AB门 if (!getGateAbEnable()) { notifyCallback(callback, false, "非AB门模式,无法执行开门"); return; } // 执行中控开门(网络接口开门) executeNetworkOpenGate(callback); } catch (Exception e) { LogManager.logError(TAG, "开门操作异常", e); notifyCallback(callback, false, "开门操作异常: " + e.getMessage()); } } }); } /** * 获取AB门关闭状态 * @return true表示AB门关闭,false表示AB门开启 */ private boolean getGateAbClose() { return currentConfig.gateAbClose; } /** * 获取AB门使能状态 * @return true表示AB门启用 */ private boolean getGateAbEnable() { return currentConfig.gateAbEnable; } /** * 获取GPIO控制使能状态 * @return true表示使用GPIO控制 */ private boolean getGateAbGpio() { return currentConfig.gateAbGpio; } /** * 获取UDP控制使能状态 * @return true表示使用UDP控制 */ private boolean getGateAbUdp() { return currentConfig.gateAbUdp; } /** * 获取AB门状态 * @return "open"表示开启状态,"close"表示关闭状态 . 当a门 b门中有任一个开启状态,则返回"open", 两个门都关闭时返回"close" */ private String getGateABState() { LogManager.logInfo(TAG, "查询AB门状态"); try { // 检查是否启用UDP门禁控制 if (getGateAbUdp() && udpController != null && udpController.isInitialized()) { LogManager.logInfo(TAG, "使用UDP查询AB门状态"); return getGateStateFromUDP(); } // 检查是否启用GPIO门禁控制 if (getGateAbGpio()) { LogManager.logInfo(TAG, "使用GPIO查询AB门状态(暂时返回配置状态)"); // TODO: 实现GPIO状态查询,目前基于配置返回 return currentConfig.gateAbClose ? "close" : "open"; } // 检查是否启用AB门模式 if (getGateAbEnable()) { LogManager.logInfo(TAG, "使用网络接口查询AB门状态(暂时返回配置状态)"); // TODO: 实现网络接口状态查询,目前基于配置返回 return currentConfig.gateAbClose ? "close" : "open"; } // 非AB门模式,默认返回关闭状态 LogManager.logInfo(TAG, "非AB门模式,返回关闭状态"); return "close"; } catch (Exception e) { LogManager.logError(TAG, "查询AB门状态异常", e); // 异常情况下返回配置状态 return currentConfig.gateAbClose ? "close" : "open"; } } /** * 设置门禁重置状态 */ private void setGateOpenReset() { currentConfig.gateOpenReset = true; LogManager.logInfo(TAG, "设置门禁重置状态"); } /** * GPIO方式开门 */ private void openDoorGpio() { LogManager.logInfo(TAG, "执行GPIO继电器开门"); try { // 使用继电器控制器开门,3秒后自动关闭 boolean success = relayController.openRelayWithAutoClose(); if (success) { LogManager.logInfo(TAG, "GPIO继电器开门成功"); } else { LogManager.logError(TAG, "GPIO继电器开门失败"); } } catch (Exception e) { LogManager.logError(TAG, "GPIO开门异常", e); } } /** * UDP方式开门 */ private void openDoorUdp() { LogManager.logInfo(TAG, "执行UDP开门"); try { if (udpController != null && udpController.isInitialized()) { // 根据场景判断开A门还是B门 // 这里暂时默认开B门,实际应该根据业务逻辑判断 udpController.openGateB(); LogManager.logInfo(TAG, "UDP开B门命令已发送"); } else { LogManager.logError(TAG, "UDP控制器未初始化或未连接"); } } catch (Exception e) { LogManager.logError(TAG, "UDP开门异常", e); } } /** * 网络接口开门 * @param callback 回调 */ private void executeNetworkOpenGate(GateControlCallback callback) { LogManager.logInfo(TAG, "执行网络接口开门"); if (acControlApiService == null) { LogManager.logError(TAG, "中控网络服务未初始化"); notifyCallback(callback, false, "中控网络服务未初始化"); return; } try { // 构建请求参数,参考JavaScript代码 PadApiService.GateControlRequest request = new PadApiService.GateControlRequest(); LogManager.logInfo(TAG, "发送中控开门请求: name=" + request.getName()); // 发送网络请求 Call> call = acControlApiService.controlGateFromAC(request); call.enqueue(new Callback>() { @Override public void onResponse(Call> call, Response> response) { if (response.isSuccessful() && response.body() != null) { ApiResponse apiResponse = response.body(); if (apiResponse.isSuccess() && apiResponse.getData() != null) { PadApiService.GateControlResult result = apiResponse.getData(); LogManager.logInfo(TAG, "中控开门成功: code=" + result.getCode()); if (result.isSuccess()) { // 检查门状态数据 if (result.getData() != null) { PadApiService.GateData gateData = result.getData(); LogManager.logInfo(TAG, "门状态 - A门: " + gateData.getGateA() + ", B门: " + gateData.getGateB()); } notifyCallback(callback, true, "执行中控开门成功"); } else { String errorMsg = result.getMessage() != null ? result.getMessage() : "中控返回错误码: " + result.getCode(); LogManager.logError(TAG, "中控开门失败: " + errorMsg); notifyCallback(callback, false, "中控开门失败: " + errorMsg); } } else { String errorMsg = apiResponse.getMessage() != null ? apiResponse.getMessage() : "服务器返回错误"; LogManager.logError(TAG, "中控API调用失败: " + errorMsg); notifyCallback(callback, false, "中控API调用失败: " + errorMsg); } } else { String errorMsg = "HTTP错误: " + response.code(); if (response.errorBody() != null) { try { errorMsg += " - " + response.errorBody().string(); } catch (Exception e) { LogManager.logError(TAG, "读取错误响应体失败", e); } } LogManager.logError(TAG, "中控网络请求失败: " + errorMsg); notifyCallback(callback, false, "中控网络请求失败: " + errorMsg); } } @Override public void onFailure(Call> call, Throwable t) { String errorMsg = "网络连接失败: " + t.getMessage(); LogManager.logError(TAG, errorMsg, t); notifyCallback(callback, false, errorMsg); } }); LogManager.logInfo(TAG, "中控开门请求已发送"); } catch (Exception e) { LogManager.logError(TAG, "网络开门异常", e); notifyCallback(callback, false, "网络开门失败: " + e.getMessage()); } } /** * 通知回调结果 * @param callback 回调接口 * @param success 是否成功 * @param message 消息 */ private void notifyCallback(GateControlCallback callback, boolean success, String message) { if (callback != null) { syncHandler.post(new Runnable() { @Override public void run() { if (success) { callback.onSuccess(message); } else { callback.onError(message); } } }); } LogManager.logInfo(TAG, "开门结果: " + (success ? "成功" : "失败") + " - " + message); } /** * 启动配置同步 */ private void startConfigSync() { LogManager.logInfo(TAG, "启动配置同步,同步间隔: " + SYNC_INTERVAL + "ms"); // 立即执行一次同步 syncConfigFromPadSetting(); // 启动定时同步 syncHandler.post(configSyncRunnable); } /** * 配置同步任务 */ private final Runnable configSyncRunnable = new Runnable() { @Override public void run() { LogManager.logDebug(TAG, "== 开始定时配置同步 =="); syncConfigFromPadSetting(); // 安排下次同步 syncHandler.postDelayed(this, SYNC_INTERVAL); LogManager.logDebug(TAG, "== 下次同步将在 " + (SYNC_INTERVAL / 1000) + " 秒后执行 =="); } }; /** * 从PadSetting同步配置参数 */ private void syncConfigFromPadSetting() { if (deviceDataManager == null) { LogManager.logWarning(TAG, "DeviceDataManager未初始化,跳过配置同步"); return; } try { LogManager.logDebug(TAG, "开始同步配置参数"); // 获取PadSetting配置 PadApiService.PadSetting padSetting = deviceDataManager.getPadSetting(); if (padSetting == null) { LogManager.logWarning(TAG, "PadSetting为空,使用默认配置"); return; } // 保存旧配置用于对比 GateABConfig oldConfig = currentConfig; // 同步配置参数 GateABConfig newConfig = new GateABConfig(); // 基础配置 newConfig.gateAbEnable = padSetting.isGateAbEnable(); newConfig.gateOpenEnable = padSetting.isGateOpenEnable(); newConfig.gateAbEnter01Enable = padSetting.isGateAbEnter01Enable(); newConfig.gateAbAlwaysCheck = padSetting.isGateAbAlwaysCheck(); newConfig.gateAbGpio = padSetting.isGateAbGpio(); newConfig.gateAbUdp = padSetting.isGateAbUdp(); newConfig.gateOpenReset = padSetting.isGateOpenReset(); newConfig.gateEnterOpenEnable = padSetting.isGateEnterOpenEnable(); newConfig.isAutoDetect = padSetting.isAutoDetect(); newConfig.gateAbTestOn = padSetting.isGateAbTestOn(); newConfig.faceDetecting = padSetting.isFaceDetecting(); newConfig.gateAbClose = padSetting.isGateAbClose(); newConfig.livingControl = padSetting.isLivingControl(); newConfig.gateAbNoVoiceAfterOrderCheck = padSetting.isGateAbNoVoiceAfterOrderCheck(); // 检测相关配置 newConfig.gateAbCameraScore = (float) padSetting.getGateAbCameraScore(); newConfig.gateAbPeopleDetectType = padSetting.getGateAbPeopleDetectType(); newConfig.gateACLoseTime = padSetting.getGateACloseTime(); newConfig.gateCameraDetectHardLevel = padSetting.isGateCameraDetectHardLevel(); newConfig.gateCameraConfigIndex = padSetting.getGateCameraConfigIndex(); newConfig.gateCamera485OXOn = padSetting.isGateCamera485OXOn(); // 轮询和状态 newConfig.gateCheckLoopOn = padSetting.isGateCheckLoopOn(); newConfig.gateAbAlwaysCheckUserEnter = padSetting.isGateAbAlwaysCheckUserEnter(); newConfig.gateAbPeopleCount = (Integer) padSetting.getGateAbPeopleCount(); newConfig.gateLoopCountPeopleLock = padSetting.isGateLoopCountPeopleLock(); newConfig.gateLoopCountPeopleTimes = (Integer) padSetting.getGateLoopCountPeopleTimes(); // 检查配置是否发生变化 boolean configChanged = hasConfigurationChanged(oldConfig, newConfig); // 更新当前配置 currentConfig = newConfig; // 同步485配置到Ox485实例 if (ox485 != null) { ox485.setGateCamera485OxOn(newConfig.gateCamera485OXOn); LogManager.logInfo(TAG, "485配置已同步: " + newConfig.gateCamera485OXOn); } if (configChanged) { LogManager.logInfo(TAG, "配置发生变化,已更新: " + currentConfig.toString()); logConfigurationChanges(oldConfig, newConfig); } else { LogManager.logDebug(TAG, "配置未发生变化"); } LogManager.logDebug(TAG, "配置同步完成"); } catch (Exception e) { LogManager.logError(TAG, "配置同步异常", e); } } /** * 获取当前配置 * @return 当前的GateAB配置 */ public GateABConfig getCurrentConfig() { return currentConfig; } /** * 停止配置同步 */ public void stopConfigSync() { if (syncHandler != null) { syncHandler.removeCallbacks(configSyncRunnable); LogManager.logInfo(TAG, "配置同步已停止"); } } /** * 释放资源 */ public void release() { stopConfigSync(); if (executorService != null && !executorService.isShutdown()) { executorService.shutdown(); } if (relayController != null) { relayController.release(); } if (ox485 != null) { ox485.release(); } if (udpController != null) { udpController.release(); } LogManager.logInfo(TAG, "GateABController资源已释放"); } /** * 检查配置是否发生变化 * @param oldConfig 旧配置 * @param newConfig 新配置 * @return true表示配置发生变化 */ private boolean hasConfigurationChanged(GateABConfig oldConfig, GateABConfig newConfig) { if (oldConfig == null || newConfig == null) { return true; } // 检查关键配置参数是否发生变化 return oldConfig.gateAbEnable != newConfig.gateAbEnable || oldConfig.gateOpenEnable != newConfig.gateOpenEnable || oldConfig.gateAbGpio != newConfig.gateAbGpio || oldConfig.gateAbUdp != newConfig.gateAbUdp || oldConfig.gateEnterOpenEnable != newConfig.gateEnterOpenEnable || oldConfig.gateAbClose != newConfig.gateAbClose || oldConfig.livingControl != newConfig.livingControl || oldConfig.isAutoDetect != newConfig.isAutoDetect || oldConfig.gateAbTestOn != newConfig.gateAbTestOn || oldConfig.faceDetecting != newConfig.faceDetecting || oldConfig.gateAbAlwaysCheck != newConfig.gateAbAlwaysCheck || oldConfig.gateACLoseTime != newConfig.gateACLoseTime || Float.compare(oldConfig.gateAbCameraScore, newConfig.gateAbCameraScore) != 0; } /** * 记录配置变化的详细信息 * @param oldConfig 旧配置 * @param newConfig 新配置 */ private void logConfigurationChanges(GateABConfig oldConfig, GateABConfig newConfig) { LogManager.logInfo(TAG, "=== 配置变化详情 ==="); if (oldConfig.gateAbEnable != newConfig.gateAbEnable) { LogManager.logInfo(TAG, "AB门启用: " + oldConfig.gateAbEnable + " -> " + newConfig.gateAbEnable); } if (oldConfig.gateOpenEnable != newConfig.gateOpenEnable) { LogManager.logInfo(TAG, "开门启用: " + oldConfig.gateOpenEnable + " -> " + newConfig.gateOpenEnable); } if (oldConfig.gateAbGpio != newConfig.gateAbGpio) { LogManager.logInfo(TAG, "GPIO控制: " + oldConfig.gateAbGpio + " -> " + newConfig.gateAbGpio); } if (oldConfig.gateAbUdp != newConfig.gateAbUdp) { LogManager.logInfo(TAG, "UDP控制: " + oldConfig.gateAbUdp + " -> " + newConfig.gateAbUdp); } if (oldConfig.gateEnterOpenEnable != newConfig.gateEnterOpenEnable) { LogManager.logInfo(TAG, "离场开门: " + oldConfig.gateEnterOpenEnable + " -> " + newConfig.gateEnterOpenEnable); } if (oldConfig.gateAbClose != newConfig.gateAbClose) { LogManager.logInfo(TAG, "AB门关闭: " + oldConfig.gateAbClose + " -> " + newConfig.gateAbClose); } if (oldConfig.livingControl != newConfig.livingControl) { LogManager.logInfo(TAG, "活体检测: " + oldConfig.livingControl + " -> " + newConfig.livingControl); } if (Float.compare(oldConfig.gateAbCameraScore, newConfig.gateAbCameraScore) != 0) { LogManager.logInfo(TAG, "摄像头评分: " + oldConfig.gateAbCameraScore + " -> " + newConfig.gateAbCameraScore); } LogManager.logInfo(TAG, "=================="); } // ==================== 485人数检测相关方法 ==================== /** * 从 UDP 获取门状态 * @return "open" 或 "close" */ private String getGateStateFromUDP() { try { LogManager.logInfo(TAG, "使用UDP查询门状态"); // 使用CompletableFuture实现异步查询 java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); // 设置临时状态监听器 OxUDP.UDPStateListener tempListener = new OxUDP.UDPStateListener() { @Override public void onGateStateUpdate(boolean gateAState, boolean gateBState, String rawData) { LogManager.logInfo(TAG, "UDP门状态更新 - A门: " + (gateAState ? "开启" : "关闭") + ", B门: " + (gateBState ? "开启" : "关闭")); // 更新AB门状态到GateABState updateGateState(gateAState, gateBState, true, ""); // 按照业务逻辑:当A门或B门中有任一个开启时,返回"open" // 两个门都关闭时返回"close" String result = (gateAState || gateBState) ? "open" : "close"; future.complete(result); } @Override public void onGateOpenResult(String gateType, boolean success) { // 不处理开门结果 } @Override public void onUDPError(String error) { LogManager.logError(TAG, "UDP查询门状态错误: " + error); // 更新状态为UDP连接失败 updateGateState(false, false, false, error); future.complete("close"); // 错误时返回关闭状态 } }; // 保存原有的监听器(如果有的话) // 设置临时监听器 udpController.setStateListener(tempListener); // 启动一次状态轮询(如果没有在运行) if (!udpController.isPolling()) { // 临时启动轮询,获取一次状态后停止 udpController.startPolling(); // 等待结果 String result = future.get(5, java.util.concurrent.TimeUnit.SECONDS); // 停止临时轮询 udpController.stopPolling(); LogManager.logInfo(TAG, "UDP查询门状态结果: " + result); return result; } else { // 如果轮询已在运行,直接等待结果 String result = future.get(3, java.util.concurrent.TimeUnit.SECONDS); LogManager.logInfo(TAG, "UDP查询门状态结果(轮询中): " + result); return result; } } catch (java.util.concurrent.TimeoutException e) { LogManager.logWarning(TAG, "UDP查询门状态超时,返回默认关闭状态"); return "close"; } catch (Exception e) { LogManager.logError(TAG, "UDP查询门状态异常", e); return "close"; } } /** * 获取485摄像头人数 * 对应uniapp中sendHex485ForPeopleNum方法 * @param callback 结果回调 */ public void get485PeopleNum(PeopleNumCallback callback) { LogManager.logInfo(TAG, "开始获取485摄像头人数"); if (ox485 == null) { String errorMsg = "Ox485未初始化"; LogManager.logError(TAG, errorMsg); if (callback != null) { syncHandler.post(() -> callback.onError(errorMsg)); } return; } // 检查485模式是否已启用 if (!currentConfig.gateCamera485OXOn) { String errorMsg = "485模式未开启,请检查配置"; LogManager.logWarning(TAG, errorMsg); if (callback != null) { syncHandler.post(() -> callback.onError(errorMsg)); } return; } // 调用Ox485获取人数 ox485.sendHex485ForPeopleNum(new Ox485.PeopleNumCallback() { @Override public void onSuccess(int peopleNum) { LogManager.logInfo(TAG, "485人数获取成功: " + peopleNum + " 人"); if (callback != null) { callback.onSuccess(peopleNum); } } @Override public void onError(String errorMessage) { LogManager.logError(TAG, "485人数获取失败: " + errorMessage); if (callback != null) { callback.onError(errorMessage); } } }); } /** * 异步获取485摄像头人数(使用CompletableFuture) * @return CompletableFuture 人数结果 */ public java.util.concurrent.CompletableFuture get485PeopleNumAsync() { LogManager.logInfo(TAG, "异步获取485摄像头人数"); java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); get485PeopleNum(new PeopleNumCallback() { @Override public void onSuccess(int peopleNum) { future.complete(peopleNum); } @Override public void onError(String errorMessage) { future.completeExceptionally(new RuntimeException(errorMessage)); } }); return future; } /** * 检查485模式是否已启用 * @return true表示485模式已启用 */ public boolean is485ModeEnabled() { return currentConfig != null && currentConfig.gateCamera485OXOn; } /** * 获取485状态信息 * @return 485状态描述 */ public String get485Status() { if (ox485 != null) { return ox485.get485Status(); } else { return "Ox485未初始化"; } } /** * 485人数检测回调接口 */ public interface PeopleNumCallback { void onSuccess(int peopleNum); void onError(String errorMessage); } /** * 获取UDP控制器实例(供外部使用) * @return UDP控制器实例 */ public OxUDP getUdpController() { return udpController; } /** * 设置AB门状态监听器 * @param listener 状态监听器 */ public void setGateStateListener(GateABStateListener listener) { this.gateStateListener = listener; } /** * 获取当前AB门状态 * @return 当前门状态 */ public GateABState getCurrentGateState() { return currentGateState; } /** * 更新AB门状态 * Fix 9.2: 当需要弹出门禁不可用弹窗时,确保先关闭OrderSelectionActivity,再显示弹窗 * @param gateAOpen A门是否开启 * @param gateBOpen B门是否开启 * @param udpConnected UDP连接状态 * @param errorMessage 错误信息 */ public void updateGateState(boolean gateAOpen, boolean gateBOpen, boolean udpConnected, String errorMessage) { boolean stateChanged = false; boolean shouldShowDialog = false; boolean oldShouldShow = false; boolean newShouldShow = false; // 检查状态是否发生变化 if (currentGateState.gateAOpen != gateAOpen || currentGateState.gateBOpen != gateBOpen || currentGateState.udpConnected != udpConnected) { stateChanged = true; // 检查是否需要触发门禁不可用弹窗 oldShouldShow = currentGateState.shouldShowUnavailableDialog(); // 更新状态信息 currentGateState.gateAOpen = gateAOpen; currentGateState.gateBOpen = gateBOpen; currentGateState.udpConnected = udpConnected; newShouldShow = currentGateState.shouldShowUnavailableDialog(); // 如果从正常状态变为需要显示弹窗状态,则触发弹窗 if (!oldShouldShow && newShouldShow) { shouldShowDialog = true; LogManager.logWarning(TAG, "检测到门状态异常,需要显示门禁不可用弹窗: " + currentGateState.getUnavailableReason()); } else if (oldShouldShow && !newShouldShow) { LogManager.logInfo(TAG, "门状态已恢复正常,可以隐藏门禁不可用弹窗"); } } else { // 即使状态没有变化,也要更新状态信息 currentGateState.gateAOpen = gateAOpen; currentGateState.gateBOpen = gateBOpen; currentGateState.udpConnected = udpConnected; } // 更新其他状态信息 currentGateState.lastUpdateTime = System.currentTimeMillis(); currentGateState.errorMessage = errorMessage != null ? errorMessage : ""; LogManager.logInfo(TAG, "更新AB门状态: " + currentGateState.toString()); // Fix 9.2: 当需要显示门禁不可用弹窗时,先通过广播关闭OrderSelectionActivity,再处理弹窗 if (shouldShowDialog && context != null) { LogManager.logInfo(TAG, "Fix 9.2 - 检测到需要弹出门禁不可用弹窗,先发送广播关闭OrderSelectionActivity"); // 发送广播通知所有OrderSelectionActivity立即关闭 android.content.Intent intent = new android.content.Intent("com.ouxuan.oxface.ACTION_GATE_UNAVAILABLE"); intent.putExtra("reason", currentGateState.getUnavailableReason()); intent.putExtra("gateAOpen", currentGateState.gateAOpen); intent.putExtra("gateBOpen", currentGateState.gateBOpen); intent.putExtra("udpConnected", currentGateState.udpConnected); context.sendBroadcast(intent); // 延迟100ms后再处理主页面的弹窗显示,确保OrderSelectionActivity有时间关闭 syncHandler.postDelayed(() -> { LogManager.logInfo(TAG, "Fix 9.2 - 延迟后处理门禁不可用弹窗显示"); notifyGateStateListener(true, false); // 处理弹窗显示 }, 100); } // 处理其他状态变化(非弹窗显示场景) if (stateChanged && gateStateListener != null && !shouldShowDialog) { final boolean shouldHideDialog = oldShouldShow && !newShouldShow; notifyGateStateListener(false, shouldHideDialog); } // 即使状态没有变化,也要触发实时状态更新(用于更新弹窗显示) else if (gateStateListener instanceof GateUnavailableListener && !shouldShowDialog) { GateUnavailableListener unavailableListener = (GateUnavailableListener) gateStateListener; syncHandler.post(() -> { unavailableListener.onGateStatusUpdate(currentGateState.gateAOpen, currentGateState.gateBOpen, currentGateState.udpConnected); }); } } /** * Fix 9.2: 通知门禁状态监听器 * @param shouldShowDialog 是否需要显示弹窗 * @param shouldHideDialog 是否需要隐藏弹窗 */ private void notifyGateStateListener(final boolean shouldShowDialog, final boolean shouldHideDialog) { if (gateStateListener == null) { return; } syncHandler.post(() -> { gateStateListener.onGateStateChanged(currentGateState); if (gateStateListener instanceof GateUnavailableListener) { GateUnavailableListener unavailableListener = (GateUnavailableListener) gateStateListener; // 先触发门状态实时更新回调(用于更新弹窗中的门状态显示) unavailableListener.onGateStatusUpdate(currentGateState.gateAOpen, currentGateState.gateBOpen, currentGateState.udpConnected); // 如果需要显示弹窗,触发不可用回调 if (shouldShowDialog) { unavailableListener.onGateUnavailable(currentGateState.getUnavailableReason()); } // 如果需要隐藏弹窗(门状态恢复正常),触发可用回调 else if (shouldHideDialog) { LogManager.logInfo(TAG, "触发门禁恢复可用回调,隐藏弹窗并恢复摄像头"); unavailableListener.onGateAvailable(); } // 特别处理:如果A门和B门都关闭,且有弹窗正在显示,应该关闭弹窗 else if (!currentGateState.gateAOpen && !currentGateState.gateBOpen && currentGateState.udpConnected) { LogManager.logInfo(TAG, "A门和B门都关闭,触发门禁恢复可用回调"); unavailableListener.onGateAvailable(); } } }); } // ========== UDP状态监听相关方法 ========== /** * 设置UDP状态监听器 */ private void setupUDPStateListener() { if (udpController == null) { LogManager.logWarning(TAG, "UDP控制器为空,无法设置状态监听器"); return; } // 设置状态监听器 udpController.setStateListener(new OxUDP.UDPStateListener() { @Override public void onGateStateUpdate(boolean gateAState, boolean gateBState, String rawData) { LogManager.logInfo(TAG, "门禁状态更新 - A门: " + (gateAState ? "开启" : "关闭") + ", B门: " + (gateBState ? "开启" : "关闭")); // 更新门状态到GateABController,UDP连接状态为true(能收到状态说明连接正常) updateGateState(gateAState, gateBState, true, ""); } @Override public void onGateOpenResult(String gateType, boolean success) { LogManager.logInfo(TAG, gateType + "门开启结果: " + (success ? "成功" : "失败")); } @Override public void onUDPError(String error) { LogManager.logError(TAG, "UDP通信错误: " + error); // UDP通信错误时,设置连接状态为false,门状态为false(默认关闭) updateGateState(false, false, false, error); } }); // 设置设备监听器 udpController.setDeviceListener(new OxUDP.UDPDeviceListener() { @Override public void onDeviceInfoUpdate(String deviceInfo) { LogManager.logInfo(TAG, "设备信息更新: " + deviceInfo); } @Override public void onDeviceConnectionChange(boolean connected) { LogManager.logInfo(TAG, "设备连接状态: " + (connected ? "已连接" : "已断开")); if (connected) { // 设备连接成功,开始轮询 startUDPPolling(); } else { // 设备连接失败,设置UDP连接状态为false updateGateState(false, false, false, "设备连接断开"); } } }); LogManager.logInfo(TAG, "UDP状态监听器设置完成"); } /** * 开始UDP门禁状态轮询 */ public void startUDPPolling() { if (udpController != null) { LogManager.logInfo(TAG, "开始UDP门禁状态轮询"); udpController.startPolling(); } else { LogManager.logWarning(TAG, "UDP控制器为空,无法开始轮询"); } } /** * 停止UDP门禁状态轮询 */ public void stopUDPPolling() { if (udpController != null) { LogManager.logInfo(TAG, "停止UDP门禁状态轮询"); udpController.stopPolling(); } else { LogManager.logWarning(TAG, "UDP控制器为空,无法停止轮询"); } } /** * 重新初始化UDP控制器(用于恢复监听器链条) */ public void reinitializeUDP() { if (context != null && udpController != null) { LogManager.logInfo(TAG, "重新初始化UDP控制器"); udpController.initUDP(context); setupUDPStateListener(); } else { LogManager.logWarning(TAG, "无法重新初始化UDP,context或udpController为空"); } } /** * 检查UDP是否已初始化 * @return true表示UDP已初始化,false表示未初始化 */ public boolean isUDPInitialized() { return udpController != null && udpController.isInitialized(); } /** * 人脸识别成功后开门处理 * 无论进场还是离场,都开启B门 * @param isEntry true: 进门, false: 出门(参数保留为兼容性,但不影响实际操作) */ public void handleFaceRecognitionSuccess(boolean isEntry) { LogManager.logInfo(TAG, "人脸识别成功,准备开B门: " + (isEntry ? "进门场景" : "离场场景")); // 无论是进场还是离场,都开启B门 if (udpController != null && udpController.isInitialized()) { udpController.openGateB(); LogManager.logInfo(TAG, "人脸识别成功,已发送B门开启命令"); } else { LogManager.logWarning(TAG, "UDP控制器未初始化,无法开启B门"); } } /** * 门禁不可用监听器接口 * 扩展GateABStateListener,增加弹窗触发功能 */ public interface GateUnavailableListener extends GateABStateListener { /** * 门禁变为不可用状态时触发 * @param reason 不可用原因 */ void onGateUnavailable(String reason); /** * 门禁恢复可用状态时触发 */ void onGateAvailable(); /** * 门状态实时更新时触发(用于更新弹窗中的门状态显示) * @param gateAOpen A门是否开启 * @param gateBOpen B门是否开启 * @param udpConnected UDP连接状态 */ default void onGateStatusUpdate(boolean gateAOpen, boolean gateBOpen, boolean udpConnected) { // 默认空实现,子类可选择实现 } } }