在安卓中使用 Modbus
經(jīng)過上面的介紹,相信大家已經(jīng)對于 Modbus 有了一個大致的了解。
那么,如何在安卓中使用 Modbus 呢?如果你理解了 Modbus 的基礎(chǔ),并且前面的兩篇文章也大致理解了,那么這就不是問題了。
核心思路就是通過上篇文章介紹的使用 android-serialport-api 或使用 USB Host 的方法打開串口,并獲取到輸入輸出流,然后在發(fā)送和接收數(shù)據(jù)時按照 Modbus 協(xié)議標準封裝或解析即可。
其中如何打開串口以及獲取輸入輸出流已經(jīng)在上篇文章介紹,因此現(xiàn)在需要解決的是如何封裝/解析數(shù)據(jù)。
當然,你可以按照 Modbus 標準文檔自己動手寫一個。
或者,你也可以不用重復造輪子,直接使用現(xiàn)成的第三方庫。
這里我們可以使用 modbus4j,但是,從它的名字就可以看出來,這是一個 java 庫,好在我們只需要使用它的解析和封裝的功能,所以在安卓中依舊可以使用。
modbus4j
老規(guī)矩,使用 modbus4j 前需要先引入依賴:
// 添加倉庫地址
repositories {
...
maven { url 'https://jitpack.io' }
}
……
// 添加依賴
implementation 'com.github.MangoAutomation:modbus4j:3.1.0'
然后在正式使用之前,我們需要新建一個類繼承自 SerialPortWrapper
,用于實現(xiàn)在安卓上的串口功能:
class AndroidWrapper : SerialPortWrapper {
// 關(guān)閉串口
override fun close() {
TODO("Not yet implemented")
}
// 打開串口
override fun open() {
TODO("Not yet implemented")
}
// 獲取輸入流
override fun getInputStream(): InputStream {
TODO("Not yet implemented")
}
// 獲取輸出流
override fun getOutputStream(): OutputStream {
TODO("Not yet implemented")
}
// 獲取波特率
override fun getBaudRate(): Int {
TODO("Not yet implemented")
}
// 獲取數(shù)據(jù)位
override fun getDataBits(): Int {
TODO("Not yet implemented")
}
// 獲取停止位
override fun getStopBits(): Int {
TODO("Not yet implemented")
}
// 獲取校驗位
override fun getParity(): Int {
TODO("Not yet implemented")
}
}
在我們新建的這個類中重寫上述幾個方法,用于提供串口通信所需要的幾個參數(shù)即可。
然后,初始化 modbus4j 并發(fā)送消息:
val modbusFactory = ModbusFactory()
val wrapper: SerialPortWrapper = AndroidWrapper()
// 創(chuàng)建管理對象
val master = modbusFactory.createRtuMaster(wrapper)
// 發(fā)送消息
val request = ……
val response = master.send(request) // requst 為要發(fā)送的數(shù)據(jù),response 為接收到的響應(yīng)數(shù)據(jù)
上面就是 modbus4j 的簡單使用方法,如果同學們甚至都不想自己去完成串口通信的話,還可以用這個庫 Modbus4Android ,這個庫基于 android-serialport-api 和 上面的 modbus4j 封裝了一個安卓上到手即用的 Modbus 庫。
不過它使用的是 android-serialport-api 實現(xiàn)串口通信,如果需要使用 USB Host 的話可能還是需要自己去封裝一個庫了。(等我找到合適的測試設(shè)備后抽空我也封裝一個)
并且,這個庫使用了 RxJava 如果不喜歡 RxJava 的話也得自己封裝一個了,其實封裝起來也不算難,完全可以基于這個庫自己改一改就好了。
Modbus4Android
使用這個庫的第一步,依舊是導入依賴:
// 添加遠程倉庫
repositories {
maven { url 'https://jitpack.io' }
}
……
// 添加依賴
dependencies {
implementation 'com.github.licheedev:Modbus4Android:2.0.2'
}
接下來,為了方便使用,同時為了避免重復初始化,我們可以創(chuàng)建一個全局單例實例 ModbusManager
:
class ModbusManager : ModbusWorker() {
/**
* 釋放整個ModbusManager,單例會被置null
*/
@Synchronized
override fun release() {
super.release()
sInstance = null
}
companion object {
@Volatile
private var sInstance: ModbusManager? = null
fun getInstance(): ModbusManager {
var manager = sInstance
if (manager == null) {
synchronized(ModbusManager::class.java) {
manager = sInstance
if (manager == null) {
manager = ModbusManager()
sInstance = manager
}
}
}
return manager!!
}
}
}
復制代碼
然后初始化串口連接:
private fun initConnect(): Boolean {
Log.i(TAG, "initConnect: 開始初始化連接 Modbus\\nconfig=$config")
val param = SerialParam
.create(config.serialPath, config.serialRate) // 串口地址和波特率
.setDataBits(config.serialDataBits) // 數(shù)據(jù)位
.setParity(config.serialParity) // 校驗位
.setStopBits(config.serialStopBits) // 停止位
.setTimeout(config.serialTimeout) //超時時間
.setRetries(config.serialRetries) // 重試次數(shù)
try {
// 初始化前先關(guān)閉,避免串口已經(jīng)被打開過
ModbusManager.getInstance().closeModbusMaster()
val modbusMaster = ModbusManager.getInstance().syncInit(param)
return true
// 初始化(打開串口)成功
} catch (e: ModbusInitException) {
Log.e(TAG, "initConnect: 初始化modbus出錯!", e)
} catch (e: InterruptedException) {
Log.e(TAG, "initConnect: 初始化modbus出錯!", e)
} catch (e: ExecutionException) {
Log.e(TAG, "initConnect: 初始化modbus出錯!", e)
} catch (e: ModbusTransportException) {
Log.e(TAG, "initConnect: 初始化modbus出錯!", e)
} catch (e: ModbusRespException) {
Log.e(TAG, "initConnect: 初始化modbus出錯!", e)
}
return false
}
完成上述步驟后,我們就可以開始發(fā)送請求并接收數(shù)據(jù)了。
這里依舊以讀取線圈數(shù)據(jù)為例,我們可以使用同步請求:
val slaveId = 1 // 從站地址
val start = 00001 // 讀取的起始位置
val len = 1 // 需要讀取的長度
val response = ModbusManager.getInstance().syncReadCoil(slaveId, start, len)
其中的 response
即為響應(yīng)數(shù)據(jù)信息。
另外,我們也可以使用異步讀取的方式:
ModbusManager.getInstance().readCoil(slaveId, start, len, object : ModbusCallback
該庫支持的所有讀取方法如下:
所有寫數(shù)據(jù)方法如下:
總結(jié)
我們在這篇文章中介紹了在安卓中使用串口通信時大概率會接觸到的一種應(yīng)用層協(xié)議 -- Modbus,并講解了如何在安卓中使用 Modbus ,另外介紹了幾個個人認為比較好用的第三方庫。
-
MODBUS
+關(guān)注
關(guān)注
28文章
1757瀏覽量
76760 -
串口通信
+關(guān)注
關(guān)注
34文章
1607瀏覽量
55381 -
安卓
+關(guān)注
關(guān)注
5文章
2116瀏覽量
56960
發(fā)布評論請先 登錄
相關(guān)推薦
評論