|
@ -44,6 +44,9 @@ public class Ox485 { |
|
|
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秒 |
|
|
|
|
|
|
|
|
|
|
|
// 当前重试次数(用于超时处理) |
|
|
|
|
|
private int currentRetryCount = 0; |
|
|
|
|
|
|
|
|
// 单例实例 |
|
|
// 单例实例 |
|
|
private static volatile Ox485 instance; |
|
|
private static volatile Ox485 instance; |
|
|
|
|
|
|
|
@ -158,18 +161,39 @@ public class Ox485 { |
|
|
return; |
|
|
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 { |
|
|
try { |
|
|
// 创建临时串口管理器 |
|
|
// 创建临时串口管理器 |
|
|
SerialPortManager serialPortManager = new SerialPortManager(); |
|
|
SerialPortManager serialPortManager = new SerialPortManager(); |
|
|
|
|
|
|
|
|
// 执行通信 |
|
|
// 执行通信 |
|
|
sendCommandAndWaitResponse(serialPortManager, callback); |
|
|
|
|
|
|
|
|
sendCommandAndWaitResponse(serialPortManager, callback, retryCount); |
|
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
} catch (Exception e) { |
|
|
String errorMsg = "485通信异常: " + e.getMessage(); |
|
|
String errorMsg = "485通信异常: " + e.getMessage(); |
|
|
LogManager.logError(TAG, errorMsg, e); |
|
|
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 serialPortManager 串口管理器实例 |
|
|
* @param callback 结果回调 |
|
|
* @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() { |
|
|
serialPortManager.setOnSerialPortDataListener(new OnSerialPortDataListener() { |
|
|
@Override |
|
|
@Override |
|
@ -228,42 +253,66 @@ public class Ox485 { |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
// 打开串口并发送HEX命令 |
|
|
|
|
|
try { |
|
|
|
|
|
File serialPortFile = new File(DEFAULT_SERIAL_PORT_PATH); |
|
|
|
|
|
|
|
|
// 打开串口并发送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)); |
|
|
|
|
|
|
|
|
// 检查串口文件是否存在 |
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
LogManager.logInfo(TAG, "串口文件状态正常: " + DEFAULT_SERIAL_PORT_PATH + |
|
|
|
|
|
" (存在:" + serialPortFile.exists() + ", 可读:" + serialPortFile.canRead() + |
|
|
|
|
|
", 可写:" + serialPortFile.canWrite() + ")"); |
|
|
|
|
|
|
|
|
if (!openResult) { |
|
|
|
|
|
|
|
|
// 配置串口参数 |
|
|
|
|
|
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; |
|
|
String errorMsg = "打开485串口失败: " + DEFAULT_SERIAL_PORT_PATH; |
|
|
LogManager.logError(TAG, errorMsg); |
|
|
LogManager.logError(TAG, errorMsg); |
|
|
closeAndCleanup(serialPortManager); |
|
|
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; |
|
|
return; |
|
|
} |
|
|
} |
|
@ -284,8 +333,15 @@ public class Ox485 { |
|
|
String errorMsg = "485命令发送失败,可能串口连接异常"; |
|
|
String errorMsg = "485命令发送失败,可能串口连接异常"; |
|
|
LogManager.logError(TAG, errorMsg); |
|
|
LogManager.logError(TAG, errorMsg); |
|
|
closeAndCleanup(serialPortManager); |
|
|
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; |
|
|
return; |
|
|
} |
|
|
} |
|
@ -298,8 +354,15 @@ public class Ox485 { |
|
|
LogManager.logError(TAG, errorMsg, e); |
|
|
LogManager.logError(TAG, errorMsg, e); |
|
|
|
|
|
|
|
|
closeAndCleanup(serialPortManager); |
|
|
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); |
|
|
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) { |
|
|
private void closeAndCleanup(SerialPortManager serialPortManager) { |
|
|
if (serialPortManager != null) { |
|
|
if (serialPortManager != null) { |
|
|
try { |
|
|
try { |
|
|
|
|
|
// 先停止读写线程 |
|
|
|
|
|
serialPortManager.stopReadThread(); |
|
|
|
|
|
serialPortManager.stopSendThread(); |
|
|
|
|
|
|
|
|
|
|
|
// 等待一小段时间确保线程停止 |
|
|
|
|
|
Thread.sleep(100); |
|
|
|
|
|
|
|
|
|
|
|
// 关闭串口 |
|
|
serialPortManager.closeSerialPort(); |
|
|
serialPortManager.closeSerialPort(); |
|
|
LogManager.logInfo(TAG, "485串口已关闭并清理资源"); |
|
|
LogManager.logInfo(TAG, "485串口已关闭并清理资源"); |
|
|
} catch (Exception e) { |
|
|
} catch (Exception e) { |
|
|
LogManager.logError(TAG, "关闭485串口时发生异常: " + e.getMessage(), e); |
|
|
LogManager.logError(TAG, "关闭485串口时发生异常: " + e.getMessage(), e); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 强制清理超时任务 |
|
|
|
|
|
cancelTimeout(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|