Przeglądaj źródła

完成CAN总线的对接和上锁解锁流程适配

GrayCarbon 5 miesięcy temu
rodzic
commit
30b48799ee
26 zmienionych plików z 561 dodań i 709 usunięć
  1. 163 308
      app/src/main/java/com/grkj/iscs_mars/BusinessManager.kt
  2. 1 1
      app/src/main/java/com/grkj/iscs_mars/MyApplication.kt
  3. 1 61
      app/src/main/java/com/grkj/iscs_mars/ble/BleCmdManager.kt
  4. 12 20
      app/src/main/java/com/grkj/iscs_mars/ble/BleConnectionManager.kt
  5. 4 3
      app/src/main/java/com/grkj/iscs_mars/ble/BleQueueDispatcher.kt
  6. 1 3
      app/src/main/java/com/grkj/iscs_mars/ble/BleReturnDispatcher.kt
  7. 1 0
      app/src/main/java/com/grkj/iscs_mars/ble/BleSendDispatcher.kt
  8. 1 1
      app/src/main/java/com/grkj/iscs_mars/ble/BleUtil.kt
  9. 10 22
      app/src/main/java/com/grkj/iscs_mars/can/CanHardwareHelper.kt
  10. 135 38
      app/src/main/java/com/grkj/iscs_mars/can/CanHelper.kt
  11. 103 156
      app/src/main/java/com/grkj/iscs_mars/can/CanReadyPlugin.kt
  12. 1 1
      app/src/main/java/com/grkj/iscs_mars/can/CustomCanConfig.kt
  13. 1 1
      app/src/main/java/com/grkj/iscs_mars/can/DeviceModel.kt
  14. 5 9
      app/src/main/java/com/grkj/iscs_mars/can/IHardwareHelper.kt
  15. 6 0
      app/src/main/java/com/grkj/iscs_mars/model/ISCSDomainData.kt
  16. 3 7
      app/src/main/java/com/grkj/iscs_mars/model/bo/WorkTicketGetBO.kt
  17. 0 1
      app/src/main/java/com/grkj/iscs_mars/presentation/PresentationLoginActivity.kt
  18. 6 5
      app/src/main/java/com/grkj/iscs_mars/service/CheckKeyInfoTask.kt
  19. 5 19
      app/src/main/java/com/grkj/iscs_mars/view/activity/HomeActivity.kt
  20. 0 5
      app/src/main/java/com/grkj/iscs_mars/view/activity/LoginActivity.kt
  21. 10 5
      app/src/main/java/com/grkj/iscs_mars/view/activity/MainActivity.kt
  22. 16 12
      app/src/main/java/com/grkj/iscs_mars/view/fragment/DeviceStatusFragment.kt
  23. 6 0
      app/src/main/java/com/grkj/iscs_mars/view/fragment/LoginFragment.kt
  24. 12 1
      app/src/main/java/com/grkj/iscs_mars/view/fragment/SwitchStatusFragment.kt
  25. 46 3
      app/src/main/java/com/grkj/iscs_mars/view/presenter/HomePresenter.kt
  26. 12 27
      app/src/main/java/com/grkj/iscs_mars/view/presenter/JobProgressPresenter.kt

+ 163 - 308
app/src/main/java/com/grkj/iscs_mars/BusinessManager.kt

@@ -1,9 +1,8 @@
 package com.grkj.iscs_mars
-//todo 所有蓝牙包替换com.clj. -> com.clj.
+
 import android.bluetooth.BluetoothGattCharacteristic
 import android.content.Context
 import android.content.Intent
-import android.util.Log
 import androidx.appcompat.app.AppCompatActivity
 import androidx.lifecycle.MutableLiveData
 import com.google.gson.Gson
@@ -19,7 +18,6 @@ import com.grkj.iscs_mars.ble.BleUtil
 import com.grkj.iscs_mars.ble.CustomBleWriteCallback
 import com.grkj.iscs_mars.can.CanCommands
 import com.grkj.iscs_mars.can.CanDeviceConst
-import com.grkj.iscs_mars.can.CanHardwareHelper
 import com.grkj.iscs_mars.can.CanHelper
 import com.grkj.iscs_mars.can.DeviceModel
 import com.grkj.iscs_mars.can.HandlerGate
@@ -30,15 +28,9 @@ import com.grkj.iscs_mars.extentions.toHexFromLe
 import com.grkj.iscs_mars.extentions.toHexStrings
 import com.grkj.iscs_mars.modbus.DockBean
 import com.grkj.iscs_mars.modbus.ModBusController
-import com.grkj.iscs_mars.modbus.ModBusController.dockList
-import com.grkj.iscs_mars.modbus.ModBusController.getOneKey
 import com.grkj.iscs_mars.model.Constants.USER_TYPE_LOCKER
-import com.grkj.iscs_mars.model.DeviceConst
 import com.grkj.iscs_mars.model.DeviceConst.DEVICE_TYPE_KEY
 import com.grkj.iscs_mars.model.DeviceConst.DEVICE_TYPE_LOCK
-import com.grkj.iscs_mars.model.DeviceConst.DOCK_TYPE_KEY
-import com.grkj.iscs_mars.model.DeviceConst.DOCK_TYPE_LOCK
-import com.grkj.iscs_mars.model.DeviceConst.DOCK_TYPE_PORTABLE
 import com.grkj.iscs_mars.model.DictAndSystemConstants
 import com.grkj.iscs_mars.model.ISCSDomainData
 import com.grkj.iscs_mars.model.bo.DeviceTakeUpdateBO
@@ -84,6 +76,7 @@ import com.huyuhui.fastble.exception.BleException
 import com.sik.sikandroid.activity.ActivityTracker
 import com.sik.sikcore.SIKCore
 import com.sik.sikcore.date.TimeUtils
+import com.sik.sikcore.extension.isNullOrEmpty
 import com.sik.sikcore.extension.toJson
 import com.sik.sikcore.thread.ThreadUtils
 import kotlinx.coroutines.Dispatchers
