Browse Source

fix 4.1

devab
赵明涛 3 weeks ago
parent
commit
fd83d3ce05
  1. 2
      app/src/main/java/com/ouxuan/oxface/debug/Ox485DebugHelper.java
  2. 174
      app/src/main/java/com/ouxuan/oxface/device/Ox485.java

2
app/src/main/java/com/ouxuan/oxface/debug/Ox485DebugHelper.java

@ -3,6 +3,8 @@ package com.ouxuan.oxface.debug;
import com.ouxuan.oxface.device.Ox485; import com.ouxuan.oxface.device.Ox485;
import com.ouxuan.oxface.utils.LogManager; import com.ouxuan.oxface.utils.LogManager;
import java.io.File;
/** /**
* Ox485调试助手 * Ox485调试助手
* 用于排查485通信问题 * 用于排查485通信问题

174
app/src/main/java/com/ouxuan/oxface/device/Ox485.java

@ -18,11 +18,11 @@ import java.util.concurrent.TimeUnit;
* Ox485 串口通信模块 * Ox485 串口通信模块
* 基于kongqw/SerialPortLibrary实现485通信功能 * 基于kongqw/SerialPortLibrary实现485通信功能
* 主要用于获取摄像头人数等485设备通信 * 主要用于获取摄像头人数等485设备通信
* 采用懒加载连接管理模式首次使用时打开保持连接状态定时检查机制
* 采用即用即连模式每次请求时打开连接完成后立即关闭确保通信可靠性
* *
* @author AI Assistant * @author AI Assistant
* @version 2.0
* @date 2024/09/15
* @version 3.0 - 即用即连模式
* @date 2024/09/22
*/ */
public class Ox485 { public class Ox485 {
@ -35,8 +35,7 @@ public class Ox485 {
private static final String HEX_COMMAND_GET_PEOPLE_NUM = "0F030001000294E5"; private static final String HEX_COMMAND_GET_PEOPLE_NUM = "0F030001000294E5";
private static final long TIMEOUT_485_MILLIS = 10000; // 10秒超时 private static final long TIMEOUT_485_MILLIS = 10000; // 10秒超时
// 懒加载连接管理配置
private static final long CONNECTION_CHECK_INTERVAL = 30000; // 30秒检查一次连接状态
// 即用即连模式配置
private static final int MAX_RETRY_COUNT = 3; // 最大重试次数 private static final int MAX_RETRY_COUNT = 3; // 最大重试次数
private static final long RETRY_DELAY = 1000; // 重试延迟1秒 private static final long RETRY_DELAY = 1000; // 重试延迟1秒
@ -44,19 +43,10 @@ public class Ox485 {
private static volatile Ox485 instance; private static volatile Ox485 instance;
// 485通信相关 // 485通信相关
private SerialPortManager serialPortManager;
private Handler mainHandler; private Handler mainHandler;
private boolean gateCamera485OxOn = false; private boolean gateCamera485OxOn = false;
private Context context; private Context context;
// 懒加载连接管理相关
private boolean isSerialPortOpen = false; // 串口是否已打开
private boolean isConnecting = false; // 是否正在连接中
private Handler connectionCheckHandler; // 连接检查处理器
private Runnable connectionCheckRunnable; // 连接检查任务
private long lastSuccessTime = 0; // 最后一次成功通信时间
private int currentRetryCount = 0; // 当前重试次数
// 数据接收相关 // 数据接收相关
private long lastRecvTime = 0; private long lastRecvTime = 0;
private Handler timeoutHandler; private Handler timeoutHandler;
@ -96,10 +86,7 @@ public class Ox485 {
*/ */
public void initialize(Context context) { public void initialize(Context context) {
this.context = context; this.context = context;
LogManager.logInfo(TAG, "15:45:22.734 Ox485 D Ox485模块初始化完成,采用懒加载连接管理模式");
// 启动定时连接检查
startConnectionCheck();
LogManager.logInfo(TAG, "Ox485模块初始化完成,采用即用即连模式");
} }
/** /**
@ -108,7 +95,7 @@ public class Ox485 {
*/ */
public void setGateCamera485OxOn(boolean enabled) { public void setGateCamera485OxOn(boolean enabled) {
this.gateCamera485OxOn = enabled; this.gateCamera485OxOn = enabled;
LogManager.logInfo(TAG, "15:45:22.734 Ox485 D 设置485模式开关: " + enabled);
LogManager.logInfo(TAG, "设置485模式开关: " + enabled);
} }
/** /**
@ -272,21 +259,6 @@ public class Ox485 {
} }
/** /**
* 关闭并清理串口资源
* @param serialPortManager 串口管理器
*/
private void closeAndCleanup(SerialPortManager serialPortManager) {
if (serialPortManager != null) {
try {
serialPortManager.closeSerialPort();
LogManager.logInfo(TAG, "485串口已关闭并清理资源");
} catch (Exception e) {
LogManager.logError(TAG, "关闭485串口时发生异常: " + e.getMessage(), e);
}
}
}
/**
* 设置超时处理 * 设置超时处理
* @param serialPortManager 串口管理器 * @param serialPortManager 串口管理器
* @param callback 结果回调 * @param callback 结果回调
@ -351,7 +323,7 @@ public class Ox485 {
// 提取第5个字节作为人数数据使用位掩码确保为无符号整数 // 提取第5个字节作为人数数据使用位掩码确保为无符号整数
int peopleNum = arr[4] & 0xFF; int peopleNum = arr[4] & 0xFF;
LogManager.logInfo(TAG, "15:45:22.734 Ox485 D 解析485人数成功: " + peopleNum);
LogManager.logInfo(TAG, "解析485人数成功: " + peopleNum);
return peopleNum; return peopleNum;
} }
@ -384,7 +356,7 @@ public class Ox485 {
* 检查是否需要打开485串口 * 检查是否需要打开485串口
*/ */
public void checkIsNeedOpen485() { public void checkIsNeedOpen485() {
LogManager.logInfo(TAG, "检查485串口状态(懒加载模式)");
LogManager.logInfo(TAG, "检查485串口状态(即用即连模式)");
String status = get485Status(); String status = get485Status();
LogManager.logInfo(TAG, status); LogManager.logInfo(TAG, status);
} }
@ -396,22 +368,71 @@ public class Ox485 {
public void send485HexCommand(String hexCommand) { public void send485HexCommand(String hexCommand) {
LogManager.logInfo(TAG, "发送485 HEX命令: " + hexCommand); LogManager.logInfo(TAG, "发送485 HEX命令: " + hexCommand);
try { try {
if (!isSerialPortOpen) {
LogManager.logWarning(TAG, "串口未打开,无法发送命令");
if (!gateCamera485OxOn) {
LogManager.logWarning(TAG, "485模式未开启,无法发送命令");
return; return;
} }
// 创建临时串口管理器发送命令
SerialPortManager serialPortManager = new SerialPortManager();
File serialPortFile = new File(DEFAULT_SERIAL_PORT_PATH);
if (!serialPortFile.exists()) {
LogManager.logWarning(TAG, "串口设备文件不存在: " + DEFAULT_SERIAL_PORT_PATH);
return;
}
boolean openResult = serialPortManager.openSerialPort(serialPortFile, DEFAULT_BAUD_RATE);
if (!openResult) {
LogManager.logWarning(TAG, "打开串口失败: " + DEFAULT_SERIAL_PORT_PATH);
return;
}
serialPortManager.startReadThread(485);
serialPortManager.startSendThread();
byte[] hexBytes = hexStringToByteArray(hexCommand); byte[] hexBytes = hexStringToByteArray(hexCommand);
serialPortManager.sendBytes(hexBytes); serialPortManager.sendBytes(hexBytes);
LogManager.logInfo(TAG, "485命令发送完成"); LogManager.logInfo(TAG, "485命令发送完成");
// 发送完成后关闭连接
closeAndCleanup(serialPortManager);
} catch (Exception e) { } catch (Exception e) {
LogManager.logError(TAG, "发送485命令异常: " + e.getMessage(), e); LogManager.logError(TAG, "发送485命令异常: " + e.getMessage(), e);
} }
} }
/** /**
* 获取485串口状态即用即连模式
* @return 串口状态描述
*/
public String get485Status() {
String status = "串口状态: 即用即连模式" +
", 路径: " + DEFAULT_SERIAL_PORT_PATH +
", 波特率: " + DEFAULT_BAUD_RATE +
", 485模式: " + (gateCamera485OxOn ? "已启用" : "未启用");
LogManager.logInfo(TAG, status);
return status;
}
/**
* 关闭485串口兼容旧接口
*/
public void close485SerialPort() {
LogManager.logInfo(TAG, "485串口即用即连模式无需手动关闭");
}
/**
* 释放资源
*/
public void release() {
LogManager.logInfo(TAG, "释放Ox485资源(即用即连模式)");
}
/**
* 485连接诊断方法 * 485连接诊断方法
* 用于排查485通信问题
*/ */
public void diagnose485Connection() { public void diagnose485Connection() {
LogManager.logInfo(TAG, "开始485连接诊断"); LogManager.logInfo(TAG, "开始485连接诊断");
@ -426,41 +447,18 @@ public class Ox485 {
LogManager.logInfo(TAG, " - 文件大小: " + serialPortFile.length()); LogManager.logInfo(TAG, " - 文件大小: " + serialPortFile.length());
} }
// 2. 检查串口管理器状态
LogManager.logInfo(TAG, "诊断2 - 串口管理器状态:");
LogManager.logInfo(TAG, " - 串口是否打开: " + (isSerialPortReallyOpen() ? "已打开" : "未打开"));
LogManager.logInfo(TAG, " - 内部连接状态: " + isSerialPortOpen);
LogManager.logInfo(TAG, " - 是否连接中: " + isConnecting);
// 3. 检查485模式开关
LogManager.logInfo(TAG, "诊断3 - 485配置:");
// 2. 检查485配置
LogManager.logInfo(TAG, "诊断2 - 485配置:");
LogManager.logInfo(TAG, " - 485模式开关: " + gateCamera485OxOn); LogManager.logInfo(TAG, " - 485模式开关: " + gateCamera485OxOn);
LogManager.logInfo(TAG, " - 串口路径: " + DEFAULT_SERIAL_PORT_PATH); LogManager.logInfo(TAG, " - 串口路径: " + DEFAULT_SERIAL_PORT_PATH);
LogManager.logInfo(TAG, " - 波特率: " + DEFAULT_BAUD_RATE); LogManager.logInfo(TAG, " - 波特率: " + DEFAULT_BAUD_RATE);
LogManager.logInfo(TAG, " - 停止位: " + DEFAULT_STOP_BITS);
LogManager.logInfo(TAG, " - 查询命令: " + HEX_COMMAND_GET_PEOPLE_NUM); LogManager.logInfo(TAG, " - 查询命令: " + HEX_COMMAND_GET_PEOPLE_NUM);
// 4. 检查连接历史
LogManager.logInfo(TAG, "诊断4 - 连接历史:");
String lastSuccessStr = lastSuccessTime > 0 ?
new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new java.util.Date(lastSuccessTime)) :
"无";
LogManager.logInfo(TAG, " - 最后成功时间: " + lastSuccessStr);
LogManager.logInfo(TAG, " - 当前重试次数: " + currentRetryCount);
LogManager.logInfo(TAG, " - 最大重试次数: " + MAX_RETRY_COUNT);
// 5. 尝试重新建立连接进行测试
LogManager.logInfo(TAG, "诊断5 - 连接测试:");
// 3. 尝试通信测试
LogManager.logInfo(TAG, "诊断3 - 通信测试:");
if (gateCamera485OxOn) { if (gateCamera485OxOn) {
LogManager.logInfo(TAG, " - 485模式已启用,尝试测试连接...");
LogManager.logInfo(TAG, " - 485模式已启用,开始测试通信...");
// 强制关闭现有连接
if (isSerialPortOpen) {
LogManager.logInfo(TAG, " - 关闭现有连接进行重新测试");
close485SerialPort();
}
// 尝试重新连接并发送测试命令
sendHex485ForPeopleNum(new PeopleNumCallback() { sendHex485ForPeopleNum(new PeopleNumCallback() {
@Override @Override
public void onSuccess(int peopleNum) { public void onSuccess(int peopleNum) {
@ -473,45 +471,27 @@ public class Ox485 {
} }
}); });
} else { } else {
LogManager.logWarning(TAG, " - 485模式未启用,无法进行连接测试");
LogManager.logWarning(TAG, " - 485模式未启用,无法进行通信测试");
} }
LogManager.logInfo(TAG, "485连接诊断完成"); LogManager.logInfo(TAG, "485连接诊断完成");
} }
/** /**
* 获取485串口状态即用即连模式
* @return 串口状态描述
*/
public String get485Status() {
String status = "串口状态: 即用即连模式" +
", 路径: " + DEFAULT_SERIAL_PORT_PATH +
", 波特率: " + DEFAULT_BAUD_RATE +
", 485模式: " + (gateCamera485OxOn ? "已启用" : "未启用");
LogManager.logInfo(TAG, status);
return status;
}
/**
* 关闭485串口兼容旧接口
*/
public void close485SerialPort() {
LogManager.logInfo(TAG, "485串口即用即连模式无需手动关闭");
}
/**
* 释放资源
* 关闭并清理串口资源
* @param serialPortManager 串口管理器
*/ */
public void release() {
LogManager.logInfo(TAG, "释放Ox485资源(即用即连模式)");
private void closeAndCleanup(SerialPortManager serialPortManager) {
if (serialPortManager != null) {
try {
serialPortManager.closeSerialPort();
LogManager.logInfo(TAG, "485串口已关闭并清理资源");
} catch (Exception e) {
LogManager.logError(TAG, "关闭485串口时发生异常: " + e.getMessage(), e);
}
}
} }
// ========== 删除所有懒加载连接管理相关方法 ==========
// 删除initConnectionCheckTaskstartConnectionCheckstopConnectionCheck
// ensureConnectioncreateConnectionretryConnectionmarkSuccessfulCommunication
// isSerialPortReallyOpen等方法
/** /**
* HEX字符串转字节数组 * HEX字符串转字节数组
* @param hexString HEX字符串 * @param hexString HEX字符串

Loading…
Cancel
Save