ModBusController.kt 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. package com.grkj.iscs.modbus
  2. import android.content.Context
  3. import com.grkj.iscs.extentions.removeLeadingZeros
  4. import com.grkj.iscs.extentions.toHexStrings
  5. import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_ELEC_LOCK_BOARD
  6. import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_KEY
  7. import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_LOCK
  8. import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_PORTABLE
  9. import com.grkj.iscs.util.Executor
  10. import com.grkj.iscs.util.log.LogUtil
  11. import java.util.concurrent.Executors
  12. /**
  13. * ModBus 主控板控制器
  14. */
  15. object ModBusController {
  16. /**
  17. * 底座列表
  18. */
  19. var dockList: MutableList<DockBean> = mutableListOf()
  20. private const val LISTENER_TYPE_STATUS = 3
  21. // 主控板管理器
  22. private var modBusManager: ModBusManager? = null
  23. private var slaveCount: Int = 0
  24. private val threadPool = Executors.newScheduledThreadPool(4)
  25. private val listeners = ArrayList<StatusListener>()
  26. // 是否中断读取状态
  27. private var interruptReadStatus: ArrayList<Boolean> = ArrayList()
  28. var shouldStopUpgrade = false
  29. fun setSlaveCount(count: Int) {
  30. modBusManager?.slaveCount = count
  31. slaveCount = count
  32. }
  33. class StatusListener(
  34. val key: Any,
  35. val listener: (Any) -> Unit,
  36. val type: Int
  37. )
  38. fun interruptReadTrashBinStatus(interrupt: Boolean) {
  39. interruptReadStatus.clear()
  40. interruptReadStatus.add(interrupt)
  41. }
  42. @ExperimentalUnsignedTypes
  43. fun start(ctx: Context) {
  44. modBusManager?.stop()
  45. PortManager.openCtrlBord(ctx)
  46. ?.let { pm ->
  47. return@let ModBusManager(slaveCount, pm, true)
  48. }
  49. // 间隔 1 秒读一遍桶的状态
  50. ?.repeatSendToAll(MBFrame.READ_STATUS, {
  51. interruptReadStatus
  52. }, { res ->
  53. // // Logger.d("ModbusController", "res: ${res.map { it.toHexString() }}")
  54. LogUtil.i("****************************************************************************")
  55. for (l in listeners) {
  56. if (l.type == LISTENER_TYPE_STATUS) {
  57. l.listener(res)
  58. }
  59. }
  60. // TODO 临时改成5s
  61. // }, 1000)
  62. }, 5000)
  63. ?.also {
  64. modBusManager = it
  65. Executor.runOnIO {
  66. // refreshAllowOpenDoorUnidentified(ctx, it)
  67. }
  68. }
  69. ?.start()
  70. }
  71. fun registerStatusListener(key: Any, listener: (Any) -> Unit) {
  72. listeners.add(StatusListener(key, listener, LISTENER_TYPE_STATUS))
  73. }
  74. fun unregisterListener(key: Any) {
  75. val it = listeners.iterator()
  76. while (it.hasNext()) {
  77. if (it.next().key == key) {
  78. it.remove()
  79. }
  80. }
  81. }
  82. fun stop() {
  83. modBusManager?.stop()
  84. }
  85. /*****************************************************************************************/
  86. /**
  87. * 初始化所有设备的状态
  88. */
  89. // TODO 通电后多久执行?App每次重启的执行是什么
  90. fun initDevicesStatus() {
  91. readDeviceType { res ->
  92. res.forEach { bytes ->
  93. if (bytes.size < 5) return@forEach
  94. // TODO 设备具体数据由0x0011寄存器提供
  95. updateDeviceType(bytes[0], bytes[4])
  96. val type = when (bytes[4]) {
  97. DOCK_TYPE_KEY -> "钥匙底座"
  98. DOCK_TYPE_LOCK -> "锁具底座"
  99. DOCK_TYPE_ELEC_LOCK_BOARD -> "电磁锁控制板"
  100. DOCK_TYPE_PORTABLE -> "便携式底座"
  101. else -> "未知"
  102. }
  103. LogUtil.i("initDevicesStatus 设备(${bytes[0].toInt()})类型:$type")
  104. }
  105. }
  106. Executor.delayOnMain({
  107. // TODO 待完善
  108. initLock() // TODO 打开所有无锁的卡扣、读取所有锁的RFID
  109. initKey() // TODO 打开所有无钥匙的卡扣、关闭所有钥匙灯光、读取所有钥匙的RFID
  110. // TODO 设置所有钥匙的模式
  111. // TODO 通过HTTP获取所有钥匙的Mac
  112. }, 3000)
  113. }
  114. /**
  115. * 初始化锁具——打开所有无锁的卡扣、读取RFID
  116. */
  117. private fun initLock() {
  118. LogUtil.i("initLock : $dockList")
  119. dockList.filter { it.type == DOCK_TYPE_LOCK }.forEach { dockBean ->
  120. val hasLockIdxList = dockBean.getLockList().filter { it.isExist }.map { it.idx }
  121. val noLockIdxList = dockBean.getLockList().filter { !it.isExist }.map { it.idx } as MutableList<Int>
  122. hasLockIdxList.forEach { idx ->
  123. readLockRfid(dockBean.addr.toInt() - 1, idx) { res ->
  124. val rfid = res.copyOfRange(3, 11).toHexStrings(false).removeLeadingZeros()
  125. LogUtil.i("初始化锁具 RFID : $rfid")
  126. updateLockRfid(dockBean.addr.toInt(), idx, rfid)
  127. }
  128. }
  129. controlLockBuckle(true, dockBean.addr.toInt() - 1, noLockIdxList)
  130. }
  131. }
  132. /**
  133. * 初始化钥匙——关闭所有钥匙灯光
  134. */
  135. private fun initKey() {
  136. LogUtil.i("initKey : $dockList")
  137. dockList.filter { it.type == DOCK_TYPE_KEY }.forEach { dockBean ->
  138. controlKeyLight(dockBean.addr.toInt() - 1, 2, 2)
  139. dockBean.getKeyList().forEach { key ->
  140. if (key.isExist) {
  141. LogUtil.i("initKey : ${dockBean.addr.toInt() - 1} : ${key.isLeft}")
  142. readKeyRfid(dockBean.addr.toInt() - 1, key.isLeft) { isLeft, res ->
  143. val rfid = res.copyOfRange(3, 11).toHexStrings(false).removeLeadingZeros()
  144. LogUtil.i("初始化钥匙 RFID : $rfid")
  145. updateKeyRfid(dockBean.addr.toInt(), isLeft, rfid)
  146. }
  147. } else {
  148. // TODO 关闭钥匙卡扣
  149. }
  150. }
  151. }
  152. }
  153. /**
  154. * 更新状态
  155. */
  156. fun updateStatus(byteArray: ByteArray): DockBean? {
  157. if (byteArray.isEmpty()) {
  158. return null
  159. }
  160. val dockB = dockList.find { it.addr == byteArray[0] }
  161. return dockB?.parseStatus(byteArray) ?: let {
  162. val temp = DockBean(byteArray[0], null, mutableListOf())
  163. dockList.add(temp)
  164. temp.parseStatus(byteArray)
  165. }
  166. }
  167. /**
  168. * 读取设备类型
  169. */
  170. fun readDeviceType(done: ((res: List<ByteArray>) -> Unit)? = null) {
  171. modBusManager?.sendToAll(MBFrame.READ_DEVICE_TYPE) { res ->
  172. done?.invoke(res)
  173. }
  174. }
  175. /**
  176. * 更新设备类型
  177. */
  178. fun updateDeviceType(idx: Byte?, type: Byte?) {
  179. dockList.find { it.addr == idx }?.type = type
  180. }
  181. /**
  182. * 读取卡扣状态
  183. *
  184. * @param isLock true:读锁具底座 false:读钥匙底座
  185. * @param type 0:钥匙底座 1:锁具底座1-8 2:锁具底座9、10
  186. */
  187. fun readBuckleStatus(isLock: Boolean, slaveIdx: Int?, doneSingle: ((type: Int, res: ByteArray) -> Unit)? = null) {
  188. // TODO 电磁锁控制板可能不是,并且锁和钥匙的读取不一样
  189. slaveIdx?.let {
  190. modBusManager?.sendTo(it, MBFrame.READ_BUCKLE_STATUS) { res ->
  191. doneSingle?.invoke(if (isLock) 1 else 0, res)
  192. }
  193. if (isLock) {
  194. modBusManager?.sendTo(it, MBFrame.READ_LOCK_BUCKLE_EXTRA_STATUS) { res ->
  195. doneSingle?.invoke(2, res)
  196. }
  197. }
  198. }
  199. }
  200. /**
  201. * 开/关锁具卡扣
  202. */
  203. fun controlLockBuckle(isOpen: Boolean, slaveIdx: Int?, lockIdx: Int, done: ((res: ByteArray) -> Unit)? = null) {
  204. slaveIdx?.let {
  205. modBusManager?.generateLockBuckleCmd(isOpen, lockIdx)?.let { cmd ->
  206. modBusManager?.sendTo(it, cmd) { res ->
  207. done?.invoke(res)
  208. }
  209. }
  210. }
  211. }
  212. fun controlLockBuckle(isOpen: Boolean, slaveIdx: Int?, lockIdxList: MutableList<Int>, done: ((res: ByteArray) -> Unit)? = null) {
  213. slaveIdx?.let {
  214. modBusManager?.generateLockBuckleCmd(isOpen, lockIdxList)?.let { cmdList ->
  215. cmdList.forEach { cmd ->
  216. modBusManager?.sendTo(it, cmd) { res ->
  217. done?.invoke(res)
  218. }
  219. }
  220. }
  221. }
  222. }
  223. /**
  224. * 读取钥匙RFID
  225. */
  226. fun readKeyRfid(slaveIdx: Int?, isLeft: Boolean, done: ((isLeft: Boolean, res: ByteArray) -> Unit)? = null) {
  227. slaveIdx?.let {
  228. modBusManager?.generateRfidCmd(if (isLeft) 0 else 1)?.let { cmd ->
  229. modBusManager?.sendTo(it, cmd) {
  230. done?.invoke(isLeft, it)
  231. }
  232. }
  233. }
  234. }
  235. /**
  236. * 读取锁具RFID
  237. */
  238. fun readLockRfid(slaveIdx: Int?, lockIdx: Int, done: ((res: ByteArray) -> Unit)? = null) {
  239. slaveIdx?.let {
  240. modBusManager?.generateRfidCmd(lockIdx)?.let { cmd ->
  241. modBusManager?.sendTo(it, cmd) { res ->
  242. done?.invoke(res)
  243. }
  244. }
  245. }
  246. }
  247. /**
  248. * 更新钥匙RFID
  249. */
  250. fun updateKeyRfid(slaveIdx: Int, isLeft: Boolean, rfid: String) {
  251. dockList.find { it.addr.toInt() == slaveIdx }?.getKeyList()?.find { it.isLeft == isLeft }?.rfid = rfid
  252. }
  253. /**
  254. * 通过RFID更新对应的Mac
  255. */
  256. fun updateKeyMacByRfid(rfid: String, mac: String) {
  257. dockList.find { it.type == DOCK_TYPE_KEY }?.getKeyList()?.find { it.rfid == rfid }?.mac = mac
  258. }
  259. /**
  260. * 更新锁具RFID
  261. */
  262. fun updateLockRfid(slaveIdx: Int, lockIdx: Int, rfid: String) {
  263. dockList.find { it.addr.toInt() == slaveIdx }?.getLockList()?.find { it.idx == lockIdx }?.rfid = rfid
  264. }
  265. /**
  266. * 操作钥匙灯
  267. *
  268. * @param leftAction、rightAction 0:保持当前状态 1:点亮 2:熄灭 默认0
  269. */
  270. fun controlKeyLight(slaveIdx: Int?, leftAction: Int = 0, rightAction: Int = 0, done: ((res: ByteArray) -> Unit)? = null) {
  271. slaveIdx?.let {
  272. modBusManager?.generateKeyLightCmd(leftAction, rightAction)?.let { cmd ->
  273. modBusManager?.sendTo(it, cmd) {
  274. done?.invoke(it)
  275. }
  276. }
  277. }
  278. }
  279. /**
  280. * 开/关钥匙卡扣
  281. *
  282. * @param isOpen true:开操作 false:关操作
  283. * @param isLeft true:左卡扣 false:右卡扣
  284. */
  285. fun controlKeyBuckle(isOpen: Boolean, isLeft: Boolean, slaveIdx: Int?, done: ((res: ByteArray) -> Unit)? = null) {
  286. slaveIdx?.let {
  287. modBusManager?.generateKeyBuckleCmd(isOpen, if (isLeft) 0 else 1)?.let { cmd ->
  288. modBusManager?.sendTo(it, cmd) { res ->
  289. done?.invoke(res)
  290. }
  291. }
  292. }
  293. }
  294. /**
  295. * 根据RFID找钥匙
  296. */
  297. fun getKeyByRfid(rfid: String): DockBean.KeyBean? {
  298. return dockList.find { it.type == DOCK_TYPE_KEY }?.getKeyList()?.find { it.rfid == rfid }
  299. }
  300. /**
  301. * 根据RFID找锁具
  302. */
  303. fun getLockByRfid(rfid: String): DockBean.LockBean? {
  304. return dockList.find { it.type == DOCK_TYPE_LOCK }?.getLockList()?.find { it.rfid == rfid }
  305. }
  306. }