rs485串口通信使用withtimeout出现的bug

业务情节很简单,就是Android 设备作为主机通过轮序发送命令,然后从机设备通过主机命令中的设备id判断是否是自己,然后反馈结果。 485 串口在Android 上的体现就是文件,所以说,从机不能同时回复消息,总线消息通信机制了解下,我们仿造了modbus 协议生成了命令。

扯远了,为了提高性能和提高容错,我们对每一个指令的回复都进行了超时处理,万一从机设备损坏了,没有回复,我死等好像也不是一个事情。

基于kotlin 是超时

kotlin 复制代码
suspend fun InputStream.readAfterAvailableGreaterThanZero(timeoutMillis: Long = 200): ByteArray? {
    return withTimeout(timeoutMillis) {
        var data: ByteArray? = null
        while (data == null) {
            val available = this@readAfterAvailableGreaterThanZero.available()
            if (available > 0) {
                // 如果有数据可读,则读取数据
                val buffer = ByteArray(10240) // 假设你每次读取 1024 字节
                val bytesRead = this@readAfterAvailableGreaterThanZero.read(buffer)
                if (bytesRead > 0) {
                    data = buffer.copyOfRange(0, bytesRead)

                } else {
                    // 如果 available() 返回大于 0 但 read() 返回 0 或 -1,可能是流已关闭或出现问题
                    return@withTimeout null
                }
            } else {
                // 如果没有数据可读,则等待一段时间,这么可以明显加大了CPU的消耗,但是这个不能不写。
                delay(5) // 每次等待 10 毫秒
            }
        }
        //LogUtils.e(bytesToHex(data))
        return@withTimeout data // 返回读取到的数据(这里我们确定 data 不为 null)
    }
}

这么写,看似完美,实则有一个bug,那就是从机可能卡在最后那么一丝丝的时间给我回复,比如说,我设置超时为300毫秒, 从机需要回复的是:

复制代码
0344120001000000000000000000000000000000003b88

因为我设置超时的原因,那么可能只读取到了一半。至于为啥,我也不是太理解,因为03设备我读取了一半,04设备我获取回文的时候,就把03设备的读取到了,就导致了后续流程一直有问题,05读取到04的结果。 emmmm? 所以说,这里面直接就是裂开了,那么解决思路是什么呢?

  • 改造代码,将同步回调改成 单独获取输出流回调,但是不好处理超时,因为因为设置了超时读取一截的问题一直没有解决。
  • 放弃设置所谓的超时概念,通过定数量的循环+挂机函数实现类似超时的逻辑。

通计数+挂起实现类似超时逻辑

因为基于kotlin 做了太多同步代码,将代码改造成多回调成本有点大。

kotlin 复制代码
suspend fun InputStream.readInput(size: Int, delay: Long): ByteArray {
    // 开启循环。
    for (i in 0..size) {
        val available = this.available()
        if (available > 0) {
            val buffer = ByteArray(available) // 假设你每次读取 1024 字节
            this.read(buffer)
            return buffer
        } else {
            // 挂起
            delay(delay)
        }
    }
    throw  TimeoutException("超时警告,循环$size 次,每次挂起$delay 毫秒,未查询到数据 ")
}

结束

目前还是没有理解到为啥withtimeout 会读取一截,而不是读取全部,明显是知识点缺失,嗯,我找到了再补充吧。

相关推荐
阿巴斯甜11 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker12 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952713 小时前
Andorid Google 登录接入文档
android
黄林晴14 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_1 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android