Android 串口通信 原来如此简单


一、前言


  1. 如果你的项目需要使用串口通信,并且项目使用了kotlin,那么这个SDK是你不能错过的;
  2. 如果你使用过串口通信,那么这个SDK最吸引你的地方应当是可在写入时同步阻塞等待数据返回,并且我们支持超时设置;如果你没有使用过串口通信,这个SDK也可以让你快熟的进行串口通信;
  3. 此SDK用于Android端的串口通信,此项目的C代码移植于谷歌官方串口库android-serialport-api ,以及GeekBugs-Android-SerialPort ;在此基础上,我进行了封装,目的是让开发者可以更加快速的进行串口通信;
  4. 此SDK可以创建2种不同作用的串口对象,一个是保持串口接收的串口对象,一个是写入并同步等待数据返回的串口对象;
  5. 当前仅支持Kotlin项目使用,对于java调用做的并不完美;
  6. 此SDK本人已经在多个项目中实践使用,并在github上进行开源,如果你在使用中有任何问题,请在issue中向我提出;

二、SDK的使用介绍


引入库

在Build.gradle(:project)下导入jitpack库

allprojects {
   
		repositories {
   
			maven {
    url 'https://jitpack.io' }
		}
}

在新版gradle中,在settings.gradle下导入jitpack库

dependencyResolutionManagement {
   
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
   
        maven {
    url "https://jitpack.io" }
    }
}

在Build.gradle(:module)中添加:

dependencies {
   
    implementation 'com.github.BASS-HY:EasySerial:1.0.0'
}

EasyKeepReceivePort的使用

1.创建一个永久接收的串口(串口开启失败返回Null);
演示:不做自定义返回数据的处理;

A). 创建一个串口,串口返回的数据默认为ByteArray类型;

val port = EasySerialBuilder.createKeepReceivePort<ByteArray>("/dev/ttyS4", BaudRate.B4800)

我们还可以这样创建串口,串口返回的数据默认为ByteArray类型;

val port = EasySerialBuilder.createKeepReceivePort<ByteArray>(
            "/dev/ttyS4",
            BaudRate.B4800, DataBit.CS8, StopBit.B1,
            Parity.NONE, 0, FlowCon.NONE
        )

B). 设置串口每次从数据流中读取的最大字节数,默认为64个字节;
注意:必须在调用[addDataCallBack]之前设置,否则设置无效;

port.setMaxReadSize(64)

C).设置数据的读取间隔;

  1. 即上一次读取完数据后,隔多少秒后读取下一次数据;
  2. 默认为10毫秒,读取时间越短,CPU的占用会越高,请合理配置此设置;
port.setReadInterval(100)

D). 监听串口返回的数据;
第一种写法;须注意,此回调处于协程之中;

val dataCallBack = port.addDataCallBack {
            //处理项目逻辑;
            // 此处示范将串口数据转化为16进制字符串;
            val hexString = it.conver2HexString()
            Log.d(tag, "接收到串口数据:$hexString")
        }
port.addDataCallBack(dataCallBack)

第二种写法;须注意,此回调处于协程之中;

val dataCallBack = object : EasyReceiveCallBack<ByteArray> {
    override suspend fun receiveData(dataList: List<ByteArray>) {
        //处理项目逻辑;
        //此处示范将串口数据转化为16进制字符串;
        if (dataList.isEmpty()) return
        val hexString = dataList.last().conver2HexString()
        Log.d(tag, "接收到串口数据:$hexString")
    }

}
port.addDataCallBack(dataCallBack)

E). 移除串口监听;

 port.removeDataCallBack(dataCallBack)

F). 关闭串口;
使用完毕关闭串口,关闭串口须在作用域中关闭,关闭时会阻塞当前协程,直到关闭处理完成;
这个过程并不会耗费太长时间,一般为1ms-4ms;

CoroutineScope(Dispatchers.IO).launch { port.close() }

2. 创建一个永久接收的串口(串口开启失败返回Null);
演示:自定义回调的数据类型,在接收到串口数据后对数据进行一次处理,再将数据返回给串口数据监听者;

A). 创建一个串口,串口返回的数据类型,我们自定义为String类型;

val port = EasySerialBuilder.createKeepReceivePort<String>("/dev/ttyS4", BaudRate.B4800)

我们还可以这样创建串口,串口返回的数据类型,我们自定义为String类型;

val port = EasySerialBuilder.createKeepReceivePort<String>(
            "/dev/ttyS4",
            BaudRate.B4800, DataBit.CS8, StopBit.B1,
            Parity.NONE, 0, FlowCon.NONE
        )

B). 设置串口每次从数据流中读取的最大字节数,默认为64个字节;
注意:必须在调用[addDataCallBack]之前设置,否则设置无效;

port.setMaxReadSize(64)

C).设置数据的读取间隔;

  1. 即上一次读取完数据后,隔多少秒后读取下一次数据;
  2. 默认为10毫秒,读取时间越短,CPU的占用会越高,请合理配置此设置;
port.setReadInterval(100)

D).因为我们设置数据返回类型不再是默认的ByteArray类型,所以我们需要设置自定义的数据解析规则;

 port.setDataHandle(CustomEasyPortDataHandle())

接下来我们创建一个自定义解析类,并将其命令为CustomEasyPortDataHandle;

class CustomEasyPortDataHandle : EasyPortDataHandle<String>() {

    private val stringList = mutableListOf<String>()//用于记录数据
    private val stringBuilder = StringBuilder()//用于记录数据
    private val pattern = Pattern.compile("(AT)(.*?)(\r\n)")//用于匹配数据

    /**
     * 数据处理方法
     *
     * @param byteArray 串口收到的原始数据
     * @return 返回自定义处理后的数据,此数据将被派发到各个监听者
     *
     *
     * 我们可以在这里做很多事情,比如有时候串口返回的数据并不是完整的数据,
     * 它可能有分包返回的情况,我们需要自行凑成一个完整的数据后再返回给监听者,
     * 在数据不完整的时候我们直接返回空数据集给监听者,告知他们这不是一个完整的数据;
     *
     * 在这里我们做个演示,假设数据返回是以AT开头,换行符为结尾的数据是正常的数据;
     *
     */
    override suspend fun portData(byteArray: ByteArray): List<String> {
        //清除之前记录的匹配成功的数据
        stringList.clear()

        //将串口数据转为16进制字符串
        val hexString = byteArray.conver2HexString()
        //记录本次读取到的串口数据
        stringBuilder.append(hexString)

        while (true) {//循环匹配,直到匹配完所有的数据
            //寻找记录中符合规则的数据
            val matcher = pattern.matcher(stringBuilder)
            //没有寻找到符合规则的数据,则返回Null
            if (!matcher.find()) break
            //寻找到符合规则的数据,记录匹配成功的数据,并将其从StringBuilder中删除
            val group = matcher.group()
            stringList.add(group)
            stringBuilder.delete(matcher.start(), matcher.end())
        }

        //返回记录的匹配成功的数据
        return stringList.toList()
    }

    /**
     * 串口关闭时会回调此方法
     * 如果您需要,可重写此方法,在此方法中做释放资源的操作
     */
    override fun close() {
        stringBuilder.clear()
        stringList.clear()
    }
}

<
  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值