refactor(serial): sendCmd 改用 Channel 保证串口写入顺序
- 新增 sendChannel(无界 Channel)作为发送队列 - openPort() 启动单一消费者协程顺序消费队列,避免并发写串口 - sendCmd() 改为 trySend() 入队,不再每次创建新协程 - release() 关闭 Channel,确保消费者协程正常退出 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,7 @@ import io.github.jeadyx.jserialport.SerialPortFactory
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -73,6 +74,9 @@ object ScaleManager {
|
|||||||
private var serialPort: AndroidSerialPort? = null
|
private var serialPort: AndroidSerialPort? = null
|
||||||
private var scope = CoroutineScope(Dispatchers.IO)
|
private var scope = CoroutineScope(Dispatchers.IO)
|
||||||
|
|
||||||
|
/** 发送队列:保证串口写入顺序,避免并发写冲突 */
|
||||||
|
private val sendChannel = Channel<String>(capacity = Channel.UNLIMITED)
|
||||||
|
|
||||||
/** 当前设备激活码,非空时收到激活请求自动应答 */
|
/** 当前设备激活码,非空时收到激活请求自动应答 */
|
||||||
private var activateCode: String = ""
|
private var activateCode: String = ""
|
||||||
|
|
||||||
@@ -141,6 +145,17 @@ object ScaleManager {
|
|||||||
parity = SerialPort.PARITY_NONE
|
parity = SerialPort.PARITY_NONE
|
||||||
)
|
)
|
||||||
} as AndroidSerialPort?
|
} as AndroidSerialPort?
|
||||||
|
// 启动单一消费者协程,顺序消费发送队列
|
||||||
|
scope.launch {
|
||||||
|
for (hexStr in sendChannel) {
|
||||||
|
try {
|
||||||
|
serialPort?.write(hexStr.hexToBytes())
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
log("发送命令失败: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
true
|
true
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
@@ -301,7 +316,7 @@ object ScaleManager {
|
|||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送十六进制字符串指令(需先调用 init() 注入发送函数)
|
* 发送十六进制字符串指令,指令进入发送队列按顺序写入串口
|
||||||
*
|
*
|
||||||
* @param hexStr 完整帧十六进制字符串,含协议头尾
|
* @param hexStr 完整帧十六进制字符串,含协议头尾
|
||||||
*/
|
*/
|
||||||
@@ -310,14 +325,7 @@ object ScaleManager {
|
|||||||
log("警告:ScaleManager 串口未打开或已释放")
|
log("警告:ScaleManager 串口未打开或已释放")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
scope.launch {
|
sendChannel.trySend(hexStr)
|
||||||
try {
|
|
||||||
serialPort?.write(hexStr.hexToBytes())
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
log("发送命令失败: ${e.message}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
@@ -423,6 +431,7 @@ object ScaleManager {
|
|||||||
* 通常在 Activity/Fragment 销毁或不再使用时调用
|
* 通常在 Activity/Fragment 销毁或不再使用时调用
|
||||||
*/
|
*/
|
||||||
suspend fun release() {
|
suspend fun release() {
|
||||||
|
sendChannel.close()
|
||||||
scope.cancel()
|
scope.cancel()
|
||||||
serialPort?.close()
|
serialPort?.close()
|
||||||
serialPort = null
|
serialPort = null
|
||||||
|
|||||||
Reference in New Issue
Block a user