diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/serial/ScaleManager.kt b/app/src/main/java/com/shuwei/intelligent/shelves/serial/ScaleManager.kt index 7e2b240..ec8cb74 100644 --- a/app/src/main/java/com/shuwei/intelligent/shelves/serial/ScaleManager.kt +++ b/app/src/main/java/com/shuwei/intelligent/shelves/serial/ScaleManager.kt @@ -20,6 +20,7 @@ import io.github.jeadyx.jserialport.SerialPortFactory import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel +import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch @@ -73,6 +74,9 @@ object ScaleManager { private var serialPort: AndroidSerialPort? = null private var scope = CoroutineScope(Dispatchers.IO) + /** 发送队列:保证串口写入顺序,避免并发写冲突 */ + private val sendChannel = Channel(capacity = Channel.UNLIMITED) + /** 当前设备激活码,非空时收到激活请求自动应答 */ private var activateCode: String = "" @@ -141,6 +145,17 @@ object ScaleManager { parity = SerialPort.PARITY_NONE ) } as AndroidSerialPort? + // 启动单一消费者协程,顺序消费发送队列 + scope.launch { + for (hexStr in sendChannel) { + try { + serialPort?.write(hexStr.hexToBytes()) + } catch (e: Exception) { + e.printStackTrace() + log("发送命令失败: ${e.message}") + } + } + } true } catch (e: Exception) { e.printStackTrace() @@ -301,7 +316,7 @@ object ScaleManager { // ---------------------------------------------------------------- /** - * 发送十六进制字符串指令(需先调用 init() 注入发送函数) + * 发送十六进制字符串指令,指令进入发送队列按顺序写入串口 * * @param hexStr 完整帧十六进制字符串,含协议头尾 */ @@ -310,14 +325,7 @@ object ScaleManager { log("警告:ScaleManager 串口未打开或已释放") return } - scope.launch { - try { - serialPort?.write(hexStr.hexToBytes()) - } catch (e: Exception) { - e.printStackTrace() - log("发送命令失败: ${e.message}") - } - } + sendChannel.trySend(hexStr) } // ---------------------------------------------------------------- @@ -423,6 +431,7 @@ object ScaleManager { * 通常在 Activity/Fragment 销毁或不再使用时调用 */ suspend fun release() { + sendChannel.close() scope.cancel() serialPort?.close() serialPort = null