From e78dbd62875992c89e1fecbd9ab24b47620c1475 Mon Sep 17 00:00:00 2001 From: MTing Date: Thu, 25 Sep 2025 15:31:55 +0800 Subject: [PATCH] fix 3 --- .../main/java/com/ouxuan/oxface/device/Ox485.java | 162 +++++++++++++++------ 1 file changed, 121 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/com/ouxuan/oxface/device/Ox485.java b/app/src/main/java/com/ouxuan/oxface/device/Ox485.java index 8836545..025c925 100644 --- a/app/src/main/java/com/ouxuan/oxface/device/Ox485.java +++ b/app/src/main/java/com/ouxuan/oxface/device/Ox485.java @@ -44,6 +44,9 @@ public class Ox485 { private static final int MAX_RETRY_COUNT = 3; // 最大重试次数 private static final long RETRY_DELAY = 1000; // 重试延迟1秒 + // 当前重试次数(用于超时处理) + private int currentRetryCount = 0; + // 单例实例 private static volatile Ox485 instance; @@ -158,18 +161,39 @@ public class Ox485 { return; } + // 使用重试机制执行通信 + executeWithRetry(callback, 0); + } + + /** + * 使用重试机制执行485通信 + * @param callback 结果回调 + * @param retryCount 当前重试次数 + */ + private void executeWithRetry(PeopleNumCallback callback, int retryCount) { + currentRetryCount = retryCount; // 设置当前重试次数 + + LogManager.logInfo(TAG, "开始执行485通信 (重试次数: " + retryCount + "/" + MAX_RETRY_COUNT + ")"); + try { // 创建临时串口管理器 SerialPortManager serialPortManager = new SerialPortManager(); // 执行通信 - sendCommandAndWaitResponse(serialPortManager, callback); + sendCommandAndWaitResponse(serialPortManager, callback, retryCount); } catch (Exception e) { String errorMsg = "485通信异常: " + e.getMessage(); LogManager.logError(TAG, errorMsg, e); - if (callback != null) { - mainHandler.post(() -> callback.onError(errorMsg)); + + // 如果还有重试次数,延迟后重试 + if (retryCount < MAX_RETRY_COUNT) { + LogManager.logInfo(TAG, "485通信失败," + (RETRY_DELAY / 1000) + "秒后进行第" + (retryCount + 1) + "次重试"); + mainHandler.postDelayed(() -> executeWithRetry(callback, retryCount + 1), RETRY_DELAY); + } else { + if (callback != null) { + mainHandler.post(() -> callback.onError(errorMsg)); + } } } } @@ -178,8 +202,9 @@ public class Ox485 { * 发送命令并等待响应(采用即用即连模式) * @param serialPortManager 串口管理器实例 * @param callback 结果回调 + * @param retryCount 当前重试次数 */ - private void sendCommandAndWaitResponse(SerialPortManager serialPortManager, PeopleNumCallback callback) { + private void sendCommandAndWaitResponse(SerialPortManager serialPortManager, PeopleNumCallback callback, final int retryCount) { // 设置数据监听器 serialPortManager.setOnSerialPortDataListener(new OnSerialPortDataListener() { @Override @@ -228,42 +253,66 @@ public class Ox485 { } }); - // 打开串口并发送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)); + // 打开串口并发送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 (retryCount < MAX_RETRY_COUNT) { + LogManager.logInfo(TAG, "串口文件不存在," + (RETRY_DELAY / 1000) + "秒后进行第" + (retryCount + 1) + "次重试"); + mainHandler.postDelayed(() -> executeWithRetry(callback, retryCount + 1), RETRY_DELAY); + } else { + if (callback != null) { + mainHandler.post(() -> callback.onError(errorMsg)); + } + } + return; } - return; - } - - // 检查串口文件是否有读写权限 - if (!serialPortFile.canRead() || !serialPortFile.canWrite()) { - String errorMsg = "485串口设备无读写权限: " + DEFAULT_SERIAL_PORT_PATH; - LogManager.logError(TAG, errorMsg); - closeAndCleanup(serialPortManager); - if (callback != null) { - mainHandler.post(() -> callback.onError(errorMsg)); + + // 检查串口文件是否有读写权限 + if (!serialPortFile.canRead() || !serialPortFile.canWrite()) { + String errorMsg = "485串口设备无读写权限: " + DEFAULT_SERIAL_PORT_PATH + + " (可读:" + serialPortFile.canRead() + ", 可写:" + serialPortFile.canWrite() + ")"; + LogManager.logError(TAG, errorMsg); + closeAndCleanup(serialPortManager); + + // 如果还有重试次数,延迟后重试 + if (retryCount < MAX_RETRY_COUNT) { + LogManager.logInfo(TAG, "串口权限不足," + (RETRY_DELAY / 1000) + "秒后进行第" + (retryCount + 1) + "次重试"); + mainHandler.postDelayed(() -> executeWithRetry(callback, retryCount + 1), RETRY_DELAY); + } else { + if (callback != null) { + mainHandler.post(() -> callback.onError(errorMsg)); + } + } + return; } - return; - } - - // 配置串口参数 - boolean openResult = serialPortManager.openSerialPort(serialPortFile, DEFAULT_BAUD_RATE); - LogManager.logInfo(TAG, "485串口打开结果: " + openResult); - - if (!openResult) { + + LogManager.logInfo(TAG, "串口文件状态正常: " + DEFAULT_SERIAL_PORT_PATH + + " (存在:" + serialPortFile.exists() + ", 可读:" + serialPortFile.canRead() + + ", 可写:" + serialPortFile.canWrite() + ")"); + + // 配置串口参数 + boolean openResult = serialPortManager.openSerialPort(serialPortFile, DEFAULT_BAUD_RATE); + LogManager.logInfo(TAG, "485串口打开结果: " + openResult + " (路径:" + DEFAULT_SERIAL_PORT_PATH + ", 波特率:" + DEFAULT_BAUD_RATE + ")"); if (!openResult) { String errorMsg = "打开485串口失败: " + DEFAULT_SERIAL_PORT_PATH; LogManager.logError(TAG, errorMsg); closeAndCleanup(serialPortManager); - if (callback != null) { - mainHandler.post(() -> callback.onError(errorMsg)); + + // 如果还有重试次数,延迟后重试 + if (retryCount < MAX_RETRY_COUNT) { + LogManager.logInfo(TAG, "串口打开失败," + (RETRY_DELAY / 1000) + "秒后进行第" + (retryCount + 1) + "次重试"); + mainHandler.postDelayed(() -> executeWithRetry(callback, retryCount + 1), RETRY_DELAY); + } else { + if (callback != null) { + mainHandler.post(() -> callback.onError(errorMsg)); + } } return; } @@ -284,8 +333,15 @@ public class Ox485 { String errorMsg = "485命令发送失败,可能串口连接异常"; LogManager.logError(TAG, errorMsg); closeAndCleanup(serialPortManager); - if (callback != null) { - mainHandler.post(() -> callback.onError(errorMsg)); + + // 如果还有重试次数,延迟后重试 + if (retryCount < MAX_RETRY_COUNT) { + LogManager.logInfo(TAG, "命令发送失败," + (RETRY_DELAY / 1000) + "秒后进行第" + (retryCount + 1) + "次重试"); + mainHandler.postDelayed(() -> executeWithRetry(callback, retryCount + 1), RETRY_DELAY); + } else { + if (callback != null) { + mainHandler.post(() -> callback.onError(errorMsg)); + } } return; } @@ -298,8 +354,15 @@ public class Ox485 { LogManager.logError(TAG, errorMsg, e); closeAndCleanup(serialPortManager); - if (callback != null) { - mainHandler.post(() -> callback.onError(errorMsg)); + + // 如果还有重试次数,延迟后重试 + if (retryCount < MAX_RETRY_COUNT) { + LogManager.logInfo(TAG, "发送命令异常," + (RETRY_DELAY / 1000) + "秒后进行第" + (retryCount + 1) + "次重试"); + mainHandler.postDelayed(() -> executeWithRetry(callback, retryCount + 1), RETRY_DELAY); + } else { + if (callback != null) { + mainHandler.post(() -> callback.onError(errorMsg)); + } } } } @@ -323,8 +386,14 @@ public class Ox485 { // 超时后关闭连接 closeAndCleanup(serialPortManager); - if (callback != null) { - callback.onError(errorMsg); + // 如果还有重试次数,延迟后重试 + if (currentRetryCount < MAX_RETRY_COUNT) { + LogManager.logInfo(TAG, "查询超时," + (RETRY_DELAY / 1000) + "秒后进行第" + (currentRetryCount + 1) + "次重试"); + mainHandler.postDelayed(() -> executeWithRetry(callback, currentRetryCount + 1), RETRY_DELAY); + } else { + if (callback != null) { + callback.onError(errorMsg); + } } }; @@ -538,12 +607,23 @@ public class Ox485 { private void closeAndCleanup(SerialPortManager serialPortManager) { if (serialPortManager != null) { try { + // 先停止读写线程 + serialPortManager.stopReadThread(); + serialPortManager.stopSendThread(); + + // 等待一小段时间确保线程停止 + Thread.sleep(100); + + // 关闭串口 serialPortManager.closeSerialPort(); LogManager.logInfo(TAG, "485串口已关闭并清理资源"); } catch (Exception e) { LogManager.logError(TAG, "关闭485串口时发生异常: " + e.getMessage(), e); } } + + // 强制清理超时任务 + cancelTimeout(); } /**