You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
867 lines
34 KiB
867 lines
34 KiB
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门配置类
|
|
* 对应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();
|
|
|
|
// 初始化中控网络服务
|
|
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);
|
|
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<ApiResponse<PadApiService.GateControlResult>> call =
|
|
acControlApiService.controlGateFromAC(request);
|
|
|
|
call.enqueue(new Callback<ApiResponse<PadApiService.GateControlResult>>() {
|
|
@Override
|
|
public void onResponse(Call<ApiResponse<PadApiService.GateControlResult>> call,
|
|
Response<ApiResponse<PadApiService.GateControlResult>> response) {
|
|
|
|
if (response.isSuccessful() && response.body() != null) {
|
|
ApiResponse<PadApiService.GateControlResult> 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<ApiResponse<PadApiService.GateControlResult>> 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<String> 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 ? "开启" : "关闭"));
|
|
|
|
// 按照业务逻辑:当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);
|
|
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<Integer> 人数结果
|
|
*/
|
|
public java.util.concurrent.CompletableFuture<Integer> get485PeopleNumAsync() {
|
|
LogManager.logInfo(TAG, "异步获取485摄像头人数");
|
|
|
|
java.util.concurrent.CompletableFuture<Integer> 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;
|
|
}
|
|
}
|
|
|