| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- package com.grkj.iscs.modbus
- import com.google.gson.Gson
- import com.google.gson.reflect.TypeToken
- import com.grkj.iscs.MyApplication
- import com.grkj.iscs.extentions.crc16
- import com.grkj.iscs.extentions.toHexStrings
- import com.grkj.iscs.util.Executor
- import com.grkj.iscs.util.SPUtils
- import com.grkj.iscs.util.jvmSeconds
- import com.grkj.iscs.util.log.LogUtil
- import com.grkj.iscs.view.fragment.DockTestFragment
- import java.util.concurrent.LinkedBlockingQueue
- /**
- * ModBus 协议管理器
- */
- class ModBusManager(
- // 串口管理器
- val portManager: PortManager,
- // 是否输出详细信息
- val verbose: Boolean = false
- ) {
- @Volatile
- private var running = true
- /**
- * 正在发送的任务
- */
- @Volatile
- private var sending: FrameTask? = null
- /**
- * 等待发送队列
- */
- private val pendings = LinkedBlockingQueue<FrameTask>()
- /**
- * 线程锁
- */
- private val lock = Any()
- private var thread: Thread? = null
- var mSlaveAddressList = mutableListOf<Byte>()
- init {
- portManager.listen { res ->
- if (verbose) {
- LogUtil.i("接收:${res.toHexStrings()}")
- }
- synchronized(lock) {
- sending?.run {
- if (match(res) && running) {
- done?.let { it(res) }
- sending = null
- } else {
- LogUtil.w("响应: ${res.toHexStrings()}未匹配, running:${running}")
- }
- }
- }
- }
- // 初始化地址池
- val dockConfigJson = SPUtils.getDockConfig(MyApplication.instance?.applicationContext!!)
- if (!dockConfigJson.isNullOrEmpty()) {
- val tempList: MutableList<DockTestFragment.DockTestBean> =
- Gson().fromJson(
- dockConfigJson,
- object : TypeToken<MutableList<DockTestFragment.DockTestBean>>() {}.type
- )
- mSlaveAddressList.addAll(tempList.map { it.address })
- }
- }
- /**
- * 发送队列的消息
- */
- private fun takePendingToSend() {
- if (sending == null) {
- sending = pendings.take()
- }
- if (!running) {
- return
- }
- sending?.run {
- waitIfNecessary()
- }
- synchronized(lock) {
- sending?.run {
- if (shouldSend()) {
- if (portManager.send(req)) {
- afterSent()
- if (verbose) {
- LogUtil.i("发送:${req.toHexStrings()}")
- }
- } else {
- LogUtil.w("无法与主控板通讯")
- }
- } else {
- LogUtil.i("未响应: ${req.toHexStrings()}")
- // 放弃处理,回调空数据
- done?.let { it(byteArrayOf()) }
- sending = null
- }
- }
- }
- }
- /**
- * 循环发送给所有从机
- * @param frame 发送报文
- * @param listener 每轮发送完后的数据监听
- * @param delayMills 每轮发送的间隔
- */
- fun repeatSendToAll(
- frame: MBFrame,
- interrupt: (() -> List<Boolean>)? = null,
- listener: (res: List<ByteArray>) -> Unit,
- delayMills: Long
- ): ModBusManager {
- val keep = interrupt?.invoke()?.run { !this[0] } ?: false
- if (keep) {
- sendToAll(frame) {
- if (running) {
- listener(it)
- Executor.delayOnIO({
- if (running) {
- repeatSendToAll(frame, interrupt, listener, delayMills)
- }
- }, delayMills)
- }
- }
- } else {
- Executor.delayOnIO({
- if (running) {
- repeatSendToAll(frame, interrupt, listener, delayMills)
- }
- }, delayMills)
- }
- return this
- }
- /**
- * 发送给所有从机
- * @param frame 发送报文
- * @param done 所有从机都发送完成后的回调
- */
- fun sendToAll(frame: MBFrame, done: ((res: List<ByteArray>) -> Unit)? = null) {
- if (mSlaveAddressList.size == 0) {
- done?.let { it(listOf()) }
- return
- }
- sendUp(0, frame, done, ArrayList())
- }
- private fun sendUp(
- index: Int,
- frame: MBFrame,
- done: ((res: List<ByteArray>) -> Unit)?,
- resList: ArrayList<ByteArray>
- ) {
- sendTo(mSlaveAddressList[index], frame) { res ->
- resList.add(res)
- if (index >= mSlaveAddressList.size - 1) {
- // 已经发送完
- if (running) {
- done?.let { it(resList) }
- }
- } else {
- // 发送给下一个从机
- sendUp(index + 1, frame, done, resList)
- }
- }
- }
- /**
- * 发送给序号为 index 的从机
- * @param slaveAddress 从机地址
- * @param frame 发送报文
- * @param done 完成回调
- */
- fun sendTo(
- slaveAddress: Byte,
- frame: MBFrame,
- allowRetransmission: Boolean = true,
- minSendIntervalNanoSeconds: Int = MODBUS_MIN_SEND_INTERVAL,
- done: ((res: ByteArray) -> Unit)? = null
- ) {
- if (mSlaveAddressList.size <= 0) {
- LogUtil.i("sendTo($slaveAddress), 地址池大小为0, 返回空数据")
- done?.invoke(byteArrayOf())
- return
- }
- if (mSlaveAddressList.none { it == slaveAddress }) {
- throw IllegalArgumentException("slaveAddress [${slaveAddress}] is not configed")
- }
- val task = FrameTask(frame.compile(slaveAddress), done)
- task.allowRetransmission = allowRetransmission
- task.minSendInterval = minSendIntervalNanoSeconds
- pendings.add(task)
- }
- /**
- * 开始通信
- */
- fun start() {
- thread = Thread {
- while (running) {
- try {
- takePendingToSend()
- } catch (e: InterruptedException) {
- }
- }
- }
- thread?.isDaemon = true
- thread?.start()
- }
- /**
- * 是否运行
- */
- fun isRunning(): Boolean {
- return running
- }
- /**
- * 停止运行
- */
- fun stop() {
- running = false
- thread?.interrupt()
- portManager.close()
- }
- }
|