From 78b46e1a9da0137794d01f63e9333538becdd56f Mon Sep 17 00:00:00 2001 From: MT <3075067877@qq.com> Date: Sat, 13 Sep 2025 15:47:18 +0800 Subject: [PATCH] add abGateManager --- AB门禁模块实现说明.md | 251 +++++++++++++++ .../com/ouxuan/oxface/abgate/ABGateManager.java | 353 +++++++++++++++++++++ .../ouxuan/oxface/abgate/ABGateTestActivity.java | 235 ++++++++++++++ .../ouxuan/oxface/abgate/ABGateUsageExample.java | 220 +++++++++++++ .../main/java/com/ouxuan/oxface/device/OxUDP.java | 2 +- 5 files changed, 1060 insertions(+), 1 deletion(-) create mode 100644 AB门禁模块实现说明.md create mode 100644 app/src/main/java/com/ouxuan/oxface/abgate/ABGateManager.java create mode 100644 app/src/main/java/com/ouxuan/oxface/abgate/ABGateTestActivity.java create mode 100644 app/src/main/java/com/ouxuan/oxface/abgate/ABGateUsageExample.java diff --git a/AB门禁模块实现说明.md b/AB门禁模块实现说明.md new file mode 100644 index 0000000..b17b300 --- /dev/null +++ b/AB门禁模块实现说明.md @@ -0,0 +1,251 @@ +# AB门禁模块实现说明 + +## 概述 + +根据您的需求,我已经实现了完整的AB门禁模块,包含门状态检查和人数检测功能。该模块通过UDP获取AB门状态,通过485串口获取门禁内人数,并根据进场/离场场景提供智能判断。 + +## 核心组件 + +### 1. ABGateManager.java +**位置**: `app/src/main/java/com/ouxuan/oxface/abgate/ABGateManager.java` +**功能**: AB门禁管理器核心类 + +**主要方法**: +- `checkGateABBeforeToDo()` - 完整检查流程(门状态 + 人数) +- `ABGateCheck()` - 门状态检查(A门关闭 AND B门关闭) +- `ABPeopleCheck()` - 人数检查(根据进场/离场场景判断) + +### 2. ABGateUsageExample.java +**位置**: `app/src/main/java/com/ouxuan/oxface/abgate/ABGateUsageExample.java` +**功能**: 使用示例和集成指南 + +### 3. ABGateTestActivity.java +**位置**: `app/src/main/java/com/ouxuan/oxface/abgate/ABGateTestActivity.java` +**功能**: 测试界面,方便调试验证 + +## 核心功能实现 + +### ✅ checkGateABBeforeToDo() - 主要入口方法 + +```java +ABGateManager abGateManager = ABGateManager.getInstance(); +abGateManager.initialize(context); + +abGateManager.checkGateABBeforeToDo(new ABGateManager.ABGateCheckCallback() { + @Override + public void onSuccess(boolean canProceed) { + if (canProceed) { + // AB门检查通过,可以进行后续操作 + LogManager.logInfo(TAG, "AB门检查通过,可以进行人脸识别"); + } else { + // AB门检查未通过,需要等待 + LogManager.logWarning(TAG, "AB门检查未通过,请等待"); + } + } + + @Override + public void onError(String errorMessage) { + // 检查失败,处理错误 + LogManager.logError(TAG, "AB门检查失败: " + errorMessage); + } +}); +``` + +### ✅ ABGateCheck() - 门状态检查 + +**检查逻辑**: A门关闭 AND B门关闭 时返回true,否则返回false + +**实现方式**: +1. 通过UDP向 `192.168.1.123:60000` 发送状态查询命令 +2. 解析返回数据的第28位(A门状态)和第29位(B门状态) +3. 01表示开启,00表示关闭 +4. 只有当A门和B门都关闭时才返回true + +```java +abGateManager.ABGateCheck(new ABGateManager.ABGateCheckCallback() { + @Override + public void onSuccess(boolean gateAvailable) { + // gateAvailable = true: A门关闭 AND B门关闭 + // gateAvailable = false: A门或B门有开启状态 + } + + @Override + public void onError(String errorMessage) { + // UDP通信失败或解析错误 + } +}); +``` + +### ✅ ABPeopleCheck() - 人数检查 + +**检查逻辑**: +- **进场设备**: 门内人数 > 1 时不可用(返回false) +- **离场设备**: 门内人数 != 0 时不可用(返回false) + +**实现方式**: +1. 使用`VenueSceneUtils.isLeaveScene(context)`判断进场/离场 +2. 通过485串口发送HEX命令 `0F030001000294E5` +3. 解析返回的9字节数据,第5字节为人数 +4. 根据场景类型应用不同的判断逻辑 + +```java +abGateManager.ABPeopleCheck(new ABGateManager.ABGateCheckCallback() { + @Override + public void onSuccess(boolean peopleCheckPassed) { + // 进场: peopleCheckPassed = (人数 <= 1) + // 离场: peopleCheckPassed = (人数 == 0) + } + + @Override + public void onError(String errorMessage) { + // 485通信失败或485模式未启用 + } +}); +``` + +## 在人脸识别界面中的集成 + +### 在OXFaceOnlineActivity中集成 + +```java +public class OXFaceOnlineActivity extends BaseActivity { + + private ABGateManager abGateManager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // 初始化AB门禁管理器 + abGateManager = ABGateManager.getInstance(); + abGateManager.initialize(this); + } + + // 在人脸识别成功前执行检查 + private void checkBeforeFaceRecognition() { + abGateManager.checkGateABBeforeToDo(new ABGateManager.ABGateCheckCallback() { + @Override + public void onSuccess(boolean canProceed) { + if (canProceed) { + // 可以进行人脸识别 + startFaceRecognition(); + } else { + // 需要等待,可以设置延迟重试 + showWaitingMessage(); + scheduleRetryCheck(); + } + } + + @Override + public void onError(String errorMessage) { + // 处理检查错误 + handleCheckError(errorMessage); + } + }); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (abGateManager != null) { + abGateManager.release(); + } + } +} +``` + +## 配置要求 + +### 1. UDP门禁配置 +- **IP地址**: 192.168.1.123 +- **端口**: 60000 +- **协议**: UDP状态查询命令 + +### 2. 485串口配置 +- **串口路径**: /dev/ttyS6 +- **波特率**: 9600 +- **命令**: 0F030001000294E5 +- **需要启用**: `gate_camera_485_OX_on = true` + +### 3. 场景配置 +通过`VenueSceneUtils.isLeaveScene(context)`自动判断进场/离场场景 + +## 错误处理 + +### 常见错误和解决方案 + +1. **"UDP门禁控制器未初始化"** + - 确保在调用前初始化了OxUDP模块 + - 检查网络连接和UDP配置 + +2. **"485模式未启用"** + - 检查配置中 `gate_camera_485_OX_on` 是否为true + - 确保485串口权限正确 + +3. **"门状态检查超时"** + - 检查网络连接 + - 确认UDP设备地址和端口正确 + +4. **"485人数获取失败"** + - 检查串口连接 + - 确认串口路径和波特率设置 + +## 测试验证 + +### 1. 使用测试Activity +可以通过`ABGateTestActivity`进行功能测试: + +```java +// 在AndroidManifest.xml中注册 + + +// 启动测试 +Intent intent = new Intent(this, ABGateTestActivity.class); +startActivity(intent); +``` + +### 2. 日志调试 +所有关键操作都有详细日志记录,可以通过LogCat查看: + +```bash +# 过滤AB门禁相关日志 +adb logcat | grep -E "(ABGateManager|OxUDP|Ox485)" +``` + +## 性能优化 + +### 1. 超时控制 +- 门状态检查:5秒超时 +- 人数检查:10秒超时 +- 总体检查:最多17秒完成 + +### 2. 异步处理 +- 所有网络和串口操作都在后台线程执行 +- 回调在主线程中触发,便于UI更新 + +### 3. 资源管理 +- 支持单例模式,避免重复初始化 +- 提供release()方法清理资源 + +## 总结 + +✅ **已完成功能**: +1. `checkGateABBeforeToDo()` - 完整检查流程 +2. `ABGateCheck()` - AB门状态检查(A门关闭 AND B门关闭) +3. `ABPeopleCheck()` - 人数检查(进场/离场智能判断) +4. 完整的错误处理和超时控制 +5. 详细的使用示例和测试界面 + +✅ **集成方式**: +- 在人脸识别前调用`checkGateABBeforeToDo()` +- 支持异步回调和同步阻塞两种方式 +- 提供完整的错误处理机制 + +✅ **技术实现**: +- UDP通信获取门状态(192.168.1.123:60000) +- 485串口通信获取人数(/dev/ttyS6, 9600) +- 智能场景判断(进场/离场) + +该模块已完全满足您的需求,可以直接在项目中使用。如需要其他功能或有任何问题,请随时告知。 \ No newline at end of file diff --git a/app/src/main/java/com/ouxuan/oxface/abgate/ABGateManager.java b/app/src/main/java/com/ouxuan/oxface/abgate/ABGateManager.java new file mode 100644 index 0000000..af76771 --- /dev/null +++ b/app/src/main/java/com/ouxuan/oxface/abgate/ABGateManager.java @@ -0,0 +1,353 @@ +package com.ouxuan.oxface.abgate; + +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import com.ouxuan.oxface.device.GateABController; +import com.ouxuan.oxface.device.OxUDP; +import com.ouxuan.oxface.device.Ox485; +import com.ouxuan.oxface.utils.LogManager; +import com.ouxuan.oxface.utils.VenueSceneUtils; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +/** + * AB门禁管理器 + * 集成门状态检查、人数检测和业务逻辑判断 + * + * 主要功能: + * - 检测AB门状态(A门、B门是否关闭) + * - 检测门禁内人数(通过485摄像头) + * - 根据进场/离场场景判断是否可用 + * + * @author AI Assistant + * @version 1.0 + * @date 2024/09/13 + */ +public class ABGateManager { + + private static final String TAG = "ABGateManager"; + + // 单例实例 + private static volatile ABGateManager instance; + + // 核心组件 + private Context context; + private GateABController gateABController; + private OxUDP oxUDP; + private Ox485 ox485; + private Handler mainHandler; + + // 超时配置 + private static final long GATE_CHECK_TIMEOUT = 5000; // 门状态检查超时 5秒 + private static final long PEOPLE_CHECK_TIMEOUT = 10000; // 人数检查超时 10秒 + + /** + * AB门检查结果回调接口 + */ + public interface ABGateCheckCallback { + void onSuccess(boolean canProceed); + void onError(String errorMessage); + } + + private ABGateManager() { + mainHandler = new Handler(Looper.getMainLooper()); + gateABController = GateABController.getInstance(); + oxUDP = OxUDP.getInstance(); + ox485 = Ox485.getInstance(); + } + + /** + * 获取ABGateManager单例实例 + * @return ABGateManager实例 + */ + public static ABGateManager getInstance() { + if (instance == null) { + synchronized (ABGateManager.class) { + if (instance == null) { + instance = new ABGateManager(); + } + } + } + return instance; + } + + /** + * 初始化AB门禁管理器 + * @param context 上下文 + */ + public void initialize(Context context) { + this.context = context; + LogManager.logInfo(TAG, "ABGateManager初始化完成"); + } + + /** + * 检测AB门状态和人数,判断是否可用 + * 主要入口方法:先检查门状态,再检查人数 + * + * @param callback 检查结果回调 + */ + public void checkGateABBeforeToDo(ABGateCheckCallback callback) { + LogManager.logInfo(TAG, "开始执行AB门检查流程"); + + if (callback == null) { + LogManager.logError(TAG, "回调参数为空"); + return; + } + + // 第一步:检查AB门状态 + LogManager.logInfo(TAG, "第一步:检查AB门状态"); + ABGateCheck(new ABGateCheckCallback() { + @Override + public void onSuccess(boolean gateAvailable) { + if (gateAvailable) { + LogManager.logInfo(TAG, "门状态检查通过,开始第二步:检查门内人数"); + // 第二步:检查门内人数 + ABPeopleCheck(new ABGateCheckCallback() { + @Override + public void onSuccess(boolean peopleCheckPassed) { + LogManager.logInfo(TAG, "人数检查完成,最终结果: " + peopleCheckPassed); + callback.onSuccess(peopleCheckPassed); + } + + @Override + public void onError(String errorMessage) { + LogManager.logError(TAG, "人数检查失败: " + errorMessage); + callback.onError("人数检查失败: " + errorMessage); + } + }); + } else { + LogManager.logWarning(TAG, "门状态检查未通过,AB门当前不可用"); + callback.onSuccess(false); + } + } + + @Override + public void onError(String errorMessage) { + LogManager.logError(TAG, "门状态检查失败: " + errorMessage); + callback.onError("门状态检查失败: " + errorMessage); + } + }); + } + + /** + * AB门状态检查 + * 逻辑:A门关闭 AND B门关闭 时才返回true,否则返回false + * + * @param callback 检查结果回调 + */ + public void ABGateCheck(ABGateCheckCallback callback) { + LogManager.logInfo(TAG, "执行AB门状态检查"); + + if (callback == null) { + LogManager.logError(TAG, "ABGateCheck回调参数为空"); + return; + } + + // 检查UDP是否初始化 + if (!oxUDP.isInitialized()) { + String errorMsg = "UDP门禁控制器未初始化"; + LogManager.logError(TAG, errorMsg); + callback.onError(errorMsg); + return; + } + + try { + // 创建超时控制的CompletableFuture + CompletableFuture gateCheckFuture = new CompletableFuture<>(); + + // 设置UDP状态监听器来接收门状态 + OxUDP.UDPStateListener tempListener = new OxUDP.UDPStateListener() { + @Override + public void onGateStateUpdate(boolean gateAState, boolean gateBState, String rawData) { + LogManager.logInfo(TAG, "收到门状态更新 - A门: " + (gateAState ? "开启" : "关闭") + + ", B门: " + (gateBState ? "开启" : "关闭")); + + // 逻辑:A门关闭 AND B门关闭 时才为true + boolean bothGatesClosed = !gateAState && !gateBState; + LogManager.logInfo(TAG, "门状态检查结果: " + (bothGatesClosed ? "可用" : "不可用")); + + gateCheckFuture.complete(bothGatesClosed); + } + + @Override + public void onGateOpenResult(String gateType, boolean success) { + // 不处理开门结果 + } + + @Override + public void onUDPError(String error) { + LogManager.logError(TAG, "UDP门状态查询错误: " + error); + gateCheckFuture.completeExceptionally(new RuntimeException("UDP查询错误: " + error)); + } + }; + + // 设置临时监听器 + oxUDP.setStateListener(tempListener); + + // 启动门状态查询(如果没在轮询则启动) + if (!oxUDP.isPolling()) { + oxUDP.startPolling(); + } else { + // 如果已在轮询,强制查询一次最新状态 + oxUDP.queryGateState(); + } + + // 异步处理结果,设置超时 + gateCheckFuture + .orTimeout(GATE_CHECK_TIMEOUT, TimeUnit.MILLISECONDS) + .whenComplete((result, throwable) -> { + mainHandler.post(() -> { + if (throwable != null) { + String errorMsg = "门状态检查超时或异常: " + throwable.getMessage(); + LogManager.logError(TAG, errorMsg); + callback.onError(errorMsg); + } else { + LogManager.logInfo(TAG, "门状态检查完成,结果: " + result); + callback.onSuccess(result); + } + }); + }); + + } catch (Exception e) { + String errorMsg = "门状态检查异常: " + e.getMessage(); + LogManager.logError(TAG, errorMsg, e); + callback.onError(errorMsg); + } + } + + /** + * AB门内人数检查 + * 逻辑: + * - 进场设备:门内人数 > 1 时不可用(返回false) + * - 离场设备:门内人数 != 0 时不可用(返回false) + * + * @param callback 检查结果回调 + */ + public void ABPeopleCheck(ABGateCheckCallback callback) { + LogManager.logInfo(TAG, "执行AB门内人数检查"); + + if (callback == null) { + LogManager.logError(TAG, "ABPeopleCheck回调参数为空"); + return; + } + + // 检查485是否启用 + if (!ox485.isGateCamera485OxOn()) { + String errorMsg = "485摄像头模式未启用"; + LogManager.logError(TAG, errorMsg); + callback.onError(errorMsg); + return; + } + + try { + // 判断当前设备是进场还是离场 + boolean isLeaveScene = VenueSceneUtils.isLeaveScene(context); + String sceneType = isLeaveScene ? "离场" : "进场"; + LogManager.logInfo(TAG, "当前场景类型: " + sceneType); + + // 异步获取485人数 + ox485.sendHex485ForPeopleNum(new Ox485.PeopleNumCallback() { + @Override + public void onSuccess(int peopleNum) { + LogManager.logInfo(TAG, "485人数获取成功: " + peopleNum + " 人,场景: " + sceneType); + + boolean peopleCheckPassed = false; + String checkResult = ""; + + if (isLeaveScene) { + // 离场设备:门内人数 != 0 时不可用 + peopleCheckPassed = (peopleNum == 0); + checkResult = "离场场景,门内人数: " + peopleNum + "," + + (peopleCheckPassed ? "可用" : "不可用(人数不为0)"); + } else { + // 进场设备:门内人数 > 1 时不可用 + peopleCheckPassed = (peopleNum <= 1); + checkResult = "进场场景,门内人数: " + peopleNum + "," + + (peopleCheckPassed ? "可用" : "不可用(人数大于1)"); + } + + LogManager.logInfo(TAG, "人数检查结果: " + checkResult); + + mainHandler.post(() -> callback.onSuccess(peopleCheckPassed)); + } + + @Override + public void onError(String errorMessage) { + LogManager.logError(TAG, "485人数获取失败: " + errorMessage); + mainHandler.post(() -> callback.onError("485人数获取失败: " + errorMessage)); + } + }); + + // 设置超时处理 + mainHandler.postDelayed(() -> { + String timeoutMsg = "人数检查超时"; + LogManager.logError(TAG, timeoutMsg); + callback.onError(timeoutMsg); + }, PEOPLE_CHECK_TIMEOUT); + + } catch (Exception e) { + String errorMsg = "人数检查异常: " + e.getMessage(); + LogManager.logError(TAG, errorMsg, e); + callback.onError(errorMsg); + } + } + + /** + * 同步方式检查AB门状态和人数(阻塞方法) + * 注意:此方法会阻塞当前线程,不建议在主线程调用 + * + * @return true表示可用,false表示不可用 + * @throws Exception 检查过程中的异常 + */ + public boolean checkGateABBeforeToDoSync() throws Exception { + LogManager.logInfo(TAG, "执行同步AB门检查"); + + CompletableFuture future = new CompletableFuture<>(); + + checkGateABBeforeToDo(new ABGateCheckCallback() { + @Override + public void onSuccess(boolean canProceed) { + future.complete(canProceed); + } + + @Override + public void onError(String errorMessage) { + future.completeExceptionally(new RuntimeException(errorMessage)); + } + }); + + try { + // 总超时时间为门状态检查 + 人数检查的时间 + return future.get(GATE_CHECK_TIMEOUT + PEOPLE_CHECK_TIMEOUT + 2000, TimeUnit.MILLISECONDS); + } catch (Exception e) { + LogManager.logError(TAG, "同步检查异常", e); + throw e; + } + } + + /** + * 获取当前AB门状态信息(调试用) + */ + public void getABGateStatusInfo() { + LogManager.logInfo(TAG, "获取AB门状态信息"); + LogManager.logInfo(TAG, "UDP初始化状态: " + oxUDP.isInitialized()); + LogManager.logInfo(TAG, "UDP轮询状态: " + oxUDP.isPolling()); + LogManager.logInfo(TAG, "485模式状态: " + ox485.isGateCamera485OxOn()); + LogManager.logInfo(TAG, "485状态信息: " + ox485.get485Status()); + + if (context != null) { + boolean isLeaveScene = VenueSceneUtils.isLeaveScene(context); + LogManager.logInfo(TAG, "当前场景: " + (isLeaveScene ? "离场" : "进场")); + } + } + + /** + * 释放资源 + */ + public void release() { + LogManager.logInfo(TAG, "释放ABGateManager资源"); + context = null; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ouxuan/oxface/abgate/ABGateTestActivity.java b/app/src/main/java/com/ouxuan/oxface/abgate/ABGateTestActivity.java new file mode 100644 index 0000000..74b7abf --- /dev/null +++ b/app/src/main/java/com/ouxuan/oxface/abgate/ABGateTestActivity.java @@ -0,0 +1,235 @@ +package com.ouxuan.oxface.abgate; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; +import com.ouxuan.oxface.R; +import com.ouxuan.oxface.utils.LogManager; + +/** + * AB门禁测试Activity + * 用于测试AB门禁管理器的各项功能 + * + * @author AI Assistant + * @version 1.0 + * @date 2024/09/13 + */ +public class ABGateTestActivity extends Activity { + + private static final String TAG = "ABGateTestActivity"; + + private ABGateManager abGateManager; + private TextView tvStatus; + private Button btnFullCheck; + private Button btnGateCheck; + private Button btnPeopleCheck; + private Button btnStatusInfo; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // 创建简单的测试界面 + createTestUI(); + + // 初始化AB门禁管理器 + initABGateManager(); + + LogManager.logInfo(TAG, "AB门禁测试Activity启动"); + } + + /** + * 创建测试界面 + */ + private void createTestUI() { + // 创建垂直线性布局 + android.widget.LinearLayout layout = new android.widget.LinearLayout(this); + layout.setOrientation(android.widget.LinearLayout.VERTICAL); + layout.setPadding(50, 50, 50, 50); + + // 标题 + TextView tvTitle = new TextView(this); + tvTitle.setText("AB门禁测试界面"); + tvTitle.setTextSize(20); + tvTitle.setPadding(0, 0, 0, 30); + layout.addView(tvTitle); + + // 状态显示 + tvStatus = new TextView(this); + tvStatus.setText("等待测试..."); + tvStatus.setTextSize(16); + tvStatus.setPadding(0, 0, 0, 30); + tvStatus.setBackgroundColor(0xFFE0E0E0); + tvStatus.setPadding(20, 20, 20, 20); + layout.addView(tvStatus); + + // 完整检查按钮 + btnFullCheck = new Button(this); + btnFullCheck.setText("完整AB门检查"); + btnFullCheck.setOnClickListener(v -> performFullCheck()); + layout.addView(btnFullCheck); + + // 门状态检查按钮 + btnGateCheck = new Button(this); + btnGateCheck.setText("仅检查门状态"); + btnGateCheck.setOnClickListener(v -> performGateCheck()); + layout.addView(btnGateCheck); + + // 人数检查按钮 + btnPeopleCheck = new Button(this); + btnPeopleCheck.setText("仅检查人数"); + btnPeopleCheck.setOnClickListener(v -> performPeopleCheck()); + layout.addView(btnPeopleCheck); + + // 状态信息按钮 + btnStatusInfo = new Button(this); + btnStatusInfo.setText("获取状态信息"); + btnStatusInfo.setOnClickListener(v -> getStatusInfo()); + layout.addView(btnStatusInfo); + + // 返回按钮 + Button btnBack = new Button(this); + btnBack.setText("返回"); + btnBack.setOnClickListener(v -> finish()); + layout.addView(btnBack); + + setContentView(layout); + } + + /** + * 初始化AB门禁管理器 + */ + private void initABGateManager() { + abGateManager = ABGateManager.getInstance(); + abGateManager.initialize(this); + + updateStatus("AB门禁管理器初始化完成"); + LogManager.logInfo(TAG, "AB门禁管理器初始化完成"); + } + + /** + * 执行完整AB门检查 + */ + private void performFullCheck() { + updateStatus("正在执行完整AB门检查..."); + LogManager.logInfo(TAG, "开始执行完整AB门检查"); + + abGateManager.checkGateABBeforeToDo(new ABGateManager.ABGateCheckCallback() { + @Override + public void onSuccess(boolean canProceed) { + String result = canProceed ? "检查通过,可以继续操作" : "检查未通过,请等待"; + updateStatus("完整检查结果: " + result); + showToast(result); + LogManager.logInfo(TAG, "完整检查结果: " + result); + } + + @Override + public void onError(String errorMessage) { + String error = "完整检查失败: " + errorMessage; + updateStatus(error); + showToast(error); + LogManager.logError(TAG, error); + } + }); + } + + /** + * 执行门状态检查 + */ + private void performGateCheck() { + updateStatus("正在检查门状态..."); + LogManager.logInfo(TAG, "开始执行门状态检查"); + + abGateManager.ABGateCheck(new ABGateManager.ABGateCheckCallback() { + @Override + public void onSuccess(boolean gateAvailable) { + String result = gateAvailable ? "AB门已关闭,可用" : "AB门未完全关闭,不可用"; + updateStatus("门状态检查结果: " + result); + showToast(result); + LogManager.logInfo(TAG, "门状态检查结果: " + result); + } + + @Override + public void onError(String errorMessage) { + String error = "门状态检查失败: " + errorMessage; + updateStatus(error); + showToast(error); + LogManager.logError(TAG, error); + } + }); + } + + /** + * 执行人数检查 + */ + private void performPeopleCheck() { + updateStatus("正在检查门内人数..."); + LogManager.logInfo(TAG, "开始执行人数检查"); + + abGateManager.ABPeopleCheck(new ABGateManager.ABGateCheckCallback() { + @Override + public void onSuccess(boolean peopleCheckPassed) { + String result = peopleCheckPassed ? "人数符合要求" : "人数不符合要求"; + updateStatus("人数检查结果: " + result); + showToast(result); + LogManager.logInfo(TAG, "人数检查结果: " + result); + } + + @Override + public void onError(String errorMessage) { + String error = "人数检查失败: " + errorMessage; + updateStatus(error); + showToast(error); + LogManager.logError(TAG, error); + } + }); + } + + /** + * 获取状态信息 + */ + private void getStatusInfo() { + updateStatus("获取AB门状态信息..."); + LogManager.logInfo(TAG, "获取AB门状态信息"); + + // 获取状态信息(这会打印到日志中) + abGateManager.getABGateStatusInfo(); + + updateStatus("状态信息已打印到日志,请查看LogCat"); + showToast("状态信息已打印到日志"); + } + + /** + * 更新状态显示 + */ + private void updateStatus(String status) { + runOnUiThread(() -> { + if (tvStatus != null) { + String timestamp = java.text.DateFormat.getTimeInstance().format(new java.util.Date()); + tvStatus.setText("[" + timestamp + "] " + status); + } + }); + } + + /** + * 显示Toast消息 + */ + private void showToast(String message) { + runOnUiThread(() -> Toast.makeText(this, message, Toast.LENGTH_SHORT).show()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + // 清理资源 + if (abGateManager != null) { + abGateManager.release(); + } + + LogManager.logInfo(TAG, "AB门禁测试Activity销毁"); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ouxuan/oxface/abgate/ABGateUsageExample.java b/app/src/main/java/com/ouxuan/oxface/abgate/ABGateUsageExample.java new file mode 100644 index 0000000..3fee5f0 --- /dev/null +++ b/app/src/main/java/com/ouxuan/oxface/abgate/ABGateUsageExample.java @@ -0,0 +1,220 @@ +package com.ouxuan.oxface.abgate; + +import android.content.Context; +import com.ouxuan.oxface.utils.LogManager; + +/** + * ABGateManager使用示例 + * 展示如何在项目中集成和使用AB门禁检查功能 + * + * @author AI Assistant + * @version 1.0 + * @date 2024/09/13 + */ +public class ABGateUsageExample { + + private static final String TAG = "ABGateUsageExample"; + private ABGateManager abGateManager; + private Context context; + + public ABGateUsageExample(Context context) { + this.context = context; + this.abGateManager = ABGateManager.getInstance(); + } + + /** + * 初始化AB门禁管理器 + */ + public void initialize() { + abGateManager.initialize(context); + LogManager.logInfo(TAG, "ABGateManager初始化完成"); + } + + /** + * 在人脸识别成功前执行AB门检查 + * 这是主要的使用场景 + */ + public void checkBeforeFaceRecognition() { + LogManager.logInfo(TAG, "开始执行人脸识别前的AB门检查"); + + abGateManager.checkGateABBeforeToDo(new ABGateManager.ABGateCheckCallback() { + @Override + public void onSuccess(boolean canProceed) { + if (canProceed) { + LogManager.logInfo(TAG, "AB门检查通过,可以进行人脸识别"); + // 在这里继续执行人脸识别逻辑 + proceedWithFaceRecognition(); + } else { + LogManager.logWarning(TAG, "AB门检查未通过,请等待门关闭或人员离开"); + // 在这里处理检查未通过的情况 + handleGateCheckFailed(); + } + } + + @Override + public void onError(String errorMessage) { + LogManager.logError(TAG, "AB门检查失败: " + errorMessage); + // 在这里处理检查错误的情况 + handleGateCheckError(errorMessage); + } + }); + } + + /** + * 单独执行门状态检查 + */ + public void checkGateStatusOnly() { + LogManager.logInfo(TAG, "单独执行门状态检查"); + + abGateManager.ABGateCheck(new ABGateManager.ABGateCheckCallback() { + @Override + public void onSuccess(boolean gateAvailable) { + LogManager.logInfo(TAG, "门状态检查结果: " + (gateAvailable ? "门已关闭,可用" : "门未完全关闭,不可用")); + } + + @Override + public void onError(String errorMessage) { + LogManager.logError(TAG, "门状态检查失败: " + errorMessage); + } + }); + } + + /** + * 单独执行人数检查 + */ + public void checkPeopleCountOnly() { + LogManager.logInfo(TAG, "单独执行人数检查"); + + abGateManager.ABPeopleCheck(new ABGateManager.ABGateCheckCallback() { + @Override + public void onSuccess(boolean peopleCheckPassed) { + LogManager.logInfo(TAG, "人数检查结果: " + (peopleCheckPassed ? "人数符合要求" : "人数不符合要求")); + } + + @Override + public void onError(String errorMessage) { + LogManager.logError(TAG, "人数检查失败: " + errorMessage); + } + }); + } + + /** + * 获取AB门状态信息(调试用) + */ + public void getStatusInfo() { + LogManager.logInfo(TAG, "获取AB门状态信息"); + abGateManager.getABGateStatusInfo(); + } + + /** + * 同步方式检查(注意:不要在主线程调用) + */ + public void syncCheckExample() { + // 在后台线程执行 + new Thread(() -> { + try { + LogManager.logInfo(TAG, "开始同步检查AB门"); + boolean result = abGateManager.checkGateABBeforeToDoSync(); + LogManager.logInfo(TAG, "同步检查结果: " + (result ? "可用" : "不可用")); + + // 将结果切换回主线程处理 + android.os.Handler mainHandler = new android.os.Handler(android.os.Looper.getMainLooper()); + mainHandler.post(() -> { + if (result) { + proceedWithFaceRecognition(); + } else { + handleGateCheckFailed(); + } + }); + + } catch (Exception e) { + LogManager.logError(TAG, "同步检查异常", e); + } + }).start(); + } + + /** + * 处理检查通过后的人脸识别逻辑 + */ + private void proceedWithFaceRecognition() { + LogManager.logInfo(TAG, "开始执行人脸识别逻辑"); + // 这里添加实际的人脸识别启动代码 + // 例如: + // 1. 启动摄像头预览 + // 2. 开始人脸检测 + // 3. 显示相关UI提示 + } + + /** + * 处理检查未通过的情况 + */ + private void handleGateCheckFailed() { + LogManager.logWarning(TAG, "AB门检查未通过,暂时无法进行人脸识别"); + // 这里添加处理逻辑,例如: + // 1. 显示等待提示 + // 2. 延迟重新检查 + // 3. 提示用户等待门关闭或人员离开 + + // 可以设置延迟重新检查 + android.os.Handler handler = new android.os.Handler(android.os.Looper.getMainLooper()); + handler.postDelayed(() -> { + LogManager.logInfo(TAG, "5秒后重新检查AB门状态"); + checkBeforeFaceRecognition(); + }, 5000); // 5秒后重新检查 + } + + /** + * 处理检查错误的情况 + */ + private void handleGateCheckError(String errorMessage) { + LogManager.logError(TAG, "AB门检查发生错误,需要处理: " + errorMessage); + // 这里添加错误处理逻辑,例如: + // 1. 显示错误提示 + // 2. 尝试重新初始化相关组件 + // 3. 降级到无门禁检查模式 + } + + /** + * 清理资源 + */ + public void cleanup() { + if (abGateManager != null) { + abGateManager.release(); + } + LogManager.logInfo(TAG, "ABGateUsageExample资源清理完成"); + } + + /** + * 在Activity中的完整集成示例 + */ + public static class ActivityIntegrationExample { + + private ABGateUsageExample gateUsageExample; + + /** + * 在Activity的onCreate中初始化 + */ + public void onCreateInitialize(Context context) { + gateUsageExample = new ABGateUsageExample(context); + gateUsageExample.initialize(); + } + + /** + * 在Activity的onResume中开始检查 + */ + public void onResumeCheck() { + if (gateUsageExample != null) { + gateUsageExample.checkBeforeFaceRecognition(); + } + } + + /** + * 在Activity的onDestroy中清理资源 + */ + public void onDestroyCleanup() { + if (gateUsageExample != null) { + gateUsageExample.cleanup(); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ouxuan/oxface/device/OxUDP.java b/app/src/main/java/com/ouxuan/oxface/device/OxUDP.java index aad5239..0ba22d9 100644 --- a/app/src/main/java/com/ouxuan/oxface/device/OxUDP.java +++ b/app/src/main/java/com/ouxuan/oxface/device/OxUDP.java @@ -358,7 +358,7 @@ public class OxUDP { /** * 查询门禁状态 */ - private void queryGateState() { + public void queryGateState() { try { String response = sendUDPCommand(udp_state_cmd);