瀏覽代碼

refactor(开关和设备异常)
- 开关和设备异常完成

周文健 5 月之前
父節點
當前提交
25724a8e2f

+ 118 - 183
app/src/main/java/com/grkj/iscs/BusinessManager.kt

@@ -73,8 +73,10 @@ import com.grkj.iscs.view.dialog.TipDialog
 import com.sik.sikcore.activity.ActivityTracker
 import com.sik.sikcore.date.TimeUtils
 import com.sik.sikcore.thread.ThreadUtils
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.withContext
 import pub.devrel.easypermissions.AfterPermissionGranted
-import java.time.LocalDateTime
 
 /**
  * 业务层管理
@@ -223,7 +225,8 @@ object BusinessManager {
                         val switchListReqVOS = ModBusController.getSwitchData().map {
                             SwitchListReqVO(
                                 it.idx.toString(),
-                                if (it.enabled) switchStatus?.find { it.dictLabel == "打开" }?.dictValue else switchStatus?.find { it.dictLabel == "关闭" }?.dictValue
+                                if (it.enabled) switchStatus?.find { it.dictLabel == "打开" }?.dictValue else switchStatus?.find { it.dictLabel == "关闭" }?.dictValue,
+                                TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT)
                             )
                         }
                         NetApi.updateSwitchList(switchListReqVOS) {
@@ -435,15 +438,11 @@ object BusinessManager {
                                         )
                                         NetApi.getKeyInfo(rfid) {
                                             ModBusController.updateKeyNewHardware(
-                                                dockBean.addr,
-                                                true,
-                                                it == null
+                                                dockBean.addr, true, it == null
                                             )
                                             if (it != null && !it.macAddress.isNullOrEmpty()) {
                                                 ModBusController.updateKeyMac(
-                                                    dockBean.addr,
-                                                    isLeft,
-                                                    it.macAddress
+                                                    dockBean.addr, isLeft, it.macAddress
                                                 )
 //                                                    showKeyReturnDialog(it.macAddress, isLeft, dockBean.addr)
                                             } else {
@@ -456,8 +455,7 @@ object BusinessManager {
 
                                 DEVICE_TYPE_LOCK -> {
                                     ModBusController.readLockRfid(
-                                        dockBean.addr,
-                                        deviceBean.idx
+                                        dockBean.addr, deviceBean.idx
                                     ) { res ->
                                         if (res.size < 11) {
                                             LogUtil.e("Lock rfid error")
@@ -466,23 +464,17 @@ object BusinessManager {
                                         val rfid = res.copyOfRange(3, 11).toHexStrings(false)
                                             .removeLeadingZeros()
                                         ModBusController.updateLockRfid(
-                                            dockBean.addr,
-                                            deviceBean.idx,
-                                            rfid
+                                            dockBean.addr, deviceBean.idx, rfid
                                         )
 
                                         NetApi.getLockInfo(rfid) {
                                             ModBusController.updateLockNewHardware(
-                                                dockBean.addr,
-                                                deviceBean.idx,
-                                                it == null
+                                                dockBean.addr, deviceBean.idx, it == null
                                             )
                                             if (it != null) {
                                                 // TODO 考虑快速拿取
                                                 ModBusController.controlLockBuckle(
-                                                    false,
-                                                    dockBean.addr,
-                                                    deviceBean.idx
+                                                    false, dockBean.addr, deviceBean.idx
                                                 ) { itRst ->
                                                     if (itRst.isNotEmpty()) {
                                                         // 上报锁具信息
@@ -630,55 +622,61 @@ object BusinessManager {
         var lockCount = 0
         NetApi.getIsLockCabinetSlotsPage { slots ->
             NetApi.getIsLockPage { locks ->
-                val lockMap = ModBusController.getLocks(
-                    needLockCount,
-                    slots?.records?.filter { it.slotType == "1" && it.status == "1" }
-                        ?.toMutableList()
-                        ?: mutableListOf(),
-                    locks?.records?.filter { it.exStatus == "1" }?.map { it.lockNfc }
-                        ?.toMutableList()
-                        ?: mutableListOf()
-                )
-                lockMap.forEach { (_, rfidList) ->
-                    lockCount += rfidList.size
-                }
+                ThreadUtils.runOnIO {
+                    val lockStatus = NetApi.getDictData(DictConstants.KEY_PAD_LOCK_STATUS)
+                    val slotsStatus = NetApi.getDictData(DictConstants.KEY_SLOT_STATUS)
+                    val keyStatus = NetApi.getDictData(DictConstants.KEY_KEY_STATUS)
+                    val slotsType = NetApi.getDictData(DictConstants.KEY_SLOT_TYPE)
+                    val lockMap = ModBusController.getLocks(
+                        needLockCount,
+                        slots?.records?.filter { it.slotType == slotsType?.find { it.dictLabel == "锁" }?.dictValue && it.status == slotsStatus?.find { it.dictLabel == "异常" }?.dictValue }
+                            ?.toMutableList() ?: mutableListOf(),
+                        locks?.records?.filter { it.exStatus == lockStatus?.find { it.dictLabel == "异常" }?.dictValue }
+                            ?.map { it.lockNfc }?.toMutableList() ?: mutableListOf()
+                    )
+                    lockMap.forEach { (_, rfidList) ->
+                        lockCount += rfidList.size
+                    }
 
-                var tipStr = ""
-                if (lockCount < needLockCount) {
-                    val msg =
-                        MyApplication.instance!!.applicationContext.resources.getString(R.string.lock_is_not_enough)
-                    LogUtil.w(msg)
-                    lockMap.clear()
-                }
+                    var tipStr = ""
+                    if (lockCount < needLockCount) {
+                        val msg =
+                            MyApplication.instance!!.applicationContext.resources.getString(R.string.lock_is_not_enough)
+                        LogUtil.w(msg)
+                        lockMap.clear()
+                    }
 
-                var key: Pair<Byte, DockBean.KeyBean?>? = null
-                if (isNeedKey && lockCount >= needLockCount) {
-                    NetApi.getIsKeyPage { keyList ->
-                        key = ModBusController.getOneKey(
-                            slots?.records?.filter { it.slotType == "0" && it.status == "1" }
-                                ?.toMutableList()
-                                ?: mutableListOf(),
-                            keyList?.records?.filter { it.exStatus == "1" }?.map { it.keyNfc }
-                                ?.toMutableList() ?: mutableListOf()
-                        )
-                        if (key == null) {
-                            val msg =
-                                MyApplication.instance!!.applicationContext.resources.getString(R.string.no_available_key)
-                            LogUtil.w(msg)
-                            tipStr = if (tipStr.isEmpty()) {
-                                msg
-                            } else {
-                                tipStr + "\n" + msg
+                    var key: Pair<Byte, DockBean.KeyBean?>? = null
+                    if (isNeedKey && lockCount >= needLockCount) {
+                        NetApi.getIsKeyPage { keyList ->
+                            key =
+                                ModBusController.getOneKey(slots?.records?.filter { it.slotType == slotsType?.find { it.dictLabel == "钥匙" }?.dictValue && it.status == slotsStatus?.find { it.dictLabel == "异常" }?.dictValue }
+                                    ?.toMutableList() ?: mutableListOf(),
+                                    keyList?.records?.filter { it.exStatus == keyStatus?.find { it.dictLabel == "异常" }?.dictValue }
+                                        ?.map { it.keyNfc }?.toMutableList() ?: mutableListOf())
+                            if (key == null) {
+                                val msg =
+                                    MyApplication.instance!!.applicationContext.resources.getString(
+                                        R.string.no_available_key
+                                    )
+                                LogUtil.w(msg)
+                                tipStr = if (tipStr.isEmpty()) {
+                                    msg
+                                } else {
+                                    tipStr + "\n" + msg
+                                }
                             }
                         }
                     }
-                }
 
-                if (tipStr.isNotEmpty()) {
-                    ToastUtils.tip(tipStr)
+                    withContext(Dispatchers.Main) {
+                        if (tipStr.isNotEmpty()) {
+                            ToastUtils.tip(tipStr)
+                        }
+                        LogUtil.i("checkEquipCount : key = $key, lockMap = $lockMap")
+                        callBack.invoke(key, lockMap)
+                    }
                 }
-                LogUtil.i("checkEquipCount : key = $key, lockMap = $lockMap")
-                callBack.invoke(key, lockMap)
             }
         }
     }
@@ -706,6 +704,7 @@ object BusinessManager {
             connectListeners.add(ConnectListener(mac, callBack))
             if (connectListeners.size > 0) {
                 Executor.runOnMain {
+                    //todo 连接钥匙
                     connectKey()
                 }
             }
@@ -715,6 +714,7 @@ object BusinessManager {
                 connectListeners.add(ConnectListener(mac, callBack))
                 if (connectListeners.size > 0) {
                     Executor.runOnMain {
+                        //todo 连接钥匙
                         connectKey()
                     }
                 }
@@ -768,9 +768,7 @@ object BusinessManager {
             return
         }
         prepareBle(
-            listener.mac,
-            ActivityUtils.currentActivity() as BaseActivity<*>,
-            false
+            listener.mac, ActivityUtils.currentActivity() as BaseActivity<*>, false
         ) { isDone, bleBean ->
             Executor.runOnMain {
                 isPreparing = false
@@ -779,7 +777,10 @@ object BusinessManager {
                     if (checkProcess(listener.mac)) {
                         unregisterConnectListener(listener.mac)
                         Executor.delayOnMain(2000) {
-                            registerConnectListener(listener.mac, listener.callBack)
+                            registerConnectListener(
+                                listener.mac,
+                                listener.callBack
+                            )
                         }
                     }
                     return@runOnMain
@@ -812,13 +813,6 @@ object BusinessManager {
             return
         }
         Executor.runOnMain {
-            // 如果是已经连上的设备,从indicate开始往下走,不需要再扫描了
-//            if (BleManager.getInstance().isConnected(mac)) {
-//                deviceList.find { it.bleDevice.mac == mac }?.let { itBleDevice ->
-//                    indicate(itBleDevice, isNeedLoading, prepareDoneCallBack)
-//                    return@runOnMain
-//                }
-//            }
             CommonUtils.checkBlePermission(activity) {
                 doScanBle(mac, isNeedLoading, prepareDoneCallBack)
             }
@@ -838,8 +832,7 @@ object BusinessManager {
         }
         if (isNeedLoading) sendEventMsg(
             MsgEvent(
-                MSG_EVENT_LOADING,
-                LoadingMsg(true, "正在扫描设备...", null)
+                MSG_EVENT_LOADING, LoadingMsg(true, "正在扫描设备...", null)
             )
         )
         BleUtil.instance?.scan(object : CustomBleScanCallback() {
@@ -854,8 +847,7 @@ object BusinessManager {
                 if (!success) {
                     if (isNeedLoading) sendEventMsg(
                         MsgEvent(
-                            MSG_EVENT_LOADING,
-                            LoadingMsg(false, null, null)
+                            MSG_EVENT_LOADING, LoadingMsg(false, null, null)
                         )
                     )
                     prepareDoneCallBack?.invoke(false, null)
@@ -865,6 +857,7 @@ object BusinessManager {
             override fun onScanning(bleDevice: BleDevice?) {
                 LogUtil.i("onScanning:${bleDevice?.mac}")
                 bleDevice?.let {
+                    deviceList
                     doConnect(it, isNeedLoading, prepareDoneCallBack)
                 }
             }
@@ -873,8 +866,7 @@ object BusinessManager {
                 LogUtil.i("onScanFinished: $mac - ${scanResultList?.none { it.mac == mac }}")
                 if (isNeedLoading) sendEventMsg(
                     MsgEvent(
-                        MSG_EVENT_LOADING,
-                        LoadingMsg(false, null, null)
+                        MSG_EVENT_LOADING, LoadingMsg(false, null, null)
                     )
                 )
                 // 没有扫描到
@@ -907,13 +899,11 @@ object BusinessManager {
         )
         BleManager.getInstance().disconnect(bleDevice)
         BleUtil.instance?.connectBySelect(
-            bleDevice,
-            object : CustomBleGattCallback() {
+            bleDevice, object : CustomBleGattCallback() {
                 override fun onPrompt(promptStr: String?) {
                     if (isNeedLoading) sendEventMsg(
                         MsgEvent(
-                            MSG_EVENT_LOADING,
-                            LoadingMsg(false, promptStr, null)
+                            MSG_EVENT_LOADING, LoadingMsg(false, promptStr, null)
                         )
                     )
                 }
@@ -932,14 +922,11 @@ object BusinessManager {
                 }
 
                 override fun onConnectSuccess(
-                    bleDevice: BleDevice?,
-                    gatt: BluetoothGatt?,
-                    status: Int
+                    bleDevice: BleDevice?, gatt: BluetoothGatt?, status: Int
                 ) {
                     if (isNeedLoading) sendEventMsg(
                         MsgEvent(
-                            MSG_EVENT_LOADING,
-                            LoadingMsg(false, null, null)
+                            MSG_EVENT_LOADING, LoadingMsg(false, null, null)
                         )
                     )
                     LogUtil.i("onConnectSuccess : ${bleDevice?.mac}")
@@ -971,8 +958,7 @@ object BusinessManager {
                 ) {
                     if (isNeedLoading) sendEventMsg(
                         MsgEvent(
-                            MSG_EVENT_LOADING,
-                            LoadingMsg(false, null, false)
+                            MSG_EVENT_LOADING, LoadingMsg(false, null, false)
                         )
                     )
                     LogUtil.i("onDisConnected : ${device?.mac} - $isActiveDisConnected")
@@ -1018,15 +1004,13 @@ object BusinessManager {
         }
         if (isNeedLoading) sendEventMsg(
             MsgEvent(
-                MSG_EVENT_LOADING,
-                LoadingMsg(true, "开始监听...", null)
+                MSG_EVENT_LOADING, LoadingMsg(true, "开始监听...", null)
             )
         )
         bleBean?.let {
             var isIndicateSuccess = false
             BleUtil.instance?.indicate(
-                it.bleDevice,
-                indicateCallback = object : CustomBleIndicateCallback() {
+                it.bleDevice, indicateCallback = object : CustomBleIndicateCallback() {
                     override fun onPrompt(promptStr: String?) {
                         LogUtil.i("indicate onPrompt : $promptStr")
                     }
@@ -1050,8 +1034,7 @@ object BusinessManager {
                     override fun onIndicateFailure(exception: BleException?) {
                         if (isNeedLoading) sendEventMsg(
                             MsgEvent(
-                                MSG_EVENT_LOADING,
-                                LoadingMsg(false, null, false)
+                                MSG_EVENT_LOADING, LoadingMsg(false, null, false)
                             )
                         )
                         LogUtil.e("onIndicateFailure : ${bleBean.bleDevice.mac} - ${exception?.description}")
@@ -1087,8 +1070,7 @@ object BusinessManager {
         }
         if (isNeedLoading) sendEventMsg(
             MsgEvent(
-                MSG_EVENT_LOADING,
-                LoadingMsg(true, "开始获取token...", null)
+                MSG_EVENT_LOADING, LoadingMsg(true, "开始获取token...", null)
             )
         )
         bleBean?.let {
@@ -1096,8 +1078,7 @@ object BusinessManager {
                 override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
                     if (isNeedLoading) sendEventMsg(
                         MsgEvent(
-                            MSG_EVENT_LOADING,
-                            LoadingMsg(false, "token获取成功", null)
+                            MSG_EVENT_LOADING, LoadingMsg(false, "token获取成功", null)
                         )
                     )
                     LogUtil.i("getToken success : ${bleBean.bleDevice.mac}")
@@ -1106,8 +1087,7 @@ object BusinessManager {
                 override fun onWriteFailure(exception: BleException?) {
                     if (isNeedLoading) sendEventMsg(
                         MsgEvent(
-                            MSG_EVENT_LOADING,
-                            LoadingMsg(false, "token获取失败", false)
+                            MSG_EVENT_LOADING, LoadingMsg(false, "token获取失败", false)
                         )
                     )
                     LogUtil.e("getToken fail : ${bleBean.bleDevice.mac}")
@@ -1193,8 +1173,7 @@ object BusinessManager {
      * 读取工作票完成情况
      */
     private fun getTicketStatusBusiness(
-        mac: String,
-        isNeedLoading: Boolean = false
+        mac: String, isNeedLoading: Boolean = false
     ) {
         registerConnectListener(mac) { isDone, bleBean ->
             if (isDone) {
@@ -1204,8 +1183,7 @@ object BusinessManager {
             } else {
                 if (isNeedLoading) sendEventMsg(
                     MsgEvent(
-                        MSG_EVENT_LOADING,
-                        LoadingMsg(false, null, false)
+                        MSG_EVENT_LOADING, LoadingMsg(false, null, false)
                     )
                 )
             }
@@ -1249,9 +1227,7 @@ object BusinessManager {
             )
         )
         BleCmdManager.sendWorkTicket(
-            jsonStr,
-            bleDevice = bleDevice,
-            callback = object : CustomBleWriteCallback() {
+            jsonStr, bleDevice = bleDevice, callback = object : CustomBleWriteCallback() {
                 override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
                     LogUtil.i("sendTicket success")
                     if (isNeedLoading) sendEventMsg(
@@ -1281,9 +1257,7 @@ object BusinessManager {
      * @param vo 工作票详情
      */
     private fun generateTicketSendJson(
-        isLock: Boolean,
-        vo: TicketDetailRespVO,
-        lockList: MutableList<String?>?
+        isLock: Boolean, vo: TicketDetailRespVO, lockList: MutableList<String?>?
     ): String {
         LogUtil.i("generateTicketSendJson : $lockList")
         // 用ticketStatus的"待上锁"进行判断
@@ -1303,8 +1277,7 @@ object BusinessManager {
         bo.password =
             SPUtils.getLoginUser(MyApplication.instance!!.applicationContext)?.keyCode ?: "123456"
         val dataBO = WorkTicketSendBO.DataBO(
-            taskCode = vo.ticketId.toString(),
-            codeId = 1
+            taskCode = vo.ticketId.toString(), codeId = 1
         )
         val taskList = ArrayList<WorkTicketSendBO.DataBO.DataListBO>()
         vo.ticketPointsVOList?.let { itList ->
@@ -1366,8 +1339,7 @@ object BusinessManager {
         when {
             // 获取令牌
             byteArray.startsWith(BleConst.RSP_GET_TOKEN) -> BleCmdManager.handleToken(
-                bleBean.bleDevice,
-                byteArray
+                bleBean.bleDevice, byteArray
             ) { isSuccess ->
                 if (isSuccess) {
                     prepareDoneCallBack?.invoke(true, bleBean)
@@ -1378,17 +1350,14 @@ object BusinessManager {
                 handleSwitchModeResult(byteArray, isNeedLoading) { res, job ->
                     sendEventMsg(
                         MsgEvent(
-                            MSG_EVENT_SWITCH_MODE,
-                            SwitchModeMsg(job.toInt(), res.toInt(), bleBean)
+                            MSG_EVENT_SWITCH_MODE, SwitchModeMsg(job.toInt(), res.toInt(), bleBean)
                         )
                     )
                 }
             }
             // 工作票下发
             byteArray.startsWith(BleConst.RSP_SEND_WORK_TICKET) -> handleWorkTicketResult(
-                bleBean,
-                byteArray,
-                isNeedLoading
+                bleBean, byteArray, isNeedLoading
             )
             // 获取设备当前状态
             byteArray.startsWith(BleConst.RSP_CURRENT_STATUS) -> BleCmdManager.handleCurrentStatus(
@@ -1397,8 +1366,9 @@ object BusinessManager {
                 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)
+            byteArray.startsWith(BleConst.RSP_WORK_TICKET_RESULT) && byteArray[3] == 0x02.toByte() -> handleTicketStatus(
+                bleBean.bleDevice, byteArray, isNeedLoading
+            )
         }
     }
 
@@ -1417,24 +1387,21 @@ object BusinessManager {
                 LogUtil.i("切换工作模式成功")
                 if (isNeedLoading) sendEventMsg(
                     MsgEvent(
-                        MSG_EVENT_LOADING,
-                        LoadingMsg(false, "切换工作模式成功", null)
+                        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)
+                        MSG_EVENT_LOADING, LoadingMsg(false, "切换待机模式成功", null)
                     )
                 )
             } else {
                 LogUtil.e("切换模式失败 : ${job.toInt()} - ${res.toInt()}")
                 if (isNeedLoading) sendEventMsg(
                     MsgEvent(
-                        MSG_EVENT_LOADING,
-                        LoadingMsg(false, null, null)
+                        MSG_EVENT_LOADING, LoadingMsg(false, null, null)
                     )
                 )
             }
@@ -1447,15 +1414,12 @@ object BusinessManager {
      * res:0x00:成功 0x01:失败 0x02:传输超时 0x0D:当前IDX超出范围 0x0E:当前数据CRC校验失败 0x14:JSON结构错误 0x63:未知错误
      */
     private fun handleWorkTicketResult(
-        bleBean: BleBean,
-        byteArray: ByteArray,
-        isNeedLoading: Boolean = false
+        bleBean: BleBean, byteArray: ByteArray, isNeedLoading: Boolean = false
     ) {
         BleCmdManager.handleWorkTicketResult(bleBean, byteArray) { isSuccess, rst ->
             if (isNeedLoading) sendEventMsg(
                 MsgEvent(
-                    MSG_EVENT_LOADING,
-                    LoadingMsg(false, null, null)
+                    MSG_EVENT_LOADING, LoadingMsg(false, null, null)
                 )
             )
             if (isSuccess) {
@@ -1463,8 +1427,7 @@ object BusinessManager {
                 LogUtil.i("工作票下发完毕")
                 if (isNeedLoading) sendEventMsg(
                     MsgEvent(
-                        MSG_EVENT_LOADING,
-                        LoadingMsg(true, "切换钥匙为工作模式", null)
+                        MSG_EVENT_LOADING, LoadingMsg(true, "切换钥匙为工作模式", null)
                     )
                 )
 
@@ -1554,9 +1517,7 @@ object BusinessManager {
      * 处理工作票完成情况
      */
     private fun handleTicketStatus(
-        bleDevice: BleDevice,
-        byteArray: ByteArray,
-        isNeedLoading: Boolean = false
+        bleDevice: BleDevice, byteArray: ByteArray, isNeedLoading: Boolean = false
     ) {
         BleCmdManager.handleTicketStatus(bleDevice, byteArray) { ticketJson ->
             if (ticketJson.isNullOrEmpty()) {
@@ -1564,16 +1525,14 @@ object BusinessManager {
             }
             if (isNeedLoading) sendEventMsg(
                 MsgEvent(
-                    MSG_EVENT_LOADING,
-                    LoadingMsg(false, "工作票完成状态读取完成", null)
+                    MSG_EVENT_LOADING, LoadingMsg(false, "工作票完成状态读取完成", null)
                 )
             )
             LogUtil.i("Get ticket status complete : ${bleDevice.mac}")
             // TD:Ticket Done
             if (isNeedLoading) sendEventMsg(
                 MsgEvent(
-                    MSG_EVENT_LOADING,
-                    LoadingMsg(false, "TD$ticketJson}", true)
+                    MSG_EVENT_LOADING, LoadingMsg(false, "TD$ticketJson}", true)
                 )
             )
 
@@ -1637,8 +1596,7 @@ object BusinessManager {
                         data.taskCode?.toLong()?.let {
                             sendEventMsg(
                                 MsgEvent(
-                                    MSG_EVENT_UPDATE_TICKET_PROGRESS,
-                                    UpdateTicketProgressMsg(it)
+                                    MSG_EVENT_UPDATE_TICKET_PROGRESS, UpdateTicketProgressMsg(it)
                                 )
                             )
                         }
@@ -1651,9 +1609,7 @@ object BusinessManager {
 
                 // 上报钥匙归还
                 NetApi.updateKeyReturn(
-                    data.taskCode?.toLong()!!,
-                    keyNfc!!,
-                    MyApplication.instance!!.serialNo()
+                    data.taskCode?.toLong()!!, keyNfc!!, MyApplication.instance!!.serialNo()
                 ) { isSuccess, msg ->
                     if (!isSuccess && msg != MyApplication.instance?.applicationContext!!.getString(
                             R.string.ticket_lost
@@ -1668,8 +1624,7 @@ object BusinessManager {
             } else {
                 SPUtils.saveUpdateLockPoint(MyApplication.instance!!, updateList)
                 SPUtils.saveUpdateKeyReturn(
-                    MyApplication.instance!!,
-                    UpdateKeyReturnBO(data.taskCode?.toLong()!!, keyNfc!!)
+                    MyApplication.instance!!, UpdateKeyReturnBO(data.taskCode?.toLong()!!, keyNfc!!)
                 )
                 // 保存待发数据,切换为待机模式
                 switchReadyMode(bleDevice)
@@ -1695,24 +1650,20 @@ object BusinessManager {
     fun handleVirtualKeyReturn(taskCode: Long, keyNfc: String, done: () -> Unit) {
         // 上报钥匙归还
         NetApi.updateKeyReturn(
-            taskCode,
-            keyNfc,
-            MyApplication.instance!!.serialNo()
+            taskCode, keyNfc, MyApplication.instance!!.serialNo()
         ) { isSuccess, msg ->
             if (!isSuccess && msg != MyApplication.instance?.applicationContext!!.getString(
                     R.string.ticket_lost
                 )
             ) {
                 SPUtils.saveUpdateKeyReturn(
-                    MyApplication.instance!!,
-                    UpdateKeyReturnBO(taskCode, keyNfc)
+                    MyApplication.instance!!, UpdateKeyReturnBO(taskCode, keyNfc)
                 )
             } else {
                 done()
                 sendEventMsg(
                     MsgEvent(
-                        MSG_EVENT_UPDATE_TICKET_PROGRESS,
-                        UpdateTicketProgressMsg(taskCode)
+                        MSG_EVENT_UPDATE_TICKET_PROGRESS, UpdateTicketProgressMsg(taskCode)
                     )
                 )
             }
@@ -1744,16 +1695,14 @@ object BusinessManager {
     ) {
         if (isNeedLoading) sendEventMsg(
             MsgEvent(
-                MSG_EVENT_LOADING,
-                LoadingMsg(true, "开始获取工作票", null)
+                MSG_EVENT_LOADING, LoadingMsg(true, "开始获取工作票", null)
             )
         )
         BleCmdManager.getTicketStatus(bleDevice, object : CustomBleWriteCallback() {
             override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
                 if (isNeedLoading) sendEventMsg(
                     MsgEvent(
-                        MSG_EVENT_LOADING,
-                        LoadingMsg(false, "工作票获取成功", null)
+                        MSG_EVENT_LOADING, LoadingMsg(false, "工作票获取成功", null)
                     )
                 )
                 LogUtil.i("getTicketStatus success")
@@ -1762,8 +1711,7 @@ object BusinessManager {
             override fun onWriteFailure(exception: BleException?) {
                 if (isNeedLoading) sendEventMsg(
                     MsgEvent(
-                        MSG_EVENT_LOADING,
-                        LoadingMsg(false, "工作票获取失败", false)
+                        MSG_EVENT_LOADING, LoadingMsg(false, "工作票获取失败", false)
                     )
                 )
                 processCallback?.invoke(false)
@@ -1796,9 +1744,7 @@ object BusinessManager {
                         sendLoadingEventMsg(null, false)
                         SPUtils.takeKey(info.ticketId)
                         NetApi.updateKeyTake(
-                            info.ticketId,
-                            info.nfc,
-                            MyApplication.instance?.serialNo()!!
+                            info.ticketId, info.nfc, MyApplication.instance?.serialNo()!!
                         ) { isSuccess ->
                             if (isSuccess) {
                                 mDeviceTakeList.removeIf { it.deviceType == DEVICE_TYPE_KEY && it.nfc == info.nfc }
@@ -1819,9 +1765,7 @@ object BusinessManager {
                         NetApi.updateLockTake(
                             mutableListOf(
                                 LockTakeUpdateReqVO(
-                                    info.ticketId,
-                                    info.nfc,
-                                    MyApplication.instance?.serialNo()!!
+                                    info.ticketId, info.nfc, MyApplication.instance?.serialNo()!!
                                 )
                             )
                         ) { isSuccess ->
@@ -1897,15 +1841,11 @@ object BusinessManager {
                     tipDialog.show()
                 } else {
                     addDeviceTake(
-                        DEVICE_TYPE_KEY,
-                        deviceTakeUpdateBO.ticketId,
-                        keyPair.second?.rfid!!
+                        DEVICE_TYPE_KEY, deviceTakeUpdateBO.ticketId, keyPair.second?.rfid!!
                     )
                     handleGiveKey(
                         DeviceTakeUpdateBO(
-                            DEVICE_TYPE_KEY,
-                            deviceTakeUpdateBO.ticketId,
-                            keyPair.second?.rfid!!
+                            DEVICE_TYPE_KEY, deviceTakeUpdateBO.ticketId, keyPair.second?.rfid!!
                         )
                     )
                 }
@@ -1951,8 +1891,7 @@ object BusinessManager {
                                         currentModeMsg.bleBean.bleDevice.mac,
                                         ticketDetail,
                                         ticketDetail.ticketLockVOList?.filter { it.lockStatus != "2" }
-                                            ?.map { it.lockNfc }
-                                            ?.toMutableList(),
+                                            ?.map { it.lockNfc }?.toMutableList(),
                                         ActivityUtils.currentActivity() as BaseActivity<*>,
                                         true
                                     )
@@ -1970,13 +1909,10 @@ object BusinessManager {
                         }
                     } ?: let {
                         ModBusController.updateKeyReadyStatus(
-                            currentModeMsg.bleBean.bleDevice.mac,
-                            true,
-                            4
+                            currentModeMsg.bleBean.bleDevice.mac, true, 4
                         )
                         ModBusController.controlKeyBuckle(
-                            false,
-                            currentModeMsg.bleBean.bleDevice.mac
+                            false, currentModeMsg.bleBean.bleDevice.mac
                         )
                         sendLoadingEventMsg(null, false)
                     }
@@ -1986,8 +1922,7 @@ object BusinessManager {
             0x03.toByte() -> {
                 // TODO 上报?
                 ToastUtils.tip(
-                    "${currentModeMsg.bleBean.bleDevice.mac} : " +
-                            "${CommonUtils.getStr(R.string.key_is_in_failure_mode)}"
+                    "${currentModeMsg.bleBean.bleDevice.mac} : " + "${CommonUtils.getStr(R.string.key_is_in_failure_mode)}"
                 )
             }
         }

+ 6 - 3
app/src/main/java/com/grkj/iscs/modbus/ModBusController.kt

@@ -221,7 +221,10 @@ object ModBusController {
                                 if (it != null && !it.macAddress.isNullOrEmpty()) {
                                     // 更新mac
                                     updateKeyMac(dockBean.addr, key.isLeft, it.macAddress)
-                                    BusinessManager.registerConnectListener(it.macAddress) { isDone, bleBean ->
+                                    BusinessManager.registerConnectListener(
+                                        it.macAddress,
+                                        false
+                                    ) { isDone, bleBean ->
                                         if (isDone && bleBean?.bleDevice != null) {
                                             Executor.delayOnMain(500) {
                                                 BusinessManager.getCurrentStatus(
@@ -909,7 +912,7 @@ object ModBusController {
             keyDockList.map { it.deviceList }.flatten()
                 .filterIsInstance<DockBean.KeyBean>()
                 .filterIndexed { index, _ -> (index + 1) !in exceptionSlots.map { it.col?.toInt() } }
-                .filter { it.rfid !in exceptionKeys }
+                .filter { it.rfid !in exceptionKeys && !it.rfid.isNullOrEmpty() && !it.mac.isNullOrEmpty() && it.isExist }
                 .toMutableList()
         LogUtil.i("keyList : $keyList")
         if (keyList.isEmpty()) {
@@ -919,7 +922,7 @@ object ModBusController {
 
         keyList.forEach {
             LogUtil.i(
-                "keyStatus : ${it.isExist} - ${it.rfid} - ${it.mac} - ${it.isReady} - " + "${
+                "keyStatus  满足条件的钥匙: ${it.isExist} - ${it.rfid} - ${it.mac} - ${it.isReady} - " + "${
                     BusinessManager.getBleDeviceByMac(
                         it.mac
                     )?.bleDevice != null

+ 5 - 0
app/src/main/java/com/grkj/iscs/model/DictConstants.kt

@@ -43,4 +43,9 @@ object DictConstants {
      * 开关状态
      */
     const val KEY_SWITCH_STATUS = "switch_status"
+
+    /**
+     * 锁仓类型
+     */
+    const val KEY_SLOT_TYPE = "slot_type"
 }

+ 2 - 1
app/src/main/java/com/grkj/iscs/model/vo/hardware/SwitchListReqVO.kt

@@ -5,5 +5,6 @@ package com.grkj.iscs.model.vo.hardware
  */
 data class SwitchListReqVO(
     val pointSerialNumber: String,
-    val switchStatus: String?
+    val switchStatus: String?,
+    val switchLastUpdateTime: String?
 )

+ 9 - 6
app/src/main/java/com/grkj/iscs/util/NetApi.kt

@@ -1235,12 +1235,15 @@ object NetApi {
             ),
             { res, _, _ ->
                 res?.let {
-                    val bean = it.toBean(SystemAttributeByKeyRespVO::class.java)
-                    BitmapUtil.loadBitmapFromUrl(
-                        MyApplication.instance?.applicationContext!!,
-                        bean.sysAttrValue,
-                        callback = callBack
-                    )
+                    val bean: SystemAttributeByKeyRespVO? = getRefBean(it)
+                    LogUtil.i("资源信息:${bean}")
+                    bean?.sysAttrValue?.let { url ->
+                        BitmapUtil.loadBitmapFromUrl(
+                            MyApplication.instance?.applicationContext!!,
+                            url,
+                            callback = callBack
+                        )
+                    }
                 }
             }, isGet = true, isAuth = true
         )

+ 94 - 75
app/src/main/java/com/grkj/iscs/view/fragment/DeviceStatusFragment.kt

@@ -6,7 +6,6 @@ import android.view.View
 import android.widget.ImageView
 import androidx.core.content.ContextCompat
 import androidx.recyclerview.widget.RecyclerView
-import com.grkj.iscs.BusinessManager
 import com.grkj.iscs.R
 import com.grkj.iscs.databinding.FragmentDeviceStatusBinding
 import com.grkj.iscs.extentions.setSelected
@@ -39,8 +38,12 @@ class DeviceStatusFragment :
 
     override fun initView() {
         presenter?.initData(mRowList)
-        presenter?.getExceptionIcon {
-            mBinding?.rvDock?.adapter?.notifyDataSetChanged()
+        presenter?.getSlotData {
+            presenter?.getExceptionIcon {
+                ThreadUtils.runOnMain {
+                    mBinding?.rvDock?.adapter?.notifyDataSetChanged()
+                }
+            }
         }
         presenter?.mExceptionHintTip = {
             tipDialog.setType(TipDialog.TYPE_HINT)
@@ -48,8 +51,17 @@ class DeviceStatusFragment :
             tipDialog.showCancelCountdown(10)
         }
         presenter?.mExceptionReporter = { row, col, slotType ->
-            SlotExceptionDialog(requireContext(), row, col, slotType) {
-                presenter?.reportException(row, col, slotType, it)
+            SlotExceptionDialog(requireContext(), row, col, slotType) { exceptionReason ->
+                presenter?.slotStatus?.find { it.dictLabel == "异常" }?.dictValue?.let { exceptionStatus ->
+                    presenter?.reportException(
+                        row,
+                        col,
+                        exceptionStatus.toInt(),
+                        exceptionReason
+                    ) {
+                        getSlotsStatus()
+                    }
+                }
             }.show()
         }
         val adapter = MultiItemTypeAdapter(requireContext(), mRowList)
@@ -68,23 +80,15 @@ class DeviceStatusFragment :
     override fun onResume() {
         super.onResume()
         mBinding?.rvDock?.adapter?.notifyDataSetChanged()
-        fun refreshBuckleStatus() {
-            if (!isResumed) {
-                return
-            }
-            ThreadUtils.runOnIODelayed(1000) {
-                presenter?.getIsLockCabinetSlotsPage {
-                    mBinding?.rvDock?.adapter?.notifyDataSetChanged()
-                }
-                BusinessManager.updateAllBuckleStatus {
-                    ThreadUtils.runOnMain {
-                        mBinding?.rvDock?.adapter?.notifyDataSetChanged()
-                        refreshBuckleStatus()
-                    }
-                }
+        getSlotsStatus()
+    }
+
+    private fun getSlotsStatus() {
+        presenter?.getIsLockCabinetSlotsPage {
+            ThreadUtils.runOnMain {
+                mBinding?.rvDock?.adapter?.notifyDataSetChanged()
             }
         }
-        refreshBuckleStatus()
     }
 
     override fun initPresenter(): DeviceStatusPresenter {
@@ -142,10 +146,10 @@ class DeviceStatusFragment :
             holder?.setText(R.id.tv_status_2, status2?.second)
             holder?.setText(R.id.tv_status_3, status3?.second)
             holder?.setText(R.id.tv_status_4, status4?.second)
-            holder?.setVisibleWithHolder(R.id.tv_repair_1, status1?.first == false)
-            holder?.setVisibleWithHolder(R.id.tv_repair_2, status2?.first == false)
-            holder?.setVisibleWithHolder(R.id.tv_repair_3, status3?.first == false)
-            holder?.setVisibleWithHolder(R.id.tv_repair_4, status4?.first == false)
+//            holder?.setVisibleWithHolder(R.id.tv_repair_1, status1?.first == false)
+//            holder?.setVisibleWithHolder(R.id.tv_repair_2, status2?.first == false)
+//            holder?.setVisibleWithHolder(R.id.tv_repair_3, status3?.first == false)
+//            holder?.setVisibleWithHolder(R.id.tv_repair_4, status4?.first == false)
             holder?.getView<View>(R.id.v_buckle_status_1)?.backgroundTintList =
                 if (presenter?.getKeyBuckleLockEnabled(
                         row.dockList.find { it.column == "1" }?.address,
@@ -190,75 +194,88 @@ class DeviceStatusFragment :
             holder?.setOnClickListener(R.id.tv_repair_4) {
                 presenter?.repairKey(row.dockList.find { it.column == "2" }?.address, false)
             }
-            presenter?.mCabinetSlotsData?.filter { it.row == "1" }?.forEach { cabinetSlotsRecord ->
-                when {
-                    cabinetSlotsRecord.col == "1" -> {
-                        if (cabinetSlotsRecord.status == "0") {
-                            holder?.setVisibleWithHolder(R.id.iv_key_exception_1, false)
-                        } else {
-                            holder?.setVisibleWithHolder(R.id.iv_key_exception_1, true)
-                            holder?.getView<ImageView>(R.id.iv_key_exception_1)
-                                ?.setImageBitmap(presenter?.mExceptionIcon)
-                            holder?.setOnClickListener(R.id.iv_key_exception_1) {
-                                presenter?.exceptionHint(cabinetSlotsRecord.remark ?: "")
+            presenter?.mCabinetSlotsData?.filter { it.row == row.row.toString() }
+                ?.forEach { cabinetSlotsRecord ->
+                    when (cabinetSlotsRecord.col) {
+                        "1" -> {
+                            if (cabinetSlotsRecord.status == "0") {
+                                holder?.setVisibleWithHolder(R.id.iv_key_exception_1, false)
+                            } else {
+                                holder?.setVisibleWithHolder(R.id.iv_key_exception_1, true)
+                                holder?.getView<ImageView>(R.id.iv_key_exception_1)
+                                    ?.setImageBitmap(presenter?.mExceptionIcon)
+                                holder?.setOnClickListener(R.id.iv_key_exception_1) {
+                                    presenter?.exceptionHint(cabinetSlotsRecord.remark ?: "")
+                                }
                             }
                         }
-                    }
 
-                    cabinetSlotsRecord.col == "2" -> {
-                        if (cabinetSlotsRecord.status == "0") {
-                            holder?.setVisibleWithHolder(R.id.iv_key_exception_2, false)
-                        } else {
-                            holder?.setVisibleWithHolder(R.id.iv_key_exception_2, true)
-                            holder?.getView<ImageView>(R.id.iv_key_exception_2)
-                                ?.setImageBitmap(presenter?.mExceptionIcon)
-                            holder?.setOnClickListener(R.id.iv_key_exception_2) {
-                                presenter?.exceptionHint(cabinetSlotsRecord.remark ?: "")
+                        "2" -> {
+                            if (cabinetSlotsRecord.status == "0") {
+                                holder?.setVisibleWithHolder(R.id.iv_key_exception_2, false)
+                            } else {
+                                holder?.setVisibleWithHolder(R.id.iv_key_exception_2, true)
+                                holder?.getView<ImageView>(R.id.iv_key_exception_2)
+                                    ?.setImageBitmap(presenter?.mExceptionIcon)
+                                holder?.setOnClickListener(R.id.iv_key_exception_2) {
+                                    presenter?.exceptionHint(cabinetSlotsRecord.remark ?: "")
+                                }
                             }
                         }
-                    }
 
-                    cabinetSlotsRecord.col == "3" -> {
-                        if (cabinetSlotsRecord.status == "0") {
-                            holder?.setVisibleWithHolder(R.id.iv_key_exception_3, false)
-                        } else {
-                            holder?.setVisibleWithHolder(R.id.iv_key_exception_3, true)
-                            holder?.getView<ImageView>(R.id.iv_key_exception_3)
-                                ?.setImageBitmap(presenter?.mExceptionIcon)
-                            holder?.setOnClickListener(R.id.iv_key_exception_3) {
-                                presenter?.exceptionHint(cabinetSlotsRecord.remark ?: "")
+                        "3" -> {
+                            if (cabinetSlotsRecord.status == "0") {
+                                holder?.setVisibleWithHolder(R.id.iv_key_exception_3, false)
+                            } else {
+                                holder?.setVisibleWithHolder(R.id.iv_key_exception_3, true)
+                                holder?.getView<ImageView>(R.id.iv_key_exception_3)
+                                    ?.setImageBitmap(presenter?.mExceptionIcon)
+                                holder?.setOnClickListener(R.id.iv_key_exception_3) {
+                                    presenter?.exceptionHint(cabinetSlotsRecord.remark ?: "")
+                                }
                             }
                         }
-                    }
 
-                    cabinetSlotsRecord.col == "4" -> {
-                        if (cabinetSlotsRecord.status == "0") {
-                            holder?.setVisibleWithHolder(R.id.iv_key_exception_4, false)
-                        } else {
-                            holder?.setVisibleWithHolder(R.id.iv_key_exception_4, true)
-                            holder?.getView<ImageView>(R.id.iv_key_exception_4)
-                                ?.setImageBitmap(presenter?.mExceptionIcon)
-                            holder?.setOnClickListener(R.id.iv_key_exception_4) {
-                                presenter?.exceptionHint(cabinetSlotsRecord.remark ?: "")
+                        "4" -> {
+                            if (cabinetSlotsRecord.status == "0") {
+                                holder?.setVisibleWithHolder(R.id.iv_key_exception_4, false)
+                            } else {
+                                holder?.setVisibleWithHolder(R.id.iv_key_exception_4, true)
+                                holder?.getView<ImageView>(R.id.iv_key_exception_4)
+                                    ?.setImageBitmap(presenter?.mExceptionIcon)
+                                holder?.setOnClickListener(R.id.iv_key_exception_4) {
+                                    presenter?.exceptionHint(cabinetSlotsRecord.remark ?: "")
+                                }
                             }
                         }
                     }
                 }
-            }
             holder?.setOnLongClickListener(R.id.iv_key_1) {
-                presenter?.mExceptionReporter?.invoke(0, 1, 0)
+                presenter?.slotType?.find { it.dictLabel == "钥匙" }?.dictValue?.let {
+                    presenter?.mExceptionReporter?.invoke(
+                        (row.row + 1),
+                        1,
+                        it.toInt()
+                    )
+                }
                 true
             }
             holder?.setOnLongClickListener(R.id.iv_key_2) {
-                presenter?.mExceptionReporter?.invoke(0, 2, 0)
+                presenter?.slotType?.find { it.dictLabel == "钥匙" }?.dictValue?.let {
+                    presenter?.mExceptionReporter?.invoke(row.row, 2, it.toInt())
+                }
                 true
             }
             holder?.setOnLongClickListener(R.id.iv_key_3) {
-                presenter?.mExceptionReporter?.invoke(0, 3, 0)
+                presenter?.slotType?.find { it.dictLabel == "钥匙" }?.dictValue?.let {
+                    presenter?.mExceptionReporter?.invoke(row.row, 3, it.toInt())
+                }
                 true
             }
             holder?.setOnLongClickListener(R.id.iv_key_4) {
-                presenter?.mExceptionReporter?.invoke(0, 4, 0)
+                presenter?.slotType?.find { it.dictLabel == "钥匙" }?.dictValue?.let {
+                    presenter?.mExceptionReporter?.invoke(row.row, 4, it.toInt())
+                }
                 true
             }
         }
@@ -298,11 +315,13 @@ class DeviceStatusFragment :
                         ModBusController.isLockExist(row.dockList[0].address, lockIdx)
                     )
                     holder?.convertView?.setOnLongClickListener {
-                        presenter?.mExceptionReporter?.invoke(
-                            row.dockList[0].row.toInt(),
-                            row.dockList[0].column.toInt(),
-                            1
-                        )
+                        presenter?.slotType?.find { it.dictLabel == "锁" }?.dictValue?.let {
+                            presenter?.mExceptionReporter?.invoke(
+                                row.row,
+                                (lockIdx + 1),
+                                it.toInt()
+                            )
+                        }
                         true
                     }
                     ColorStateList.valueOf(statusNotLightTintColor).let {

+ 34 - 44
app/src/main/java/com/grkj/iscs/view/fragment/SwitchStatusFragment.kt

@@ -28,7 +28,26 @@ class SwitchStatusFragment :
 
     override fun initView() {
         initMap()
-        presenter?.getMapInfo(5) { itMapInfo ->
+    }
+
+    override fun onResume() {
+        super.onResume()
+        getMap()
+        fun refreshSwitchStatus() {
+            if (!isResumed) {
+                return
+            }
+            ThreadUtils.runOnIODelayed(1000) {
+                BusinessManager.updateSwitchStatus {
+                    refreshSwitchStatus()
+                }
+            }
+        }
+        refreshSwitchStatus()
+    }
+
+    private fun getMap() {
+        presenter?.getMapInfo(8) { itMapInfo ->
             // 如果没有图 URL,直接返回
             val imageUrl = itMapInfo?.imageUrl ?: return@getMapInfo
 
@@ -58,8 +77,7 @@ class SwitchStatusFragment :
                 val offsetY = itMapInfo.y!!.toFloat()
                 // 图标请求尺寸:逻辑 45px * 缩放比
                 val iconReqPx = (45f * ratioX).toInt().coerceAtLeast(1)
-
-                itMapInfo.pointList?.forEach { pt ->
+                itMapInfo.pointList?.filter { it.x != null && it.y != null }?.forEach { pt ->
                     // 1) 格数 → 全局像素
                     val globalX = pt.x!!.toFloat() * cellPx
                     val globalY = pt.y!!.toFloat() * cellPx
@@ -70,55 +88,26 @@ class SwitchStatusFragment :
                     val finalX = localX * ratioX
                     val finalY = localY * ratioY
                     // 异步加载点位图标,固定请求尺寸
-                    BitmapUtil.loadBitmapFromUrl(
-                        requireContext(),
-                        pt.pointIcon!!,
-                        reqWidth = iconReqPx,
-                        reqHeight = iconReqPx
-                    ) { bmpIcon ->
-                        val icon = bmpIcon ?: BitmapUtil.getResizedBitmapFromMipmap(
-                            requireContext(),
-                            R.mipmap.ticket_type_placeholder,
-                            iconReqPx,
-                            iconReqPx
+                    mStationList.add(
+                        CustomStationLayer.IsolationPoint(
+                            PointF(finalX, finalY),
+                            pt.entityName!!,
+                            null,
+                            pt.entityId!!.toLong(),
+                            pt.pointSerialNumber,
+                            false
                         )
+                    )
 
-                        mStationList.add(
-                            CustomStationLayer.IsolationPoint(
-                                PointF(finalX, finalY),
-                                pt.entityName!!,
-                                icon,
-                                pt.entityId!!.toLong(),
-                                pt.pointSerialNumber,
-                                false
-                            )
-                        )
-
-                        // 全部点都加载完后,设置给 layer 并绘制
-                        if (mStationList.size == itMapInfo.pointList.size) {
-                            mBinding?.mapview?.loadMap(mapBmp)
-                        }
+                    // 全部点都加载完后,设置给 layer 并绘制
+                    if (mStationList.size == itMapInfo.pointList.count { it.x != null && it.y != null }) {
+                        mBinding?.mapview?.loadMap(mapBmp)
                     }
                 }
             }
         }
     }
 
-    override fun onResume() {
-        super.onResume()
-        fun refreshSwitchStatus() {
-            if (!isResumed) {
-                return
-            }
-            ThreadUtils.runOnIODelayed(1000) {
-                BusinessManager.updateSwitchStatus {
-                    refreshSwitchStatus()
-                }
-            }
-        }
-        refreshSwitchStatus()
-    }
-
     /**
      * 初始化地图
      */
@@ -133,6 +122,7 @@ class SwitchStatusFragment :
                 stationLayer = CustomStationLayer(mBinding?.mapview, mStationList)
                 mBinding?.mapview?.addLayer(stationLayer)
                 stationLayer?.setRatio(mapRatio)
+                stationLayer?.stopAnimation()
                 stationLayer?.startAnimation()
             }
 

+ 26 - 7
app/src/main/java/com/grkj/iscs/view/presenter/DeviceStatusPresenter.kt

@@ -9,9 +9,10 @@ import com.grkj.iscs.BusinessManager.getCurrentStatus
 import com.grkj.iscs.R
 import com.grkj.iscs.extentions.removeLeadingZeros
 import com.grkj.iscs.extentions.toHexStrings
-import com.grkj.iscs.modbus.DockBean
 import com.grkj.iscs.modbus.ModBusController
 import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_LOCK
+import com.grkj.iscs.model.DictConstants
+import com.grkj.iscs.model.vo.dict.CommonDictRespVO
 import com.grkj.iscs.model.vo.hardware.CabinetSlotsRecord
 import com.grkj.iscs.model.vo.hardware.SlotExDTO
 import com.grkj.iscs.util.Executor
@@ -23,9 +24,7 @@ import com.grkj.iscs.view.base.BasePresenter
 import com.grkj.iscs.view.fragment.DeviceStatusFragment.DockStatusBO
 import com.grkj.iscs.view.fragment.DockTestFragment.DockTestBean
 import com.grkj.iscs.view.iview.IDeviceStatusView
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
+import com.sik.sikcore.thread.ThreadUtils
 
 class DeviceStatusPresenter : BasePresenter<IDeviceStatusView>() {
     var mCabinetSlotsData: List<CabinetSlotsRecord> = listOf()
@@ -33,6 +32,8 @@ class DeviceStatusPresenter : BasePresenter<IDeviceStatusView>() {
     var mExceptionHintTip: ((String) -> Unit)? = null
     var mExceptionReporter: ((row: Int, col: Int, slotType: Int) -> Unit)? =
         null
+    var slotType: MutableList<CommonDictRespVO>? = null
+    var slotStatus: MutableList<CommonDictRespVO>? = null
 
     fun initData(rowList: MutableList<DockStatusBO>) {
         val dockConfigJson = SPUtils.getDockConfig(mContext!!)
@@ -103,7 +104,7 @@ class DeviceStatusPresenter : BasePresenter<IDeviceStatusView>() {
                     BleManager.getInstance().disconnect(it)
                 }
                 Executor.delayOnMain(2000) {
-                    BusinessManager.registerConnectListener(mac) { isDone, bleBean ->
+                    BusinessManager.registerConnectListener(mac, false) { isDone, bleBean ->
                         if (isDone && bleBean != null) {
                             Executor.delayOnMain(300) {
                                 getCurrentStatus(7, bleBean.bleDevice)
@@ -190,22 +191,40 @@ class DeviceStatusPresenter : BasePresenter<IDeviceStatusView>() {
     /**
      * 上报异常
      */
-    fun reportException(row: Int, col: Int, slotType: Int, exceptionReason: String) {
+    fun reportException(
+        row: Int,
+        col: Int,
+        slotStatus: Int,
+        exceptionReason: String,
+        done: () -> Unit
+    ) {
         NetApi.updateHardwareEsStatus(
             slotsExDTOList = mutableListOf(
                 SlotExDTO(
                     col.toString(),
                     exceptionReason,
                     row.toString(),
-                    slotType.toString()
+                    slotStatus.toString()
                 )
             )
         ) {
             if (it) {
                 ToastUtils.tip(R.string.report_success)
+                done()
             } else {
                 ToastUtils.tip(R.string.report_failed)
             }
         }
     }
+
+    /**
+     * 获取锁仓的字典数据
+     */
+    fun getSlotData(done: () -> Unit) {
+        ThreadUtils.runOnIO {
+            slotStatus = NetApi.getDictData(DictConstants.KEY_SLOT_STATUS)
+            slotType = NetApi.getDictData(DictConstants.KEY_SLOT_TYPE)
+            done()
+        }
+    }
 }

+ 13 - 3
app/src/main/java/com/grkj/iscs/view/presenter/HomePresenter.kt

@@ -25,11 +25,21 @@ class HomePresenter : BasePresenter<IHomeView>() {
                             Executor.repeatOnMain({
                                 keyBean.mac?.let {
                                     BusinessManager.sendLoadingEventMsg(mContext?.getString(R.string.loading_msg_return_key_start))
-                                    BusinessManager.registerConnectListener(it) { isDone, bleBean ->
+                                    BusinessManager.registerConnectListener(
+                                        it,
+                                        true
+                                    ) { isDone, bleBean ->
                                         if (isDone && bleBean != null) {
                                             Executor.delayOnMain(300) {
-                                                BusinessManager.sendLoadingEventMsg(mContext?.getString(R.string.loading_msg_get_ticket_status_start))
-                                                BusinessManager.getCurrentStatus(4, bleBean.bleDevice)
+                                                BusinessManager.sendLoadingEventMsg(
+                                                    mContext?.getString(
+                                                        R.string.loading_msg_get_ticket_status_start
+                                                    )
+                                                )
+                                                BusinessManager.getCurrentStatus(
+                                                    4,
+                                                    bleBean.bleDevice
+                                                )
                                             }
                                         }
                                     }

+ 7 - 1
app/src/main/java/com/grkj/iscs/view/widget/CustomStationLayer.kt

@@ -87,6 +87,11 @@ class CustomStationLayer @JvmOverloads constructor(
         mapView.postDelayed(refreshRunnable, FRAME_INTERVAL)
     }
 
+    fun stopAnimation() {
+        // 先干掉前一次没执行的
+        mapView.removeCallbacks(refreshRunnable)
+    }
+
     override fun onTouch(event: MotionEvent) {
 
     }
@@ -102,8 +107,9 @@ class CustomStationLayer @JvmOverloads constructor(
         canvas.save()
         // 把 mapView 本身的缩放/平移/旋转一次性 concat 到 Canvas
         canvas.concat(currentMatrix)
+        val switchData = ModBusController.getSwitchData()
         pointList.forEach { point ->
-            val switchStatus = ModBusController.getSwitchData()
+            val switchStatus = switchData
                 .find { it.idx == point.pointSerialNumber?.toInt() }?.enabled
             // point.pos.x/y 已经是「图内像素坐标」
             val x = point.pos.x

+ 62 - 38
app/src/main/res/layout/item_rv_key_dock_status.xml

@@ -17,8 +17,7 @@
         <RelativeLayout
             android:layout_width="0dp"
             android:layout_height="match_parent"
-            android:layout_weight="1"
-            android:orientation="vertical">
+            android:layout_weight="1">
 
             <ImageView
                 android:id="@+id/iv_key_1"
@@ -35,7 +34,8 @@
                 android:layout_centerHorizontal="true"
                 android:layout_marginVertical="@dimen/common_spacing_small"
                 android:background="@drawable/dock_key_status_bg_selector"
-                android:gravity="center">
+                android:gravity="center"
+                android:visibility="invisible">
 
                 <TextView
                     android:id="@+id/tv_status_1"
@@ -50,33 +50,38 @@
                 android:layout_alignLeft="@+id/rl_status_1"
                 android:layout_alignRight="@+id/rl_status_1"
                 android:background="@drawable/common_btn_red_bg"
-                android:text="@string/repair_key" />
+                android:text="@string/repair_key"
+                android:visibility="invisible" />
 
             <View
                 android:id="@+id/v_buckle_status_1"
                 android:layout_width="@dimen/common_status_circle_small"
                 android:layout_height="@dimen/common_status_circle_small"
                 android:layout_toRightOf="@+id/iv_key_1"
-                android:background="@drawable/common_status_circle" />
+                android:background="@drawable/common_status_circle"
+                android:visibility="invisible" />
 
             <ImageView
                 android:id="@+id/iv_key_exception_1"
-                android:layout_width="match_parent"
-                android:layout_height="80dp"
-                android:layout_centerInParent="true"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignLeft="@+id/iv_key_1"
+                android:layout_alignTop="@+id/iv_key_1"
+                android:layout_alignRight="@+id/iv_key_1"
+                android:layout_alignBottom="@+id/iv_key_1"
                 android:visibility="gone" />
         </RelativeLayout>
 
         <RelativeLayout
             android:layout_width="0dp"
             android:layout_height="match_parent"
-            android:layout_weight="1"
-            android:gravity="center_horizontal">
+            android:layout_weight="1">
 
             <ImageView
                 android:id="@+id/iv_key_2"
                 android:layout_width="50dp"
                 android:layout_height="35dp"
+                android:layout_centerHorizontal="true"
                 android:background="@drawable/dock_key_selector" />
 
             <RelativeLayout
@@ -84,9 +89,11 @@
                 android:layout_width="50dp"
                 android:layout_height="20dp"
                 android:layout_below="@+id/iv_key_2"
+                android:layout_centerHorizontal="true"
                 android:layout_marginVertical="@dimen/common_spacing_small"
                 android:background="@drawable/dock_key_status_bg_selector"
-                android:gravity="center">
+                android:gravity="center"
+                android:visibility="invisible">
 
                 <TextView
                     android:id="@+id/tv_status_2"
@@ -101,22 +108,27 @@
                 android:layout_alignLeft="@+id/rl_status_2"
                 android:layout_alignRight="@+id/rl_status_2"
                 android:background="@drawable/common_btn_red_bg"
-                android:text="@string/repair_key" />
+                android:text="@string/repair_key"
+                android:visibility="invisible" />
 
             <View
                 android:id="@+id/v_buckle_status_2"
                 android:layout_width="@dimen/common_status_circle_small"
                 android:layout_height="@dimen/common_status_circle_small"
                 android:layout_toRightOf="@+id/iv_key_2"
-                android:background="@drawable/common_status_circle" />
-        </RelativeLayout>
+                android:background="@drawable/common_status_circle"
+                android:visibility="invisible" />
 
-        <ImageView
-            android:id="@+id/iv_key_exception_2"
-            android:layout_width="match_parent"
-            android:layout_height="80dp"
-            android:layout_centerInParent="true"
-            android:visibility="gone" />
+            <ImageView
+                android:id="@+id/iv_key_exception_2"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignLeft="@+id/iv_key_2"
+                android:layout_alignTop="@+id/iv_key_2"
+                android:layout_alignRight="@+id/iv_key_2"
+                android:layout_alignBottom="@+id/iv_key_2"
+                android:visibility="gone" />
+        </RelativeLayout>
     </LinearLayout>
 
     <LinearLayout
@@ -129,14 +141,13 @@
         <RelativeLayout
             android:layout_width="0dp"
             android:layout_height="match_parent"
-            android:layout_weight="1"
-            android:gravity="center_horizontal"
-            android:orientation="vertical">
+            android:layout_weight="1">
 
             <ImageView
                 android:id="@+id/iv_key_3"
                 android:layout_width="50dp"
                 android:layout_height="35dp"
+                android:layout_centerHorizontal="true"
                 android:background="@drawable/dock_key_selector" />
 
             <RelativeLayout
@@ -144,9 +155,11 @@
                 android:layout_width="50dp"
                 android:layout_height="20dp"
                 android:layout_below="@+id/iv_key_3"
+                android:layout_centerHorizontal="true"
                 android:layout_marginVertical="@dimen/common_spacing_small"
                 android:background="@drawable/dock_key_status_bg_selector"
-                android:gravity="center">
+                android:gravity="center"
+                android:visibility="invisible">
 
                 <TextView
                     android:id="@+id/tv_status_3"
@@ -161,34 +174,38 @@
                 android:layout_alignLeft="@+id/rl_status_3"
                 android:layout_alignRight="@+id/rl_status_3"
                 android:background="@drawable/common_btn_red_bg"
-                android:text="@string/repair_key" />
+                android:text="@string/repair_key"
+                android:visibility="invisible" />
 
             <View
                 android:id="@+id/v_buckle_status_3"
                 android:layout_width="@dimen/common_status_circle_small"
                 android:layout_height="@dimen/common_status_circle_small"
                 android:layout_toRightOf="@+id/iv_key_3"
-                android:background="@drawable/common_status_circle" />
+                android:background="@drawable/common_status_circle"
+                android:visibility="invisible" />
 
             <ImageView
                 android:id="@+id/iv_key_exception_3"
-                android:layout_width="match_parent"
-                android:layout_height="80dp"
-                android:layout_centerInParent="true"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignLeft="@+id/iv_key_3"
+                android:layout_alignTop="@+id/iv_key_3"
+                android:layout_alignRight="@+id/iv_key_3"
+                android:layout_alignBottom="@+id/iv_key_3"
                 android:visibility="gone" />
         </RelativeLayout>
 
         <RelativeLayout
             android:layout_width="0dp"
             android:layout_height="match_parent"
-            android:layout_weight="1"
-            android:gravity="center"
-            android:orientation="vertical">
+            android:layout_weight="1">
 
             <ImageView
                 android:id="@+id/iv_key_4"
                 android:layout_width="50dp"
                 android:layout_height="35dp"
+                android:layout_centerHorizontal="true"
                 android:background="@drawable/dock_key_selector" />
 
             <RelativeLayout
@@ -196,9 +213,11 @@
                 android:layout_width="50dp"
                 android:layout_height="20dp"
                 android:layout_below="@+id/iv_key_4"
+                android:layout_centerHorizontal="true"
                 android:layout_marginVertical="@dimen/common_spacing_small"
                 android:background="@drawable/dock_key_status_bg_selector"
-                android:gravity="center">
+                android:gravity="center"
+                android:visibility="invisible">
 
                 <TextView
                     android:id="@+id/tv_status_4"
@@ -213,20 +232,25 @@
                 android:layout_alignLeft="@+id/rl_status_4"
                 android:layout_alignRight="@+id/rl_status_4"
                 android:background="@drawable/common_btn_red_bg"
-                android:text="@string/repair_key" />
+                android:text="@string/repair_key"
+                android:visibility="invisible" />
 
             <View
                 android:id="@+id/v_buckle_status_4"
                 android:layout_width="@dimen/common_status_circle_small"
                 android:layout_height="@dimen/common_status_circle_small"
                 android:layout_toRightOf="@+id/iv_key_4"
-                android:background="@drawable/common_status_circle" />
+                android:background="@drawable/common_status_circle"
+                android:visibility="invisible" />
 
             <ImageView
                 android:id="@+id/iv_key_exception_4"
-                android:layout_width="match_parent"
-                android:layout_height="80dp"
-                android:layout_centerInParent="true"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignLeft="@+id/iv_key_4"
+                android:layout_alignTop="@+id/iv_key_4"
+                android:layout_alignRight="@+id/iv_key_4"
+                android:layout_alignBottom="@+id/iv_key_4"
                 android:visibility="gone" />
         </RelativeLayout>
     </LinearLayout>

+ 2 - 1
app/src/main/res/layout/item_rv_lock_dock_child_status.xml

@@ -21,6 +21,7 @@
         android:layout_toRightOf="@+id/root"
         android:divider="@drawable/divider_dock_lock_status"
         android:gravity="center"
+        android:visibility="invisible"
         android:orientation="vertical"
         android:showDividers="middle">
 
@@ -43,7 +44,7 @@
         android:layout_height="wrap_content"
         android:layout_alignLeft="@+id/root"
         android:layout_alignTop="@+id/root"
-        android:layout_alignRight="@+id/ll_lock_status"
+        android:layout_alignRight="@+id/root"
         android:layout_alignBottom="@+id/root"
         android:visibility="gone" />
 </RelativeLayout>

+ 4 - 0
app/src/main/res/values-en/strings.xml

@@ -216,6 +216,10 @@
     <string name="exception_report_type_hint">Please select exception type</string>
     <string name="exception_report_level">Severity Level:</string>
     <string name="exception_report_level_hint">Please select severity level</string>
+    <string name="exception_report_hardware_key">Key number:</string>
+    <string name="exception_report_hardware_lock">Lock number:</string>
+    <string name="exception_report_hardware_job_card">Job card number:</string>
+    <string name="exception_report_hardware_rfid_point">Rfid number:</string>
     <string name="exception_report_description">Exception Description:</string>
     <string name="fingerprint_config">Fingerprint Settings</string>
     <string name="face_config">Face Settings</string>

+ 4 - 0
app/src/main/res/values-zh/strings.xml

@@ -217,6 +217,10 @@
     <string name="exception_report_level">严重等级:</string>
     <string name="exception_report_level_hint">请选择严重等级</string>
     <string name="exception_report_description">异常描述:</string>
+    <string name="exception_report_hardware_key">钥匙编号:</string>
+    <string name="exception_report_hardware_lock">挂锁编号:</string>
+    <string name="exception_report_hardware_job_card">工卡编号:</string>
+    <string name="exception_report_hardware_rfid_point">Rfid标记:</string>
     <string name="fingerprint_config">指纹设置</string>
     <string name="face_config">人脸设置</string>
     <string name="add_fingerprint">添加指纹</string>

+ 5 - 1
app/src/main/res/values/strings.xml

@@ -217,6 +217,10 @@
     <string name="exception_report_level">严重等级:</string>
     <string name="exception_report_level_hint">请选择严重等级</string>
     <string name="exception_report_description">异常描述:</string>
+    <string name="exception_report_hardware_key">钥匙编号:</string>
+    <string name="exception_report_hardware_lock">挂锁编号:</string>
+    <string name="exception_report_hardware_job_card">工卡编号:</string>
+    <string name="exception_report_hardware_rfid_point">Rfid标记:</string>
     <string name="fingerprint_config">指纹设置</string>
     <string name="face_config">人脸设置</string>
     <string name="add_fingerprint">添加指纹</string>
@@ -306,7 +310,7 @@
     <string name="repair_key">修复</string>
     <string name="no_key_to_repair">钥匙不存在,无法修复</string>
     <string name="key_take_error_tip">钥匙分配失败,请检查硬件状态</string>
-    
+
     <string name="index_number">编号</string>
     <string name="icon">图标</string>
     <string name="ticket_name">作业票名称</string>