@@ -131,12 +124,8 @@ object BusinessManager {
     // 有问题的钥匙的列表 - rfid
     var mExceptionKeyList = mutableListOf<String>()
 
-    /**
-     * 检查钥匙任务
-     */
-//    var checkKeyInfoTask: CheckKeyInfoTask = CheckKeyInfoTask()
-
-    var canManager: CanHardwareHelper? = null
+    // Can是否初始化
+    var isCanInit = false
 
     /**
      * 初始化消息总线
@@ -173,31 +162,20 @@ object BusinessManager {
                         // 工作模式
                         1 -> {
                             if (it.data.res == 1) {
+                                val opt = HardwareMode.getCurrentHardwareMode()
                                 // 只能在这里断开,不能全部断开
                                 BleCmdManager.shutdownOrRebootReq(mac = it.data.bleBean.bleDevice.mac)
                                 BleSendDispatcher.scheduleDisconnect(it.data.bleBean.bleDevice.mac)
                                 // 打开钥匙卡扣
-                                val keyBean =
-                                    ModBusController.getKeyByMac(it.data.bleBean.bleDevice.mac)
+                                val keyBean = opt.getKeyBeanByMac(it.data.bleBean.bleDevice.mac)
                                 if (keyBean == null) {
-                                    sendEventMsg(
-                                        MsgEvent(
-                                            MSG_EVENT_LOADING,
-                                            LoadingMsg(false, "未找到钥匙信息", false)
-                                        )
-                                    )
+                                    sendEventMsg(MsgEvent(MSG_EVENT_LOADING, LoadingMsg(false, "未找到钥匙信息", false)))
                                     ToastUtils.tip(R.string.key_not_exists)
                                 } else {
                                     sendLoadingEventMsg(CommonUtils.getStr(R.string.take_out_key_tip))
-                                    val dock =
-                                        ModBusController.getDockByKeyMac(it.data.bleBean.bleDevice.mac)
                                     keyBean.isReady = false
-                                    ModBusController.controlKeyBuckle(
-                                        true, keyBean.isLeft, dock?.addr
-                                    )
-                                    ModBusController.updateKeyReadyStatus(
-                                        it.data.bleBean.bleDevice.mac, false, 1
-                                    )
+                                    opt.controlKeyBuckle(true, it.data.bleBean.bleDevice.mac)
+                                    opt.updateKeyReadyStatus(it.data.bleBean.bleDevice.mac, false, 1)
                                     ToastUtils.tip(R.string.take_out_key)
                                     ThreadUtils.runOnIO {
                                         checkMyTodoForHandleKey(it.data.bleBean.bleDevice.mac)
@@ -213,9 +191,7 @@ object BusinessManager {
                         // 待机模式
                         2 -> {
                             if (it.data.res == 1) {
-                                ModBusController.updateKeyReadyStatus(
-                                    it.data.bleBean.bleDevice.mac, true, 2
-                                )
+                                HardwareMode.getCurrentHardwareMode().updateKeyReadyStatus(it.data.bleBean.bleDevice.mac, true, 2)
                                 BleReturnDispatcher.scheduleDisconnect(it.data.bleBean.bleDevice.mac)
                                 // 延时再次获取当前状态,触发handleCurrentMode里工作票下发状态检查
                                 //切换回待机之后不再次查询状态,没有意义,单机操作没有并发需求
@@ -288,24 +264,22 @@ object BusinessManager {
      */
     fun connectDock(isNeedInit: Boolean = false) {
         val dockData = SPUtils.getDockConfig(SIKCore.getApplication())
-        LogUtil.i("基座数据:${dockData}")
+        LogUtil.i("connectDock $isNeedInit 基座数据:${dockData}")
         if (dockData?.isEmpty() == true || dockData == "[]") return
-        if (canManager == null) {
-            canManager = CanHardwareHelper()
-            // CAN总线连接和监听
-            canManager?.interruptReadTrashBinStatus(true)
-            canManager?.connectAndAddListener()
-            CanHelper.addDeviceChangeListener(this) { canDeviceStatusHandle(it) }
+        if (!isCanInit) {
+            isCanInit = true
+            HardwareMode.getCurrentHardwareMode().interruptReadTrashBinStatus(true)
+            HardwareMode.getCurrentHardwareMode().connectAndAddListener()
+            registerMainListener()
         }
-        // 是否需要初始化Dock数据
-        // if (isNeedInit) initDevicesStatus()
     }
 
     /**
      * 断开底座链接
      */
     fun disconnectDock() {
-        canManager?.disconnect()
+        // 取消所有监听
+        listeners.clear()
     }
 
     /**
@@ -386,9 +360,6 @@ object BusinessManager {
                 // TODO 物资柜主控板
             }
         }
-        Executor.delayOnMain(200) {
-            listeners.forEach { it.callBack(res) }
-        }
         Executor.delayOnMain(200) {
             if (ISCSDomainData.isDeviceRegistration) {
                 initListener?.invoke()
@@ -403,10 +374,9 @@ object BusinessManager {
      */
     private fun canDeviceKeyHandler(keyBean: DeviceModel.DeviceKey) {
         if (!keyBean.deviceChange) return
-        Log.i("Manager", "钥匙状态变化canDeviceKeyHandler:$keyBean")
+        LogUtil.i("canDeviceKeyHandler $keyBean")
         if (keyBean.isExist) {
-            val req = CanCommands.forDevice(keyBean.nodeId)
-                .let { if (keyBean.id == 0) it.getLeftRfid() else it.getRightRfid() }
+            val req = CanCommands.forDevice(keyBean.nodeId).let { if (keyBean.id == 0) it.getLeftRfid() else it.getRightRfid() }
             CanHelper.readFrom(req) { res ->
                 val rfidData = res?.payload ?: byteArrayOf()
                 if (!ISCSDomainData.isDeviceRegistration) {
@@ -416,14 +386,14 @@ object BusinessManager {
                     ) {}
                 }
                 if (rfidData.size < 4) {
-                    Log.e("Manager", "Key rfid error")
+                    LogUtil.e("Key rfid error")
                     keyBean.deviceChange = false
                     return@readFrom
                 }
                 val rfid = rfidData.toHexFromLe()
-                Log.i("Manager", "读取到的rfid:$rfid")
+                LogUtil.i("读取到的rfid:$rfid")
                 keyBean.rfid = rfid
-                Log.i("Manager", "更新rfid完成:$keyBean")
+                LogUtil.i("更新rfid完成:$keyBean")
 
                 ThreadUtils.runOnIO {
                     val slotStatus = async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_SLOT_STATUS) }
@@ -443,27 +413,22 @@ object BusinessManager {
                     // 锁钥匙未异常正常请求锁数据,关锁
                     if (rfid in (keyData?.records?.filter { it.exStatus == keyStatus.find { it.dictLabel == "异常" }?.dictValue }
                             ?.map { it.keyNfc }?.toMutableList() ?: mutableListOf())) {
-                        ToastUtils.tip(
-                            MyApplication.instance?.applicationContext!!.getString(
-                                R.string.key_exception_tag
-                            )
-                        )
+                        ToastUtils.tip(MyApplication.instance?.applicationContext!!.getString(R.string.key_exception_tag))
                     } else if (slotsPage?.records?.filter {
                             it.slotType == slotTypeList.find { d -> d.dictLabel == "钥匙" }?.dictValue && it.status == slotStatusList.find { d -> d.dictLabel == "异常" }?.dictValue
                         }
                             ?.find { it.row?.toInt() == keyBean.nodeId && it.col?.toInt() == (keyBean.nodeId + (keyBean.id) * 2 + 1) } != null) {
-                        ToastUtils.tip(
-                            MyApplication.instance?.applicationContext!!.getString(
-                                R.string.slot_exception_tag
-                            )
-                        )
+                        ToastUtils.tip(MyApplication.instance?.applicationContext!!.getString(R.string.slot_exception_tag))
                     } else {
+                        HardwareMode.getCurrentHardwareMode().updateKeyRfid(keyBean.nodeId, keyBean.id, rfid)
                         val ctrl = CanCommands.forDevice(keyBean.nodeId).controlLatch(keyBean.id, 1)
                         CanHelper.writeTo(ctrl) { _ ->
                             NetApi.getKeyInfo(rfid) {
-                                // TODO QUEST ModBusController.updateKeyNewHardware(dockBean.addr, true, it == null)
+                                HardwareMode.getCurrentHardwareMode().updateKeyNewHardware(keyBean.nodeId, keyBean.id, it == null)
                                 if (it != null && !it.macAddress.isNullOrEmpty()) {
-                                    keyBean.mac = it.macAddress
+                                    keyBean.mac = it.macAddress ?: ""
+                                    HardwareMode.getCurrentHardwareMode().updateKeyMac(keyBean.nodeId, keyBean.id, it.macAddress!!)
+                                    HardwareMode.getCurrentHardwareMode().updateKeyReadyStatus(it.macAddress, false, 5)
                                 } else {
                                     LogUtil.e("Get key info fail : $rfid")
                                     if (!ISCSDomainData.isDeviceRegistration) {
@@ -472,14 +437,29 @@ object BusinessManager {
                                     val unlock = CanCommands.forDevice(keyBean.nodeId).controlLatch(keyBean.id, 0)
                                     CanHelper.writeTo(unlock) {}
                                 }
+                                Executor.delayOnMain(200) {
+                                    try {
+                                        listeners.forEach { it.callBack(listOf(keyBean)) }
+                                    } finally {
+                                        keyBean.deviceChange = false
+                                    }
+                                }
                             }
                         }
                     }
                 }
             }
         } else if (!keyBean.isCharging) {
-            unregisterConnectListener(keyBean.mac)
+            if (keyBean.mac.isNullOrEmpty()) unregisterConnectListener(keyBean.mac)
+            keyBean.deviceChange = false
             sendEventMsg(MsgEvent(MSG_EVENT_DEVICE_TAKE_UPDATE, DeviceTakeUpdateMsg(DEVICE_TYPE_KEY, keyBean.rfid)))
+            Executor.delayOnMain(200) {
+                try {
+                    listeners.forEach { it.callBack(listOf(keyBean)) }
+                } catch (_: Exception) {
+
+                }
+            }
         }
     }
 
@@ -489,6 +469,7 @@ object BusinessManager {
      */
     private fun canDeviceLockHandler(lockBean: DeviceModel.CommonDevice) {
         if (!lockBean.deviceChange) return
+        LogUtil.i("canDeviceLockHandler $lockBean")
         if (lockBean.isExist) {
             val req = CanCommands.forDevice(lockBean.nodeId).getSlotRfid_1to5(lockBean.id)
             CanHelper.readFrom(req) { res ->
@@ -513,9 +494,8 @@ object BusinessManager {
                     val slotStatusList = slotStatus.await()
                     val slotTypeList = slotType.await()
 
-
                     NetApi.getIsLockPage { lockData ->
-                        //锁rfid未异常正常请求锁数据,关锁
+                        // 锁rfid未异常正常请求锁数据,关锁
                         if (rfid in (lockData?.records?.filter { it.exStatus == lockStatus.find { it.dictLabel == "异常" }?.dictValue }
                                 ?.map { it.lockNfc }?.toMutableList() ?: mutableListOf())) {
                             ToastUtils.tip(
@@ -538,8 +518,8 @@ object BusinessManager {
                                     NetApi.getLockStateByNfc(rfid) {
                                         if (it != 1) {
                                             val ctrl = CanCommands.forDevice(lockBean.nodeId).controlOne_1to5(lockBean.id, true)
+                                            // 上报锁具信息
                                             CanHelper.writeTo(ctrl) {
-                                                // 上报锁具信息
                                                 NetApi.updateLockReturn(rfid, MyApplication.instance!!.serialNo()) {}
                                             }
                                         } else {
@@ -547,6 +527,13 @@ object BusinessManager {
                                         }
                                     }
                                 }
+                                Executor.delayOnMain(200) {
+                                    try {
+                                        listeners.forEach { it.callBack(listOf(lockBean)) }
+                                    } finally {
+                                        lockBean.deviceChange = false
+                                    }
+                                }
                             }
                         }
                     }
@@ -555,7 +542,14 @@ object BusinessManager {
         } else {
             LogUtil.i("挂锁取出-:${lockBean.rfid}")
             sendEventMsg(MsgEvent(MSG_EVENT_DEVICE_TAKE_UPDATE, DeviceTakeUpdateMsg(DEVICE_TYPE_LOCK, lockBean.rfid)))
-            lockBean.deviceChange = false // 取出分支可在同步处理后立即归零
+            lockBean.deviceChange = false
+            Executor.delayOnMain(200) {
+                try {
+                    listeners.forEach { it.callBack(listOf(lockBean)) }
+                } catch (_: Exception) {
+
+                }
+            }
         }
     }
 
@@ -723,7 +717,7 @@ object BusinessManager {
                 LogUtil.i("锁柜id:${SPUtils.getHardwareId()}")
                 // —— 在 Default 线程做计算密集操作 ——
                 val lockMap = withContext(Dispatchers.Default) {
-                    ModBusController.getLocks(
+                    CanHelper.getLocks(
                         needLockCount,
                         locksPage?.records?.filter { it.hardwareId != null && it.hardwareId == SPUtils.getHardwareId() }
                             ?.mapNotNull { it.lockNfc } ?: mutableListOf(),
@@ -740,7 +734,7 @@ object BusinessManager {
                 if (isNeedKey) {
                     val keyPage = withContext(Dispatchers.IO) { getKeyPage() }
                     keyPair = withContext(Dispatchers.Default) {
-                        getOneKey(
+                        CanHelper.getOneKey(
                             slotsPage?.records?.filter {
                                 it.slotType == slotTypeList.find { d -> d.dictLabel == "钥匙" }?.dictValue && it.status == slotStatusList.find { d -> d.dictLabel == "异常" }?.dictValue
                             }?.toMutableList() ?: mutableListOf(),
@@ -768,11 +762,7 @@ object BusinessManager {
     /**
      * 注册连接监听
      */
-    fun registerConnectListener(
-        mac: String, connectNow: Boolean = false, isSend: Boolean = true, callBack: ((
-            Boolean, BleBean?
-        ) -> Unit)? = null
-    ) {
+    fun registerConnectListener(mac: String, connectNow: Boolean = false, isSend: Boolean = true, callBack: ((Boolean, BleBean?) -> Unit)? = null) {
         BleConnectionManager.registerConnectListener(mac, connectNow, isSend, callBack)
     }
 
@@ -866,10 +856,7 @@ object BusinessManager {
             getBleDeviceByMac(mac)?.bleDevice?.let {
                 LogUtil.i("开始读取作业票")
                 BleReturnDispatcher.busy(mac)
-                getTicketStatusWithRetry(
-                    it,
-                    isNeedLoading
-                )
+                getTicketStatusWithRetry(it, isNeedLoading)
             }
         } else {
             //如果连接在待发列表则断开连接,重新使用归还队列连接之后检查
@@ -879,11 +866,7 @@ object BusinessManager {
                     getTicketStatusBusiness(mac, isNeedLoading)
                 }
             }
-            if (isNeedLoading) sendEventMsg(
-                MsgEvent(
-                    MSG_EVENT_LOADING, LoadingMsg(false, null, false)
-                )
-            )
+            if (isNeedLoading) sendEventMsg(MsgEvent(MSG_EVENT_LOADING, LoadingMsg(false, null, false)))
         }
     }
 
@@ -1016,7 +999,7 @@ object BusinessManager {
             // TODO 挂锁数组
             if (!lockList.isNullOrEmpty()) {
                 bo.lockList = mutableListOf()
-                lockList.forEachIndexed { index, s ->
+                lockList?.forEachIndexed { index, s ->
                     if (s.isNullOrEmpty()) {
                         LogUtil.w("Lock nfc is null or empty")
                         return@forEachIndexed
@@ -1055,40 +1038,19 @@ object BusinessManager {
         return jsonStr
     }
 
-    fun handleRsp(
-        bleBean: BleBean,
-        byteArray: ByteArray,
-        isNeedLoading: Boolean = false,
-        prepareDoneCallBack: ((Boolean, BleBean?) -> Unit)?
-    ) {
-        // TODO Token校验
-//        val len = byteArray[2].toInt()
-//        val token = byteArray.copyOfRange(len + 7, len + 11)
-//        if (token.contentEquals(bleBean.token)) {
-//            LogUtil.i("Token is right")
-//        } else {
-//            LogUtil.e("Token is wrong")
-//        }
+    fun handleRsp(bleBean: BleBean, byteArray: ByteArray, isNeedLoading: Boolean = false, prepareDoneCallBack: ((Boolean, BleBean?) -> Unit)?) {
         when {
             // 获取令牌
-            byteArray.startsWith(BleConst.RSP_GET_TOKEN) -> BleCmdManager.handleToken(
-                bleBean.bleDevice, byteArray
-            ) { isSuccess ->
+            byteArray.startsWith(BleConst.RSP_GET_TOKEN) -> BleCmdManager.handleToken(bleBean.bleDevice, byteArray) { isSuccess ->
                 if (isSuccess) {
-                    //尝试使用命令作为心跳 ,获取token完成之后就要建立心跳了
-                    BleCmdManager.getPower(
-                        bleBean.bleDevice.mac, null
-                    )
+                    // 尝试使用命令作为心跳 ,获取token完成之后就要建立心跳了
+                    BleCmdManager.getPower(bleBean.bleDevice.mac, null)
                 }
             }
             // 工作模式切换
             byteArray.startsWith(BleConst.RSP_SWITCH_MODE) -> {
                 handleSwitchModeResult(byteArray, isNeedLoading) { res, job ->
-                    sendEventMsg(
-                        MsgEvent(
-                            MSG_EVENT_SWITCH_MODE, SwitchModeMsg(job.toInt(), res.toInt(), bleBean)
-                        )
-                    )
+                    sendEventMsg(MsgEvent(MSG_EVENT_SWITCH_MODE, SwitchModeMsg(job.toInt(), res.toInt(), bleBean)))
                 }
             }
             // 工作票下发
@@ -1096,23 +1058,24 @@ object BusinessManager {
                 bleBean, byteArray, isNeedLoading
             )
             // 获取设备当前状态
-            byteArray.startsWith(BleConst.RSP_CURRENT_STATUS) -> BleCmdManager.handleCurrentStatus(
-                byteArray
-            ) {
+            byteArray.startsWith(BleConst.RSP_CURRENT_STATUS) -> BleCmdManager.handleCurrentStatus(byteArray) {
                 sendEventMsg(MsgEvent(MSG_EVENT_CURRENT_MODE, CurrentModeMsg(bleBean, it)))
             }
             // 获取设备工作票完成情况
             byteArray.startsWith(BleConst.RSP_WORK_TICKET_RESULT) && byteArray[3] == 0x02.toByte() -> handleTicketStatus(
-                bleBean.bleDevice, byteArray, isNeedLoading
+                bleBean.bleDevice,
+                byteArray,
+                isNeedLoading
             )
-
+            // 查询电池电量
             byteArray.startsWith(BleConst.RSP_POWER_STATUS) -> {
                 val power = byteArray[4].toInt()
-                ModBusController.updateKeyPower(power, bleBean.bleDevice.mac)
+                HardwareMode.getCurrentHardwareMode().updateKeyPower(power, bleBean.bleDevice.mac)
                 LogUtil.i("电量(${bleBean.bleDevice.mac}):${power}")
                 prepareDoneCallBack?.invoke(true, bleBean)
-                if (power < 50) {//如果电量小于50就打开仓位充电
-                    ModBusController.controlKeyCharge(true, bleBean.bleDevice.mac) {
+                if (power < 50) {
+                    // 如果电量小于50就打开仓位充电
+                    HardwareMode.getCurrentHardwareMode().controlKeyCharge(true, bleBean.bleDevice.mac) {
                         LogUtil.i("钥匙: ${bleBean.bleDevice.mac} 开始充电")
                     }
                 }
@@ -1134,24 +1097,14 @@ object BusinessManager {
             if (res == 0x01.toByte() && job == 0x01.toByte()) {
                 LogUtil.i("切换工作模式成功")
                 if (isNeedLoading) sendEventMsg(
-                    MsgEvent(
-                        MSG_EVENT_LOADING, LoadingMsg(false, "切换工作模式成功", null)
-                    )
+                    MsgEvent(MSG_EVENT_LOADING, LoadingMsg(false, "切换工作模式成功", null))
                 )
             } else if (res == 0x01.toByte() && job == 0x02.toByte()) {
                 LogUtil.i("切换待机模式成功")
-                if (isNeedLoading) sendEventMsg(
-                    MsgEvent(
-                        MSG_EVENT_LOADING, LoadingMsg(false, "切换待机模式成功", null)
-                    )
-                )
+                if (isNeedLoading) sendEventMsg(MsgEvent(MSG_EVENT_LOADING, LoadingMsg(false, "切换待机模式成功", null)))
             } else {
                 LogUtil.e("切换模式失败 : ${job.toInt()} - ${res.toInt()}")
-                if (isNeedLoading) sendEventMsg(
-                    MsgEvent(
-                        MSG_EVENT_LOADING, LoadingMsg(false, null, null)
-                    )
-                )
+                if (isNeedLoading) sendEventMsg(MsgEvent(MSG_EVENT_LOADING, LoadingMsg(false, null, null)))
             }
             callBack?.invoke(res, job)
         }
@@ -1166,9 +1119,7 @@ object BusinessManager {
     ) {
         BleCmdManager.handleWorkTicketResult(bleBean, byteArray) { isSuccess, rst ->
             if (isNeedLoading) sendEventMsg(
-                MsgEvent(
-                    MSG_EVENT_LOADING, LoadingMsg(false, null, null)
-                )
+                MsgEvent(MSG_EVENT_LOADING, LoadingMsg(false, null, null))
             )
             if (isSuccess) {
                 // 下发完毕,切换工作模式
@@ -1193,7 +1144,7 @@ object BusinessManager {
                 } else {
                     ToastUtils.tip(R.string.send_ticket_fail)
                     LogUtil.e("Send ticket fail")
-                    ModBusController.getKeyByMac(bleBean.bleDevice.mac)?.let { itKey ->
+                    HardwareMode.getCurrentHardwareMode().getKeyBeanByMac(bleBean.bleDevice.mac)?.let { itKey ->
                         mDeviceTakeList.removeIf { it.deviceType == DEVICE_TYPE_KEY && it.nfc == itKey.rfid }
                     }
                 }
@@ -1213,7 +1164,7 @@ object BusinessManager {
         LogUtil.i("getCurrentStatus - ${bleDevice.mac} - from : $from")
         var isTimeout = true
         // 加1秒防止早于onWriteFailure开始处理导致多次处理
-        Executor.delayOnMain((BleUtil.OPERATE_TIMEOUT + 1).toLong()) {
+        Executor.delayOnMain((BleUtil.OPERATE_TIMEOUT + 1)) {
             if (isTimeout) {
                 LogUtil.e("getCurrentStatus timeout : mac = ${bleDevice.mac}, retryCount = $retryCount")
                 if (retryCount > 0) {
@@ -1224,23 +1175,20 @@ object BusinessManager {
                             BleSendDispatcher.scheduleDisconnect(bleDevice.mac)
                         }
                         BleSendDispatcher.submit(bleDevice.mac) {
-                            getCurrentStatus(
-                                from, bleDevice, retryCount - 1, timeoutCallBack
-                            )
+                            getCurrentStatus(from, bleDevice, retryCount - 1, timeoutCallBack)
                         }
                     } else {
                         BleReturnDispatcher.clearNoBusyConnectedDevice()
                         BleReturnDispatcher.scheduleDisconnect(bleDevice.mac)
                         BleReturnDispatcher.submit(bleDevice.mac) {
-                            getCurrentStatus(
-                                from, bleDevice, retryCount - 1, timeoutCallBack
-                            )
+                            getCurrentStatus(from, bleDevice, retryCount - 1, timeoutCallBack)
                         }
                     }
                 } else {
                     BleSendDispatcher.scheduleDisconnect(bleDevice.mac)
                     BleReturnDispatcher.scheduleDisconnect(bleDevice.mac)
-                    ModBusController.getKeyByMac(bleDevice.mac)?.rfid?.let {
+                    val keyBean = HardwareMode.getCurrentHardwareMode().getKeyBeanByMac(bleDevice.mac)
+                    keyBean?.rfid?.let {
                         addExceptionKey(it)
                         timeoutCallBack?.invoke(true)
                     }
@@ -1274,10 +1222,7 @@ object BusinessManager {
                 LogUtil.i("getCurrentStatus fail : ${bleDevice.mac}")
                 isTimeout = false
                 Executor.delayOnMain(1000) {
-                    getCurrentStatus(
-                        from, bleDevice,
-                        retryCount - 1, timeoutCallBack = timeoutCallBack
-                    )
+                    getCurrentStatus(from, bleDevice, retryCount - 1, timeoutCallBack = timeoutCallBack)
                 }
             }
         })
@@ -1393,18 +1338,13 @@ object BusinessManager {
                 if (finishedStatus.first) {
                     Executor.delayOnMain(500) {
                         handleKeyReturn(bleDevice, workTicketGetBO, finishedStatus.second)
-                        //检查钥匙是否代取,如果是的话给钥匙
-                        val keyBean = ModBusController.getKeyByMac(bleDevice.mac)
-                        mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && it.nfc == keyBean?.rfid }
-                            ?.let { itKey ->
-                                LogUtil.i("检查到存在待取钥匙:${itKey}")
-                                sendLoadingEventMsg(
-                                    MyApplication.instance?.applicationContext!!.getString(
-                                        R.string.ble_connecting
-                                    )
-                                )
-                                handleGiveKey(itKey)
-                            }
+                        // 检查钥匙是否代取,如果是的话给钥匙
+                        val keyBean = HardwareMode.getCurrentHardwareMode().getKeyBeanByMac(bleDevice.mac)
+                        mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && it.nfc == keyBean?.rfid }?.let { itKey ->
+                            LogUtil.i("检查到存在待取钥匙:${itKey}")
+                            sendLoadingEventMsg(MyApplication.instance?.applicationContext!!.getString(R.string.ble_connecting))
+                            handleGiveKey(itKey)
+                        }
                     }
                 } else {
                     // 当前策略:作业票未完成禁止归还钥匙
@@ -1412,14 +1352,10 @@ object BusinessManager {
                         showKeyReturnUploadDataForceDialog({
                             handleKeyReturn(bleDevice, workTicketGetBO, finishedStatus.second)
                             //检查钥匙是否代取,如果是的话给钥匙
-                            val keyBean = ModBusController.getKeyByMac(bleDevice.mac)
+                            val keyBean = HardwareMode.getCurrentHardwareMode().getKeyBeanByMac(bleDevice.mac)
                             mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && it.nfc == keyBean?.rfid }
                                 ?.let { itKey ->
-                                    sendLoadingEventMsg(
-                                        MyApplication.instance?.applicationContext!!.getString(
-                                            R.string.ble_connecting
-                                        )
-                                    )
+                                    sendLoadingEventMsg(MyApplication.instance?.applicationContext!!.getString(R.string.ble_connecting))
                                     handleGiveKey(itKey)
                                 }
                         }) {
@@ -1443,20 +1379,17 @@ object BusinessManager {
     /**
      * ticketFinished主要是后端的作业票是否已经结束,结束了,就直接修改状态就好了
      */
-    private fun handleKeyReturn(
-        bleDevice: BleDevice, workTicketGetBO: WorkTicketGetBO?, ticketFinished: Boolean
-    ) {
-        val dock = ModBusController.getDockByKeyMac(bleDevice.mac)
-        val keyBean = dock?.getKeyList()?.find { it.mac == bleDevice.mac }
-        keyBean?.let {
-            ModBusController.controlKeyBuckle(false, keyBean.isLeft, dock.addr)
-        }
+    private fun handleKeyReturn(bleDevice: BleDevice, workTicketGetBO: WorkTicketGetBO?, ticketFinished: Boolean) {
+        val dockBean = HardwareMode.getCurrentHardwareMode().getKeyDockData().find { dock -> dock.keyData.find { it.mac == bleDevice.mac } != null }
+        val keyBean = dockBean?.keyData?.find { it.mac == bleDevice.mac }
+        val opt = HardwareMode.getCurrentHardwareMode()
+        opt.controlKeyBuckle(false, bleDevice.mac)
         if (ticketFinished) {
             mDeviceTakeList.removeIf { it.nfc == keyBean?.rfid }
             switchReadyMode(bleDevice)
         } else {
             // 上报隔离点状态
-            val keyNfc = ModBusController.getKeyByMac(bleDevice.mac)?.rfid ?: "key rfid lost"
+            val keyNfc = opt.getKeyBeanByMac(bleDevice.mac)?.rfid ?: "key rfid lost"
             workTicketGetBO?.data?.forEach { data ->
                 val updateList = mutableListOf<LockPointUpdateReqVO>()
                 data.dataList?.filter { it.closed == 1 && it.status == it.target }
@@ -1514,13 +1447,11 @@ object BusinessManager {
                                                 )
                                             }
                                     } else {
-                                        val dock = ModBusController.getDockByKeyMac(bleDevice.mac)
-                                        val keyBean =
-                                            dock?.getKeyList()?.find { it.mac == bleDevice.mac }
+                                        val dockBean = HardwareMode.getCurrentHardwareMode().getKeyDockData()
+                                            .find { dock -> dock.keyData.find { it.mac == bleDevice.mac } != null }
+                                        val keyBean = dockBean?.keyData?.find { it.mac == bleDevice.mac }
                                         keyBean?.let {
-                                            ModBusController.controlKeyBuckle(
-                                                true, keyBean.isLeft, dock.addr
-                                            )
+                                            opt.controlKeyBuckle(true, keyBean.idx, keyBean.addr)
                                         }
                                     }
                                 }
@@ -1546,21 +1477,10 @@ object BusinessManager {
      * 钥匙归还
      */
     private fun keyReturn(ticketId: Long, keyNfc: String) {
-        NetApi.updateKeyReturn(
-            ticketId,
-            keyNfc,
-            MyApplication.instance!!.serialNo()
-        ) { isSuccess, msg, code ->
+        NetApi.updateKeyReturn(ticketId, keyNfc, MyApplication.instance!!.serialNo()) { isSuccess, msg, code ->
             if (!isSuccess) {
-                if (msg == MyApplication.instance?.applicationContext!!.getString(
-                        R.string.ticket_lost
-                    )
-                ) {
-                    sendEventMsg(
-                        MsgEvent(
-                            MsgEventConstants.MSG_EVENT_TICKET_FINISHED, null
-                        )
-                    )
+                if (msg == MyApplication.instance?.applicationContext!!.getString(R.string.ticket_lost)) {
+                    sendEventMsg(MsgEvent(MsgEventConstants.MSG_EVENT_TICKET_FINISHED, null))
                 }
                 SPUtils.clearUpdateKeyReturn(MyApplication.instance!!)
                 ToastUtils.tip(R.string.key_return_success)
@@ -1713,31 +1633,23 @@ object BusinessManager {
         "$nodeId-$deviceType-$id"
 
     private fun handleDeviceTake(deviceTakeUpdateBO: DeviceTakeUpdateMsg, rfid: String? = null) {
-        LogUtil.i("$deviceTakeUpdateBO")
+        LogUtil.i("handleDeviceTake $deviceTakeUpdateBO")
         when (deviceTakeUpdateBO.deviceType) {
             // 钥匙
             DEVICE_TYPE_KEY -> {
                 mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && it.nfc == deviceTakeUpdateBO.nfc }
                     ?.let { info ->
-                        if (mDeviceTakeList.any { it.deviceType == DeviceConst.DEVICE_TYPE_LOCK && it.ticketId == info.ticketId }) {
+                        if (mDeviceTakeList.any { it.deviceType == DEVICE_TYPE_LOCK && it.ticketId == info.ticketId }) {
                             LogUtil.i("存在未取出的挂锁,不继续操作")
                             return
                         }
                         sendLoadingEventMsg(null, false)
-                        NetApi.updateKeyTake(
-                            info.ticketId, info.nfc, MyApplication.instance?.serialNo()!!
-                        ) { isSuccess ->
+                        NetApi.updateKeyTake(info.ticketId, info.nfc, MyApplication.instance?.serialNo()!!) { isSuccess ->
                             if (isSuccess) {
                                 mDeviceTakeList.removeIf {
-                                    it.deviceType == DEVICE_TYPE_KEY && it.nfc == info.nfc && it.ticketId ==
-                                            info.ticketId
+                                    it.deviceType == DEVICE_TYPE_KEY && it.nfc == info.nfc && it.ticketId == info.ticketId
                                 }
-                                sendEventMsg(
-                                    MsgEvent(
-                                        MSG_EVENT_UPDATE_TICKET_PROGRESS,
-                                        UpdateTicketProgressMsg(info.ticketId)
-                                    )
-                                )
+                                sendEventMsg(MsgEvent(MSG_EVENT_UPDATE_TICKET_PROGRESS, UpdateTicketProgressMsg(info.ticketId)))
                                 // 钥匙取出之后重新再连一把钥匙待机
                                 HardwareMode.getCurrentHardwareMode().getKeyMacByRfid(info.nfc)?.let {
                                     HardwareMode.getCurrentHardwareMode().getKeyBeanByMac(it)?.let { keyBean ->
@@ -1747,9 +1659,6 @@ object BusinessManager {
                                 }
                                 // 待机数不够就再连一把,但不能是原来那把
                                 HardwareMode.getCurrentHardwareMode().getKeyMacByRfid(info.nfc)?.let {
-                                    HardwareMode.getCurrentHardwareMode().getKeyBeanByMac(it)?.let { keyBean ->
-                                        HandlerGate.leave(devKey(keyBean.addr, keyBean.type, keyBean.idx))
-                                    }
                                     ThreadUtils.runOnIO { checkMyTodoForHandleKey(it) }
                                 }
                             }
@@ -1760,7 +1669,15 @@ object BusinessManager {
             DEVICE_TYPE_LOCK -> {
                 mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_LOCK && it.nfc == deviceTakeUpdateBO.nfc }
                     ?.let { info ->
-                        NetApi.updateLockTake(mutableListOf(LockTakeUpdateReqVO(info.ticketId, info.nfc, MyApplication.instance?.serialNo()!!))) { isSuccess ->
+                        NetApi.updateLockTake(
+                            mutableListOf(
+                                LockTakeUpdateReqVO(
+                                    info.ticketId,
+                                    info.nfc,
+                                    MyApplication.instance?.serialNo()!!
+                                )
+                            )
+                        ) { isSuccess ->
                             Executor.runOnMain {
                                 if (isSuccess == false) {
                                     LogUtil.e("Lock take report fail")
@@ -1792,13 +1709,10 @@ object BusinessManager {
                                     return@runOnMain
                                 }
                                 // 检查有无当前工作票的钥匙
-                                mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && it.ticketId == info.ticketId }
-                                    ?.let { itKey ->
-                                        sendLoadingEventMsg(MyApplication.instance?.applicationContext!!.getString(
-                                                R.string.ble_connecting
-                                            ))
-                                        handleGiveKey(itKey)
-                                    }
+                                mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && it.ticketId == info.ticketId }?.let { itKey ->
+                                    sendLoadingEventMsg(MyApplication.instance?.applicationContext!!.getString(R.string.ble_connecting))
+                                    handleGiveKey(itKey)
+                                }
                             }
                         }
                     }
@@ -1810,61 +1724,40 @@ object BusinessManager {
      * 分配钥匙
      */
     private fun handleGiveKey(deviceTakeUpdateBO: DeviceTakeUpdateBO) {
-        getBleDeviceByMac(ModBusController.getKeyByRfid(deviceTakeUpdateBO.nfc)?.mac)?.let {
-            getCurrentStatus(
-                2,
-                getBleDeviceByMac(ModBusController.getKeyByRfid(deviceTakeUpdateBO.nfc)?.mac)!!.bleDevice
-            ) {
-                if (!it) {
-                    return@getCurrentStatus
-                }
+        LogUtil.i("handleGiveKey $deviceTakeUpdateBO")
+        val optDevice = HardwareMode.getCurrentHardwareMode()
+        val keyMac = optDevice.getKeyMacByRfid(deviceTakeUpdateBO.nfc)
+        getBleDeviceByMac(keyMac)?.let {
+            getCurrentStatus(2, getBleDeviceByMac(keyMac)!!.bleDevice) {
+                if (!it) return@getCurrentStatus
                 LogUtil.w("handleGiveKey timeout")
                 removeDeviceTake(DEVICE_TYPE_KEY, deviceTakeUpdateBO.nfc)
-                checkEquipCount(0, true) { keyPair, lockMap ->
+                checkEquipCount(0, true) { keyPair, _ ->
                     if (keyPair == null) {
                         ThreadUtils.runOnMain {
                             val tipDialog = TipDialog(SIKCore.getApplication())
-                            tipDialog.setTip(
-                                SIKCore.getApplication().getString(R.string.key_take_error_tip)
-                            )
+                            tipDialog.setTip(SIKCore.getApplication().getString(R.string.key_take_error_tip))
                             tipDialog.setConfirmListener {
                                 tipDialog.dismiss()
-                                sendEventMsg(
-                                    MsgEvent(
-                                        MSG_EVENT_DEVICE_EXCEPTION,
-                                        DeviceExceptionMsg(DEVICE_TYPE_KEY, deviceTakeUpdateBO.nfc)
-                                    )
-                                )
+                                sendEventMsg(MsgEvent(MSG_EVENT_DEVICE_EXCEPTION, DeviceExceptionMsg(DEVICE_TYPE_KEY, deviceTakeUpdateBO.nfc)))
                             }
                             tipDialog.show()
                         }
                     } else {
-                        addDeviceTake(
-                            DEVICE_TYPE_KEY, deviceTakeUpdateBO.ticketId, keyPair.second?.rfid!!
-                        )
-                        handleGiveKey(
-                            DeviceTakeUpdateBO(
-                                DEVICE_TYPE_KEY, deviceTakeUpdateBO.ticketId, keyPair.second?.rfid!!
-                            )
-                        )
+                        addDeviceTake(DEVICE_TYPE_KEY, deviceTakeUpdateBO.ticketId, keyPair.second?.rfid!!)
+                        handleGiveKey(DeviceTakeUpdateBO(DEVICE_TYPE_KEY, deviceTakeUpdateBO.ticketId, keyPair.second?.rfid!!))
                     }
                 }
             }
         } ?: run {
             ThreadUtils.runOnMain {
                 ActivityTracker.getCurrentActivity()?.let {
+                    // 钥匙分配失败
                     val tipDialog = TipDialog(it)
-                    tipDialog.setTip(
-                        SIKCore.getApplication().getString(R.string.key_take_error_tip)
-                    )
+                    tipDialog.setTip(SIKCore.getApplication().getString(R.string.key_take_error_tip))
                     tipDialog.setConfirmListener {
                         tipDialog.dismiss()
-                        sendEventMsg(
-                            MsgEvent(
-                                MSG_EVENT_DEVICE_EXCEPTION,
-                                DeviceExceptionMsg(DEVICE_TYPE_KEY, deviceTakeUpdateBO.nfc)
-                            )
-                        )
+                        sendEventMsg(MsgEvent(MSG_EVENT_DEVICE_EXCEPTION, DeviceExceptionMsg(DEVICE_TYPE_KEY, deviceTakeUpdateBO.nfc)))
                     }
                     tipDialog.show()
                 }
@@ -1876,6 +1769,7 @@ object BusinessManager {
      * 根据当前模式进行处理
      */
     private fun handleCurrentMode(currentModeMsg: CurrentModeMsg) {
+        LogUtil.i("handleCurrentMode ${currentModeMsg.mode}")
         when (currentModeMsg.mode) {
             // 工作模式
             0x01.toByte() -> {
@@ -1885,12 +1779,12 @@ object BusinessManager {
             // 待机模式
             0x02.toByte() -> {
                 // 根据情况看是否需要下发工作票
-                ModBusController.getKeyByMac(currentModeMsg.bleBean.bleDevice.mac)?.let { key ->
+                val opt = HardwareMode.getCurrentHardwareMode()
+                opt.getKeyBeanByMac(currentModeMsg.bleBean.bleDevice.mac)?.let { key ->
                     // 判断是否有待取的钥匙
-                    val updateBo =
-                        mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && key.rfid == it.nfc }
+                    val updateBo = mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && key.rfid == it.nfc }
                     if (mDeviceTakeList.any { it.deviceType == DEVICE_TYPE_LOCK && it.ticketId == updateBo?.ticketId }) {
-                        //todo 如果有钥匙待取但是对应的作业票的锁还有的,就不发
+                        LogUtil.i("没有代取的钥匙,不做继续处理")
                         return
                     }
                     updateBo?.let { itBO ->
@@ -1908,26 +1802,21 @@ object BusinessManager {
                                 checkAndSendTicket(currentModeMsg, itBO)
                             }
                         }
-
                     } ?: let {
-                        ModBusController.updateKeyReadyStatus(
-                            currentModeMsg.bleBean.bleDevice.mac, true, 4
-                        )
+                        opt.updateKeyReadyStatus(currentModeMsg.bleBean.bleDevice.mac, true, 4)
                         sendLoadingEventMsg(null, false)
                         BleCmdManager.shutdownOrRebootReq(mac = currentModeMsg.bleBean.bleDevice.mac)
                         BleReturnDispatcher.scheduleDisconnect(currentModeMsg.bleBean.bleDevice.mac)
-                        //连上之后没有工作票要下发就断开 看是否还有设备等待连接,没有就不断开,有就让路,一般是初始化的时候
+                        // 连上之后没有工作票要下发就断开 看是否还有设备等待连接,没有就不断开,有就让路,一般是初始化的时候
                         ThreadUtils.runOnIO {
                             checkMyTodoForHandleKey(currentModeMsg.bleBean.bleDevice.mac)
                         }
                     }
                 } ?: let {
-                    ModBusController.updateKeyReadyStatus(
-                        currentModeMsg.bleBean.bleDevice.mac, true, 4
-                    )
+                    opt.updateKeyReadyStatus(currentModeMsg.bleBean.bleDevice.mac, true, 4)
                     sendLoadingEventMsg(null, false)
                     BleReturnDispatcher.scheduleDisconnect(currentModeMsg.bleBean.bleDevice.mac)
-                    //连上之后没有工作票要下发就断开 看是否还有设备等待连接,没有就不断开,有就让路,一般是初始化的时候
+                    // 连上之后没有工作票要下发就断开 看是否还有设备等待连接,没有就不断开,有就让路,一般是初始化的时候
                     ThreadUtils.runOnIO {
                         checkMyTodoForHandleKey(currentModeMsg.bleBean.bleDevice.mac)
                     }
@@ -1935,10 +1824,7 @@ object BusinessManager {
             }
             // 故障模式
             0x03.toByte() -> {
-                // TODO 上报?
-                ToastUtils.tip(
-                    "${currentModeMsg.bleBean.bleDevice.mac} : " + "${CommonUtils.getStr(R.string.key_is_in_failure_mode)}"
-                )
+                ToastUtils.tip("${currentModeMsg.bleBean.bleDevice.mac} : " + "${CommonUtils.getStr(R.string.key_is_in_failure_mode)}")
             }
         }
     }
@@ -2087,38 +1973,7 @@ object BusinessManager {
         reConnectKey()
         NetApi.logout()
         // 关所有有设备的卡扣
-        dockList.filter { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }
-            .forEach { dockBean ->
-                val hasLockIdxList =
-                    dockBean.getLockList().filter { it.isExist }.map { it.idx } as MutableList<Int>
-                val noLockIdxList =
-                    dockBean.getLockList().filter { !it.isExist }.map { it.idx } as MutableList<Int>
-                ModBusController.controlLockBuckle(false, dockBean.addr, hasLockIdxList)
-                ModBusController.controlLockBuckle(true, dockBean.addr, noLockIdxList)
-            }
-        dockList.filter { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }
-            .forEach { dockBean ->
-                dockBean.getKeyList().forEach { key ->
-                    if (key.isExist) {
-                        NetApi.getKeyInfo(key.rfid.toString()) {
-                            if (it != null && !it.macAddress.isNullOrEmpty()) {
-                                ModBusController.updateKeyMac(
-                                    dockBean.addr, key.isLeft, it.macAddress
-                                )
-                                ModBusController.controlKeyBuckle(
-                                    false, key.isLeft, dockBean.addr
-                                )
-                            } else {
-                                ModBusController.controlKeyBuckle(
-                                    true, key.isLeft, dockBean.addr
-                                )
-                            }
-                        }
-                    } else {
-                        ModBusController.controlKeyBuckle(true, key.isLeft, dockBean.addr)
-                    }
-                }
-            }
+        HardwareMode.getCurrentHardwareMode().allSlotOff()
         BleSendDispatcher.disconnectAll(60_0000L)
         sendLoadingEventMsg(null, false)
         context.startActivity(Intent(context, LoginActivity::class.java).apply {
@@ -2136,8 +1991,8 @@ object BusinessManager {
         mDeviceTakeList.clear()
         // 连接后直接切换待机模式,让钥匙作业票失效并且重新准备完毕
         keyList.forEach {
-            val mac = ModBusController.getKeyByRfid(it.nfc)?.mac
-            if (mac == null) {
+            val mac = HardwareMode.getCurrentHardwareMode().getKeyMacByRfid(it.nfc)
+            if (mac.isNullOrEmpty()) {
                 NetApi.getKeyInfo(it.nfc) { keyInfo ->
                     keyInfo?.macAddress?.let { itMac ->
                         registerConnectListener(itMac, isSend = true) { isDone, bleBean ->
@@ -2148,7 +2003,7 @@ object BusinessManager {
                     }
                 }
             } else {
-                registerConnectListener(mac, isSend = true) { isDone, bleBean ->
+                registerConnectListener(mac!!, isSend = true) { isDone, bleBean ->
                     if (isDone && bleBean != null) {
                         switchReadyMode(bleBean.bleDevice)
                     }

+ 1 - 1
app/src/main/java/com/grkj/iscs_mars/MyApplication.kt

@@ -53,7 +53,7 @@ class MyApplication : Application() {
         Token.clear(this)
 
         Executor.runOnIO {
-            BusinessManager.registerMainListener()
+            // BusinessManager.registerMainListener()
             WebSocketConfig.instance.connect()
         }
         LogUtil.i("App start : ${serialNo()}")

+ 1 - 61
app/src/main/java/com/grkj/iscs_mars/ble/BleCmdManager.kt

@@ -72,37 +72,6 @@ object BleCmdManager {
         return timeStampArr
     }
 
-    fun handleRsp(bleBean: BleBean, byteArray: ByteArray) {
-        when {
-            // 获取令牌
-            byteArray.startsWith(BleConst.RSP_GET_TOKEN) -> handleToken(
-                bleBean.bleDevice,
-                byteArray
-            )
-            // 工作模式切换
-            byteArray.startsWith(BleConst.RSP_SWITCH_MODE) -> handleSwitchModeResult(byteArray)
-            // 工作票下发
-            byteArray.startsWith(BleConst.RSP_SEND_WORK_TICKET) -> handleWorkTicketResult(
-                bleBean,
-                byteArray
-            )
-            // 获取设备当前状态
-            byteArray.startsWith(BleConst.RSP_CURRENT_STATUS) -> handleCurrentStatus(byteArray)
-            // 获取钥匙电量
-            byteArray.startsWith(BleConst.RSP_POWER_STATUS) -> handlePowerStatus(byteArray)
-            // 传输文件
-            byteArray.startsWith(BleConst.RSP_TRANSFER_FILE) && byteArray[3] == 0x01.toByte() -> handleFileRsp(
-                bleBean,
-                byteArray
-            )
-            // 获取固件版本号
-            byteArray.startsWith(BleConst.RSP_GET_VERSION) -> handleVersion(byteArray)
-            // 获取设备工作票完成情况
-            byteArray.startsWith(BleConst.RSP_WORK_TICKET_RESULT) && byteArray[3] == 0x02.toByte() ->
-                handleTicketStatus(bleBean.bleDevice, byteArray)
-        }
-    }
-
     /**
      * 获取令牌
      */
@@ -124,11 +93,7 @@ object BleCmdManager {
      *
      * @param callBack 是否成功
      */
-    fun handleToken(
-        bleDevice: BleDevice,
-        byteArray: ByteArray,
-        callBack: ((Boolean) -> Unit)? = null
-    ) {
+    fun handleToken(bleDevice: BleDevice, byteArray: ByteArray, callBack: ((Boolean) -> Unit)? = null) {
         LogUtil.i("handleToken : ${byteArray.toHexStrings()}")
         BusinessManager.getBleDeviceByMac(bleDevice.mac)?.let {
             it.token = byteArrayOf(byteArray[11], byteArray[12], byteArray[13], byteArray[14])
@@ -481,31 +446,6 @@ object BleCmdManager {
         }
     }
 
-    /**
-     * 处理钥匙电量
-     * bat:电量百分比,范围 0-100,单位:%
-     * chg:0x01:未充电 0x02:充电中 0x03:充满
-     */
-    private fun handlePowerStatus(byteArray: ByteArray) {
-        LogUtil.i("handlePowerStatus : ${byteArray.toHexStrings()}")
-        val bat = byteArray[4].toInt()
-        val chg = byteArray[5]
-        LogUtil.i("钥匙电量 : $bat%")
-        when (chg) {
-            0x01.toByte() -> {
-                LogUtil.i("充电状态:未充电")
-            }
-
-            0x02.toByte() -> {
-                LogUtil.i("充电状态:充电中")
-            }
-
-            0x03.toByte() -> {
-                LogUtil.i("充电状态:充满")
-            }
-        }
-    }
-
     /**
      * 发送文件
      * type: 1:固件文件 2:点位PNG文件

+ 12 - 20
app/src/main/java/com/grkj/iscs_mars/ble/BleConnectionManager.kt

@@ -11,9 +11,8 @@ import com.grkj.iscs_mars.BusinessManager.removeExceptionKey
 import com.grkj.iscs_mars.BusinessManager.sendEventMsg
 import com.grkj.iscs_mars.BusinessManager.sendLoadingEventMsg
 import com.grkj.iscs_mars.R
+import com.grkj.iscs_mars.enums.HardwareMode
 import com.grkj.iscs_mars.extentions.toHexStrings
-import com.grkj.iscs_mars.modbus.ModBusController
-import com.grkj.iscs_mars.modbus.ModBusController.controlKeyCharge
 import com.grkj.iscs_mars.model.Constants.PERMISSION_REQUEST_CODE
 import com.grkj.iscs_mars.model.eventmsg.LoadingMsg
 import com.grkj.iscs_mars.model.eventmsg.MsgEvent
@@ -260,11 +259,7 @@ object BleConnectionManager {
             override fun onScanStarted(success: Boolean) {
                 LogUtil.i("蓝牙连接-onScanStarted:${success}")
                 if (!success && retryTimes == 0) {
-                    if (isNeedLoading) sendEventMsg(
-                        MsgEvent(
-                            MSG_EVENT_LOADING, LoadingMsg(false, null, null)
-                        )
-                    )
+                    if (isNeedLoading) sendEventMsg(MsgEvent(MSG_EVENT_LOADING, LoadingMsg(false, null, null)))
                     prepareDoneCallBack?.invoke(false, null)
                 } else if (!success && retryTimes > 0) {
                     BleManager.cancelScan()
@@ -413,9 +408,9 @@ object BleConnectionManager {
                             if (isTestMode) {
                                 return
                             }
-                            ModBusController.updateKeyReadyStatus(bleDevice.mac, false, 3)
+                            HardwareMode.getCurrentHardwareMode().updateKeyReadyStatus(bleDevice.mac, false, 3)
                         } else {
-                            ModBusController.updateKeyReadyStatus(bleDevice.mac, false, 3)
+                            HardwareMode.getCurrentHardwareMode().updateKeyReadyStatus(bleDevice.mac, false, 3)
                         }
                     }
 
@@ -584,30 +579,27 @@ object BleConnectionManager {
         withContext(Dispatchers.IO) {
             // -------- 第二次尝试:先开电,再连 --------
             // 开电,并等待回调
-            suspendCoroutine<Unit> { unitCont ->
-                controlKeyCharge(false, mac) {
+            suspendCoroutine { unitCont ->
+                HardwareMode.getCurrentHardwareMode().controlKeyCharge(false, mac) {
+                    LogUtil.i("接收到消息,关闭充电")
                     ThreadUtils.runOnIO {
                         delay(500)
-                        controlKeyCharge(true, mac) {
+                        HardwareMode.getCurrentHardwareMode().controlKeyCharge(true, mac) {
+                            LogUtil.i("接收到消息,打开充电")
                             unitCont.resume(Unit)
                         }
                     }
                 }
             }
-            LogUtil.i("蓝牙连接-开启充电并等待500ms")
-            // 等 500ms 保证硬件电源稳定
             delay(500)
-
             // 再次注册连接监听
-            val secondTry = suspendCancellableCoroutine<Boolean> { cont ->
+            val secondTry = suspendCancellableCoroutine { cont ->
                 var isCalled = false
                 BusinessManager.registerConnectListener(mac, true, isSend) { isDone, _ ->
-                    if (isCalled) {
-                        return@registerConnectListener
-                    }
+                    if (isCalled) return@registerConnectListener
                     isCalled = true
                     // 无论成功或失败,都先把电关掉
-                    controlKeyCharge(false, mac) { }
+                    HardwareMode.getCurrentHardwareMode().controlKeyCharge(false, mac) { }
                     if (cont.isActive) {
                         cont.resume(isDone)
                     }

+ 4 - 3
app/src/main/java/com/grkj/iscs_mars/ble/BleQueueDispatcher.kt

@@ -1,6 +1,7 @@
 package com.grkj.iscs_mars.ble
 
 import android.annotation.SuppressLint
+import android.util.Log
 import com.grkj.iscs_mars.BusinessManager
 import com.grkj.iscs_mars.util.log.LogUtil
 import com.huyuhui.fastble.BleManager
@@ -58,18 +59,18 @@ abstract class BleQueueDispatcher {
     @Synchronized
     fun submit(mac: String, onResult: (Boolean) -> Unit) {
         LogUtil.i("开始检查钥匙状态:${mac}")
-        if (activeMacs.containsKey(mac) || taskQueue.any { it.first == mac } || connectedMacs.contains(
-                mac
-            )) {
+        if (activeMacs.containsKey(mac) || taskQueue.any { it.first == mac } || connectedMacs.contains(mac)) {
             when {
                 connectedMacs.contains(mac) -> {
                     LogUtil.i("${this::class.java} 检查到钥匙已连接")
                     onResult(true)
                 }
+
                 activeMacs.containsKey(mac) -> {
                     LogUtil.i("${this::class.java} 检查到钥匙连接中添加回调")
                     activeMacs[mac]?.add(onResult)
                 }
+
                 taskQueue.find { it.first == mac } != null -> {
                     LogUtil.i("${this::class.java} 检查到钥匙队列中添加回调")
                     taskQueue.find { it.first == mac }?.second?.add(onResult)

+ 1 - 3
app/src/main/java/com/grkj/iscs_mars/ble/BleReturnDispatcher.kt

@@ -10,9 +10,7 @@ object BleReturnDispatcher : BleQueueDispatcher() {
 
     override fun doConnect(mac: String, callback: (Boolean) -> Unit) {
         ThreadUtils.runOnMain {
-            BusinessManager.sendLoadingEventMsg(
-                CommonUtils.getStr(R.string.loading_msg_return_key_start).toString()
-            )
+            BusinessManager.sendLoadingEventMsg(CommonUtils.getStr(R.string.loading_msg_return_key_start).toString())
         }
         ThreadUtils.runOnIO {
             val isConnected = BleConnectionManager.tryConnectWithOptionalCharge(mac, isSend = false)

+ 1 - 0
app/src/main/java/com/grkj/iscs_mars/ble/BleSendDispatcher.kt

@@ -1,5 +1,6 @@
 package com.grkj.iscs_mars.ble
 
+import android.util.Log
 import com.sik.sikcore.thread.ThreadUtils
 
 object BleSendDispatcher : BleQueueDispatcher() {

+ 1 - 1
app/src/main/java/com/grkj/iscs_mars/ble/BleUtil.kt

@@ -43,7 +43,7 @@ class BleUtil private constructor() {
             BleManager.init(application)
             BleManager.enableLog(false)
                 .apply {
-                    maxConnectCount = 0
+                    maxConnectCount = 1
                     splitWriteNum = 500
                     operateTimeout = OPERATE_TIMEOUT
                 }

+ 10 - 22
app/src/main/java/com/grkj/iscs_mars/can/CanHardwareHelper.kt

@@ -3,31 +3,21 @@ package com.grkj.iscs_mars.can
 import com.grkj.iscs_mars.extentions.toHexFromLe
 import com.grkj.iscs_mars.model.DeviceConst
 import com.grkj.iscs_mars.model.vo.hardware.CabinetSlotsRecord
+import com.grkj.iscs_mars.util.log.LogUtil
 import com.sik.comm.impl_can.SdoOp
 import com.sik.comm.impl_can.toCommMessage
 import com.sik.sikcore.thread.ThreadUtils
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
 
 /**
  * Can硬件读写帮助类
  */
 class CanHardwareHelper : IHardwareHelper {
-    private val logger: Logger = LoggerFactory.getLogger(CanHardwareHelper::class.java)
     override fun connectAndAddListener() {
         ThreadUtils.runOnIO {
             CanHelper.connect()
-            // StartListenerEvent.sendStartListenerEvent()
         }
     }
 
-    /**
-     * 断开连接操作
-     */
-    fun disconnect() {
-        ThreadUtils.runOnIO { CanHelper.disconnect() }
-    }
-
     override fun getKeyMacByRfid(rfid: String): String? {
         return CanHelper.getKeyByRfid(rfid)?.mac
     }
@@ -228,7 +218,7 @@ class CanHardwareHelper : IHardwareHelper {
         done: ((ByteArray) -> Unit)?
     ) {
         val keyDevice = CanHelper.getKeyDeviceByMac(mac)
-        logger.info("钥匙硬件信息:${keyDevice}")
+        LogUtil.i("controlKeyCharge $keyDevice")
         keyDevice?.let {
             val leftOn = if (it.id == 0 && isOpen) true else if (it.id == 0) false else null
             val rightOn = if (it.id == 1 && isOpen) true else if (it.id == 1) false else null
@@ -289,11 +279,16 @@ class CanHardwareHelper : IHardwareHelper {
         isReady: Boolean,
         from: Int
     ) {
-        logger.info("updateKeyReadyStatus mac:$mac isReady:$isReady from:$from")
+        LogUtil.i("updateKeyReadyStatus mac:$mac isReady:$isReady from:$from")
         val deviceKey = CanHelper.getKeyDeviceByMac(mac)
         deviceKey?.isReady = isReady
     }
 
+    override fun updateAllBuckleStatus(done: () -> Unit) {
+        // 执行一次更新设备状态
+        CustomCanConfig.instance.canReadyPlugin.startPollingSingleLoop()
+    }
+
     override fun updateKeyPower(power: Int, mac: String) {
         val deviceKey = CanHelper.getKeyDeviceByMac(mac)
         deviceKey?.power = power
@@ -329,7 +324,7 @@ class CanHardwareHelper : IHardwareHelper {
             }
             CanHelper.readFrom(req) {
                 it?.let {
-                    logger.info("返回的数据:${it.toCommMessage().payload}")
+                    LogUtil.i("返回的数据:${it.toCommMessage().payload}")
                     done?.invoke(idx, it.toCommMessage().payload.toHexFromLe())
                 }
             }
@@ -376,7 +371,7 @@ class CanHardwareHelper : IHardwareHelper {
             }
             CanHelper.readFrom(req) {
                 it?.let {
-                    logger.info("返回的数据:${it.toCommMessage().payload}")
+                    LogUtil.i("返回的数据:${it.toCommMessage().payload}")
                     done?.invoke(it.toCommMessage().payload.toHexFromLe())
                 }
             }
@@ -450,11 +445,4 @@ class CanHardwareHelper : IHardwareHelper {
         return if (lockData == null) "not_in_slot" else "${lockData.nodeId}-${lockData.id + 1}"
     }
 
-    override suspend fun getOneKey(
-        exceptionSlots: List<CabinetSlotsRecord>,
-        exceptionKeysRfid: List<String>,
-        exceptionKeysMac: List<String>
-    ): Pair<Any, String?>? {
-        return CanHelper.getOneKey(exceptionSlots, exceptionKeysRfid, exceptionKeysMac)
-    }
 }

+ 135 - 38
app/src/main/java/com/grkj/iscs_mars/can/CanHelper.kt

@@ -1,9 +1,14 @@
 package com.grkj.iscs_mars.can
 
 import android.annotation.SuppressLint
+import com.grkj.iscs_mars.ble.BleCmdManager
 import com.grkj.iscs_mars.ble.BleReturnDispatcher
 import com.grkj.iscs_mars.ble.BleSendDispatcher
+import com.grkj.iscs_mars.enums.NoKeyReason
+import com.grkj.iscs_mars.modbus.DockBean
+import com.grkj.iscs_mars.model.ISCSDomainData
 import com.grkj.iscs_mars.model.vo.hardware.CabinetSlotsRecord
+import com.grkj.iscs_mars.util.log.LogUtil
 import com.huyuhui.fastble.BleManager
 import com.sik.comm.core.protocol.ProtocolManager
 import com.sik.comm.core.protocol.ProtocolType
@@ -17,8 +22,6 @@ import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.SupervisorJob
 import kotlinx.coroutines.isActive
 import kotlinx.coroutines.launch
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
 import kotlin.coroutines.resume
 import kotlin.coroutines.suspendCoroutine
 
@@ -26,7 +29,6 @@ import kotlin.coroutines.suspendCoroutine
  * can总线帮助工具
  */
 object CanHelper {
-    private val logger: Logger = LoggerFactory.getLogger(CanHelper::class.java)
 
     /**
      * 作用域
@@ -171,7 +173,7 @@ object CanHelper {
             }.onSuccess { rsp ->
                 callback(rsp.toSdoResponse() as SdoResponse.ReadData)
             }.onFailure {
-                logger.info("读取失败:${it}")
+                LogUtil.i("读取失败:${it}")
                 callback(null)
             }
         }
@@ -188,7 +190,7 @@ object CanHelper {
             }.onSuccess { rsp ->
                 callback(rsp.toSdoResponse() as SdoResponse.WriteAck)
             }.onFailure {
-                logger.info("写入失败:${it}")
+                LogUtil.i("写入失败:${it}")
             }
         }
     }
@@ -203,7 +205,7 @@ object CanHelper {
         }.onSuccess { rsp ->
             rsp
         }.onFailure {
-            logger.info("写入失败:${it}")
+            LogUtil.i("写入失败:${it}")
             null
         }.getOrNull()?.toSdoResponse() as? SdoResponse.WriteAck
     }
@@ -242,7 +244,7 @@ object CanHelper {
     ): MutableMap<Any, MutableList<Pair<Int, String>>> {
 
         val map = mutableMapOf<Any, MutableList<Pair<Int, String>>>()
-        logger.info("需要的锁具: $needLockCount")
+        LogUtil.i("需要的锁具: $needLockCount")
         if (needLockCount <= 0) return map
 
         // 1) 拿数据 + 排序(要接收返回值)
@@ -252,9 +254,9 @@ object CanHelper {
             .filter { !it.isException }
             .sortedBy { it.nodeId }
 
-        logger.info("锁具基座列表: $lockDockList")
-        logger.info("异常锁rfid: $exceptionLocks")
-        logger.info("异常锁仓位: ${exceptionSlots.joinToString(",") { "${it.row},${it.col}" }}")
+        LogUtil.i("锁具基座列表: $lockDockList")
+        LogUtil.i("异常锁rfid: $exceptionLocks")
+        LogUtil.i("异常锁仓位: ${exceptionSlots.joinToString(",") { "${it.row},${it.col}" }}")
 
         // 2) 预先把“该 nodeId 下哪些 id(列) 被禁用”整理成 Map,过滤更清晰
         val blockedIdsByNode: Map<Int, Set<Int>> =
@@ -280,65 +282,148 @@ object CanHelper {
 
         map.putAll(grouped)
 
-        logger.info("待取锁: $map")
+        LogUtil.i("待取锁: $map")
         return map
     }
 
     /**
-     * 获取一把钥匙
+     * 获取挂锁
+     */
+    fun getLocks(
+        needLockCount: Int,
+        registerLockRfid: List<String>,
+        exceptionSlots: MutableList<CabinetSlotsRecord>,
+        exceptionLocks: MutableList<String>
+    ): MutableMap<Byte, MutableList<DockBean.LockBean>> {
+        val map = mutableMapOf<Byte, MutableList<DockBean.LockBean>>()
+        if (needLockCount == 0) {
+            return map
+        }
+        // 1) 拿数据 + 排序(要接收返回值)
+        val lockDockList = deviceData.values
+            .flatten()
+            .filterIsInstance<DeviceModel.CommonDevice>()
+            .filter { !it.isException }
+            .sortedBy { it.nodeId }
+
+        LogUtil.i("锁具基座列表: $lockDockList")
+        LogUtil.i("异常锁rfid: $exceptionLocks")
+        LogUtil.i("异常锁仓位: ${exceptionSlots.joinToString(",") { "${it.row},${it.col}" }}")
+
+        // 2) 预先把“该 nodeId 下哪些 id(列) 被禁用”整理成 Map,过滤更清晰
+        val blockedIdsByNode: Map<Int, Set<Int>> =
+            exceptionSlots
+                .filter { it.row != null }
+                .groupBy(
+                    keySelector = { it.row!!.toInt() },                 // nodeId
+                    valueTransform = { (it.col?.toInt() ?: 1) - 1 }      // 被占/异常的列 -> 对应 lock.id
+                )
+                .mapValues { (_, cols) -> cols.toSet() }
+
+        // 3) 过滤合法锁
+        val validLocks = lockDockList.filter { l ->
+            l.isExist && l.rfid !in exceptionLocks && blockedIdsByNode[l.nodeId]?.contains(l.id) != true
+        }
+
+        // 4) 取够数量并分组 -> 显式写回 map
+        val selected = validLocks.take(needLockCount)
+        // 数据类型转换
+        val grouped = selected.groupBy { it.nodeId.toByte() }.mapValues { (_, list) ->
+            val outList = ArrayList<DockBean.LockBean>()
+            list.forEach { outList.add(DockBean.LockBean(it.id, it.isExist, it.locked, it.rfid)) }
+            outList
+        }
+        // 这里做数据类型转换
+        map.putAll(grouped)
+
+        LogUtil.i("待取锁: $map")
+        return map
+    }
+
+    /**
+     * 随机获取一个钥匙(存在的、有RFID、有Mac、连接的、是待机模式的)
+     *
+     * @return 底座地址,钥匙
      */
     @SuppressLint("MissingPermission")
     suspend fun getOneKey(
         exceptionSlots: List<CabinetSlotsRecord>,
         exceptionKeysRfid: List<String>,
         exceptionKeysMac: List<String> = mutableListOf(),
-    ): Pair<Any, String?>? {
+    ): Pair<Byte, DockBean.KeyBean?>? {
+        ISCSDomainData.noKeyReason = NoKeyReason.NONE
         // 1. 过滤并准备钥匙列表
         val slotCols = exceptionSlots.mapNotNull { it.col?.toInt() }
         val noBelongDevice = BleManager.getAllConnectedDevice().filter {
-            !BleSendDispatcher.isConnected(it.mac) && !BleSendDispatcher.isConnecting(it.mac) && !BleReturnDispatcher.isConnected(
-                it.mac
-            ) && !BleReturnDispatcher.isConnecting(it.mac)
+            !BleSendDispatcher.isConnected(it.mac)
+                    && !BleSendDispatcher.isConnecting(it.mac)
+                    && !BleReturnDispatcher.isConnected(it.mac)
+                    && !BleReturnDispatcher.isConnecting(it.mac)
         }
-        logger.info("检查到不属于任何队列的设备:${noBelongDevice.map { it.mac }},立即断开连接让路")
+        LogUtil.i("检查到不属于任何队列的设备:${noBelongDevice.map { it.mac }},立即断开连接让路")
         noBelongDevice.forEach {
+            BleCmdManager.shutdownOrRebootReq(it.mac)
             BleManager.disconnect(it)
         }
-        var keyList = deviceData.flatMap { it.value }.filterIsInstance<DeviceModel.DeviceKey>()
-            .filter { !it.isException }
-            //RFID不为空,RFID不在异常列表,mac不在异常列表,mac不为空,存在,不在归还连接列表,不在归还连接中列表
+        val findKeyList = deviceData.flatMap { it.value }.filterIsInstance<DeviceModel.DeviceKey>()
+        LogUtil.i("查找钥匙 - 过滤前 $findKeyList")
+        var keyList = findKeyList.filter { !it.isException }
+            // RFID不为空,RFID不在异常列表,mac不在异常列表,mac不为空,存在,不在归还连接列表,不在归还连接中列表
             .filterIndexed { idx, _ -> (idx + 1) !in slotCols }.filter { kb ->
-                kb.rfid !in exceptionKeysRfid && kb.mac !in exceptionKeysMac && kb.isExist && !BleReturnDispatcher.isConnected(
-                    kb.mac
-                ) && !BleReturnDispatcher.isConnecting(kb.mac)
+                val notExcept = kb.rfid !in exceptionKeysRfid
+                val macCanUse = kb.mac !in exceptionKeysMac && kb.mac.isNotEmpty()
+                val isReturnDisconnected = !BleReturnDispatcher.isConnected(kb.mac)
+                val isNotReturnConnecting = !BleReturnDispatcher.isConnecting(kb.mac)
+                val canUse = notExcept && macCanUse && kb.isExist && isReturnDisconnected && isNotReturnConnecting
+                LogUtil.i("查找钥匙 - 是否可用:$canUse notExcept: $notExcept macCanUse: $macCanUse isExist: ${kb.isExist} isReturnDisconnected: $isReturnDisconnected isNotReturnConnecting: $isNotReturnConnecting \nkey:$kb")
+                canUse
             }
 
-        logger.info("蓝牙连接-获取到钥匙信息:${keyList}")
+        LogUtil.i("查找钥匙 - 已过滤可用 蓝牙连接 - 获取到钥匙信息:${keyList}")
         if (keyList.isEmpty()) {
+            ISCSDomainData.noKeyReason = NoKeyReason.NO_KEY
             return null
         }
         val sendConnectingAndConnected = BleSendDispatcher.getConnectedAndConnecting()
-        //如果已连接和连接中的设备不在钥匙列表中,直接断开连接让路
+        // 如果已连接和连接中的设备不在钥匙列表中,直接断开连接让路
         sendConnectingAndConnected.filter { it !in keyList.map { it.mac } }.forEach {
             BleSendDispatcher.scheduleDisconnect(it)
         }
         keyList = keyList.sortedWith(compareByDescending<DeviceModel.DeviceKey> {
-            BleSendDispatcher.isConnected(it.mac) || BleSendDispatcher.isConnecting(
-                it.mac
-            )
-        }    // 主键:在线优先
-            .thenByDescending { it.power }                                                // 三级:电量越高
-        )
+            BleSendDispatcher.isConnected(it.mac) || BleSendDispatcher.isConnecting(it.mac)
+        }.thenByDescending { it.power })
         val connectedKey = keyList.find { BleSendDispatcher.isConnected(it.mac) }
         if (connectedKey != null) {
-            return connectedKey.nodeId to connectedKey.rfid
+            return connectedKey.nodeId.toByte() to DockBean.KeyBean(
+                connectedKey.id,
+                connectedKey.isExist,
+                connectedKey.id == 0,
+                connectedKey.isCharging,
+                connectedKey.locked,
+                connectedKey.rfid,
+                connectedKey.mac,
+                connectedKey.power,
+                connectedKey.isReady
+            )
         }
         val connectingKey = keyList.find { BleSendDispatcher.isConnecting(it.mac) }
         if (connectingKey != null) {
             val result = suspendCoroutine { cont ->
                 BleSendDispatcher.submit(connectingKey.mac) { connected ->
                     if (connected) {
-                        cont.resume(connectingKey.nodeId to connectingKey.rfid)
+                        cont.resume(
+                            connectingKey.nodeId.toByte() to DockBean.KeyBean(
+                                connectingKey.id,
+                                connectingKey.isExist,
+                                connectingKey.id == 0,
+                                connectingKey.isCharging,
+                                connectingKey.locked,
+                                connectingKey.rfid,
+                                connectingKey.mac,
+                                connectingKey.power,
+                                connectingKey.isReady
+                            )
+                        )
                     } else {
                         cont.resume(null)
                     }
@@ -353,11 +438,23 @@ object CanHelper {
             val result = suspendCoroutine { cont ->
                 BleSendDispatcher.submit(mac) { connected ->
                     if (connected) {
-                        logger.info("蓝牙连接完成 :${mac}")
+                        LogUtil.i("蓝牙连接完成 :${mac}")
                         // 找到第一个能连的:从 keyDockList 里拿同 rfid 的 addr
-                        logger.info("蓝牙连接-找到的底座地址 :${kb.nodeId}")
+                        LogUtil.i("蓝牙连接-找到的底座地址 :${kb.nodeId}")
                         if (cont.context.isActive) {
-                            cont.resume(kb.nodeId to kb.rfid)
+                            cont.resume(
+                                kb.nodeId.toByte() to DockBean.KeyBean(
+                                    kb.id,
+                                    kb.isExist,
+                                    kb.id == 0,
+                                    kb.isCharging,
+                                    kb.locked,
+                                    kb.rfid,
+                                    kb.mac,
+                                    kb.power,
+                                    kb.isReady
+                                )
+                            )
                         }
                     } else {
                         if (cont.context.isActive) {
@@ -370,9 +467,9 @@ object CanHelper {
                 return result
             }
         }
-
+        ISCSDomainData.noKeyReason = NoKeyReason.KEY_POWER_LOW
         // 一个都没成功
-        logger.error("getOneKey : no key match")
+        LogUtil.e("getOneKey : no key match")
         return null
     }
 }

+ 103 - 156
app/src/main/java/com/grkj/iscs_mars/can/CanReadyPlugin.kt

@@ -1,8 +1,16 @@
 package com.grkj.iscs_mars.can
 
-import android.util.Log
+import com.grkj.iscs_mars.BusinessManager
+import com.grkj.iscs_mars.R
 import com.grkj.iscs_mars.enums.HardwareMode
 import com.grkj.iscs_mars.extentions.toHexFromLe
+import com.grkj.iscs_mars.modbus.DockBean
+import com.grkj.iscs_mars.model.DeviceConst
+import com.grkj.iscs_mars.model.ISCSDomainData
+import com.grkj.iscs_mars.model.eventmsg.MsgEvent
+import com.grkj.iscs_mars.model.eventmsg.MsgEventConstants
+import com.grkj.iscs_mars.util.NetApi
+import com.grkj.iscs_mars.util.ToastUtils
 import com.grkj.iscs_mars.util.log.LogUtil
 import com.sik.comm.core.model.ProtocolState
 import com.sik.comm.core.plugin.CommPlugin
@@ -10,6 +18,7 @@ import com.sik.comm.core.plugin.PluginScope
 import com.sik.comm.impl_can.SdoRequest
 import com.sik.comm.impl_can.SdoResponse
 import com.sik.sikcore.extension.toJson
+import com.sik.sikcore.thread.ThreadUtils
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Job
@@ -18,13 +27,10 @@ import kotlinx.coroutines.delay
 import kotlinx.coroutines.isActive
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withTimeoutOrNull
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
 import kotlin.coroutines.resume
 import kotlin.coroutines.suspendCoroutine
 
 class CanReadyPlugin : CommPlugin {
-    private val logger: Logger = LoggerFactory.getLogger(CanReadyPlugin::class.java)
 
     /** 轮询哪些节点 */
     private val activeNodes = mutableSetOf<Int>()
@@ -68,46 +74,37 @@ class CanReadyPlugin : CommPlugin {
     }
 
     /** 单协程,逐节点轮询 */
-    private fun startPollingSingleLoop() {
+    fun startPollingSingleLoop() {
         pollJob?.cancel()
         pollJob = scope.launch {
             NodeIdHelper.scanRangeLinear({ nodeId ->
                 safeRead(CanCommands.Common.getDeviceType(nodeId))?.let {
-                    logger.info("硬件类型:${it.payload[0].toInt()}")
+                    LogUtil.i("硬件类型:${it.payload[0].toInt()}")
                     activeNodes.add(nodeId)
                     CanHelper.addNode(nodeId, it.payload[0].toInt())
                 }
             }, endInclusive = 14)
-            logger.info("当前检测到的硬件:{}", activeNodes)
+            LogUtil.i("当前检测到的硬件:${activeNodes}")
             for (nodeId in activeNodes) {
                 try {
                     val cmds = CanCommands.forDevice(nodeId)
-
                     // 1) 读状态 0x6010/00 (2B)
                     if (CanHelper.getDeviceTypeByNodeId(nodeId) != CanDeviceConst.DEVICE_MATERIAL_CABINET_CONTROL_BOARD) {
                         safeRead(cmds.getStatus())?.let { rd ->
                             deviceStatusListener.forEach {
-                                it.value.deviceStatus(
-                                    nodeId,
-                                    rd.index,
-                                    rd.payload
-                                )
+                                it.value.deviceStatus(nodeId, rd.index, rd.payload)
                             }
                         }
                     }
                     safeRead(cmds.readControlReg())?.let { rd ->
                         deviceStatusListener.forEach {
-                            it.value.deviceStatus(
-                                nodeId,
-                                rd.index,
-                                rd.payload
-                            )
+                            it.value.deviceStatus(nodeId, rd.index, rd.payload)
                         }
                     }
 
                 } catch (t: Throwable) {
                     // 单个节点出错不影响整体循环
-                    logger.warn("poll node={} error: {}", nodeId, t.toString())
+                    LogUtil.w("poll node=${nodeId} error: ${t.toString()}")
                 }
 
                 // 给总线/固件留点缝,避免贴脸轰
@@ -127,7 +124,7 @@ class CanReadyPlugin : CommPlugin {
                                 deviceStatusListener.forEach {
                                     try {
                                         it.value.deviceStatus(nodeId, rd.index, rd.payload)
-                                    } catch (e: Exception){
+                                    } catch (e: Exception) {
                                         LogUtil.e("deviceStatusListener $e")
                                     }
 
@@ -146,7 +143,7 @@ class CanReadyPlugin : CommPlugin {
 
                     } catch (t: Throwable) {
                         // 单个节点出错不影响整体循环
-                        logger.warn("poll node={} error: {}", nodeId, t.toString())
+                        LogUtil.w("poll node=${nodeId} error: ${t.toString()}")
                     }
 
                     // 给总线/固件留点缝,避免贴脸轰
@@ -155,8 +152,8 @@ class CanReadyPlugin : CommPlugin {
             }
         }.also { job ->
             job.invokeOnCompletion { e ->
-                if (e != null) logger.warn("single-loop completed with error: {}", e.toString())
-                else logger.info("single-loop stopped.")
+                if (e != null) LogUtil.w("single-loop completed with error: ${e.toString()}")
+                else LogUtil.i("single-loop stopped.")
             }
         }
     }
@@ -165,11 +162,7 @@ class CanReadyPlugin : CommPlugin {
      * 初始化锁具——打开所有无锁的卡扣、读取RFID
      */
     private fun initLock() {
-        logger.info(
-            "initLock : ${
-                HardwareMode.getCurrentHardwareMode().getLockDockData().toJson()
-            }"
-        )
+        LogUtil.i("initLock : ${HardwareMode.getCurrentHardwareMode().getLockDockData().toJson()}")
         HardwareMode.getCurrentHardwareMode().getLockDockData()
             .forEach { dockBean ->
                 val hasLockIdxList =
@@ -182,27 +175,16 @@ class CanReadyPlugin : CommPlugin {
                     CanHelper.readFrom(readRfidReq) { result ->
                         val res = result?.payload ?: return@readFrom
                         if (res.size < 4) {
-                            logger.error("Lock rfid error")
+                            LogUtil.e("Lock rfid error")
                             return@readFrom
                         }
                         val rfid = res.toHexFromLe()
-                        logger.info("初始化锁具 RFID : $rfid")
-                        HardwareMode.getCurrentHardwareMode()
-                            .updateLockRfid(dockBean.addr, idx, rfid)
-                        // todo 为设备录入增加
-//                        LogicManager.hardwareLogic.getLockInfo(rfid) {
-//                            HardwareMode.getCurrentHardwareMode().updateLockNewHardware(
-//                                dockBean.addr,
-//                                idx,
-//                                it == null || it.lockNfc?.isEmpty() == true
-//                            )
-//                        }
+                        LogUtil.i("初始化锁具 RFID : $rfid")
+                        HardwareMode.getCurrentHardwareMode().updateLockRfid(dockBean.addr, idx, rfid)
                     }
                 }
-                HardwareMode.getCurrentHardwareMode()
-                    .controlLockBuckle(false, dockBean.addr, hasLockIdxList)
-                HardwareMode.getCurrentHardwareMode()
-                    .controlLockBuckle(true, dockBean.addr, noLockIdxList)
+                HardwareMode.getCurrentHardwareMode().controlLockBuckle(false, dockBean.addr, hasLockIdxList)
+                HardwareMode.getCurrentHardwareMode().controlLockBuckle(true, dockBean.addr, noLockIdxList)
             }
     }
 
@@ -210,115 +192,86 @@ class CanReadyPlugin : CommPlugin {
      * 初始化钥匙
      */
     private fun initKey() {
-        logger.info("initKey : ${HardwareMode.getCurrentHardwareMode().getKeyDockData()}")
-//        HardwareMode.getCurrentHardwareMode().getKeyDockData()
-//            .forEach { dockBean ->
-//                if (dockBean.keyData.isEmpty()) {
-//                    ISCSConfig.canInitDevice = true
-//                    ModbusInitCompleteEvent.sendModbusInitCompleteEvent()
-//                } else {
-//                    dockBean.keyData.forEach { key ->
-//                        if (key.isExist) {
-//                            logger.info("initKey : ${dockBean.addr} : ${key.idx == 0}")
-//                            HardwareMode.getCurrentHardwareMode()
-//                                .readKeyRfidStr(dockBean.addr, key.idx) { idx, rfid ->
-//                                    logger.info("初始化钥匙 RFID : $rfid")
-//                                    // 更新rfid
-//                                    HardwareMode.getCurrentHardwareMode()
-//                                        .updateKeyRfid(dockBean.addr, key.idx, rfid)
-//                                    // 蓝牙准备操作
-//                                    LogicManager.hardwareLogic.getKeyInfo(rfid) { keyInfo ->
-//                                        logger.info("getKeyInfo : $rfid - ${keyInfo?.macAddress}")
-//                                        HardwareMode.getCurrentHardwareMode().updateKeyNewHardware(
-//                                            dockBean.addr,
-//                                            key.idx,
-//                                            keyInfo == null || keyInfo.keyNfc?.isEmpty() == true || keyInfo.macAddress?.isEmpty() == true
-//                                        )
-//                                        logger.info(
-//                                            "钥匙是否为新设备:{}",
-//                                            keyInfo == null || keyInfo.keyNfc?.isEmpty() == true || keyInfo.macAddress?.isEmpty() == true
-//                                        )
-//                                        if (keyInfo != null && !keyInfo.macAddress.isNullOrEmpty()) {
-//                                            // 更新mac
-//                                            HardwareMode.getCurrentHardwareMode().updateKeyMac(
-//                                                dockBean.addr,
-//                                                key.idx,
-//                                                keyInfo.macAddress!!
-//                                            )
-//                                            //已经初始化完成才会去连接
-//                                            if (ISCSConfig.isInit) {
-//                                                HardwareMode.getCurrentHardwareMode()
-//                                                    .controlKeyCharge(true, key.idx, dockBean.addr)
-//                                            }
-//                                            HardwareMode.getCurrentHardwareMode()
-//                                                .controlKeyBuckle(false, key.idx, dockBean.addr)
-//                                        } else {
-//                                            if (ISCSConfig.isInit) {
-//                                                ToastEvent.sendToastEvent(I18nManager.t("get_key_info_fail"))
-//                                            }
-//                                            HardwareMode.getCurrentHardwareMode()
-//                                                .controlKeyLockAndCharge(
-//                                                    true,
-//                                                    key.idx,
-//                                                    dockBean.addr
-//                                                )
-//                                        }
-//                                        val isKeyReady =
-//                                            HardwareMode.getCurrentHardwareMode().getKeyDockData()
-//                                                .all {
-//                                                    it.keyData.filter { it.type == DeviceConst.DEVICE_TYPE_KEY }
-//                                                        .filterIsInstance<DockBean.KeyBean>()
-//                                                        .filter { it.isExist }
-//                                                        .all {
-//                                                            logger.info("钥匙信息:${it.rfid}")
-//                                                            it.rfid?.isNotEmpty() == true
-//                                                        }
-//                                                }
-//                                        logger.info("钥匙是否准备完毕:${isKeyReady},${ISCSConfig.isInit}")
-//                                        if (isKeyReady && ISCSConfig.isInit) {
-//                                            ISCSConfig.canInitDevice = true
-//                                            logger.info("发送初始化完成事件")
-//                                            ModbusInitCompleteEvent.sendModbusInitCompleteEvent()
-//                                        } else if (isKeyReady) {
-//                                            ISCSConfig.canInitDevice = true
-//                                            ModbusInitCompleteEvent.sendModbusInitCompleteEvent()
-//                                        }
-//                                    }
-//                                }
-//                        } else {
-//                            HardwareMode.getCurrentHardwareMode()
-//                                .controlKeyBuckle(true, key.idx, dockBean.addr)
-//                            val isKeyReady =
-//                                HardwareMode.getCurrentHardwareMode().getKeyDockData()
-//                                    .all {
-//                                        it.keyData.filter { it.type == DeviceConst.DEVICE_TYPE_KEY }
-//                                            .filterIsInstance<DockBean.KeyBean>()
-//                                            .filter { it.isExist }
-//                                            .all {
-//                                                logger.info("钥匙信息:${it.rfid}")
-//                                                it.rfid?.isNotEmpty() == true
-//                                            }
-//                                    }
-//                            logger.info("钥匙是否准备完毕:${isKeyReady},${ISCSConfig.isInit}")
-//                            if (isKeyReady && ISCSConfig.isInit) {
-//                                ISCSConfig.canInitDevice = true
-//                                logger.info("发送初始化完成事件")
-//                                ModbusInitCompleteEvent.sendModbusInitCompleteEvent()
-//                            } else if (isKeyReady) {
-//                                ISCSConfig.canInitDevice = true
-//                                ModbusInitCompleteEvent.sendModbusInitCompleteEvent()
-//                            }
-//                        }
-//
-//                    }
-//                }
-//            }
+        LogUtil.i("initKey : ${HardwareMode.getCurrentHardwareMode().getKeyDockData()}")
+        HardwareMode.getCurrentHardwareMode().getKeyDockData().forEach { dockBean ->
+            if (dockBean.addr != 3) {
+                if (dockBean.keyData.isEmpty()) {
+                    ISCSDomainData.canInitDevice = true
+                    BusinessManager.sendEventMsg(MsgEvent(MsgEventConstants.MSG_EVENT_INIT_KEY_COMPLETE, null))
+                } else {
+                    dockBean.keyData.forEach { key ->
+                        if (key.isExist) {
+                            LogUtil.i("initKey : ${dockBean.addr} : ${key.idx == 0}")
+                            HardwareMode.getCurrentHardwareMode().readKeyRfidStr(dockBean.addr, key.idx) { _, rfid ->
+                                    LogUtil.i("初始化钥匙 RFID : $rfid")
+                                    // 更新rfid
+                                    HardwareMode.getCurrentHardwareMode().updateKeyRfid(dockBean.addr, key.idx, rfid)
+                                    // 蓝牙准备操作
+                                    NetApi.getKeyInfo(rfid) { keyInfo ->
+                                        LogUtil.i("getKeyInfo : $rfid - ${keyInfo?.macAddress}")
+                                        HardwareMode.getCurrentHardwareMode().updateKeyNewHardware(
+                                            dockBean.addr,
+                                            key.idx,
+                                            keyInfo == null || keyInfo.keyNfc?.isEmpty() == true || keyInfo.macAddress?.isEmpty() == true
+                                        )
+                                        LogUtil.i("钥匙是否为新设备:${keyInfo == null || keyInfo.keyNfc?.isEmpty() == true || keyInfo.macAddress?.isEmpty() == true}")
+                                        if (keyInfo != null && !keyInfo.macAddress.isNullOrEmpty()) {
+                                            // 更新底座蓝牙Mac信息
+                                            HardwareMode.getCurrentHardwareMode().updateKeyMac(dockBean.addr, key.idx, keyInfo.macAddress)
+                                            HardwareMode.getCurrentHardwareMode().controlKeyBuckle(false, key.idx, dockBean.addr)
+                                            ThreadUtils.runOnIO {
+                                                delay(1000)
+                                                // 已经初始化完成才会去连接
+                                                HardwareMode.getCurrentHardwareMode().controlKeyCharge(true, key.idx, dockBean.addr)
+                                            }
+                                        } else {
+                                            ToastUtils.tip(R.string.get_key_info_fail)
+                                            HardwareMode.getCurrentHardwareMode().controlKeyLockAndCharge(true, key.idx, dockBean.addr)
+                                        }
+                                        val isKeyReady = HardwareMode.getCurrentHardwareMode().getKeyDockData().all {
+                                            it.keyData.filter { it.type == DeviceConst.DEVICE_TYPE_KEY }
+                                                .filterIsInstance<DockBean.KeyBean>()
+                                                .filter { it.isExist }
+                                                .all {
+                                                    LogUtil.i("钥匙信息:${it.rfid}")
+                                                    it.rfid?.isNotEmpty() == true
+                                                }
+                                        }
+                                        LogUtil.i("钥匙是否准备完毕:${isKeyReady}")
+                                        if (isKeyReady) {
+                                            ISCSDomainData.canInitDevice = true
+                                            LogUtil.i("发送初始化完成事件")
+                                            BusinessManager.sendEventMsg(MsgEvent(MsgEventConstants.MSG_EVENT_INIT_KEY_COMPLETE, null))
+                                        }
+                                    }
+                                }
+                        } else {
+                            HardwareMode.getCurrentHardwareMode()
+                                .controlKeyBuckle(true, key.idx, dockBean.addr)
+                            val isKeyReady =
+                                HardwareMode.getCurrentHardwareMode().getKeyDockData()
+                                    .all {
+                                        it.keyData.filter { it.type == DeviceConst.DEVICE_TYPE_KEY }
+                                            .filterIsInstance<DockBean.KeyBean>()
+                                            .filter { it.isExist }
+                                            .all {
+                                                LogUtil.i("钥匙信息:${it.rfid}")
+                                                it.rfid?.isNotEmpty() == true
+                                            }
+                                    }
+                            LogUtil.i("钥匙是否准备完毕:${isKeyReady}")
+                        }
+
+                    }
+                }
+            }
+        }
     }
 
     private fun stopPolling() {
         pollJob?.cancel()
         pollJob = null
-        logger.info("CAN poll stopped.")
+        LogUtil.i("CAN poll stopped.")
     }
 
     /** 一次性读取:超时返回 null,不抛异常、不打崩循环 */
@@ -333,17 +286,11 @@ class CanReadyPlugin : CommPlugin {
                 }
             }.also { rsp ->
                 if (rsp == null) {
-                    logger.debug(
-                        "read timeout node={} idx=0x{} sub=0x{}",
-                        req.nodeId, req.index.toString(16), req.subIndex.toString(16)
-                    )
+                    LogUtil.d("read timeout node=${req.nodeId} idx=0x${req.index.toString(16)} sub=0x${req.subIndex.toString(16)}")
                 }
             }
         } catch (t: Throwable) {
-            logger.warn(
-                "read exception node={} idx=0x{} sub=0x{} : {}",
-                req.nodeId, req.index.toString(16), req.subIndex.toString(16), t.toString()
-            )
+            LogUtil.w("read exception node=${req.nodeId} idx=0x${req.index.toString(16)} sub=0x${req.subIndex.toString(16)} : ${t.toString()}")
             null
         }
     }

+ 1 - 1
app/src/main/java/com/grkj/iscs_mars/can/CustomCanConfig.kt

@@ -26,7 +26,7 @@ class CustomCanConfig : CanConfig(
     /**
      * 状态读取插件
      */
-    private val canReadyPlugin = CanReadyPlugin()
+    val canReadyPlugin = CanReadyPlugin()
 
     override val additionalInterceptors: List<CommInterceptor>
         get() = super.additionalInterceptors + canSendDelayInterceptor

+ 1 - 1
app/src/main/java/com/grkj/iscs_mars/can/DeviceModel.kt

@@ -56,7 +56,7 @@ sealed class DeviceModel {
     var deviceChange: Boolean = false
         set(value) {
             if (field != value) {
-                android.util.Log.e("DeviceChange", "targetParam changed: $field -> $value\n" + android.util.Log.getStackTraceString(Exception("who touched targetParam")))
+                android.util.Log.e("DeviceChange", "targetParam changed: $field -> $value")
             }
             field = value
         }

+ 5 - 9
app/src/main/java/com/grkj/iscs_mars/can/IHardwareHelper.kt

@@ -27,15 +27,6 @@ interface IHardwareHelper {
         exceptionLocks: MutableList<String>
     ): MutableMap<Any, MutableList<Pair<Int, String>>>
 
-    /**
-     * 获取钥匙
-     */
-    suspend fun getOneKey(
-        exceptionSlots: List<CabinetSlotsRecord>,
-        exceptionKeysRfid: List<String>,
-        exceptionKeysMac: List<String> = mutableListOf()
-    ): Pair<Any, String?>?
-
     /**
      * 根据钥匙的MAC地址获取RFID
      */
@@ -189,6 +180,11 @@ interface IHardwareHelper {
      */
     fun updateKeyReadyStatus(mac: String, isReady: Boolean, from: Int)
 
+    /**
+     * 更新所有状态
+     */
+    fun updateAllBuckleStatus(done: () -> Unit)
+
     /**
      * 获取基座数据
      */

+ 6 - 0
app/src/main/java/com/grkj/iscs_mars/model/ISCSDomainData.kt

@@ -7,6 +7,7 @@ import com.grkj.iscs_mars.enums.NoKeyReason
  * 业务数据
  */
 object ISCSDomainData {
+
     /**
      * 设备是否初始化完成
      */
@@ -31,4 +32,9 @@ object ISCSDomainData {
      * 无钥匙原因
      */
     var noKeyReason: NoKeyReason = NoKeyReason.NONE
+
+    /**
+     * can初始化设备
+     */
+    var canInitDevice: Boolean = false
 }

+ 3 - 7
app/src/main/java/com/grkj/iscs_mars/model/bo/WorkTicketGetBO.kt

@@ -90,6 +90,7 @@ class WorkTicketGetBO {
 
     // 判断是否有closed字段为0的
     suspend fun hasFinished(): Pair<Boolean, Boolean> {
+        LogUtil.i("hasFinished ${toString()}")
         // 如果没有数据,默认本地完成且远程未完成
         if (data.isNullOrEmpty()) return true to false
 
@@ -112,17 +113,12 @@ class WorkTicketGetBO {
             val (localTicketFinish, remoteTicketFinished) = suspendCoroutine<Pair<Boolean, Boolean>> { cont ->
                 NetApi.getTicketDetail(item.taskCode?.toLong() ?: 0) { res, code ->
                     LogUtil.i("作业票状态: ${res?.ticketStatus}")
-                    if (res?.ticketStatus in listOf(
-                            "5",
-                            "6"
-                        ) || code == 500
-                    ) {
+                    if (res?.ticketStatus in listOf("5", "6") || code == 500) {
                         // 只要远程状态是 5 或 6,就认为 remoteTicketFinished = true
                         cont.resume(true to true)
                     } else {
                         // 否则,用本地 dataList 的所有 closed 字段判断 localTicketFinish,本地没完成就返回 false
-                        val allClosed =
-                            item.dataList?.all { it.closed == 1 && it.status == it.target } == true
+                        val allClosed = item.dataList?.all { it.closed == 1 && it.status == it.target } == true
                         cont.resume(allClosed to false)
                     }
                 }

+ 0 - 1
app/src/main/java/com/grkj/iscs_mars/presentation/PresentationLoginActivity.kt

@@ -63,7 +63,6 @@ class PresentationLoginActivity : BaseActivity<ActivityPresentationLoginBinding>
 
         handleLoading(true, "正在初始化设备...")
         BusinessManager.connectDock(true)
-        // TODO 时间需要由ModBusController重置后来通知
         Executor.delayOnMain(2000) {
             handleLoading(false)
         }

+ 6 - 5
app/src/main/java/com/grkj/iscs_mars/service/CheckKeyInfoTask.kt

@@ -3,6 +3,7 @@ package com.grkj.iscs_mars.service
 import android.annotation.SuppressLint
 import com.grkj.iscs_mars.ble.BleSendDispatcher
 import com.grkj.iscs_mars.modbus.ModBusController
+import com.grkj.iscs_mars.util.log.LogUtil
 import com.sik.cronjob.annotations.CronJob
 import kotlinx.coroutines.*
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -71,7 +72,7 @@ class CheckKeyInfoTask {
      */
     @SuppressLint("MissingPermission")
     private suspend fun safeCheckKeyInfo() = runMutex.withLock {
-        logger.info("开始检查钥匙信息")
+        LogUtil.i("开始检查钥匙信息")
         awaitLogin()
 
         for (bean in ModBusController.getExistsKey()) {
@@ -79,7 +80,7 @@ class CheckKeyInfoTask {
             handleSingleMac(mac) // 串行执行
         }
 
-        logger.info("检查钥匙信息结束")
+        LogUtil.i("检查钥匙信息结束")
     }
 
     /**
@@ -91,7 +92,7 @@ class CheckKeyInfoTask {
         waitUntilCanConnect()
 
         if (!isInLogin) {
-            logger.info("检测到不在登录页,暂停检查;mac=$mac")
+            LogUtil.i("检测到不在登录页,暂停检查;mac=$mac")
             awaitLogin()
         }
 
@@ -122,9 +123,9 @@ class CheckKeyInfoTask {
      */
     private suspend fun awaitLogin() {
         if (loginGate.value) return
-        logger.info("不在登录页,挂起等待 …")
+        LogUtil.i("不在登录页,挂起等待 …")
         loginGate.first { it } // 挂起直到变为 true
-        logger.info("登录页已就绪,恢复检查")
+        LogUtil.i("登录页已就绪,恢复检查")
     }
 
     /**

+ 5 - 19
app/src/main/java/com/grkj/iscs_mars/view/activity/HomeActivity.kt

@@ -7,11 +7,10 @@ import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.Observer
 import com.grkj.iscs_mars.BusinessManager
 import com.grkj.iscs_mars.R
-import com.grkj.iscs_mars.can.CanHardwareHelper
 import com.grkj.iscs_mars.databinding.ActivityHomeBinding
+import com.grkj.iscs_mars.enums.HardwareMode
 import com.grkj.iscs_mars.extentions.toByteArrays
 import com.grkj.iscs_mars.extentions.toHexStrings
-import com.grkj.iscs_mars.modbus.ModBusController
 import com.grkj.iscs_mars.model.Constants.USER_ROLE_ADMHDWSETTER
 import com.grkj.iscs_mars.model.Constants.USER_ROLE_ADMHDWTESTER
 import com.grkj.iscs_mars.model.Constants.USER_ROLE_COLOCKER
@@ -36,8 +35,6 @@ import com.grkj.iscs_mars.view.fragment.ExceptionReportFragment
 import com.grkj.iscs_mars.view.fragment.JobManagementFragment
 import com.grkj.iscs_mars.view.fragment.SettingFragment
 import com.grkj.iscs_mars.view.fragment.SystemSettingFragment
-import com.grkj.iscs_mars.view.fragment.TempJobFragment
-import com.grkj.iscs_mars.view.fragment.TempJobManagementFragment
 import com.grkj.iscs_mars.view.iview.IHomeView
 import com.grkj.iscs_mars.view.presenter.HomePresenter
 import com.zhy.adapter.recyclerview.CommonAdapter
@@ -78,18 +75,6 @@ class HomeActivity : BaseMvpActivity<IHomeView, HomePresenter, ActivityHomeBindi
                     )
                 )
             }
-            // 临时作业入口
-//            if (userInfo.roles?.any { it == USER_ROLE_DRAWER || it == USER_ROLE_LOCKER || it == USER_ROLE_COLOCKER || it == USER_ROLE_GUARD } == true) {
-//                mMenuList.addAll(
-//                    mutableListOf(
-//                        Menu(
-//                            "临时作业",
-//                            R.mipmap.job_management,
-//                            TempJobManagementFragment()
-//                        )
-//                    )
-//                )
-//            }
             if (userInfo.roles?.any { it == USER_ROLE_ADMHDWTESTER } == true) {
                 BusinessManager.isTestMode = true
                 mMenuList.add(
@@ -184,7 +169,8 @@ class HomeActivity : BaseMvpActivity<IHomeView, HomePresenter, ActivityHomeBindi
         }
 
         BusinessManager.mEventBus.observe(this, observer)
-        ModBusController.updateAllBuckleStatus {}
+        // 执行一次状态初始化操作
+        HardwareMode.getCurrentHardwareMode().updateAllBuckleStatus { }
     }
 
     override fun dispatchKeyEvent(event: KeyEvent): Boolean {
@@ -199,13 +185,13 @@ class HomeActivity : BaseMvpActivity<IHomeView, HomePresenter, ActivityHomeBindi
                 }
                 if (cardNo == null) {
                     ToastUtils.tip(R.string.card_invalid)
-                    return super.dispatchKeyEvent(event)
+                    return false
                 }
                 LogUtil.i("Swipe card home: $cardNo")
                 cardNoLiveData.postValue(cardNo)
                 // 重置cardNo
                 cardNo = ""
-                return super.dispatchKeyEvent(event)
+                return false
             }
             cardNo += event.keyCharacterMap.getDisplayLabel(event.keyCode)
         }

+ 0 - 5
app/src/main/java/com/grkj/iscs_mars/view/activity/LoginActivity.kt

@@ -34,11 +34,6 @@ class LoginActivity : BaseMvpActivity<ILoginView, LoginPresenter, ActivityLoginB
         mBinding?.vp2?.offscreenPageLimit = 1 // 只两页,提前缓存,不卡顿
         mBinding?.vp2?.isUserInputEnabled = false
 
-        // TODO 只适配armeabi-v7a
-
-        if (ModBusController.isRunning() != true) {
-            BusinessManager.connectDock(true)
-        }
         presenter?.downloadLicense()
         presenter?.registerListener()
         FingerprintUtil.init(this)

+ 10 - 5
app/src/main/java/com/grkj/iscs_mars/view/activity/MainActivity.kt

@@ -1,17 +1,22 @@
 package com.grkj.iscs_mars.view.activity
 
 import android.content.Intent
-import com.grkj.iscs_mars.view.activity.test.face.FaceActivity
-import com.grkj.iscs_mars.view.base.BaseActivity
+import android.util.Log
+import androidx.lifecycle.lifecycleScope
+import com.grkj.iscs_mars.ble.BleSendDispatcher
 import com.grkj.iscs_mars.databinding.ActivityMainBinding
 import com.grkj.iscs_mars.presentation.PresentationActivity
 import com.grkj.iscs_mars.presentation.PresentationLoginActivity
-import com.grkj.iscs_mars.view.activity.test.RfidActivity
 import com.grkj.iscs_mars.view.activity.test.ModbusActivity
-import com.grkj.iscs_mars.view.activity.test.WidgetTestActivity
+import com.grkj.iscs_mars.view.activity.test.RfidActivity
 import com.grkj.iscs_mars.view.activity.test.WebSocketActivity
+import com.grkj.iscs_mars.view.activity.test.WidgetTestActivity
+import com.grkj.iscs_mars.view.activity.test.face.FaceActivity
 import com.grkj.iscs_mars.view.activity.test.face.arcsoft.ArcsoftTestActivity
 import com.grkj.iscs_mars.view.activity.test.fingerprint.FingerPrintActivity
+import com.grkj.iscs_mars.view.base.BaseActivity
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
 
 class MainActivity : BaseActivity<ActivityMainBinding>() {
 
@@ -48,7 +53,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
         }
 
         mBinding?.login?.setOnClickListener {
-            startActivity(Intent(this, LoginActivity::class.java))
+             startActivity(Intent(this, LoginActivity::class.java))
         }
 
         mBinding?.createTicket?.setOnClickListener {

+ 16 - 12
app/src/main/java/com/grkj/iscs_mars/view/fragment/DeviceStatusFragment.kt

@@ -2,11 +2,13 @@ package com.grkj.iscs_mars.view.fragment
 
 import android.content.Context
 import android.content.res.ColorStateList
+import android.util.Log
 import android.view.View
 import android.widget.ImageView
 import androidx.core.content.ContextCompat
 import androidx.recyclerview.widget.RecyclerView
 import com.grkj.iscs_mars.R
+import com.grkj.iscs_mars.can.CanHardwareHelper
 import com.grkj.iscs_mars.databinding.FragmentDeviceStatusBinding
 import com.grkj.iscs_mars.extentions.setSelected
 import com.grkj.iscs_mars.extentions.setVisibleWithHolder
@@ -161,22 +163,21 @@ class DeviceStatusFragment :
             ContextCompat.getColor(context, R.color.common_status_red)
         private val statusOpenTintColor =
             ContextCompat.getColor(context, R.color.common_status_green)
+        private val canHelper = CanHardwareHelper()
 
         override fun getItemViewLayoutId(): Int {
             return R.layout.item_rv_key_dock_status
         }
 
         override fun convert(holder: ViewHolder?, row: DockStatusBO, position: Int) {
+            val dock = row.dockList[position]
+            val keyDatas = canHelper.getKeyDockData().find { it.addr == 1 }
+            val left1 = keyDatas?.keyData?.find { it.idx == 0 }
+            val left2 = keyDatas?.keyData?.find { it.idx == 1 }
             holder?.setVisibleWithHolder(R.id.ll_left, row.dockList.any { it.column == "1" })
             holder?.setVisibleWithHolder(R.id.ll_right, row.dockList.any { it.column == "2" })
-            holder?.setSelected(
-                R.id.iv_key_1,
-                ModBusController.isKeyExist(row.dockList.find { it.column == "1" }?.address, true)
-            )
-            holder?.setSelected(
-                R.id.iv_key_2,
-                ModBusController.isKeyExist(row.dockList.find { it.column == "1" }?.address, false)
-            )
+            holder?.setSelected(R.id.iv_key_1, left1?.isExist ?: false)
+            holder?.setSelected(R.id.iv_key_2, left2?.isExist ?: false)
             holder?.setSelected(
                 R.id.iv_key_3,
                 ModBusController.isKeyExist(row.dockList.find { it.column == "2" }?.address, true)
@@ -392,12 +393,16 @@ class DeviceStatusFragment :
         private val statusNotLightTintColor =
             ContextCompat.getColor(context, R.color.common_status_not_light)
 
+        private val canHelper = CanHardwareHelper()
+
         override fun getItemViewLayoutId(): Int {
             return R.layout.item_rv_lock_dock_status
         }
 
         override fun convert(holder: ViewHolder?, row: DockStatusBO, position: Int) {
             val rv = holder?.getView<RecyclerView>(R.id.rv_root)
+            val lockDockData = canHelper.getLockDockData().find { it.addr == 2 }
+            val lockList = lockDockData?.lockData ?: emptyList()
             rv?.adapter = object :
                 CommonAdapter<Int>(
                     ctx,
@@ -405,10 +410,9 @@ class DeviceStatusFragment :
                     row.dockList[0].deviceList
                 ) {
                 override fun convert(holder: ViewHolder?, lockIdx: Int, position: Int) {
-                    holder?.setSelected(
-                        R.id.root,
-                        ModBusController.isLockExist(row.dockList[0].address, lockIdx)
-                    )
+                    val key = lockList.find { it.idx == (lockIdx + 1) }
+                    // 配置锁是否存在
+                    holder?.setSelected(R.id.root, key?.isExist ?: false)
                     holder?.convertView?.setOnLongClickListener {
                         presenter?.slotType?.find { it.dictLabel == "锁" }?.dictValue?.let {
                             presenter?.mExceptionReporter?.invoke(

+ 6 - 0
app/src/main/java/com/grkj/iscs_mars/view/fragment/LoginFragment.kt

@@ -2,11 +2,15 @@ package com.grkj.iscs_mars.view.fragment
 
 import android.content.Intent
 import android.widget.ImageView
+import androidx.lifecycle.lifecycleScope
 import androidx.viewpager2.widget.ViewPager2
 import com.arcsoft.face.FaceEngine
 import com.arcsoft.face.model.ActiveDeviceInfo
 import com.grkj.iscs_mars.BusinessManager
 import com.grkj.iscs_mars.R
+import com.grkj.iscs_mars.ble.BleCmdManager
+import com.grkj.iscs_mars.ble.BleConnectionManager
+import com.grkj.iscs_mars.ble.BleSendDispatcher
 import com.grkj.iscs_mars.databinding.FragmentLoginBinding
 import com.grkj.iscs_mars.extentions.serialNo
 import com.grkj.iscs_mars.model.vo.user.UserInfoRespVO
@@ -23,6 +27,8 @@ import com.sik.sikcore.extension.setDebouncedClickListener
 import com.sik.sikcore.shell.ShellUtils
 import com.zhy.adapter.recyclerview.CommonAdapter
 import com.zhy.adapter.recyclerview.base.ViewHolder
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
 
 class LoginFragment :
     BaseMvpFragment<ILoginView, LoginPresenter, FragmentLoginBinding>() {

+ 12 - 1
app/src/main/java/com/grkj/iscs_mars/view/fragment/SwitchStatusFragment.kt

@@ -1,10 +1,13 @@
 package com.grkj.iscs_mars.view.fragment
 
+import android.bluetooth.BluetoothGatt
+import android.util.Log
 import android.view.GestureDetector
 import android.view.Gravity
 import android.view.MotionEvent
 import android.widget.LinearLayout
 import androidx.core.view.isVisible
+import androidx.lifecycle.lifecycleScope
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.viewpager2.widget.ViewPager2
 import com.drake.brv.BindingAdapter
@@ -15,6 +18,10 @@ import com.drake.brv.utils.models
 import com.drake.brv.utils.setup
 import com.grkj.iscs_mars.BusinessManager
 import com.grkj.iscs_mars.R
+import com.grkj.iscs_mars.ble.BleSendDispatcher
+import com.grkj.iscs_mars.ble.BleUtil
+import com.grkj.iscs_mars.ble.CustomBleGattCallback
+import com.grkj.iscs_mars.ble.CustomBleScanCallback
 import com.grkj.iscs_mars.databinding.FragmentSwitchStatusBinding
 import com.grkj.iscs_mars.databinding.ItemMapBinding
 import com.grkj.iscs_mars.databinding.ItemSwitchBinding
@@ -30,9 +37,13 @@ import com.grkj.iscs_mars.view.dialog.SwitchInfoDialog
 import com.grkj.iscs_mars.view.iview.ISwitchStatusView
 import com.grkj.iscs_mars.view.presenter.SwitchStatusPresenter
 import com.grkj.iscs_mars.view.widget.CustomSwitchStationLayer
+import com.huyuhui.fastble.data.BleDevice
+import com.huyuhui.fastble.exception.BleException
 import com.onlylemi.mapview.library.MapViewListener
 import com.sik.sikcore.extension.setDebouncedClickListener
 import com.sik.sikcore.thread.ThreadUtils
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
 
 class SwitchStatusFragment :
     BaseMvpFragment<ISwitchStatusView, SwitchStatusPresenter, FragmentSwitchStatusBinding>() {
@@ -68,7 +79,7 @@ class SwitchStatusFragment :
                 }
             })
         mBinding?.cbLogin?.setDebouncedClickListener {
-            vp2?.currentItem = 1
+              vp2?.currentItem = 1
         }
         mBinding?.cbShow?.setDebouncedClickListener {
             if (mBinding?.pointList?.isVisible == true) {

+ 46 - 3
app/src/main/java/com/grkj/iscs_mars/view/presenter/HomePresenter.kt

@@ -1,14 +1,17 @@
 package com.grkj.iscs_mars.view.presenter
 
+import android.util.Log
 import com.grkj.iscs_mars.BusinessManager
 import com.grkj.iscs_mars.MyApplication
 import com.grkj.iscs_mars.R
 import com.grkj.iscs_mars.ble.BleReturnDispatcher
+import com.grkj.iscs_mars.can.CanDeviceConst
+import com.grkj.iscs_mars.can.DeviceModel
+import com.grkj.iscs_mars.enums.HardwareMode
 import com.grkj.iscs_mars.extentions.serialNo
 import com.grkj.iscs_mars.modbus.DockBean
 import com.grkj.iscs_mars.modbus.ModBusController
 import com.grkj.iscs_mars.model.DeviceConst
-import com.grkj.iscs_mars.model.DeviceConst.DOCK_TYPE_KEY
 import com.grkj.iscs_mars.model.DictAndSystemConstants
 import com.grkj.iscs_mars.model.ISCSDomainData
 import com.grkj.iscs_mars.util.CommonUtils
@@ -27,8 +30,48 @@ class HomePresenter : BasePresenter<IHomeView>() {
      * 注册设备状态监听
      */
     fun registerStatusListener() {
-        BusinessManager.registerStatusListener(this) { dockBean ->
-
+        BusinessManager.registerStatusListener(this) { devices ->
+            if (!BusinessManager.CAN_RETURN || ISCSDomainData.isDeviceRegistration) return@registerStatusListener
+            devices.filterIsInstance<DeviceModel.DeviceKey>().forEach { device ->
+                if (device.deviceType == CanDeviceConst.DEVICE_KEY_DOCK) {
+                    if (device.isExist && device.deviceChange) {
+                        LogUtil.i("HomePresenter $device")
+                        Executor.repeatOnMain({
+                            // 标记当前状态为无变化
+                            device.deviceChange = false
+                            if (device.mac.isNotEmpty()) {
+                                ThreadUtils.runOnIO {
+                                    fun readJobTicket(mac: String) {
+                                        BleReturnDispatcher.submit(mac) { isConnect ->
+                                            if (isConnect) {
+                                                val bleBean = BusinessManager.getBleDeviceByMac(mac)
+                                                Executor.delayOnMain(300) {
+                                                    bleBean?.let {
+                                                        BusinessManager.sendLoadingEventMsg(
+                                                            mContext?.getString(
+                                                                R.string.loading_msg_get_ticket_status_start
+                                                            )
+                                                        )
+                                                        BusinessManager.getCurrentStatus(4, it.bleDevice)
+                                                    }
+                                                }
+                                            } else {
+                                                HardwareMode.getCurrentHardwareMode().controlKeyBuckle(true, mac) {
+                                                    ToastUtils.tip(CommonUtils.getStr(R.string.ticket_get_failed).toString())
+                                                }
+                                            }
+                                        }
+                                    }
+                                    if (!ISCSDomainData.isDeviceRegistration) {
+                                        readJobTicket(device.mac)
+                                    }
+                                }
+                            }
+                            return@repeatOnMain device.mac.isEmpty()
+                        }, 1000, true)
+                    }
+                }
+            }
         }
     }
 

+ 12 - 27
app/src/main/java/com/grkj/iscs_mars/view/presenter/JobProgressPresenter.kt

@@ -1,12 +1,13 @@
 package com.grkj.iscs_mars.view.presenter
 
 import android.content.Context
+import android.util.Log
 import com.grkj.iscs_mars.BusinessManager
 import com.grkj.iscs_mars.R
+import com.grkj.iscs_mars.enums.HardwareMode
 import com.grkj.iscs_mars.enums.NoKeyReason
 import com.grkj.iscs_mars.extentions.serialNo
 import com.grkj.iscs_mars.modbus.DockBean
-import com.grkj.iscs_mars.modbus.ModBusController
 import com.grkj.iscs_mars.model.Constants.JOB_STATUS_ACQUIRE_KEY
 import com.grkj.iscs_mars.model.Constants.JOB_STATUS_ACQUIRE_LOCK
 import com.grkj.iscs_mars.model.Constants.JOB_STATUS_NOT_STARTED
@@ -299,13 +300,9 @@ class JobProgressPresenter : BasePresenter<IJobProgressView>() {
                 )
             })
             // 开锁卡扣
-            ModBusController.controlLockBuckle(true, addr, mLockList.map { it.idx }.toMutableList())
+            HardwareMode.getCurrentHardwareMode().controlLockBuckle(true, addr.toInt(), mLockList.map { it.idx }.toMutableList())
             mLockList.forEach { itLock ->
-                BusinessManager.addDeviceTake(
-                    DEVICE_TYPE_LOCK,
-                    ticketDetail.ticketId!!,
-                    itLock.rfid
-                )
+                BusinessManager.addDeviceTake(DEVICE_TYPE_LOCK, ticketDetail.ticketId!!, itLock.rfid)
             }
         }
         if (lockList.isNotEmpty()) {
@@ -321,29 +318,16 @@ class JobProgressPresenter : BasePresenter<IJobProgressView>() {
                 BusinessManager.sendLoadingEventMsg(null, false)
             }
         } else {
-            BusinessManager.addDeviceTake(
-                DEVICE_TYPE_KEY,
-                ticketDetail.ticketId!!,
-                keyPair.second?.rfid!!
-            )
-            //如果挂锁都已经取了,并且点位不都是冲突点位,直接开始检查是否下发作业票
+            BusinessManager.addDeviceTake(DEVICE_TYPE_KEY, ticketDetail.ticketId!!, keyPair.second?.rfid!!)
+            // 如果挂锁都已经取了,并且点位不都是冲突点位,直接开始检查是否下发作业票
             if (ticketDetail.ticketLockVOList?.all { it.lockId != null } == true &&
-                ticketDetail.ticketPointsVOList?.map { it.pointId }?.all {
-                    ticketDetail.noUnlockTicketPointsVOSet?.map { it.pointId }?.contains(it) == true
-                } == false
+                ticketDetail.ticketPointsVOList?.map { it.pointId }
+                    ?.all { ticketDetail.noUnlockTicketPointsVOSet?.map { it.pointId }?.contains(it) == true } == false
             ) {
-                BusinessManager.getCurrentStatus(
-                    5,
-                    BusinessManager.getBleDeviceByMac(keyPair.second?.mac)!!.bleDevice
-                ) {
-                    if (!it) {
-                        return@getCurrentStatus
-                    }
+                BusinessManager.getCurrentStatus(5, BusinessManager.getBleDeviceByMac(keyPair.second?.mac)!!.bleDevice) {
+                    if (!it) return@getCurrentStatus
                     LogUtil.w("handleUnlockProcess timeout")
-                    BusinessManager.removeDeviceTake(
-                        DEVICE_TYPE_KEY,
-                        keyPair.second?.rfid!!
-                    )
+                    BusinessManager.removeDeviceTake(DEVICE_TYPE_KEY, keyPair.second?.rfid!!)
                     handleUnlockProcess(ticketDetail.ticketId, keyPair.second?.rfid!!)
                 }
             }
@@ -418,6 +402,7 @@ class JobProgressPresenter : BasePresenter<IJobProgressView>() {
 
     private fun showKeyErrorDialog(keyRfid: String) {
         Executor.runOnMain {
+            // 钥匙分配失败
             tipDialog ?: let {
                 tipDialog = TipDialog(mContext!!)
                 tipDialog?.setTip(mContext!!.getString(R.string.key_take_error_tip))