Bladeren bron

refactor(更新) :
- 修复钥匙归还失败后无法再次读取作业票的问题
- 修改钥匙连接策略,优先连接已连接或者连接中的钥匙,减少不必要的断开和重连
- 增加钥匙归还强制上传数据的弹窗
- 修复钥匙下发作业票时过滤条件错误的问题
- 增加蓝牙扫描超时时间
- 优化蓝牙连接和断开逻辑

周文健 3 maanden geleden
bovenliggende
commit
dd9017d464

+ 196 - 115
app/src/main/java/com/grkj/iscs_mars/BusinessManager.kt

@@ -24,8 +24,8 @@ 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
 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_CARD
 import com.grkj.iscs_mars.model.DeviceConst.DEVICE_TYPE_FINGERPRINT
 import com.grkj.iscs_mars.model.DeviceConst.DEVICE_TYPE_KEY
@@ -84,7 +84,6 @@ import com.sik.sikcore.date.TimeUtils
 import com.sik.sikcore.thread.ThreadUtils
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.async
-import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.suspendCancellableCoroutine
 import kotlinx.coroutines.withContext
 import kotlin.coroutines.resume
@@ -251,19 +250,16 @@ object BusinessManager {
         val result = suspendCancellableCoroutine<Boolean> { cont ->
             NetApi.getMySelfState {
                 if (it) {
-                    val maxPowerMac = getMaxPowerKey(mac ?: "").mac
-                    if (maxPowerMac != mac) {
-                        BleSendDispatcher.scheduleDisconnect(mac ?: "", delayMillis)
-                        connectExistsKey(listOf(mac ?: ""))
-                    } else {
-                        connectExistsKey()
+                    LogUtil.i("蓝牙连接-存在上锁解锁待办")
+                    if (BleSendDispatcher.canConnect()) {
+                        LogUtil.i("蓝牙连接-发送队列可以连接")
+                        mac?.let {
+                            connectExistsKey(listOf(it))
+                        }
                     }
                 } else {
-                    mac?.let {
-                        BleSendDispatcher.scheduleDisconnect(mac, delayMillis)
-                    } ?: let {
-                        BleSendDispatcher.disconnectAll(delayMillis)
-                    }
+                    LogUtil.i("蓝牙连接-没有待办数据,延迟断开所有发送连接")
+                    BleSendDispatcher.disconnectAll(delayMillis)
                 }
                 if (cont.isActive) {
                     cont.resume(it)
@@ -370,13 +366,6 @@ object BusinessManager {
         }
     }
 
-    /**
-     * 获取最多电量的钥匙
-     */
-    fun getMaxPowerKey(mac: String): DockBean.KeyBean {
-        return ModBusController.getMaxPowerKey(mac)
-    }
-
     /**
      * 硬件状态
      * 1、检测到有钥匙
@@ -652,6 +641,28 @@ object BusinessManager {
         ModBusController.updateSwitchStatus(done)
     }
 
+    /**
+     * 钥匙归还提示确认弹窗,当前策略:作业票未完成是否强制上传数据
+     */
+    private fun showKeyReturnUploadDataForceDialog(onConfirm: () -> Unit, onCancel: () -> Unit) {
+        val ctx = ActivityUtils.currentActivity() as BaseActivity<*>
+        val dlg = TipDialog(ctx)
+        dlg.setTip(ctx.getString(R.string.key_return_force_tip))
+        dlg.setType(TipDialog.TYPE_ALL)
+        // 加个选择判断,如果是直接取消弹框而不是点击“确定”,当成确定
+        var state = 0
+        dlg.setConfirmListener {
+            state = 1
+            onConfirm.invoke()
+        }
+        dlg.setOnDismissListener {
+            if (state == 0) {
+                onConfirm.invoke()
+            }
+        }
+        dlg.show()
+    }
+
     /**
      * 钥匙归还提示确认弹框,当前策略:作业票未完成禁止归还钥匙
      */
@@ -854,8 +865,7 @@ object BusinessManager {
      * 注册连接监听
      */
     fun registerConnectListener(
-        mac: String, connectNow: Boolean = false,
-        isSend: Boolean = true, callBack: ((
+        mac: String, connectNow: Boolean = false, isSend: Boolean = true, callBack: ((
             Boolean, BleBean?
         ) -> Unit)? = null
     ) {
@@ -894,14 +904,11 @@ object BusinessManager {
         activity: AppCompatActivity,
         isNeedLoading: Boolean = false,
     ) {
-        registerConnectListener(mac, true, true) { isDone, bleBean ->
-            if (!isDone) {
-                sendTicketBusiness(isLock, mac, ticketDetail, lockList, activity, isNeedLoading)
-                return@registerConnectListener
-            }
+        if (BleSendDispatcher.isConnected(mac)) {
+            val bleBean = getBleDeviceByMac(mac)
             if (bleBean == null) {
                 LogUtil.e("sendTicketBusiness fail : $mac, bleBean is null")
-                return@registerConnectListener
+                return
             }
             // 单bleBean json赋值
             bleBean.retryCount = 0
@@ -909,6 +916,10 @@ object BusinessManager {
             bleBean.ticketSend?.let { itJson ->
                 sendTicketWithRetry(itJson, bleBean.bleDevice, isNeedLoading)
             }
+        } else {
+            ThreadUtils.runOnIODelayed(1000) {
+                sendTicketBusiness(isLock, mac, ticketDetail, lockList, activity, isNeedLoading)
+            }
         }
     }
 
@@ -946,18 +957,21 @@ object BusinessManager {
     private fun getTicketStatusBusiness(
         mac: String, isNeedLoading: Boolean = false
     ) {
-        registerConnectListener(mac, true, false) { isDone, bleBean ->
-            if (isDone) {
-                Executor.delayOnMain(500) {
-                    getTicketStatusWithRetry(bleBean!!.bleDevice, isNeedLoading)
-                }
-            } else {
-                if (isNeedLoading) sendEventMsg(
-                    MsgEvent(
-                        MSG_EVENT_LOADING, LoadingMsg(false, null, false)
-                    )
+        LogUtil.i("检查钥匙连接情况")
+        if (BleReturnDispatcher.isConnected(mac)) {
+            getBleDeviceByMac(mac)?.bleDevice?.let {
+                LogUtil.i("开始读取作业票")
+                getTicketStatusWithRetry(
+                    it,
+                    isNeedLoading
                 )
             }
+        } else {
+            if (isNeedLoading) sendEventMsg(
+                MsgEvent(
+                    MSG_EVENT_LOADING, LoadingMsg(false, null, false)
+                )
+            )
         }
     }
 
@@ -1062,27 +1076,28 @@ object BusinessManager {
             taskCode = vo.ticketId.toString(), codeId = 1
         )
         val taskList = ArrayList<WorkTicketSendBO.DataBO.DataListBO>()
-        vo.ticketPointsVOList?.let { itList ->
-            itList.forEach { pointVO ->
-                if (vo.noUnlockTicketPointsVOSet?.any { it.pointId == pointVO.pointId } == true && isLock == false) {
-                    return@forEach
-                }
-                val task = WorkTicketSendBO.DataBO.DataListBO(
-                    dataId = pointVO.pointId?.toInt(),
-                    equipRfidNo = pointVO.pointNfc,
-                    equipName = pointVO.pointName,
-                    target = if (isLock) 0 else 1
-                )
-                if (!isLock) {
-                    task.infoRfidNo = pointVO.lockNfc
-                }
-                pointVO.prePointId?.let {
-                    task.prevId = it.toInt()
+        vo.ticketPointsVOList?.filter { it.pointStatus == if (isLock) "0" else "1" }
+            ?.let { itList ->
+                itList.forEach { pointVO ->
+                    if (vo.noUnlockTicketPointsVOSet?.any { it.pointId == pointVO.pointId } == true && !isLock) {
+                        return@forEach
+                    }
+                    val task = WorkTicketSendBO.DataBO.DataListBO(
+                        dataId = pointVO.pointId?.toInt(),
+                        equipRfidNo = pointVO.pointNfc,
+                        equipName = pointVO.pointName,
+                        target = if (isLock) 0 else 1
+                    )
+                    if (!isLock) {
+                        task.infoRfidNo = pointVO.lockNfc
+                    }
+                    pointVO.prePointId?.let {
+                        task.prevId = it.toInt()
+                    }
+                    // TODO partCode待补充
+                    taskList.add(task)
                 }
-                // TODO partCode待补充
-                taskList.add(task)
             }
-        }
         dataBO.dataList = taskList
         bo.data = mutableListOf(dataBO)
         if (isLock) {
@@ -1150,8 +1165,7 @@ object BusinessManager {
                 if (isSuccess) {
                     //尝试使用命令作为心跳 ,获取token完成之后就要建立心跳了
                     BleCmdManager.getPower(
-                        bleBean.bleDevice.mac,
-                        null
+                        bleBean.bleDevice.mac, null
                     )
                 }
             }
@@ -1291,10 +1305,21 @@ object BusinessManager {
             if (isTimeout) {
                 LogUtil.e("getCurrentStatus timeout : mac = ${bleDevice.mac}, retryCount = $retryCount")
                 if (retryCount > 0) {
-                    Executor.delayOnMain(1000) {
-                        getCurrentStatus(from, bleDevice, retryCount - 1, timeoutCallBack)
+                    if (from != 4) {
+                        val canConnect = BleSendDispatcher.canConnect()
+                        LogUtil.i("发送队列是否可以连接:${canConnect}")
+                        if (BleSendDispatcher.isConnected(bleDevice.mac)) {
+                            BleSendDispatcher.scheduleDisconnect(bleDevice.mac)
+                        }
+                        BleSendDispatcher.submit(bleDevice.mac) {
+                            getCurrentStatus(
+                                from, bleDevice, retryCount - 1, timeoutCallBack
+                            )
+                        }
                     }
                 } else {
+                    BleSendDispatcher.scheduleDisconnect(bleDevice.mac)
+                    BleReturnDispatcher.scheduleDisconnect(bleDevice.mac)
                     ModBusController.getKeyByMac(bleDevice.mac)?.rfid?.let {
                         addExceptionKey(it)
                         timeoutCallBack?.invoke(true)
@@ -1329,7 +1354,10 @@ object BusinessManager {
                 LogUtil.i("getCurrentStatus fail : ${bleDevice.mac}")
                 isTimeout = false
                 Executor.delayOnMain(1000) {
-                    getCurrentStatus(from, bleDevice, timeoutCallBack = timeoutCallBack)
+                    getCurrentStatus(
+                        from, bleDevice,
+                        retryCount - 1, timeoutCallBack = timeoutCallBack
+                    )
                 }
             }
         })
@@ -1459,7 +1487,20 @@ object BusinessManager {
                 } else {
                     // 当前策略:作业票未完成禁止归还钥匙
                     withContext(Dispatchers.Main) {
-                        showKeyReturnDialog {
+                        showKeyReturnUploadDataForceDialog({
+                            handleKeyReturn(bleDevice, workTicketGetBO, finishedStatus.second)
+                            //检查钥匙是否代取,如果是的话给钥匙
+                            val keyBean = ModBusController.getKeyByMac(bleDevice.mac)
+                            mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && it.nfc == keyBean?.rfid }
+                                ?.let { itKey ->
+                                    sendLoadingEventMsg(
+                                        MyApplication.instance?.applicationContext!!.getString(
+                                            R.string.ble_connecting
+                                        )
+                                    )
+                                    handleGiveKey(itKey)
+                                }
+                        }) {
                             sendLoadingEventMsg(null, false)
                             ToastUtils.tip(R.string.continue_the_ticket)
                             BleReturnDispatcher.scheduleDisconnect(bleDevice.mac)
@@ -1495,20 +1536,21 @@ object BusinessManager {
             val keyNfc = ModBusController.getKeyByMac(bleDevice.mac)?.rfid ?: "key rfid lost"
             workTicketGetBO?.data?.forEach { data ->
                 val updateList = mutableListOf<LockPointUpdateReqVO>()
-                data.dataList?.forEach { dataListDTO ->
-                    data.taskCode?.toLong()?.let {
-                        SPUtils.returnKey(it)
+                data.dataList?.filter { it.closed == 1 && it.status == it.target }
+                    ?.forEach { dataListDTO ->
+                        data.taskCode?.toLong()?.let {
+                            SPUtils.returnKey(it)
+                        }
+                        val updateVO = LockPointUpdateReqVO(
+                            data.taskCode?.toLong(),
+                            dataListDTO.infoRfidNo,
+                            dataListDTO.equipRfidNo,
+                            keyNfc,
+                            dataListDTO.target,
+                            dataListDTO.status
+                        )
+                        updateList.add(updateVO)
                     }
-                    val updateVO = LockPointUpdateReqVO(
-                        data.taskCode?.toLong(),
-                        dataListDTO.infoRfidNo,
-                        dataListDTO.equipRfidNo,
-                        keyNfc,
-                        dataListDTO.target,
-                        dataListDTO.status
-                    )
-                    updateList.add(updateVO)
-                }
 
                 sendLoadingEventMsg(null, false)
                 if (CAN_RETURN) {
@@ -1750,6 +1792,10 @@ object BusinessManager {
             0 -> {
                 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 }) {
+                            LogUtil.i("存在未取出的挂锁,不继续操作")
+                            return
+                        }
                         sendLoadingEventMsg(null, false)
                         SPUtils.takeKey(info.ticketId)
                         NetApi.updateKeyTake(
@@ -1927,45 +1973,20 @@ object BusinessManager {
                         return
                     }
                     updateBo?.let { itBO ->
-                        NetApi.getStepDetail(itBO.ticketId) {
-                            var step = 0
-                            it?.filter { it.stepStatus == "1" }
-                                ?.maxByOrNull { it.stepIndex!! }?.stepIndex?.let {
-                                    step = it
-                                }
-                            NetApi.getTicketDetail(itBO.ticketId) { ticketDetail, _ ->
-                                if (ticketDetail == null) {
-                                    return@getTicketDetail
-                                }
-                                val role = ticketDetail?.ticketUserVOList?.find {
-                                    it.userId == SPUtils.getLoginUser(MyApplication.instance?.applicationContext!!)?.userId && it.userType == USER_TYPE_LOCKER
-                                }
-                                if (role == null) {
-                                    ToastUtils.tip(R.string.you_are_not_locker_tip)
-                                    return@getTicketDetail
-                                }
-                                if (step == 4) {    // 上锁工作票
-                                    sendTicketBusiness(
-                                        true,
-                                        currentModeMsg.bleBean.bleDevice.mac,
-                                        ticketDetail,
-                                        ticketDetail.ticketLockVOList?.filter { it.lockStatus != "2" }
-                                            ?.map { it.lockNfc }?.toMutableList(),
-                                        ActivityUtils.currentActivity() as BaseActivity<*>,
-                                        true
-                                    )
-                                } else if (step == 7) { // 解锁工作票
-                                    sendTicketBusiness(
-                                        false,
-                                        currentModeMsg.bleBean.bleDevice.mac,
-                                        ticketDetail,
-                                        null,
-                                        ActivityUtils.currentActivity() as BaseActivity<*>,
-                                        true
-                                    )
-                                }
+                        if (BleReturnDispatcher.isConnected(currentModeMsg.bleBean.bleDevice.mac)) {
+                            LogUtil.i("当前钥匙在归还队列,断开连接")
+                            BleReturnDispatcher.scheduleDisconnect(currentModeMsg.bleBean.bleDevice.mac)
+                        }
+                        if (BleSendDispatcher.isConnected(currentModeMsg.bleBean.bleDevice.mac)) {
+                            LogUtil.i("当前钥匙已在发送队列连接")
+                            checkAndSendTicket(currentModeMsg, itBO)
+                        } else {
+                            LogUtil.i("当前钥匙未加入发送队列,连接后发送")
+                            BleSendDispatcher.submit(currentModeMsg.bleBean.bleDevice.mac) {
+                                checkAndSendTicket(currentModeMsg, itBO)
                             }
                         }
+
                     } ?: let {
                         ModBusController.updateKeyReadyStatus(
                             currentModeMsg.bleBean.bleDevice.mac, true, 4
@@ -1977,6 +1998,16 @@ object BusinessManager {
                             checkMyTodoForHandleKey(currentModeMsg.bleBean.bleDevice.mac)
                         }
                     }
+                } ?: let {
+                    ModBusController.updateKeyReadyStatus(
+                        currentModeMsg.bleBean.bleDevice.mac, true, 4
+                    )
+                    sendLoadingEventMsg(null, false)
+                    BleReturnDispatcher.scheduleDisconnect(currentModeMsg.bleBean.bleDevice.mac)
+                    //连上之后没有工作票要下发就断开 看是否还有设备等待连接,没有就不断开,有就让路,一般是初始化的时候
+                    ThreadUtils.runOnIO {
+                        checkMyTodoForHandleKey(currentModeMsg.bleBean.bleDevice.mac)
+                    }
                 }
             }
             // 故障模式
@@ -1989,6 +2020,54 @@ object BusinessManager {
         }
     }
 
+
+    /**
+     * 检查并下发作业票
+     */
+    private fun checkAndSendTicket(currentModeMsg: CurrentModeMsg, itBO: DeviceTakeUpdateBO) {
+        NetApi.getStepDetail(itBO.ticketId) {
+            var step = 0
+            it?.filter { it.stepStatus == "1" }
+                ?.maxByOrNull { it.stepIndex!! }?.stepIndex?.let {
+                    step = it
+                }
+            NetApi.getTicketDetail(itBO.ticketId) { ticketDetail, _ ->
+                if (ticketDetail == null) {
+                    return@getTicketDetail
+                }
+                val role = ticketDetail?.ticketUserVOList?.find {
+                    it.userId == SPUtils.getLoginUser(MyApplication.instance?.applicationContext!!)?.userId && it.userType == USER_TYPE_LOCKER
+                }
+                if (role == null) {
+                    ToastUtils.tip(R.string.you_are_not_locker_tip)
+                    return@getTicketDetail
+                }
+                if (step == 4) {    // 上锁工作票
+                    sendTicketBusiness(
+                        true,
+                        currentModeMsg.bleBean.bleDevice.mac,
+                        ticketDetail,
+                        ticketDetail.ticketLockVOList?.filter {
+                            ticketDetail.ticketPointsVOList?.mapNotNull { it.lockId }
+                                ?.contains(it.lockId) != true
+                        }?.map { it.lockNfc }?.toMutableList(),
+                        ActivityUtils.currentActivity() as BaseActivity<*>,
+                        true
+                    )
+                } else if (step == 7) { // 解锁工作票
+                    sendTicketBusiness(
+                        false,
+                        currentModeMsg.bleBean.bleDevice.mac,
+                        ticketDetail,
+                        null,
+                        ActivityUtils.currentActivity() as BaseActivity<*>,
+                        true
+                    )
+                }
+            }
+        }
+    }
+
     /**
      * 检查步骤和作业票详情并且下发作业票
      */
@@ -2014,8 +2093,10 @@ object BusinessManager {
                         true,
                         mac,
                         ticketDetail,
-                        ticketDetail.ticketLockVOList?.filter { it.lockStatus != "2" }
-                            ?.map { it.lockNfc }?.toMutableList(),
+                        ticketDetail.ticketLockVOList?.filter {
+                            ticketDetail.ticketPointsVOList?.mapNotNull { it.lockId }
+                                ?.contains(it.lockId) != true
+                        }?.map { it.lockNfc }?.toMutableList(),
                         ActivityUtils.currentActivity() as BaseActivity<*>,
                         true
                     )

+ 9 - 13
app/src/main/java/com/grkj/iscs_mars/ble/BleConnectionManager.kt

@@ -40,6 +40,7 @@ import java.util.LinkedList
 import java.util.concurrent.atomic.AtomicInteger
 import kotlin.coroutines.resume
 import kotlin.coroutines.suspendCoroutine
+import kotlin.text.clear
 
 /**
  * BLE 连接管理工具:保持原有扫描、连接、监听、取 Token 流程,
@@ -105,7 +106,6 @@ object BleConnectionManager {
         }
         if (connectNow) {
             LogUtil.w("蓝牙连接-立即连接 mac: $mac")
-            if (isSend) BleSendDispatcher.disconnectAll() else BleReturnDispatcher.disconnectAll()
             unregisterConnectListener(mac)
             currentConnectingMac.removeIf { it == mac }
         }
@@ -283,8 +283,8 @@ object BleConnectionManager {
                 newDevice: BleDevice,
                 scannedBefore: Boolean
             ) {
-                val bleMac = newDevice.mac ?: return
-                LogUtil.i("蓝牙连接-onScanning:$bleMac")
+                val bleMac = newDevice.mac
+                LogUtil.i("蓝牙连接-onScanning:$mac,$bleMac")
                 if (mac.equals(bleMac, ignoreCase = true)) {
                     // 找到目标设备,马上停止扫描
                     LogUtil.i("蓝牙连接-找到目标设备 $bleMac,停止扫描并尝试连接")
@@ -401,6 +401,12 @@ object BleConnectionManager {
                             )
                         )
                         LogUtil.i("蓝牙连接-onDisConnected : ${device?.mac} - $isActiveDisConnected")
+                        if (BleSendDispatcher.isConnected(bleDevice.mac)) {
+                            BleSendDispatcher.clear(bleDevice.mac)
+                        }
+                        if (BleReturnDispatcher.isConnected(bleDevice.mac)) {
+                            BleSendDispatcher.clear(bleDevice.mac)
+                        }
                         bleDevice.mac.let { itMac ->
                             unregisterConnectListener(
                                 itMac
@@ -411,16 +417,6 @@ object BleConnectionManager {
                             if (isTestMode) {
                                 return
                             }
-                            // 断开和重连之间最好间隔一段时间,否则可能会出现长时间连接不上的情况
-//                            Executor.delayOnMain(300) {
-//                                registerConnectListener(bleDevice.mac) { isDone, bleBean ->
-//                                    if (isDone && bleBean != null) {
-//                                        Executor.delayOnMain(300) {
-//                                            getCurrentStatus(6, bleBean.bleDevice)
-//                                        }
-//                                    }
-//                                }
-//                            }
                             ModBusController.updateKeyReadyStatus(bleDevice.mac, false, 3)
                         } else {
                             ModBusController.updateKeyReadyStatus(bleDevice.mac, false, 3)

+ 36 - 17
app/src/main/java/com/grkj/iscs_mars/ble/BleQueueDispatcher.kt

@@ -2,7 +2,9 @@ package com.grkj.iscs_mars.ble
 
 import android.annotation.SuppressLint
 import com.grkj.iscs_mars.BusinessManager
+import com.grkj.iscs_mars.util.log.LogUtil
 import com.huyuhui.fastble.BleManager
+import com.sik.sikcore.thread.ThreadUtils
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Job
@@ -13,44 +15,60 @@ import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 
 abstract class BleQueueDispatcher {
-    private val logger: Logger = LoggerFactory.getLogger(BleQueueDispatcher::class.java)
-    private val taskQueue = ArrayDeque<Pair<String, (Boolean) -> Unit>>() // mac + callback
-    private val activeMacs = mutableMapOf<String, (Boolean) -> Unit>()
+    private val taskQueue =
+        ArrayDeque<Pair<String, MutableList<(Boolean) -> Unit>>>() // mac + callback
+    private val activeMacs = mutableMapOf<String, MutableList<(Boolean) -> Unit>>()
     private val connectedMacs = mutableSetOf<String>()
     private val pendingDisconnectJobs = mutableMapOf<String, Job>()
 
     open val maxConnections: Int = 1
     private val dispatcherScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
 
+    /**
+     * 检查钥匙状态
+     */
     @Synchronized
     fun submit(mac: String, onResult: (Boolean) -> Unit) {
+        LogUtil.i("开始检查钥匙状态:${mac}")
 
         if (activeMacs.containsKey(mac) || taskQueue.any { it.first == mac } || connectedMacs.contains(
                 mac
             )) {
             if (connectedMacs.contains(mac)) {
+                LogUtil.i("${this::class.java} 检查到钥匙已连接")
                 onResult(true)
+            } else if (activeMacs.containsKey(mac)) {
+                LogUtil.i("${this::class.java} 检查到钥匙连接中添加回调")
+                activeMacs[mac]?.add(onResult)
+            } else if (taskQueue.find { it.first == mac } != null) {
+                LogUtil.i("${this::class.java} 检查到钥匙队列中添加回调")
+                taskQueue.find { it.first == mac }?.second?.add(onResult)
             }
             // 如果已存在断连计划,取消它
             pendingDisconnectJobs.remove(mac)?.cancel()
             return
         }
-        taskQueue.add(mac to onResult)
+        taskQueue.add(mac to mutableListOf(onResult))
         tryStartNext()
     }
 
+    /**
+     * 开始连接
+     */
     @Synchronized
     private fun tryStartNext() {
         if ((activeMacs.size + connectedMacs.size) >= maxConnections || taskQueue.isEmpty()) return
-        val (mac, callback) = taskQueue.removeFirst()
-        activeMacs[mac] = callback
+        val (mac, callbacks) = taskQueue.removeFirst()
+        activeMacs[mac] = callbacks
         doConnect(mac) { success ->
             synchronized(this) {
                 activeMacs.remove(mac)
                 if (success) {
                     connectedMacs.add(mac)
                 }
-                callback(success)
+                callbacks.forEach {
+                    it.invoke(success)
+                }
                 tryStartNext()
             }
         }
@@ -64,9 +82,6 @@ abstract class BleQueueDispatcher {
         activeMacs.remove(mac)
         connectedMacs.remove(mac)
         pendingDisconnectJobs.remove(mac)?.cancel()
-        if ((activeMacs.size + connectedMacs.size) < maxConnections && taskQueue.isNotEmpty()) {
-            tryStartNext()
-        }
     }
 
     @SuppressLint("MissingPermission")
@@ -78,14 +93,18 @@ abstract class BleQueueDispatcher {
             delay(delayMillis)
             synchronized(this@BleQueueDispatcher) {
                 if (connectedMacs.remove(mac)) {
-                    val deviceBean = BusinessManager.deviceList.find { it.bleDevice.mac == mac }
-                    deviceBean?.let {
-                        disconnectDeviceByMac(mac)
-                        BusinessManager.deviceList.removeIf { it.bleDevice.mac == deviceBean.bleDevice.mac }
+                    ThreadUtils.runOnIO {
+                        val deviceBean = BusinessManager.deviceList.find { it.bleDevice.mac == mac }
+                        deviceBean?.let {
+                            disconnectDeviceByMac(mac)
+                            BusinessManager.deviceList.removeIf { it.bleDevice.mac == deviceBean.bleDevice.mac }
+                        }
+                        LogUtil.i("当前线程:${Thread.currentThread().name}")
+                        clear(mac)
+                        if ((activeMacs.size + connectedMacs.size) < maxConnections && taskQueue.isNotEmpty()) {
+                            tryStartNext()
+                        }
                     }
-                    logger.info("当前线程:${Thread.currentThread().name}")
-                    clear(mac)
-                    tryStartNext()
                 }
                 pendingDisconnectJobs.remove(mac)
             }

+ 7 - 0
app/src/main/java/com/grkj/iscs_mars/ble/BleReturnDispatcher.kt

@@ -1,11 +1,18 @@
 package com.grkj.iscs_mars.ble
 
+import com.grkj.iscs_mars.BusinessManager
+import com.grkj.iscs_mars.R
+import com.grkj.iscs_mars.util.CommonUtils
+import com.sik.sikcore.SIKCore
 import com.sik.sikcore.thread.ThreadUtils
 
 object BleReturnDispatcher : BleQueueDispatcher() {
     override val maxConnections = 1
 
     override fun doConnect(mac: String, callback: (Boolean) -> Unit) {
+        ThreadUtils.runOnMain {
+            BusinessManager.sendLoadingEventMsg(CommonUtils.getStr(R.string.loading_msg_return_key_start).toString())
+        }
         ThreadUtils.runOnIO {
             val isConnected = BleConnectionManager.tryConnectWithOptionalCharge(mac, isSend = false)
             callback(isConnected)

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

@@ -52,7 +52,7 @@ class BleUtil private constructor() {
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
                 //Android 12及以上不允许添加过滤器
                 val bleScanRuleConfig = BleScanRuleConfig.Builder()
-                    .setScanTimeOut(3_000L)
+                    .setScanTimeOut(6_000L)
                     .setDeviceName(Constants.BLE_LOCAL_NAME)
                     .apply {
                         setScanSettings(ScanSettings.Builder().apply {
@@ -205,8 +205,6 @@ class BleUtil private constructor() {
                                 cmd,
                                 callback = writeCallback
                             )
-                        } else {
-                            checkAndWrite()
                         }
                     }
                 }

+ 50 - 20
app/src/main/java/com/grkj/iscs_mars/modbus/ModBusController.kt

@@ -1051,6 +1051,16 @@ object ModBusController {
             dockList.filter { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }
                 .sortedBy { it.addr }.onEach { it.deviceList.sortBy { dev -> dev.idx } }
 
+        val noBelongDevice = BleManager.getAllConnectedDevice().filter {
+            !BleSendDispatcher.isConnected(it.mac) &&
+                    !BleSendDispatcher.isConnecting(it.mac) &&
+                    !BleReturnDispatcher.isConnected(it.mac) &&
+                    !BleReturnDispatcher.isConnecting(it.mac)
+        }
+        LogUtil.i("检查到不属于任何队列的设备:${noBelongDevice.map { it.mac }},立即断开连接让路")
+        noBelongDevice.forEach {
+            BleManager.disconnect(it)
+        }
         var keyList = keyDockList.flatMap { it.deviceList }.apply {
             LogUtil.i("keyStatus:${this}")
         }.filterIsInstance<DockBean.KeyBean>()
@@ -1071,14 +1081,44 @@ object ModBusController {
                     it.mac ?: ""
                 )
             }    // 主键:在线优先
-                .thenByDescending { BusinessManager.getBleDeviceByMac(it.mac)?.token != null } // 次键:有 token 优先
                 .thenByDescending { it.power }
         )
-
+        val connectedKey = keyList.find { BleSendDispatcher.isConnected(it.mac ?: "") }
+        if (connectedKey != null) {
+            val addr =
+                keyDockList.firstOrNull {
+                    it.getKeyList().any { it.rfid == connectedKey.rfid }
+                }?.addr
+            if (addr != null) {
+                return addr to connectedKey
+            }
+        }
+        val connectingKey = keyList.find { BleSendDispatcher.isConnecting(it.mac ?: "") }
+        if (connectingKey != null) {
+            val result = suspendCoroutine { cont ->
+                BleSendDispatcher.submit(connectingKey.mac ?: "") { connected ->
+                    if (connected) {
+                        val addr =
+                            keyDockList.firstOrNull {
+                                it.getKeyList().any { it.rfid == connectingKey.rfid }
+                            }?.addr
+                        if (addr != null) {
+                            cont.resume(addr to connectingKey)
+                        } else {
+                            cont.resume(null)
+                        }
+                    } else {
+                        cont.resume(null)
+                    }
+                }
+            }
+            if (result != null) {
+                return result
+            }
+        }
         for (kb in keyList) {
             val mac = kb.mac ?: continue
-
-            val result = suspendCoroutine<Pair<Byte, DockBean.KeyBean>?> { cont ->
+            val result = suspendCoroutine { cont ->
                 BleSendDispatcher.submit(mac) { connected ->
                     if (connected) {
                         LogUtil.i("蓝牙连接完成 :${mac}")
@@ -1092,10 +1132,14 @@ object ModBusController {
                                 cont.resume(addr to kb)
                             }
                         } else {
-                            null
+                            if (cont.context.isActive) {
+                                cont.resume(null)
+                            }
                         }
                     } else {
-                        null
+                        if (cont.context.isActive) {
+                            cont.resume(null)
+                        }
                     }
                 }
             }
@@ -1176,20 +1220,6 @@ object ModBusController {
         }
     }
 
-    /**
-     * 获取最多电量的钥匙
-     */
-    fun getMaxPowerKey(mac: String): DockBean.KeyBean {
-        return dockList.filter {
-            it.type in listOf(
-                DeviceConst.DOCK_TYPE_KEY,
-                DeviceConst.DOCK_TYPE_PORTABLE
-            )
-        }
-            .flatMap { it.deviceList }.filterIsInstance<DockBean.KeyBean>().filter { it.mac != mac }
-            .maxBy { it.power }
-    }
-
     /**
      * 更新钥匙电量
      */

+ 13 - 7
app/src/main/java/com/grkj/iscs_mars/view/presenter/HomePresenter.kt

@@ -11,6 +11,7 @@ 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.ISCSDomainData
+import com.grkj.iscs_mars.util.CommonUtils
 import com.grkj.iscs_mars.util.Executor
 import com.grkj.iscs_mars.util.NetApi
 import com.grkj.iscs_mars.util.SPUtils
@@ -23,6 +24,9 @@ import kotlinx.coroutines.delay
 
 class HomePresenter : BasePresenter<IHomeView>() {
 
+    /**
+     * 注册设备状态监听
+     */
     fun registerStatusListener() {
         BusinessManager.registerStatusListener(this) { dockBean ->
             if (!BusinessManager.CAN_RETURN || ISCSDomainData.isDeviceRegistration) {
@@ -34,15 +38,12 @@ class HomePresenter : BasePresenter<IHomeView>() {
                         if (keyBean.isExist) {
                             Executor.repeatOnMain({
                                 keyBean.mac?.let { mac ->
-                                    ThreadUtils.runOnMain {
-                                        BusinessManager.sendLoadingEventMsg(mContext?.getString(R.string.loading_msg_return_key_start))
-                                    }
                                     ThreadUtils.runOnIO {
                                         fun readJobTicket(mac: String) {
-                                            val isConnect =
-                                                BleReturnDispatcher.submit(mac){isConnect->
+                                                BleReturnDispatcher.submit(mac) { isConnect ->
                                                     if (isConnect) {
-                                                        val bleBean = BusinessManager.getBleDeviceByMac(mac)
+                                                        val bleBean =
+                                                            BusinessManager.getBleDeviceByMac(mac)
                                                         Executor.delayOnMain(300) {
                                                             bleBean?.let {
                                                                 BusinessManager.sendLoadingEventMsg(
@@ -57,7 +58,9 @@ class HomePresenter : BasePresenter<IHomeView>() {
                                                             }
                                                         }
                                                     } else {
-                                                        readJobTicket(mac)
+                                                        ModBusController.controlKeyBuckle(true,mac){
+                                                            ToastUtils.tip(CommonUtils.getStr(R.string.ticket_get_failed).toString())
+                                                        }
                                                     }
                                                 }
                                         }
@@ -75,6 +78,9 @@ class HomePresenter : BasePresenter<IHomeView>() {
         }
     }
 
+    /**
+     * 取消设备注册监听
+     */
     fun unregisterListener() {
         BusinessManager.unregisterListener(this)
     }