ModBusController.kt 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. package com.grkj.iscs.modbus
  2. import android.content.Context
  3. import com.clj.fastble.BleManager
  4. import com.grkj.iscs.BusinessManager
  5. import com.grkj.iscs.R
  6. import com.grkj.iscs.extentions.removeLeadingZeros
  7. import com.grkj.iscs.extentions.toHexStrings
  8. import com.grkj.iscs.model.DeviceConst.DEVICE_TYPE_KEY
  9. import com.grkj.iscs.model.DeviceConst.DEVICE_TYPE_LOCK
  10. import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_ELEC_LOCK_BOARD
  11. import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_KEY
  12. import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_LOCK
  13. import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_PORTABLE
  14. import com.grkj.iscs.util.Executor
  15. import com.grkj.iscs.util.NetApi
  16. import com.grkj.iscs.util.ToastUtils
  17. import com.grkj.iscs.util.log.LogUtil
  18. import java.util.concurrent.Executors
  19. import java.util.stream.Collectors
  20. /**
  21. * ModBus 主控板控制器
  22. */
  23. object ModBusController {
  24. var isInitReady = false
  25. /**
  26. * 底座列表
  27. */
  28. var dockList: MutableList<DockBean> = mutableListOf()
  29. private const val LISTENER_TYPE_STATUS = 3
  30. // 主控板管理器
  31. var modBusManager: ModBusManager? = null
  32. private var slaveCount: Int = 0
  33. private val threadPool = Executors.newScheduledThreadPool(4)
  34. private val listeners = ArrayList<StatusListener>()
  35. // 是否中断读取状态
  36. private var interruptReadStatus: ArrayList<Boolean> = ArrayList()
  37. var shouldStopUpgrade = false
  38. // TODO 临时改成5s
  39. const val REPEAT_FREQUENCY = 800L
  40. fun setSlaveCount(count: Int) {
  41. modBusManager?.slaveCount = count
  42. slaveCount = count
  43. }
  44. class StatusListener(
  45. val key: Any,
  46. val listener: (Any) -> Unit,
  47. val type: Int
  48. )
  49. fun interruptReadTrashBinStatus(interrupt: Boolean) {
  50. interruptReadStatus.clear()
  51. interruptReadStatus.add(interrupt)
  52. }
  53. @ExperimentalUnsignedTypes
  54. fun start(ctx: Context) {
  55. modBusManager?.stop()
  56. PortManager.openCtrlBord(ctx)
  57. ?.let { pm ->
  58. return@let ModBusManager(slaveCount, pm, true)
  59. }
  60. // 间隔 1 秒读一遍桶的状态
  61. ?.repeatSendToAll(MBFrame.READ_STATUS, {
  62. interruptReadStatus
  63. }, { res ->
  64. // // Logger.d("ModbusController", "res: ${res.map { it.toHexString() }}")
  65. LogUtil.i("****************************************************************************")
  66. // 过滤非空的数据,重置slaveCount
  67. // 不再使用slaveCount,改用地址池
  68. // val onlineCount = res.filter { it.isNotEmpty() }.size
  69. // setSlaveCount(onlineCount)
  70. for (l in listeners) {
  71. if (l.type == LISTENER_TYPE_STATUS) {
  72. l.listener(res)
  73. }
  74. }
  75. }, REPEAT_FREQUENCY)
  76. ?.also {
  77. modBusManager = it
  78. Executor.runOnIO {
  79. // refreshAllowOpenDoorUnidentified(ctx, it)
  80. }
  81. }
  82. ?.start()
  83. }
  84. fun registerStatusListener(key: Any, listener: (Any) -> Unit) {
  85. listeners.add(StatusListener(key, listener, LISTENER_TYPE_STATUS))
  86. }
  87. fun unregisterListener(key: Any) {
  88. val it = listeners.iterator()
  89. while (it.hasNext()) {
  90. if (it.next().key == key) {
  91. it.remove()
  92. }
  93. }
  94. }
  95. fun stop() {
  96. modBusManager?.stop()
  97. }
  98. fun isRunning(): Boolean? {
  99. return modBusManager?.isRunning()
  100. }
  101. /*****************************************************************************************/
  102. /**
  103. * 初始化所有设备的状态
  104. */
  105. fun initDevicesStatus() {
  106. readDeviceType { res ->
  107. res.forEach { bytes ->
  108. if (bytes.size < 5) return@forEach
  109. // 设备具体数据由0x0011寄存器提供
  110. updateDeviceType(bytes[0], bytes[4])
  111. val type = when (bytes[4]) {
  112. DOCK_TYPE_KEY -> "钥匙底座"
  113. DOCK_TYPE_LOCK -> "锁具底座"
  114. DOCK_TYPE_ELEC_LOCK_BOARD -> "电磁锁控制板"
  115. DOCK_TYPE_PORTABLE -> "便携式底座"
  116. else -> "未知"
  117. }
  118. LogUtil.i("initDevicesStatus 设备(${bytes[0].toInt()})类型:$type")
  119. }
  120. // TODO 待完善
  121. Executor.repeatOnMain({
  122. if (isInitReady) {
  123. initLock() // 打开所有无锁的卡扣、关闭所有有锁的卡扣、读取所有锁的RFID
  124. initKey() // 打开所有无钥匙的卡扣、关闭所有有钥匙的卡扣、读取所有钥匙的RFID
  125. return@repeatOnMain false
  126. } else {
  127. return@repeatOnMain true
  128. }
  129. }, REPEAT_FREQUENCY, true)
  130. }
  131. }
  132. /**
  133. * 初始化锁具——打开所有无锁的卡扣、读取RFID
  134. */
  135. private fun initLock() {
  136. LogUtil.i("initLock : $dockList")
  137. dockList.filter { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }.forEach { dockBean ->
  138. val hasLockIdxList = dockBean.getLockList().filter { it.isExist }.map { it.idx } as MutableList<Int>
  139. val noLockIdxList = dockBean.getLockList().filter { !it.isExist }.map { it.idx } as MutableList<Int>
  140. hasLockIdxList.forEach { idx ->
  141. readLockRfid(dockBean.addr, idx) { res ->
  142. if (res.size < 11) {
  143. LogUtil.e("Lock rfid error")
  144. return@readLockRfid
  145. }
  146. val rfid = res.copyOfRange(3, 11).toHexStrings(false).removeLeadingZeros()
  147. LogUtil.i("初始化锁具 RFID : $rfid")
  148. updateLockRfid(dockBean.addr, idx, rfid)
  149. }
  150. }
  151. controlLockBuckle(false, dockBean.addr, hasLockIdxList)
  152. controlLockBuckle(true, dockBean.addr, noLockIdxList)
  153. }
  154. }
  155. /**
  156. * 初始化钥匙
  157. */
  158. private fun initKey() {
  159. LogUtil.i("initKey : $dockList")
  160. dockList.filter { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }.forEach { dockBean ->
  161. dockBean.getKeyList().forEach { key ->
  162. if (key.isExist) {
  163. LogUtil.i("initKey : ${dockBean.addr} : ${key.isLeft}")
  164. readKeyRfid(dockBean.addr, if (key.isLeft) 0 else 1) { isLeft, res ->
  165. if (res.size < 11) {
  166. LogUtil.e("Key rfid error")
  167. return@readKeyRfid
  168. }
  169. val rfid = res.copyOfRange(3, 11).toHexStrings(false).removeLeadingZeros()
  170. LogUtil.i("初始化钥匙 RFID : $rfid")
  171. // 更新rfid
  172. updateKeyRfid(dockBean.addr, isLeft, rfid)
  173. // 蓝牙准备操作
  174. NetApi.getKeyInfo(rfid) {
  175. LogUtil.i("getKeyInfo : $rfid - ${it?.macAddress}")
  176. if (it != null && !it.macAddress.isNullOrEmpty()) {
  177. // 更新mac
  178. updateKeyMac(dockBean.addr, key.isLeft, it.macAddress)
  179. BusinessManager.registerConnectListener(it.macAddress) { isDone, bleBean ->
  180. if (isDone && bleBean?.bleDevice != null) {
  181. Executor.delayOnMain(500) {
  182. BusinessManager.getCurrentStatus(3, bleBean.bleDevice)
  183. }
  184. }
  185. }
  186. } else {
  187. ToastUtils.tip(R.string.get_key_info_fail)
  188. }
  189. }
  190. }
  191. controlKeyBuckle(false, key.isLeft, dockBean.addr)
  192. } else {
  193. controlKeyBuckle(true, key.isLeft, dockBean.addr)
  194. }
  195. }
  196. }
  197. }
  198. /**
  199. * 更新状态
  200. */
  201. fun updateStatus(byteArray: ByteArray): DockBean? {
  202. if (byteArray.isEmpty()) {
  203. return null
  204. }
  205. val dockB = dockList.find { it.addr == byteArray[0] }
  206. return dockB?.parseStatus(byteArray)
  207. }
  208. /**
  209. * 读取设备类型
  210. */
  211. private fun readDeviceType(done: ((res: List<ByteArray>) -> Unit)? = null) {
  212. modBusManager?.sendToAll(MBFrame.READ_DEVICE_TYPE) { res ->
  213. done?.invoke(res)
  214. }
  215. }
  216. /**
  217. * 更新设备类型
  218. */
  219. private fun updateDeviceType(idx: Byte, type: Byte?) {
  220. val dock = dockList.find { it.addr == idx }
  221. dock?.let {
  222. it.type = type
  223. } ?: let {
  224. dockList.add(DockBean(idx, type, mutableListOf()))
  225. }
  226. }
  227. /**
  228. * 读取卡扣状态
  229. *
  230. * @param isLock true:读锁具底座 false:读钥匙底座
  231. * @param type 0:钥匙底座 1:锁具底座1-8 2:锁具底座9、10
  232. */
  233. fun readBuckleStatus(isLock: Boolean, slaveAddress: Byte?, doneSingle: ((type: Int, res: ByteArray) -> Unit)? = null) {
  234. // TODO 电磁锁控制板可能不是,并且锁和钥匙的读取不一样
  235. slaveAddress?.let {
  236. modBusManager?.sendTo(it, MBFrame.READ_BUCKLE_STATUS) { res ->
  237. doneSingle?.invoke(if (isLock) 1 else 0, res)
  238. }
  239. if (isLock) {
  240. modBusManager?.sendTo(it, MBFrame.READ_LOCK_BUCKLE_EXTRA_STATUS) { res ->
  241. doneSingle?.invoke(2, res)
  242. }
  243. }
  244. }
  245. }
  246. /**
  247. * 开/关锁具卡扣
  248. */
  249. fun controlLockBuckle(isOpen: Boolean, slaveAddress: Byte?, lockIdx: Int, done: ((res: ByteArray) -> Unit)? = null) {
  250. slaveAddress?.let {
  251. modBusManager?.generateLockBuckleCmd(isOpen, lockIdx)?.let { cmd ->
  252. modBusManager?.sendTo(it, cmd) { res ->
  253. done?.invoke(res)
  254. }
  255. }
  256. }
  257. }
  258. fun controlLockBuckle(isOpen: Boolean, slaveAddress: Byte?, lockIdxList: MutableList<Int>, done: ((res: ByteArray) -> Unit)? = null) {
  259. slaveAddress?.let {
  260. modBusManager?.generateLockBuckleCmd(isOpen, lockIdxList)?.let { cmdList ->
  261. cmdList.forEach { cmd ->
  262. modBusManager?.sendTo(it, cmd) { res ->
  263. done?.invoke(res)
  264. }
  265. }
  266. }
  267. }
  268. }
  269. /**
  270. * 读取钥匙RFID
  271. */
  272. fun readKeyRfid(slaveAddress: Byte?, idx: Int, done: ((isLeft: Boolean, res: ByteArray) -> Unit)? = null) {
  273. slaveAddress?.let {
  274. modBusManager?.generateRfidCmd(idx)?.let { cmd ->
  275. modBusManager?.sendTo(it, cmd) {
  276. done?.invoke(idx == 0, it)
  277. }
  278. }
  279. }
  280. }
  281. /**
  282. * 读取锁具RFID
  283. */
  284. fun readLockRfid(slaveAddress: Byte?, lockIdx: Int, done: ((res: ByteArray) -> Unit)? = null) {
  285. slaveAddress?.let {
  286. modBusManager?.generateRfidCmd(lockIdx)?.let { cmd ->
  287. modBusManager?.sendTo(it, cmd) { res ->
  288. done?.invoke(res)
  289. }
  290. }
  291. }
  292. }
  293. /**
  294. * 读便携式底座卡RFID
  295. */
  296. fun readPortalCaseCardRfid(slaveAddress: Byte?, done: ((res: ByteArray) -> Unit)? = null) {
  297. slaveAddress?.let {
  298. modBusManager?.generateRfidCmd(8)?.let { cmd ->
  299. modBusManager?.sendTo(it, cmd) { res ->
  300. done?.invoke(res)
  301. }
  302. }
  303. }
  304. }
  305. /**
  306. * 更新钥匙RFID
  307. */
  308. fun updateKeyRfid(slaveAddress: Byte, isLeft: Boolean, rfid: String) {
  309. dockList.find { it.addr == slaveAddress }?.getKeyList()?.find { it.isLeft == isLeft }?.rfid = rfid
  310. }
  311. /**
  312. * 更新钥匙MAC
  313. */
  314. fun updateKeyMac(slaveAddress: Byte, isLeft: Boolean, mac: String) {
  315. dockList.find { it.addr == slaveAddress }?.getKeyList()?.find { it.isLeft == isLeft }?.mac = mac
  316. }
  317. /**
  318. * 通过RFID更新对应的Mac
  319. */
  320. fun updateKeyMacByRfid(rfid: String, mac: String) {
  321. dockList.find { it.type == DOCK_TYPE_KEY }?.getKeyList()?.find { it.rfid == rfid }?.mac = mac
  322. }
  323. /**
  324. * 更新锁具RFID
  325. */
  326. fun updateLockRfid(slaveAddress: Byte, lockIdx: Int, rfid: String) {
  327. dockList.find { it.addr == slaveAddress }?.getLockList()?.find { it.idx == lockIdx }?.rfid = rfid
  328. }
  329. /**
  330. * 设备是否存在,加入deviceType防止有重复的但是不同类型的
  331. *
  332. * @param deviceType {@link [com.grkj.iscs.model.bo.DeviceTakeUpdateBO]<class>#[deviceType]}
  333. */
  334. fun isDeviceExist(rfid: String, deviceType: Int) : Boolean {
  335. return when (deviceType) {
  336. DEVICE_TYPE_KEY -> {
  337. dockList.find { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }?.getKeyList()?.find { it.rfid == rfid } != null
  338. }
  339. DEVICE_TYPE_LOCK -> {
  340. dockList.find { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }?.getLockList()?.find { it.rfid == rfid } != null
  341. }
  342. else -> {
  343. false
  344. }
  345. }
  346. }
  347. /**
  348. * 操作钥匙灯
  349. *
  350. * @param leftAction、rightAction 0:保持当前状态 1:点亮 2:熄灭 默认0
  351. */
  352. fun controlKeyLight(slaveAddress: Byte?, leftAction: Int = 0, rightAction: Int = 0, done: ((res: ByteArray) -> Unit)? = null) {
  353. slaveAddress?.let {
  354. modBusManager?.generateKeyLightCmd(leftAction, rightAction)?.let { cmd ->
  355. modBusManager?.sendTo(it, cmd) {
  356. done?.invoke(it)
  357. }
  358. }
  359. }
  360. }
  361. /**
  362. * 控制钥匙卡扣
  363. */
  364. fun controlKeyBuckle(isOpen: Boolean, mac: String, done: ((res: ByteArray) -> Unit)? = null) {
  365. val dockBean = getDockByKeyMac(mac)
  366. dockBean ?: return
  367. val key = getKeyByMac(mac)
  368. key ?: return
  369. controlKeyBuckle(isOpen, key.isLeft, dockBean.addr, done)
  370. }
  371. /**
  372. * 开/关钥匙卡扣
  373. *
  374. * @param isOpen true:开操作 false:关操作
  375. * @param isLeft true:左卡扣 false:右卡扣
  376. */
  377. fun controlKeyBuckle(isOpen: Boolean, isLeft: Boolean, slaveAddress: Byte?, done: ((res: ByteArray) -> Unit)? = null) {
  378. slaveAddress?.let {
  379. modBusManager?.generateKeyBuckleCmd(isOpen, if (isLeft) 0 else 1)?.let { cmd ->
  380. modBusManager?.sendTo(it, cmd) { res ->
  381. done?.invoke(res)
  382. }
  383. }
  384. }
  385. }
  386. /**
  387. * 根据RFID找钥匙
  388. */
  389. fun getKeyByRfid(rfid: String): DockBean.KeyBean? {
  390. return dockList.filter { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }.flatMap { it.getKeyList() }.find { it.rfid == rfid }
  391. }
  392. /**
  393. * 根据Mac找钥匙
  394. */
  395. fun getKeyByMac(mac: String): DockBean.KeyBean? {
  396. return dockList.filter { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }.flatMap { it.getKeyList() }.find { it.mac == mac }
  397. }
  398. fun getKeyByDock(dockAddr: Byte?, isLeft: Boolean): DockBean.KeyBean? {
  399. dockAddr ?: return null
  400. return dockList.find { it.addr == dockAddr }?.getKeyList()?.find { it.isLeft == isLeft }
  401. }
  402. /**
  403. * 根据RFID找锁具
  404. */
  405. fun getLockByRfid(rfid: String): DockBean.LockBean? {
  406. return dockList.filter { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }.flatMap { it.getLockList() }.find { it.rfid == rfid }
  407. }
  408. fun isKeyExist(dockAddr: Byte?, isLeft: Boolean): Boolean {
  409. dockAddr ?: return false
  410. return dockList.find { it.addr == dockAddr }?.getKeyList()
  411. ?.find { it.isLeft == isLeft && it.isExist } != null
  412. }
  413. fun isLockExist(dockAddr: Byte?, lockIdx: Int): Boolean {
  414. dockAddr ?: return false
  415. return dockList.find { it.addr == dockAddr }?.getLockList()
  416. ?.find { it.idx == lockIdx && it.isExist } != null
  417. }
  418. /**
  419. * 获取钥匙状态
  420. *
  421. * @return 0:不存在 1:存在 2:有RFID 3:有MAC 4:连接上 5:待机模式 6: 待机模式无异常
  422. */
  423. fun getKeyStatus(dockAddr: Byte?, isLeft: Boolean): Int {
  424. dockAddr ?: return 0
  425. val key = dockList.find { it.addr == dockAddr }?.getKeyList()?.find { it.isLeft == isLeft }
  426. LogUtil.i("getKeyStatus key : $key")
  427. key ?: return 0
  428. var status = 0
  429. if (key.isExist) {
  430. status = 1
  431. } else {
  432. return status
  433. }
  434. if (key.rfid != null) {
  435. status = 2
  436. } else {
  437. return status
  438. }
  439. if (key.mac != null) {
  440. status = 3
  441. } else {
  442. return status
  443. }
  444. if (BleManager.getInstance().isConnected(BusinessManager.getBleDeviceByMac(key.mac)?.bleDevice)) {
  445. status = 4
  446. } else {
  447. return status
  448. }
  449. if (key.isReady) {
  450. status = 5
  451. } else {
  452. return status
  453. }
  454. if (key.rfid != null && BusinessManager.mExceptionKeyList.none { it == key.rfid }) {
  455. status = 6
  456. } else {
  457. return status
  458. }
  459. return status
  460. }
  461. /**
  462. * 更新钥匙的准备状态
  463. */
  464. fun updateKeyReadyStatus(mac: String, isReady: Boolean, from: Int) {
  465. LogUtil.i("updateKeyReadyStatus mac : $mac - $isReady - $from")
  466. dockList.forEach {
  467. if (it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE) {
  468. if (it.getKeyList().any { it.mac == mac }) {
  469. it.getKeyList().find { it.mac == mac }?.isReady = isReady
  470. }
  471. }
  472. }
  473. }
  474. /**
  475. * 根据钥匙Mac获取底座
  476. */
  477. fun getDockByKeyMac(mac: String): DockBean? {
  478. return dockList.find {
  479. (it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE)
  480. && it.getKeyList().any { it.mac == mac }
  481. }
  482. }
  483. fun getDockByLockNfc(nfc: String): DockBean? {
  484. return dockList.find {
  485. (it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE)
  486. && it.getLockList().any { it.rfid == nfc }
  487. }
  488. }
  489. /**
  490. * 根据类型获取底座列表
  491. */
  492. fun getDockByType(type: Byte): List<DockBean> {
  493. return dockList.filter { it.type == type }
  494. }
  495. fun getKeyByDockType(type: Byte): MutableList<DockBean.KeyBean>? {
  496. return dockList.find { it.type == type }?.let {
  497. it.getKeyList()
  498. }
  499. }
  500. fun controlAllLockBuckles(isOpen: Boolean) {
  501. dockList.filter { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }.forEach { dockBean ->
  502. val list = dockBean.getLockList().stream().map { it.idx }.collect(Collectors.toList())
  503. controlLockBuckle(isOpen, dockBean.addr, list) {
  504. LogUtil.i("${if (isOpen) "开启" else "关闭"}所有锁卡扣 : ${it.toHexStrings()}")
  505. }
  506. }
  507. }
  508. fun printDockInfo() {
  509. LogUtil.i("当前底座列表 : $dockList")
  510. dockList.forEach { dockBean ->
  511. when (dockBean.type) {
  512. DOCK_TYPE_LOCK -> {
  513. dockBean.getLockList().forEach { lockBean ->
  514. LogUtil.i("${dockBean.addr}锁${lockBean.idx} : ${lockBean.rfid}")
  515. }
  516. }
  517. DOCK_TYPE_KEY -> {
  518. dockBean.getKeyList().forEach { keyBean ->
  519. LogUtil.i("${dockBean.addr}钥${keyBean.idx} : ${keyBean.rfid}")
  520. }
  521. }
  522. DOCK_TYPE_PORTABLE -> {
  523. dockBean.getLockList().forEach { lockBean ->
  524. LogUtil.i("${dockBean.addr}柜锁${lockBean.idx} : ${lockBean.rfid}")
  525. }
  526. dockBean.getKeyList().forEach { keyBean ->
  527. LogUtil.i("${dockBean.addr}柜钥${keyBean.idx} : ${keyBean.rfid}")
  528. }
  529. }
  530. }
  531. }
  532. }
  533. fun updateDeviceType() {
  534. LogUtil.i("____________________________________")
  535. readDeviceType { res ->
  536. LogUtil.i("设备类型数量 : ${res.size}")
  537. LogUtil.i("设备类型 : ${res.map { it.toHexStrings()}}")
  538. res.forEach { bytes ->
  539. if (bytes.size < 5) return@forEach
  540. // 设备具体数据由0x0011寄存器提供
  541. updateDeviceType(bytes[0], bytes[4])
  542. val type = when (bytes[4]) {
  543. DOCK_TYPE_KEY -> "钥匙底座"
  544. DOCK_TYPE_LOCK -> "锁具底座"
  545. DOCK_TYPE_ELEC_LOCK_BOARD -> "电磁锁控制板"
  546. DOCK_TYPE_PORTABLE -> "便携式底座"
  547. else -> "未知"
  548. }
  549. LogUtil.i("设备(${bytes[0].toInt()})类型:$type")
  550. }
  551. LogUtil.i("____________________________________")
  552. }
  553. }
  554. /**
  555. * 随机获取一个钥匙(存在的、有RFID、有Mac、连接的、是待机模式的)
  556. *
  557. * @return 底座地址,钥匙
  558. */
  559. fun getOneKey(): Pair<Byte, DockBean.KeyBean?>? {
  560. val keyDockList = dockList.filter { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }
  561. val keyList = keyDockList.flatMap { it.getKeyList() }.filter { it.isExist }
  562. LogUtil.i("keyList : $keyList")
  563. if (keyList.isEmpty()) {
  564. ToastUtils.tip(R.string.no_available_key)
  565. return null
  566. }
  567. keyList.forEach {
  568. LogUtil.i("keyStatus : ${it.isExist} - ${it.rfid} - ${it.mac} - ${it.isReady} - " +
  569. "${BusinessManager.getBleDeviceByMac(it.mac)?.bleDevice != null} - " +
  570. "${BleManager.getInstance().isConnected(BusinessManager.getBleDeviceByMac(it.mac)?.bleDevice)} - " +
  571. "${!BusinessManager.mExceptionKeyList.contains(it.rfid)}")
  572. }
  573. val key = keyList.filter { it.isExist && it.rfid != null && it.mac != null && it.isReady
  574. && BleManager.getInstance().isConnected(BusinessManager.getBleDeviceByMac(it.mac)?.bleDevice)
  575. && !BusinessManager.mExceptionKeyList.contains(it.rfid) }
  576. .shuffled().firstOrNull()
  577. if (key == null) {
  578. LogUtil.e("getOneKey : no key match")
  579. return null
  580. }
  581. val address = keyDockList.find { it.getKeyList().any { it.rfid == key.rfid } }?.addr
  582. if (address == null) {
  583. LogUtil.e("getOneKey : no dock match")
  584. return null
  585. }
  586. return Pair(address, key)
  587. }
  588. /**
  589. * 根据数量获取锁具(基于锁柜和便携柜不存在接一起的情况)
  590. *
  591. * @param needLockCount 需要打开的锁具数量
  592. *
  593. * @return key: dock地址,value: 锁具RFID列表
  594. */
  595. fun getLocks(needLockCount: Int): MutableMap<Byte, MutableList<DockBean.LockBean>> {
  596. val map = mutableMapOf<Byte, MutableList<DockBean.LockBean>>()
  597. if (needLockCount == 0) {
  598. return map
  599. }
  600. val lockDockList = dockList.filter { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }
  601. var provideCount = 0
  602. lockDockList.forEach loop@ { lockDock ->
  603. val lockList = lockDock.getLockList().filter { it.isExist }.toMutableList()
  604. if (lockList.size < (needLockCount - provideCount)) {
  605. provideCount += lockList.size
  606. map[lockDock.addr] = lockList
  607. } else {
  608. val rfidList = lockList.subList(0, needLockCount - provideCount)
  609. map[lockDock.addr] = rfidList
  610. return@loop
  611. }
  612. }
  613. return map
  614. }
  615. // fun getLocks(needLockCount: Int): MutableMap<Byte, MutableList<DockBean.LockBean>> {
  616. // val map = mutableMapOf<Byte, MutableList<DockBean.LockBean>>()
  617. // if (needLockCount == 0) {
  618. // return map
  619. // }
  620. //
  621. // val lockList =
  622. // dockList.filter { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }
  623. // .flatMap { it.getLockList() }.filter { it.isExist }.shuffled().take(needLockCount)
  624. // lockList.forEach loop@{ lock ->
  625. // lock.rfid ?: return@loop
  626. // val dock = getDockByLockNfc(lock.rfid!!)
  627. // dock ?: return@loop
  628. // if (map[dock.addr] == null) {
  629. // map[dock.addr] = mutableListOf()
  630. // }
  631. // map[dock.addr]!!.add(lock)
  632. // }
  633. // return map
  634. // }
  635. }