EasySerial串口通信SDK
一、前言
- 如果你的项目需要使用串口通信,并且项目使用了kotlin,那么这个SDK是你不能错过的;
- 如果你使用过串口通信,那么这个SDK最吸引你的地方应当是可在写入时同步阻塞等待数据返回,并且我们支持超时设置;如果你没有使用过串口通信,这个SDK也可以让你快熟的进行串口通信;
- 此SDK用于Android端的串口通信,此项目的C代码移植于谷歌官方串口库android-serialport-api ,以及GeekBugs-Android-SerialPort ;在此基础上,我进行了封装,目的是让开发者可以更加快速的进行串口通信;
- 此SDK可以创建2种不同作用的串口对象,一个是保持串口接收的串口对象,一个是写入并同步等待数据返回的串口对象;
- 当前仅支持Kotlin项目使用,对于java调用做的并不完美;
- 此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).设置数据的读取间隔;
- 即上一次读取完数据后,隔多少秒后读取下一次数据;
- 默认为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).设置数据的读取间隔;
- 即上一次读取完数据后,隔多少秒后读取下一次数据;
- 默认为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()
}
}
<