Browse Source

fix 4 remove 485 lazy

devab
赵明涛 3 weeks ago
parent
commit
42d016eeb0
  1. 234
      485通信超时问题排查指南.md
  2. 49
      app/src/main/java/com/ouxuan/oxface/debug/Ox485DebugHelper.java
  3. 365
      app/src/main/java/com/ouxuan/oxface/device/Ox485.java

234
485通信超时问题排查指南.md

@ -1,195 +1,129 @@
# 485通信超时问题排查指南
## 问题描述
根据您提供的日志,485模块在查询摄像头人数时出现超时问题:
```
10:34:13.824 Ox485 D 发送485人数查询命令: 0F030001000294E5
10:34:23.825 Ox485 E 485人数查询超时
```
# 485通信超时问题解决方案(即用即连模式)
## 问题分析
1. **命令发送成功**:日志显示命令 `0F030001000294E5` 已成功发送
2. **无响应数据**:在10秒超时时间内,没有收到任何响应数据
3. **可能原因**
- 485设备未正常工作或断电
- 485通信线路故障
- 设备地址配置错误
- 波特率不匹配
- 串口权限或占用问题
## 代码修改内容
根据之前的排查日志和问题反馈,发现485模块存在以下问题:
### 1. 增强的发送命令方法
1. **懒加载模式复杂性高**:需要维护多个连接状态变量
2. **连接状态不一致**:容易出现连接打开但状态标志未更新的问题
3. **超时问题频繁**:连接一段时间后容易出现通信超时
4. **资源管理困难**:长时间保持串口连接可能导致资源泄露
- 添加了串口状态检查
- 增加了详细的发送日志
- 验证命令发送结果
## 解决方案:采用即用即连模式
### 2. 改进的连接建立方法
### 设计思路
- 增加了设备文件存在性检查
- 添加了文件权限检查
- 验证串口打开状态
**即用即连模式**的核心思想是:
- 每次485通信请求时创建新的串口连接
- 通信完成后立即关闭并释放所有资源
- 下次请求时重新建立全新连接
### 3. 详细的超时处理
### 优势
- 记录准确的等待时间
- 输出详细的状态信息
- 提供故障诊断信息
1. ✅ **简化状态管理**:无需维护复杂的连接状态
2. ✅ **自动错误恢复**:每次都是全新连接,自动恢复异常状态
3. ✅ **资源安全**:确保每次通信后都释放所有资源
4. ✅ **适合485特性**:485设备通常设计为按需通信
### 4. 新增诊断功能
### 实现细节
- `diagnose485Connection()` 方法:全面检查485连接状态
- `Ox485DebugHelper` 类:提供完整的诊断工具
## 使用调试工具
### 在代码中调用诊断方法
#### 1. 核心通信流程
```java
// 方法1:完整诊断(推荐)
Ox485DebugHelper.runFullDiagnosis();
public void sendHex485ForPeopleNum(PeopleNumCallback callback) {
// 1. 创建临时串口管理器
SerialPortManager serialPortManager = new SerialPortManager();
// 方法2:快速测试
Ox485DebugHelper.quickTest();
// 2. 打开串口并发送命令
openAndSendCommand(serialPortManager, callback);
// 方法3:单独诊断连接
Ox485.getInstance().diagnose485Connection();
// 3. 通信完成后自动关闭连接(无论成功或失败)
}
```
### 查看诊断结果
诊断工具会检查以下内容:
1. **串口设备文件**
- 文件是否存在:`/dev/ttyS6`
- 文件权限:可读/可写权限
#### 2. 资源管理
2. **串口管理器状态**
- 串口是否打开
- 内部连接状态
- 连接中状态
3. **485配置**
- 485模式开关状态
- 串口路径、波特率等参数
- 查询命令格式
4. **连接历史**
- 最后成功通信时间
- 重试次数统计
```java
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);
}
}
}
```
5. **实际通信测试**
- 尝试发送命令并等待响应
#### 3. 错误处理
## 排查步骤
无论通信成功或失败,都会执行资源清理:
- 超时时自动关闭连接
- 数据解析失败时关闭连接
- 异常发生时关闭连接
- 正常完成时关闭连接
### 第一步:运行诊断工具
## 使用方式
在您的Activity中添加以下代码:
### 在代码中调用
```java
// 在onCreate或其他适当位置调用
// 方法1:完整诊断(推荐)
Ox485DebugHelper.runFullDiagnosis();
```
### 第二步:检查硬件连接
1. 确认485设备电源是否正常
2. 检查485通信线路连接
3. 验证设备地址设置(当前使用0F)
4. 确认设备波特率设置(当前使用9600)
### 第三步:检查系统权限
```bash
# 检查串口设备文件
ls -l /dev/ttyS6
// 方法2:快速测试
Ox485DebugHelper.quickTest();
# 检查权限
chmod 666 /dev/ttyS6 # 如果权限不足
// 方法3:单独诊断连接
Ox485DebugHelper.diagnose485Connection();
```
### 第四步:测试通信协议
当前使用的485命令:
- **命令**:`0F030001000294E5`
- **含义**:查询地址为0F的设备的人数数据
- **期望响应**:9字节数据,格式为 `[15, 3, 4, 0, 人数, *, *, *, *]`
### 预期日志输出
### 第五步:逐步排查
修改后,正常的485通信日志应该类似:
1. **确认设备响应**
```java
// 发送简单的测试命令
Ox485.getInstance().send485HexCommand("0F030001000294E5");
```
2. **监控所有接收数据**
- 查看日志中是否有任何 `Ox485接收到数据` 的记录
- 即使是错误格式的数据也会被记录
3. **尝试不同的设备地址**
```java
// 如果0F不响应,尝试其他地址
Ox485.getInstance().send485HexCommand("01030001000295F4"); // 地址01
Ox485 D 开始通过485获取摄像头人数(即用即连模式)
Ox485 D 485串口打开结果: true
Ox485 D 准备发送485命令: 0F030001000294E5
Ox485 D 485命令发送结果: true
Ox485 D Ox485发送数据成功: 0f030001000294e5
Ox485 D Ox485接收到数据: 0f03040000xxxx
Ox485 D 485获取人数成功: X
Ox485 D 485串口已关闭并清理资源
```
## 常见问题解决方案
## 验证方法
### 问题1:串口设备文件不存在
### 1. 功能测试
**解决方案**:
- 检查硬件连接
- 确认设备树配置
- 重启设备
### 问题2:权限不足
**解决方案**:
```bash
chmod 666 /dev/ttyS6
chown system:system /dev/ttyS6
```java
// 多次调用测试连接稳定性
for (int i = 0; i < 5; i++) {
Ox485.getInstance().sendHex485ForPeopleNum(callback);
Thread.sleep(1000); // 间隔1秒
}
```
### 问题3:设备不响应
### 2. 资源泄露检查
**解决方案**:
- 检查485设备电源
- 验证设备地址配置
- 使用万用表检查485信号
- 尝试不同的波特率
监控系统资源使用情况,确认串口文件描述符是否正确释放。
### 问题4:数据格式错误
### 3. 异常恢复测试
**解决方案**:
- 确认设备协议文档
- 检查命令格式
- 验证校验码计算
## 预期的正常日志
修改后,正常的485通信日志应该类似:
```
Ox485 D 485串口状态检查通过,开始发送命令
Ox485 D 准备发送485命令: 0F030001000294E5, 转换后字节数组: [15, 3, 0, 1, 0, 2, -108, -27]
Ox485 D 485命令发送结果: true
Ox485 D Ox485发送数据成功: 0f030001000294e5, 数据长度: 8
Ox485 D Ox485接收到数据: 0f03040000xxxx, 字节数组: [15, 3, 4, 0, X, ...], 数据长度: 9
Ox485 D 485获取人数成功: X
```
模拟以下场景验证自动恢复能力:
- 485设备断电后恢复
- 串口被其他程序占用后释放
- 系统资源紧张情况
## 联系支持
## 总结
如果按照上述步骤仍无法解决问题,请提供
通过采用即用即连模式,我们从根本上解决了485通信的超时问题:
1. 完整的诊断日志
2. 硬件连接图
3. 485设备型号和协议文档
4. 系统版本信息
1. **消除了复杂的状态管理**
2. **确保了每次通信的独立性**
3. **自动实现了错误恢复机制**
4. **简化了代码逻辑,提高了可靠性**
修改后的代码增加了大量诊断信息,应该能帮助您快速定位485通信超时的根本原因
这种设计更符合485通信的实际使用场景,避免了长连接模式的各种问题。

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

@ -42,6 +42,55 @@ public class Ox485DebugHelper {
}
/**
* 485连接诊断方法
* 用于排查485通信问题适配即用即连模式
*/
public static void diagnose485Connection() {
LogManager.logInfo(TAG, "========== 开始485连接诊断(即用即连模式) ==========");
Ox485 ox485 = Ox485.getInstance();
// 1. 检查串口设备文件
File serialPortFile = new File("/dev/ttyS6");
LogManager.logInfo(TAG, "诊断1 - 串口设备文件: /dev/ttyS6");
LogManager.logInfo(TAG, " - 文件存在: " + serialPortFile.exists());
if (serialPortFile.exists()) {
LogManager.logInfo(TAG, " - 可读权限: " + serialPortFile.canRead());
LogManager.logInfo(TAG, " - 可写权限: " + serialPortFile.canWrite());
LogManager.logInfo(TAG, " - 文件大小: " + serialPortFile.length());
}
// 2. 检查485配置
LogManager.logInfo(TAG, "诊断2 - 485配置:");
LogManager.logInfo(TAG, " - 485模式开关: " + ox485.isGateCamera485OxOn());
LogManager.logInfo(TAG, " - 串口路径: /dev/ttyS6");
LogManager.logInfo(TAG, " - 波特率: 9600");
LogManager.logInfo(TAG, " - 查询命令: 0F030001000294E5");
// 3. 尝试通信测试
LogManager.logInfo(TAG, "诊断3 - 通信测试:");
if (ox485.isGateCamera485OxOn()) {
LogManager.logInfo(TAG, " - 485模式已启用,开始测试通信...");
ox485.sendHex485ForPeopleNum(new Ox485.PeopleNumCallback() {
@Override
public void onSuccess(int peopleNum) {
LogManager.logInfo(TAG, "诊断测试成功 - 获取到人数: " + peopleNum);
}
@Override
public void onError(String errorMessage) {
LogManager.logError(TAG, "诊断测试失败: " + errorMessage);
}
});
} else {
LogManager.logWarning(TAG, " - 485模式未启用,无法进行通信测试");
}
LogManager.logInfo(TAG, "========== 485连接诊断完成 ==========");
}
/**
* 测试485通信
*/
private static void testCommunication() {

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

@ -70,22 +70,9 @@ public class Ox485 {
void onError(String errorMessage);
}
/**
* 连接回调接口
*/
private interface ConnectionCallback {
void onConnected();
void onError(String errorMessage);
}
private Ox485() {
mainHandler = new Handler(Looper.getMainLooper());
timeoutHandler = new Handler(Looper.getMainLooper());
connectionCheckHandler = new Handler(Looper.getMainLooper());
serialPortManager = new SerialPortManager();
// 初始化连接检查任务
initConnectionCheckTask();
}
/**
@ -134,12 +121,11 @@ public class Ox485 {
/**
* 通过485获取摄像头人数
* 对应uniapp中的sendHex485ForPeopleNum方法
* 采用懒加载连接管理首次使用时才打开串口
* 采用即用即连模式每次请求时打开连接完成后立即关闭
* @param callback 结果回调
*/
public void sendHex485ForPeopleNum(PeopleNumCallback callback) {
LogManager.logInfo(TAG, "15:45:22.734 Ox485 D 开始通过485获取摄像头人数(懒加载模式)");
LogManager.logInfo(TAG, "开始通过485获取摄像头人数(即用即连模式)");
if (!gateCamera485OxOn) {
String errorMsg = "485模式未开启";
@ -151,22 +137,12 @@ public class Ox485 {
}
try {
// 懒加载检查连接状态需要时才建立连接
ensureConnection(new ConnectionCallback() {
@Override
public void onConnected() {
// 连接成功发送命令
sendCommandAndWaitResponse(callback);
}
// 创建临时串口管理器
SerialPortManager serialPortManager = new SerialPortManager();
// 执行通信
sendCommandAndWaitResponse(serialPortManager, callback);
@Override
public void onError(String errorMessage) {
// 连接失败
if (callback != null) {
mainHandler.post(() -> callback.onError(errorMessage));
}
}
});
} catch (Exception e) {
String errorMsg = "485通信异常: " + e.getMessage();
LogManager.logError(TAG, errorMsg, e);
@ -177,23 +153,11 @@ public class Ox485 {
}
/**
* 发送命令并等待响应采用懒加载连接复用
* 发送命令并等待响应采用即用即连模式
* @param serialPortManager 串口管理器实例
* @param callback 结果回调
*/
private void sendCommandAndWaitResponse(PeopleNumCallback callback) {
// 发送前检查串口状态
if (!isSerialPortReallyOpen()) {
String errorMsg = "串口未打开,无法发送命令";
LogManager.logError(TAG, errorMsg);
isSerialPortOpen = false;
if (callback != null) {
mainHandler.post(() -> callback.onError(errorMsg));
}
return;
}
LogManager.logInfo(TAG, "485串口状态检查通过,开始发送命令");
private void sendCommandAndWaitResponse(SerialPortManager serialPortManager, PeopleNumCallback callback) {
// 设置数据监听器
serialPortManager.setOnSerialPortDataListener(new OnSerialPortDataListener() {
@Override
@ -207,25 +171,28 @@ public class Ox485 {
// 数据包过滤只处理以[15, 3, 4, 0]开头的正常响应数据包
if (!isNormalResponsePacket(bytes)) {
LogManager.logInfo(TAG, "Ox485接收到非正常响应数据包,已过滤: " + hexData + ", 期望格式: [15, 3, 4, 0]");
// 即用即连模式下收到任何数据都关闭连接
closeAndCleanup(serialPortManager);
return;
}
// 取消超时处理
cancelTimeout();
// 标记成功通信用于连接健康检查
markSuccessfulCommunication();
// 解析人数数据
int peopleNum = get485PeopleNum(bytes);
if (peopleNum >= 0) {
LogManager.logInfo(TAG, "485获取人数成功: " + peopleNum);
// 完成后关闭连接
closeAndCleanup(serialPortManager);
if (callback != null) {
mainHandler.post(() -> callback.onSuccess(peopleNum));
}
} else {
String errorMsg = "485数据解析失败,数据: " + hexData;
LogManager.logError(TAG, errorMsg);
// 完成后关闭连接
closeAndCleanup(serialPortManager);
if (callback != null) {
mainHandler.post(() -> callback.onError(errorMsg));
}
@ -239,8 +206,39 @@ public class Ox485 {
}
});
// 发送HEX命令
// 打开串口并发送HEX命令
try {
File serialPortFile = new File(DEFAULT_SERIAL_PORT_PATH);
// 检查串口文件是否存在
if (!serialPortFile.exists()) {
String errorMsg = "485串口设备文件不存在: " + DEFAULT_SERIAL_PORT_PATH;
LogManager.logError(TAG, errorMsg);
closeAndCleanup(serialPortManager);
if (callback != null) {
mainHandler.post(() -> callback.onError(errorMsg));
}
return;
}
// 配置串口参数
boolean openResult = serialPortManager.openSerialPort(serialPortFile, DEFAULT_BAUD_RATE);
LogManager.logInfo(TAG, "485串口打开结果: " + openResult);
if (!openResult) {
String errorMsg = "打开485串口失败: " + DEFAULT_SERIAL_PORT_PATH;
LogManager.logError(TAG, errorMsg);
closeAndCleanup(serialPortManager);
if (callback != null) {
mainHandler.post(() -> callback.onError(errorMsg));
}
return;
}
// 启动读写线程
serialPortManager.startReadThread(485);
serialPortManager.startSendThread();
byte[] hexBytes = hexStringToByteArray(HEX_COMMAND_GET_PEOPLE_NUM);
// 验证要发送的数据
@ -252,7 +250,7 @@ public class Ox485 {
if (!sendResult) {
String errorMsg = "485命令发送失败,可能串口连接异常";
LogManager.logError(TAG, errorMsg);
isSerialPortOpen = false;
closeAndCleanup(serialPortManager);
if (callback != null) {
mainHandler.post(() -> callback.onError(errorMsg));
}
@ -260,15 +258,13 @@ public class Ox485 {
}
// 设置超时处理
setupTimeout(callback);
setupTimeout(serialPortManager, callback);
} catch (Exception e) {
String errorMsg = "发送485命令异常: " + e.getMessage();
LogManager.logError(TAG, errorMsg, e);
// 发送失败可能是连接问题重置连接状态
isSerialPortOpen = false;
closeAndCleanup(serialPortManager);
if (callback != null) {
mainHandler.post(() -> callback.onError(errorMsg));
}
@ -276,10 +272,26 @@ 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 callback 结果回调
*/
private void setupTimeout(PeopleNumCallback callback) {
private void setupTimeout(SerialPortManager serialPortManager, PeopleNumCallback callback) {
cancelTimeout(); // 先取消之前的超时任务
long startTime = System.currentTimeMillis();
@ -289,13 +301,9 @@ public class Ox485 {
long elapsedTime = System.currentTimeMillis() - startTime;
String errorMsg = "485人数查询超时(等待时间: " + elapsedTime + "ms)";
LogManager.logError(TAG, errorMsg);
LogManager.logError(TAG, "485超时详情 - 串口状态: " + (isSerialPortReallyOpen() ? "已打开" : "未打开") +
", 内部连接状态: " + isSerialPortOpen +
", 最后成功时间: " + (lastSuccessTime > 0 ?
new java.text.SimpleDateFormat("HH:mm:ss.SSS").format(new java.util.Date(lastSuccessTime)) : "无"));
// 超时可能是连接问题重置连接状态
isSerialPortOpen = false;
// 超时后关闭连接
closeAndCleanup(serialPortManager);
if (callback != null) {
callback.onError(errorMsg);
@ -472,240 +480,37 @@ public class Ox485 {
}
/**
* 获取485串口状态懒加载连接管理模式
* 获取485串口状态即用即连模式
* @return 串口状态描述
*/
public String get485Status() {
String connectionStatus = isSerialPortOpen ? "已连接" : (
isConnecting ? "连接中" : "未连接"
);
String lastSuccessStr = lastSuccessTime > 0 ?
new java.text.SimpleDateFormat("HH:mm:ss.SSS").format(new java.util.Date(lastSuccessTime)) :
"无";
String status = "串口状态: " + connectionStatus +
String status = "串口状态: 即用即连模式" +
", 路径: " + DEFAULT_SERIAL_PORT_PATH +
", 波特率: " + DEFAULT_BAUD_RATE +
", 485模式: " + (gateCamera485OxOn ? "已启用" : "未启用") +
", 最后成功时间: " + lastSuccessStr +
", 重试次数: " + currentRetryCount;
", 485模式: " + (gateCamera485OxOn ? "已启用" : "未启用");
LogManager.logInfo(TAG, status);
return status;
}
/**
* 关闭485串口
* 关闭485串口兼容旧接口
*/
public void close485SerialPort() {
LogManager.logInfo(TAG, "关闭485串口");
try {
cancelTimeout();
if (serialPortManager != null) {
serialPortManager.closeSerialPort();
LogManager.logInfo(TAG, "485串口已关闭");
}
// 重置连接状态
isSerialPortOpen = false;
isConnecting = false;
lastSuccessTime = 0;
currentRetryCount = 0;
} catch (Exception e) {
LogManager.logError(TAG, "关闭485串口异常: " + e.getMessage(), e);
}
LogManager.logInfo(TAG, "485串口即用即连模式无需手动关闭");
}
/**
* 释放资源
*/
public void release() {
LogManager.logInfo(TAG, "释放Ox485资源");
// 停止连接检查
stopConnectionCheck();
// 关闭串口
close485SerialPort();
LogManager.logInfo(TAG, "释放Ox485资源(即用即连模式)");
}
// ========== 懒加载连接管理相关方法 ==========
/**
* 初始化连接检查任务
*/
private void initConnectionCheckTask() {
connectionCheckRunnable = new Runnable() {
@Override
public void run() {
LogManager.logDebug(TAG, "定时检查485连接状态");
// 检查最后一次成功时间如果超过一定时间没有成功通信则认为连接异常
long currentTime = System.currentTimeMillis();
if (isSerialPortOpen && lastSuccessTime > 0 &&
(currentTime - lastSuccessTime) > CONNECTION_CHECK_INTERVAL * 2) {
LogManager.logWarning(TAG, "检测到485连接异常,最后成功时间: " +
new java.text.SimpleDateFormat("HH:mm:ss.SSS").format(new java.util.Date(lastSuccessTime)));
// 重置连接状态
isSerialPortOpen = false;
// 尝试重连
if (gateCamera485OxOn) {
LogManager.logInfo(TAG, "尝试重新建立485连接");
retryConnection();
}
}
// 安排下次检查
connectionCheckHandler.postDelayed(this, CONNECTION_CHECK_INTERVAL);
}
};
}
/**
* 启动连接检查
*/
private void startConnectionCheck() {
LogManager.logInfo(TAG, "启动485连接定时检查,检查间隔: " + (CONNECTION_CHECK_INTERVAL / 1000) + "秒");
connectionCheckHandler.post(connectionCheckRunnable);
}
/**
* 停止连接检查
*/
private void stopConnectionCheck() {
if (connectionCheckHandler != null && connectionCheckRunnable != null) {
connectionCheckHandler.removeCallbacks(connectionCheckRunnable);
LogManager.logInfo(TAG, "485连接定时检查已停止");
}
}
/**
* 确保连接可用懒加载核心逻辑
* @param callback 连接结果回调
*/
private void ensureConnection(ConnectionCallback callback) {
// 如果正在连接中等待连接完成
if (isConnecting) {
LogManager.logInfo(TAG, "连接正在进行中,等待连接完成...");
// 简单等待机制实际项目中可以优化为队列机制
mainHandler.postDelayed(() -> ensureConnection(callback), 500);
return;
}
// 如果已经连接直接返回
if (isSerialPortOpen) {
LogManager.logDebug(TAG, "485连接已存在,直接复用");
callback.onConnected();
return;
}
// 需要建立新连接
LogManager.logInfo(TAG, "首次使用或连接已断开,建立485连接");
createConnection(callback);
}
/**
* 建立485连接
* @param callback 连接结果回调
*/
private void createConnection(ConnectionCallback callback) {
isConnecting = true;
currentRetryCount = 0;
try {
LogManager.logInfo(TAG, "开始建立485连接 - 路径: " + DEFAULT_SERIAL_PORT_PATH + ", 波特率: " + DEFAULT_BAUD_RATE);
// 检查串口文件是否存在
File serialPortFile = new File(DEFAULT_SERIAL_PORT_PATH);
if (!serialPortFile.exists()) {
isConnecting = false;
String errorMsg = "485串口设备文件不存在: " + DEFAULT_SERIAL_PORT_PATH;
LogManager.logError(TAG, errorMsg);
callback.onError(errorMsg);
return;
}
LogManager.logInfo(TAG, "485串口设备文件存在,文件权限: 可读=" + serialPortFile.canRead() + ", 可写=" + serialPortFile.canWrite());
// 配置串口参数
boolean openResult = serialPortManager.openSerialPort(serialPortFile, DEFAULT_BAUD_RATE);
LogManager.logInfo(TAG, "485串口打开结果: " + openResult);
if (!openResult) {
isConnecting = false;
String errorMsg = "打开485串口失败: " + DEFAULT_SERIAL_PORT_PATH + ",可能原因:设备不存在、权限不足或设备被占用";
LogManager.logError(TAG, errorMsg);
callback.onError(errorMsg);
return;
}
// 先设置连接成功状态再进行验证
isSerialPortOpen = true;
isConnecting = false;
lastSuccessTime = System.currentTimeMillis();
currentRetryCount = 0;
// 启动读写线程
serialPortManager.startReadThread(485);
serialPortManager.startSendThread();
LogManager.logInfo(TAG, "485连接建立成功,进入懒加载复用模式,最后成功时间: " +
new java.text.SimpleDateFormat("HH:mm:ss.SSS").format(new java.util.Date(lastSuccessTime)));
callback.onConnected();
} catch (Exception e) {
isConnecting = false;
isSerialPortOpen = false;
String errorMsg = "建立485连接异常: " + e.getMessage();
LogManager.logError(TAG, errorMsg, e);
callback.onError(errorMsg);
}
}
/**
* 重试连接
*/
private void retryConnection() {
if (currentRetryCount >= MAX_RETRY_COUNT) {
LogManager.logError(TAG, "485连接重试次数超限,停止重试");
return;
}
currentRetryCount++;
LogManager.logInfo(TAG, "485连接重试第 " + currentRetryCount + " 次");
// 延迟重试
mainHandler.postDelayed(() -> {
createConnection(new ConnectionCallback() {
@Override
public void onConnected() {
LogManager.logInfo(TAG, "485连接重试成功");
}
@Override
public void onError(String errorMessage) {
LogManager.logWarning(TAG, "485连接重试失败: " + errorMessage);
// 继续重试
retryConnection();
}
});
}, RETRY_DELAY);
}
/**
* 标记成功通信用于连接健康检查
*/
private void markSuccessfulCommunication() {
lastSuccessTime = System.currentTimeMillis();
currentRetryCount = 0; // 重置重试次数
LogManager.logDebug(TAG, "485通信成功,更新最后成功时间");
}
// ========== 删除所有懒加载连接管理相关方法 ==========
// 删除initConnectionCheckTaskstartConnectionCheckstopConnectionCheck
// ensureConnectioncreateConnectionretryConnectionmarkSuccessfulCommunication
// isSerialPortReallyOpen等方法
/**
* HEX字符串转字节数组
@ -738,14 +543,4 @@ public class Ox485 {
// 15: 0x0F, 3: 0x03, 4: 0x04, 0: 0x00
return (bytes[0] == 15 && bytes[1] == 3 && bytes[2] == 4 && bytes[3] == 0);
}
/**
* 检查串口是否真正打开
* 由于 SerialPortManager 没有 isOpened() 方法
* 我们通过检查内部状态变量来判断
* @return true表示串口已打开
*/
private boolean isSerialPortReallyOpen() {
return isSerialPortOpen && serialPortManager != null;
}
}
Loading…
Cancel
Save