Browse Source

refactor(更新) :
- 双路蓝牙

周文健 3 months ago
parent
commit
c41fec2058
24 changed files with 720 additions and 875 deletions
  1. 0 3
      app/src/main/AndroidManifest.xml
  2. 160 122
      app/src/main/java/com/grkj/iscs_mars/BusinessManager.kt
  3. 1 1
      app/src/main/java/com/grkj/iscs_mars/ble/BleBean.kt
  4. 38 6
      app/src/main/java/com/grkj/iscs_mars/ble/BleCmdManager.kt
  5. 177 106
      app/src/main/java/com/grkj/iscs_mars/ble/BleConnectionManager.kt
  6. 125 0
      app/src/main/java/com/grkj/iscs_mars/ble/BleQueueDispatcher.kt
  7. 14 0
      app/src/main/java/com/grkj/iscs_mars/ble/BleReturnDispatcher.kt
  8. 14 0
      app/src/main/java/com/grkj/iscs_mars/ble/BleSendDispatcher.kt
  9. 86 70
      app/src/main/java/com/grkj/iscs_mars/ble/BleUtil.kt
  10. 1 1
      app/src/main/java/com/grkj/iscs_mars/ble/CustomBleGattCallback.kt
  11. 1 1
      app/src/main/java/com/grkj/iscs_mars/ble/CustomBleIndicateCallback.kt
  12. 2 2
      app/src/main/java/com/grkj/iscs_mars/ble/CustomBleScanCallback.kt
  13. 1 1
      app/src/main/java/com/grkj/iscs_mars/ble/CustomBleWriteCallback.kt
  14. 53 15
      app/src/main/java/com/grkj/iscs_mars/modbus/ModBusController.kt
  15. 1 1
      app/src/main/java/com/grkj/iscs_mars/model/eventmsg/GetTicketStatusMsg.kt
  16. 17 55
      app/src/main/java/com/grkj/iscs_mars/service/CheckKeyInfoTask.kt
  17. 0 5
      app/src/main/java/com/grkj/iscs_mars/view/activity/MainActivity.kt
  18. 0 363
      app/src/main/java/com/grkj/iscs_mars/view/activity/test/BleActivity.kt
  19. 0 57
      app/src/main/java/com/grkj/iscs_mars/view/dialog/KeyReturnConfirmDialog.kt
  20. 5 3
      app/src/main/java/com/grkj/iscs_mars/view/presenter/DeviceStatusPresenter.kt
  21. 20 22
      app/src/main/java/com/grkj/iscs_mars/view/presenter/HomePresenter.kt
  22. 2 3
      app/src/main/java/com/grkj/iscs_mars/view/viewmodel/DeviceRegistrationKeyAndLockViewModel.kt
  23. 0 36
      app/src/main/res/layout/activity_ble.xml
  24. 2 2
      gradle/libs.versions.toml

+ 0 - 3
app/src/main/AndroidManifest.xml

@@ -107,9 +107,6 @@
         <activity
             android:name=".view.activity.test.ModbusActivity"
             android:exported="false" />
-        <activity
-            android:name=".view.activity.test.BleActivity"
-            android:exported="false" />
         <activity
             android:name=".view.activity.MainActivity"
             android:exported="true"></activity>

+ 160 - 122
app/src/main/java/com/grkj/iscs_mars/BusinessManager.kt

@@ -1,12 +1,10 @@
 package com.grkj.iscs_mars
 //todo 所有蓝牙包替换com.clj. -> com.clj.
+import android.bluetooth.BluetoothGattCharacteristic
 import android.content.Context
 import android.content.Intent
 import androidx.appcompat.app.AppCompatActivity
 import androidx.lifecycle.MutableLiveData
-import com.clj.fastble.BleManager
-import com.clj.fastble.data.BleDevice
-import com.clj.fastble.exception.BleException
 import com.google.gson.Gson
 import com.grkj.iscs_mars.ble.BleBean
 import com.grkj.iscs_mars.ble.BleCmdManager
@@ -14,6 +12,8 @@ import com.grkj.iscs_mars.ble.BleConnectionManager
 import com.grkj.iscs_mars.ble.BleConst
 import com.grkj.iscs_mars.ble.BleConst.STATUS_READY
 import com.grkj.iscs_mars.ble.BleConst.STATUS_WORK
+import com.grkj.iscs_mars.ble.BleReturnDispatcher
+import com.grkj.iscs_mars.ble.BleSendDispatcher
 import com.grkj.iscs_mars.ble.BleUtil
 import com.grkj.iscs_mars.ble.CustomBleWriteCallback
 import com.grkj.iscs_mars.extentions.removeLeadingZeros
@@ -75,7 +75,10 @@ import com.grkj.iscs_mars.util.log.LogUtil
 import com.grkj.iscs_mars.view.activity.LoginActivity
 import com.grkj.iscs_mars.view.base.BaseActivity
 import com.grkj.iscs_mars.view.dialog.TipDialog
+import com.huyuhui.fastble.data.BleDevice
+import com.huyuhui.fastble.exception.BleException
 import com.sik.cronjob.managers.CronJobScanner
+import com.sik.sikandroid.activity.ActivityTracker
 import com.sik.sikcore.SIKCore
 import com.sik.sikcore.date.TimeUtils
 import com.sik.sikcore.thread.ThreadUtils
@@ -107,11 +110,6 @@ object BusinessManager {
 
     private var initListener: (() -> Unit)? = null
 
-    /**
-     * 断开连接任务
-     */
-    private val disconnectJob: HashMap<String, String> = hashMapOf()
-
     // 归还设备是否需要登录
     var NEED_AUTH = true
 
@@ -168,8 +166,7 @@ object BusinessManager {
                         1 -> {
                             if (it.data.res == 1) {
                                 // 只能在这里断开,不能全部断开
-                                BleManager.getInstance().disconnect(it.data.bleBean.bleDevice)
-                                deviceList.removeIf { device -> device.bleDevice.mac == it.data.bleBean.bleDevice.mac }
+                                BleSendDispatcher.scheduleDisconnect(it.data.bleBean.bleDevice.mac)
                                 // 打开钥匙卡扣
                                 val keyBean =
                                     ModBusController.getKeyByMac(it.data.bleBean.bleDevice.mac)
@@ -247,25 +244,25 @@ object BusinessManager {
     /**
      * 检查我的待办
      */
-    suspend fun checkMyTodoForHandleKey(mac: String? = null): Boolean {
+    suspend fun checkMyTodoForHandleKey(mac: String? = null, delayMillis: Long = 60_0000): Boolean {
         if (!CAN_RETURN) {
             return false
         }
         val result = suspendCancellableCoroutine<Boolean> { cont ->
             NetApi.getMySelfState {
                 if (it) {
-                    val maxPowerMac = getMaxPowerKey().mac
+                    val maxPowerMac = getMaxPowerKey(mac ?: "").mac
                     if (maxPowerMac != mac) {
+                        BleSendDispatcher.scheduleDisconnect(mac ?: "", delayMillis)
                         connectExistsKey(listOf(mac ?: ""))
-                        launchDisconnectJob(mac ?: "")
                     } else {
                         connectExistsKey()
                     }
                 } else {
                     mac?.let {
-                        launchDisconnectJob(it)
+                        BleSendDispatcher.scheduleDisconnect(mac, delayMillis)
                     } ?: let {
-                        launchDisconnectAllJob()
+                        BleSendDispatcher.disconnectAll(delayMillis)
                     }
                 }
                 if (cont.isActive) {
@@ -281,14 +278,6 @@ object BusinessManager {
      */
     fun connectExistsKey(exceptKeyMac: List<String> = listOf()) {
         ThreadUtils.runOnIO {
-            cancelDisconnectAllJob()
-            val connectedDevice = BleManager.getInstance().allConnectedDevice
-            if (connectedDevice.isNotEmpty() && connectedDevice.subtract(exceptKeyMac.toSet())
-                    .isNotEmpty()
-            ) {
-                LogUtil.i("已有钥匙连接")
-                return@runOnIO
-            }
             // —— 串行请求1 & 2 ——
             val slotsPage = getSlotsPage()
 
@@ -384,8 +373,8 @@ object BusinessManager {
     /**
      * 获取最多电量的钥匙
      */
-    fun getMaxPowerKey(): DockBean.KeyBean {
-        return ModBusController.getMaxPowerKey()
+    fun getMaxPowerKey(mac: String): DockBean.KeyBean {
+        return ModBusController.getMaxPowerKey(mac)
     }
 
     /**
@@ -865,11 +854,12 @@ object BusinessManager {
      * 注册连接监听
      */
     fun registerConnectListener(
-        mac: String, connectNow: Boolean = false, callBack: ((
+        mac: String, connectNow: Boolean = false,
+        isSend: Boolean = true, callBack: ((
             Boolean, BleBean?
         ) -> Unit)? = null
     ) {
-        BleConnectionManager.registerConnectListener(mac, connectNow, callBack)
+        BleConnectionManager.registerConnectListener(mac, connectNow, isSend, callBack)
     }
 
     /**
@@ -893,55 +883,6 @@ object BusinessManager {
         return null
     }
 
-    /**
-     * 启动断连任务
-     */
-    fun launchDisconnectJob(mac: String) {
-        val jobId = ThreadUtils.runOnIODelayed(Constants.BLE_DISCONNECT_DELAY_TIME) {
-            val bleBean = getBleDeviceByMac(mac)
-            bleBean?.bleDevice?.let {
-                BleManager.getInstance().disconnect(it)
-            }
-        }
-        disconnectJob[mac] = jobId
-    }
-
-    /**
-     * 启动断连所有设备任务
-     */
-    fun launchDisconnectAllJob() {
-        deviceList.forEach { bleBean ->
-            val jobId = ThreadUtils.runOnIODelayed(Constants.BLE_DISCONNECT_DELAY_TIME) {
-                val bleBean = getBleDeviceByMac(bleBean.bleDevice.mac)
-                bleBean?.bleDevice?.let {
-                    BleManager.getInstance().disconnect(it)
-                    deviceList.removeIf { it == bleBean }
-
-                }
-            }
-            disconnectJob[bleBean.bleDevice.mac] = jobId
-        }
-    }
-
-    /**
-     * 取消断连所有设备任务
-     */
-    fun cancelDisconnectAllJob() {
-        disconnectJob.forEach {
-            ThreadUtils.cancel(it.value)
-        }
-    }
-
-    /**
-     * 取消断连任务
-     */
-    fun cancelDisconnectJob(mac: String) {
-        val jobId = disconnectJob[mac]
-        jobId?.let {
-            ThreadUtils.cancel(it)
-        }
-    }
-
     /**
      * 下发工作票
      */
@@ -953,13 +894,12 @@ object BusinessManager {
         activity: AppCompatActivity,
         isNeedLoading: Boolean = false,
     ) {
-        registerConnectListener(mac, true) { isDone, bleBean ->
+        registerConnectListener(mac, true, true) { isDone, bleBean ->
             if (!isDone) {
                 sendTicketBusiness(isLock, mac, ticketDetail, lockList, activity, isNeedLoading)
                 return@registerConnectListener
             }
             if (bleBean == null) {
-//                ToastUtils.tip(R.string.simple_key_is_not_connected)
                 LogUtil.e("sendTicketBusiness fail : $mac, bleBean is null")
                 return@registerConnectListener
             }
@@ -1006,7 +946,7 @@ object BusinessManager {
     private fun getTicketStatusBusiness(
         mac: String, isNeedLoading: Boolean = false
     ) {
-        registerConnectListener(mac, true) { isDone, bleBean ->
+        registerConnectListener(mac, true, false) { isDone, bleBean ->
             if (isDone) {
                 Executor.delayOnMain(500) {
                     getTicketStatusWithRetry(bleBean!!.bleDevice, isNeedLoading)
@@ -1059,7 +999,14 @@ object BusinessManager {
         )
         BleCmdManager.sendWorkTicket(
             jsonStr, bleDevice = bleDevice, callback = object : CustomBleWriteCallback() {
-                override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
+                override fun onWriteSuccess(
+                    bleDevice: BleDevice,
+                    characteristic: BluetoothGattCharacteristic,
+                    current: Int,
+                    total: Int,
+                    justWrite: ByteArray,
+                    data: ByteArray
+                ) {
                     LogUtil.i("sendTicket success")
                     if (isNeedLoading) sendEventMsg(
                         MsgEvent(
@@ -1069,7 +1016,16 @@ object BusinessManager {
                     )
                 }
 
-                override fun onWriteFailure(exception: BleException?) {
+                override fun onWriteFailure(
+                    bleDevice: BleDevice,
+                    characteristic: BluetoothGattCharacteristic?,
+                    exception: BleException,
+                    current: Int,
+                    total: Int,
+                    justWrite: ByteArray?,
+                    data: ByteArray?,
+                    isTotalFail: Boolean
+                ) {
                     LogUtil.e("sendTicket fail : ${bleDevice.mac}")
                     if (isNeedLoading) sendEventMsg(
                         MsgEvent(
@@ -1192,7 +1148,11 @@ object BusinessManager {
                 bleBean.bleDevice, byteArray
             ) { isSuccess ->
                 if (isSuccess) {
-                    prepareDoneCallBack?.invoke(true, bleBean)
+                    //尝试使用命令作为心跳 ,获取token完成之后就要建立心跳了
+                    BleCmdManager.getPower(
+                        bleBean.bleDevice.mac,
+                        null
+                    )
                 }
             }
             // 工作模式切换
@@ -1222,7 +1182,9 @@ object BusinessManager {
 
             byteArray.startsWith(BleConst.RSP_POWER_STATUS) -> {
                 val power = byteArray[4].toInt()
-                ModBusController.getKeyByMac(bleBean.bleDevice.mac)?.power = power
+                ModBusController.updateKeyPower(power, bleBean.bleDevice.mac)
+                LogUtil.i("电量(${bleBean.bleDevice.mac}):${power}")
+                prepareDoneCallBack?.invoke(true, bleBean)
                 if (power < 50) {//如果电量小于50就打开仓位充电
                     ModBusController.controlKeyCharge(true, bleBean.bleDevice.mac) {
                         LogUtil.i("钥匙: ${bleBean.bleDevice.mac} 开始充电")
@@ -1341,13 +1303,29 @@ object BusinessManager {
             }
         }
         BleCmdManager.getCurrentStatus(bleDevice, object : CustomBleWriteCallback() {
-            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
+            override fun onWriteSuccess(
+                bleDevice: BleDevice,
+                characteristic: BluetoothGattCharacteristic,
+                current: Int,
+                total: Int,
+                justWrite: ByteArray,
+                data: ByteArray
+            ) {
                 LogUtil.i("getCurrentStatus success : ${bleDevice.mac}")
                 isTimeout = false
                 timeoutCallBack?.invoke(false)
             }
 
-            override fun onWriteFailure(exception: BleException?) {
+            override fun onWriteFailure(
+                bleDevice: BleDevice,
+                characteristic: BluetoothGattCharacteristic?,
+                exception: BleException,
+                current: Int,
+                total: Int,
+                justWrite: ByteArray?,
+                data: ByteArray?,
+                isTotalFail: Boolean
+            ) {
                 LogUtil.i("getCurrentStatus fail : ${bleDevice.mac}")
                 isTimeout = false
                 Executor.delayOnMain(1000) {
@@ -1363,11 +1341,27 @@ object BusinessManager {
     fun getBatteryPower(bleDevice: BleDevice) {
         LogUtil.i("获取电池电量:${bleDevice.mac}")
         BleCmdManager.getPower(bleDevice.mac, object : CustomBleWriteCallback() {
-            override fun onWriteSuccess(p0: Int, p1: Int, p2: ByteArray?) {
+            override fun onWriteSuccess(
+                bleDevice: BleDevice,
+                characteristic: BluetoothGattCharacteristic,
+                current: Int,
+                total: Int,
+                justWrite: ByteArray,
+                data: ByteArray
+            ) {
                 LogUtil.i("发送获取电池电量命令成功:${bleDevice.mac}")
             }
 
-            override fun onWriteFailure(p0: BleException?) {
+            override fun onWriteFailure(
+                bleDevice: BleDevice,
+                characteristic: BluetoothGattCharacteristic?,
+                exception: BleException,
+                current: Int,
+                total: Int,
+                justWrite: ByteArray?,
+                data: ByteArray?,
+                isTotalFail: Boolean
+            ) {
                 ThreadUtils.runOnIODelayed(500) {
                     LogUtil.i("发送获取电池电量命令失败:${bleDevice.mac}")
                     getBatteryPower(bleDevice)
@@ -1382,11 +1376,27 @@ object BusinessManager {
     private fun switchWorkMode(bleDevice: BleDevice, isNeedLoading: Boolean = false) {
         LogUtil.i("switchWorkMode - ${bleDevice.mac}")
         BleCmdManager.switchMode(STATUS_WORK, bleDevice, object : CustomBleWriteCallback() {
-            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
+            override fun onWriteSuccess(
+                bleDevice: BleDevice,
+                characteristic: BluetoothGattCharacteristic,
+                current: Int,
+                total: Int,
+                justWrite: ByteArray,
+                data: ByteArray
+            ) {
                 LogUtil.i("switch mode work success : ${bleDevice.mac}")
             }
 
-            override fun onWriteFailure(exception: BleException?) {
+            override fun onWriteFailure(
+                bleDevice: BleDevice,
+                characteristic: BluetoothGattCharacteristic?,
+                exception: BleException,
+                current: Int,
+                total: Int,
+                justWrite: ByteArray?,
+                data: ByteArray?,
+                isTotalFail: Boolean
+            ) {
                 LogUtil.e("switch mode work fail : ${exception?.code} - ${exception?.description}")
                 Executor.delayOnMain(500) {
                     switchWorkMode(bleDevice, isNeedLoading)
@@ -1452,8 +1462,7 @@ object BusinessManager {
                         showKeyReturnDialog {
                             sendLoadingEventMsg(null, false)
                             ToastUtils.tip(R.string.continue_the_ticket)
-                            BleManager.getInstance().disconnect(bleDevice)
-                            deviceList.removeIf { device -> device.bleDevice.mac == bleDevice.mac }
+                            BleReturnDispatcher.scheduleDisconnect(bleDevice.mac)
                             // 打开卡扣,防止初始化的时候选择不处理钥匙导致无法使用
                             val dock = ModBusController.getDockByKeyMac(bleDevice.mac)
                             val keyBean = dock?.getKeyList()?.find { it.mac == bleDevice.mac }
@@ -1552,8 +1561,7 @@ object BusinessManager {
                                 showKeyReturnDialog {
                                     sendLoadingEventMsg(null, false)
                                     ToastUtils.tip(R.string.continue_the_ticket)
-                                    BleManager.getInstance().disconnect(bleDevice)
-                                    deviceList.removeIf { device -> device.bleDevice.mac == bleDevice.mac }
+                                    BleReturnDispatcher.scheduleDisconnect(bleDevice.mac)
                                     // 打开卡扣,防止初始化的时候选择不处理钥匙导致无法使用
                                     if (workTicketGetBO.data?.all { it.dataList?.all { it.closed == 1 } == true } == true) {
                                         workTicketGetBO.data?.firstOrNull()?.taskCode?.toLong()
@@ -1641,11 +1649,27 @@ object BusinessManager {
 
     fun switchReadyMode(bleDevice: BleDevice) {
         BleCmdManager.switchMode(STATUS_READY, bleDevice, object : CustomBleWriteCallback() {
-            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
+            override fun onWriteSuccess(
+                bleDevice: BleDevice,
+                characteristic: BluetoothGattCharacteristic,
+                current: Int,
+                total: Int,
+                justWrite: ByteArray,
+                data: ByteArray
+            ) {
                 LogUtil.i("switch mode ready success : ${bleDevice.mac}")
             }
 
-            override fun onWriteFailure(exception: BleException?) {
+            override fun onWriteFailure(
+                bleDevice: BleDevice,
+                characteristic: BluetoothGattCharacteristic?,
+                exception: BleException,
+                current: Int,
+                total: Int,
+                justWrite: ByteArray?,
+                data: ByteArray?,
+                isTotalFail: Boolean
+            ) {
                 LogUtil.e("switch mode ready fail : ${bleDevice.mac}")
                 Executor.delayOnMain(300) {
                     switchReadyMode(bleDevice)
@@ -1668,7 +1692,14 @@ object BusinessManager {
             )
         )
         BleCmdManager.getTicketStatus(bleDevice, object : CustomBleWriteCallback() {
-            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
+            override fun onWriteSuccess(
+                bleDevice: BleDevice,
+                characteristic: BluetoothGattCharacteristic,
+                current: Int,
+                total: Int,
+                justWrite: ByteArray,
+                data: ByteArray
+            ) {
                 if (isNeedLoading) sendEventMsg(
                     MsgEvent(
                         MSG_EVENT_LOADING, LoadingMsg(false, "工作票获取成功", null)
@@ -1677,7 +1708,16 @@ object BusinessManager {
                 LogUtil.i("getTicketStatus success")
             }
 
-            override fun onWriteFailure(exception: BleException?) {
+            override fun onWriteFailure(
+                bleDevice: BleDevice,
+                characteristic: BluetoothGattCharacteristic?,
+                exception: BleException,
+                current: Int,
+                total: Int,
+                justWrite: ByteArray?,
+                data: ByteArray?,
+                isTotalFail: Boolean
+            ) {
                 if (isNeedLoading) sendEventMsg(
                     MsgEvent(
                         MSG_EVENT_LOADING, LoadingMsg(false, "工作票获取失败", false)
@@ -1730,17 +1770,11 @@ object BusinessManager {
                                     unregisterConnectListener(it)
                                 }
                                 //待机数不够就再连一把,但不能是原来那把
-                                NetApi.getMySelfState {
-                                    if (it) {
-                                        ModBusController.getKeyByRfid(
-                                            info.nfc
-                                        )?.mac?.let {
-                                            val maxPowerMac = getMaxPowerKey().mac
-                                            if (maxPowerMac != it) {
-                                                connectExistsKey(listOf(it ?: ""))
-                                                launchDisconnectJob(it ?: "")
-                                            }
-                                        }
+                                ModBusController.getKeyByRfid(
+                                    info.nfc
+                                )?.mac?.let {
+                                    ThreadUtils.runOnIO {
+                                        checkMyTodoForHandleKey(it)
                                     }
                                 }
                             }
@@ -1851,18 +1885,22 @@ object BusinessManager {
             }
         } ?: run {
             ThreadUtils.runOnMain {
-                val tipDialog = TipDialog(SIKCore.getApplication())
-                tipDialog.setTip(SIKCore.getApplication().getString(R.string.key_take_error_tip))
-                tipDialog.setConfirmListener {
-                    tipDialog.dismiss()
-                    sendEventMsg(
-                        MsgEvent(
-                            MSG_EVENT_DEVICE_EXCEPTION,
-                            DeviceExceptionMsg(DEVICE_TYPE_KEY, deviceTakeUpdateBO.nfc)
-                        )
+                ActivityTracker.getCurrentActivity()?.let {
+                    val tipDialog = TipDialog(it)
+                    tipDialog.setTip(
+                        SIKCore.getApplication().getString(R.string.key_take_error_tip)
                     )
+                    tipDialog.setConfirmListener {
+                        tipDialog.dismiss()
+                        sendEventMsg(
+                            MsgEvent(
+                                MSG_EVENT_DEVICE_EXCEPTION,
+                                DeviceExceptionMsg(DEVICE_TYPE_KEY, deviceTakeUpdateBO.nfc)
+                            )
+                        )
+                    }
+                    tipDialog.show()
                 }
-                tipDialog.show()
             }
         }
     }
@@ -1933,8 +1971,8 @@ object BusinessManager {
                             currentModeMsg.bleBean.bleDevice.mac, true, 4
                         )
                         sendLoadingEventMsg(null, false)
+                        BleReturnDispatcher.scheduleDisconnect(currentModeMsg.bleBean.bleDevice.mac)
                         //连上之后没有工作票要下发就断开 看是否还有设备等待连接,没有就不断开,有就让路,一般是初始化的时候
-                        launchDisconnectJob(currentModeMsg.bleBean.bleDevice.mac)
                         ThreadUtils.runOnIO {
                             checkMyTodoForHandleKey(currentModeMsg.bleBean.bleDevice.mac)
                         }
@@ -2089,7 +2127,7 @@ object BusinessManager {
                     }
                 }
             }
-        launchDisconnectAllJob()
+        BleSendDispatcher.disconnectAll(60_0000L)
         sendLoadingEventMsg(null, false)
         context.startActivity(Intent(context, LoginActivity::class.java).apply {
             flags = Intent.FLAG_ACTIVITY_NEW_TASK
@@ -2110,7 +2148,7 @@ object BusinessManager {
             if (mac == null) {
                 NetApi.getKeyInfo(it.nfc) { keyInfo ->
                     keyInfo?.macAddress?.let { itMac ->
-                        registerConnectListener(itMac) { isDone, bleBean ->
+                        registerConnectListener(itMac, isSend = true) { isDone, bleBean ->
                             if (isDone && bleBean != null) {
                                 switchReadyMode(bleBean.bleDevice)
                             }
@@ -2118,7 +2156,7 @@ object BusinessManager {
                     }
                 }
             } else {
-                registerConnectListener(mac) { isDone, bleBean ->
+                registerConnectListener(mac, isSend = true) { isDone, bleBean ->
                     if (isDone && bleBean != null) {
                         switchReadyMode(bleBean.bleDevice)
                     }

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

@@ -1,6 +1,6 @@
 package com.grkj.iscs_mars.ble
 
-import com.clj.fastble.data.BleDevice
+import com.huyuhui.fastble.data.BleDevice
 import java.io.File
 
 data class BleBean(

+ 38 - 6
app/src/main/java/com/grkj/iscs_mars/ble/BleCmdManager.kt

@@ -1,7 +1,6 @@
 package com.grkj.iscs_mars.ble
 
-import com.clj.fastble.data.BleDevice
-import com.clj.fastble.exception.BleException
+import android.bluetooth.BluetoothGattCharacteristic
 import com.grkj.iscs_mars.BusinessManager
 import com.grkj.iscs_mars.ble.BleConst.REQ_CURRENT_STATUS
 import com.grkj.iscs_mars.ble.BleConst.REQ_GET_TOKEN
@@ -22,6 +21,8 @@ import com.grkj.iscs_mars.model.eventmsg.MsgEvent
 import com.grkj.iscs_mars.model.eventmsg.MsgEventConstants.MSG_EVENT_GET_TICKET_STATUS
 import com.grkj.iscs_mars.util.Executor
 import com.grkj.iscs_mars.util.log.LogUtil
+import com.huyuhui.fastble.data.BleDevice
+import com.huyuhui.fastble.exception.BleException
 import java.io.File
 
 /**
@@ -256,13 +257,28 @@ object BleCmdManager {
                     bleBean.bleDevice,
                     object : CustomBleWriteCallback() {
                         override fun onWriteSuccess(
+                            bleDevice: BleDevice,
+                            characteristic: BluetoothGattCharacteristic,
                             current: Int,
                             total: Int,
-                            justWrite: ByteArray?
+                            justWrite: ByteArray,
+                            data: ByteArray
                         ) {
+
                         }
 
-                        override fun onWriteFailure(exception: BleException?) {}
+                        override fun onWriteFailure(
+                            bleDevice: BleDevice,
+                            characteristic: BluetoothGattCharacteristic?,
+                            exception: BleException,
+                            current: Int,
+                            total: Int,
+                            justWrite: ByteArray?,
+                            data: ByteArray?,
+                            isTotalFail: Boolean
+                        ) {
+
+                        }
                     })
             } else {
                 callBack?.invoke(false, res)
@@ -356,11 +372,27 @@ object BleCmdManager {
                 byteArrayOf(0x00.toByte()),
                 bleDevice,
                 object : CustomBleWriteCallback() {
-                    override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
+                    override fun onWriteSuccess(
+                        bleDevice: BleDevice,
+                        characteristic: BluetoothGattCharacteristic,
+                        current: Int,
+                        total: Int,
+                        justWrite: ByteArray,
+                        data: ByteArray
+                    ) {
                         LogUtil.i("getTicketStatusPart success")
                     }
 
-                    override fun onWriteFailure(exception: BleException?) {
+                    override fun onWriteFailure(
+                        bleDevice: BleDevice,
+                        characteristic: BluetoothGattCharacteristic?,
+                        exception: BleException,
+                        current: Int,
+                        total: Int,
+                        justWrite: ByteArray?,
+                        data: ByteArray?,
+                        isTotalFail: Boolean
+                    ) {
                         LogUtil.e("getTicketStatusPart fail")
                         BusinessManager.getBleDeviceByMac(bleDevice.mac)?.let {
                             it.ticketStatus = byteArrayOf()

+ 177 - 106
app/src/main/java/com/grkj/iscs_mars/ble/BleConnectionManager.kt

@@ -1,10 +1,9 @@
 package com.grkj.iscs_mars.ble
 
+import android.annotation.SuppressLint
 import android.bluetooth.BluetoothGatt
+import android.bluetooth.BluetoothGattCharacteristic
 import androidx.appcompat.app.AppCompatActivity
-import com.clj.fastble.BleManager
-import com.clj.fastble.data.BleDevice
-import com.clj.fastble.exception.BleException
 import com.grkj.iscs_mars.BusinessManager
 import com.grkj.iscs_mars.BusinessManager.deviceList
 import com.grkj.iscs_mars.BusinessManager.getBleDeviceByMac
@@ -16,6 +15,7 @@ import com.grkj.iscs_mars.R
 import com.grkj.iscs_mars.extentions.toHexStrings
 import com.grkj.iscs_mars.modbus.ModBusController
 import com.grkj.iscs_mars.modbus.ModBusController.controlKeyCharge
+import com.grkj.iscs_mars.model.Constants
 import com.grkj.iscs_mars.model.Constants.PERMISSION_REQUEST_CODE
 import com.grkj.iscs_mars.model.eventmsg.LoadingMsg
 import com.grkj.iscs_mars.model.eventmsg.MsgEvent
@@ -26,6 +26,9 @@ import com.grkj.iscs_mars.util.CommonUtils
 import com.grkj.iscs_mars.util.Executor
 import com.grkj.iscs_mars.util.log.LogUtil
 import com.grkj.iscs_mars.view.base.BaseActivity
+import com.huyuhui.fastble.BleManager
+import com.huyuhui.fastble.data.BleDevice
+import com.huyuhui.fastble.exception.BleException
 import com.sik.sikandroid.activity.ActivityTracker
 import com.sik.sikcore.thread.ThreadUtils
 import kotlinx.coroutines.Dispatchers
@@ -78,12 +81,23 @@ object BleConnectionManager {
     fun registerConnectListener(
         mac: String,
         connectNow: Boolean = false,
+        isSend: Boolean = true,
         callBack: ((Boolean, BleBean?) -> Unit)? = null
     ) {
         LogUtil.i("蓝牙连接-开始连接 : $mac")
         // 已连接且已获取 token
+        LogUtil.i("蓝牙连接-记录的设备:${deviceList}")
+        LogUtil.i(
+            "蓝牙连接-是否连接:${
+                if (isSend) BleSendDispatcher.isConnected(mac) else BleReturnDispatcher.isConnected(
+                    mac
+                )
+            },记录的设备是否存在:${deviceList.any { it.bleDevice.mac == mac }}"
+        )
         deviceList.find {
-            it.bleDevice.mac == mac && BleManager.getInstance().isConnected(mac) && it.token != null
+            it.bleDevice.mac == mac && (if (isSend) BleSendDispatcher.isConnected(mac) else BleReturnDispatcher.isConnected(
+                mac
+            )) && it.token != null
         }?.let { bean ->
             LogUtil.i("蓝牙连接-设备已连接")
             callBack?.invoke(true, bean)
@@ -91,7 +105,9 @@ object BleConnectionManager {
         }
         if (connectNow) {
             LogUtil.w("蓝牙连接-立即连接 mac: $mac")
+            if (isSend) BleSendDispatcher.disconnectAll() else BleReturnDispatcher.disconnectAll()
             unregisterConnectListener(mac)
+            currentConnectingMac.removeIf { it == mac }
         }
         // 重复注册检查
         if (currentConnectingMac.contains(mac)) {
@@ -102,14 +118,22 @@ object BleConnectionManager {
         // 加入队列并启动连接
         fun checkAndConnect(isDisconnectAll: Boolean = false) {
             LogUtil.w("蓝牙连接-开始检查连接 mac: $mac")
-            if (BleManager.getInstance().allConnectedDevice.size < maxConnectCount) {
+            val canConnect = if (isSend) {
+                BleSendDispatcher.canConnect()
+            } else {
+                BleReturnDispatcher.canConnect()
+            }
+            if (canConnect) {
                 connectListeners.add(ConnectListener(mac, callBack))
-                connectKey()
+                connectKey(isSend)
             } else {
                 if (connectNow && !isDisconnectAll) {
                     LogUtil.i("蓝牙连接-超过最大连接数,但是需要立即连接,断开所有连接进行连接")
-                    BleManager.getInstance().disconnectAllDevice()
-                    deviceList.clear()
+                    if (isSend) {
+                        BleSendDispatcher.disconnectAll()
+                    } else {
+                        BleReturnDispatcher.disconnectAll()
+                    }
                     checkAndConnect(true)
                 } else {
                     ThreadUtils.runOnIODelayed(500) {
@@ -149,11 +173,16 @@ object BleConnectionManager {
     /**
      * 连接钥匙,单个mac走完prepare再进行下一个
      */
-    private fun connectKey() {
+    private fun connectKey(isSend: Boolean) {
         if (connectListeners.isEmpty()) return
-        if (isPreparing || BleManager.getInstance().allConnectedDevice.size > maxStandbyCount) {
-            LogUtil.i("暂时不能连接:${isPreparing},${BleManager.getInstance().allConnectedDevice.size > maxStandbyCount}")
-            Executor.delayOnMain(1000) { connectKey() }
+        val canConnect = if (isSend) {
+            BleSendDispatcher.canConnect()
+        } else {
+            BleReturnDispatcher.canConnect()
+        }
+        if (isPreparing || !canConnect) {
+            LogUtil.i("暂时不能连接:${isPreparing},${canConnect}")
+            Executor.delayOnMain(1000) { connectKey(isSend) }
             return
         }
         val listener = connectListeners.first()
@@ -189,7 +218,7 @@ object BleConnectionManager {
                         listener.mac
                     )
                 }
-                if (connectListeners.isNotEmpty()) connectKey()
+                if (connectListeners.isNotEmpty()) connectKey(isSend)
             }
         }
     }
@@ -212,6 +241,7 @@ object BleConnectionManager {
     }
 
     @AfterPermissionGranted(PERMISSION_REQUEST_CODE)
+    @SuppressLint("MissingPermission")
     private fun doScanBle(
         mac: String,
         isNeedLoading: Boolean = false,
@@ -228,7 +258,6 @@ object BleConnectionManager {
             override fun onPrompt(promptStr: String?) {
                 // 蓝牙未启动重试
                 LogUtil.i("蓝牙连接-参数:${promptStr}")
-                BleManager.getInstance().enableBluetooth()
                 doScanBle(mac, isNeedLoading, retryTimes, prepareDoneCallBack)
             }
 
@@ -242,26 +271,30 @@ object BleConnectionManager {
                     )
                     prepareDoneCallBack?.invoke(false, null)
                 } else if (!success && retryTimes > 0) {
-                    BleManager.getInstance().cancelScan()
+                    BleManager.cancelScan()
                     ThreadUtils.runOnMainDelayed(3000) {
                         doScanBle(mac, isNeedLoading, retryTimes - 1, prepareDoneCallBack)
                     }
                 }
             }
 
-            override fun onScanning(bleDevice: BleDevice?) {
-                val bleMac = bleDevice?.mac ?: return
+            override fun onLeScan(
+                oldDevice: BleDevice,
+                newDevice: BleDevice,
+                scannedBefore: Boolean
+            ) {
+                val bleMac = newDevice.mac ?: return
                 LogUtil.i("蓝牙连接-onScanning:$bleMac")
                 if (mac.equals(bleMac, ignoreCase = true)) {
                     // 找到目标设备,马上停止扫描
                     LogUtil.i("蓝牙连接-找到目标设备 $bleMac,停止扫描并尝试连接")
-                    BleManager.getInstance().cancelScan()
+                    BleManager.cancelScan()
                     // 立刻调用 doConnect,下一步进入连接流程
-                    doConnect(bleDevice, isNeedLoading, prepareDoneCallBack)
+                    doConnect(newDevice, isNeedLoading, prepareDoneCallBack)
                 }
             }
 
-            override fun onScanFinished(scanResultList: MutableList<BleDevice>?) {
+            override fun onScanFinished(scanResultList: List<BleDevice>) {
                 LogUtil.i("蓝牙连接-onScanFinished: $mac - ${scanResultList?.none { it.mac == mac }}")
                 if (isNeedLoading) sendEventMsg(
                     MsgEvent(
@@ -274,12 +307,17 @@ object BleConnectionManager {
                     prepareDoneCallBack?.invoke(false, null)
                 }
             }
+
+            override fun onFilter(bleDevice: BleDevice): Boolean {
+                return bleDevice.name == Constants.BLE_LOCAL_NAME
+            }
         })
     }
 
     /**
      * 连接蓝牙设备
      */
+    @SuppressLint("MissingPermission")
     private fun doConnect(
         bleDevice: BleDevice,
         isNeedLoading: Boolean = false,
@@ -293,8 +331,6 @@ object BleConnectionManager {
             )
         )
         ThreadUtils.runOnIO {
-            BleManager.getInstance().disconnect(bleDevice)
-            deviceList.removeIf { device -> device.bleDevice.mac == bleDevice.mac }
             delay(300)
             BleUtil.instance?.connectBySelect(
                 bleDevice, object : CustomBleGattCallback() {
@@ -307,11 +343,11 @@ object BleConnectionManager {
                         )
                     }
 
-                    override fun onStartConnect() {
+                    override fun onStartConnect(bleDevice: BleDevice) {
                         LogUtil.i("蓝牙连接-开始连接")
                     }
 
-                    override fun onConnectFail(bleDevice: BleDevice?, exception: BleException?) {
+                    override fun onConnectFail(bleDevice: BleDevice?, exception: BleException) {
                         if (isNeedLoading) sendEventMsg(
                             MsgEvent(
                                 MSG_EVENT_LOADING,
@@ -327,7 +363,9 @@ object BleConnectionManager {
                     }
 
                     override fun onConnectSuccess(
-                        bleDevice: BleDevice?, gatt: BluetoothGatt?, status: Int
+                        bleDevice: BleDevice,
+                        gatt: BluetoothGatt?,
+                        status: Int
                     ) {
                         if (isNeedLoading) sendEventMsg(
                             MsgEvent(
@@ -353,7 +391,7 @@ object BleConnectionManager {
 
                     override fun onDisConnected(
                         isActiveDisConnected: Boolean,
-                        device: BleDevice?,
+                        device: BleDevice,
                         gatt: BluetoothGatt?,
                         status: Int
                     ) {
@@ -363,12 +401,10 @@ object BleConnectionManager {
                             )
                         )
                         LogUtil.i("蓝牙连接-onDisConnected : ${device?.mac} - $isActiveDisConnected")
-                        getBleDeviceByMac(device?.mac)?.let {
-                            deviceList.remove(it)
-                            it.token = null
-                        }
-                        bleDevice.mac?.let { itMac ->
-                            unregisterConnectListener(itMac)
+                        bleDevice.mac.let { itMac ->
+                            unregisterConnectListener(
+                                itMac
+                            )
                         }
                         if (!isActiveDisConnected) {
                             // 测试模式下不重连
@@ -390,6 +426,15 @@ object BleConnectionManager {
                             ModBusController.updateKeyReadyStatus(bleDevice.mac, false, 3)
                         }
                     }
+
+                    override fun onConnectCancel(bleDevice: BleDevice, skip: Boolean) {
+                        if (isNeedLoading) sendEventMsg(
+                            MsgEvent(
+                                MSG_EVENT_LOADING, LoadingMsg(false, null, false)
+                            )
+                        )
+                        LogUtil.i("蓝牙连接-onConnectCancel : ${bleDevice?.mac}")
+                    }
                 })
         }
     }
@@ -423,13 +468,20 @@ object BleConnectionManager {
                         LogUtil.i("蓝牙连接-indicate onDisConnectPrompt : $promptStr")
                     }
 
-                    override fun onIndicateSuccess() {
+                    override fun onIndicateSuccess(
+                        bleDevice: BleDevice,
+                        characteristic: BluetoothGattCharacteristic
+                    ) {
                         LogUtil.i("蓝牙连接-onIndicateSuccess")
                         isIndicateSuccess = true
                         getToken(bleBean, isNeedLoading, prepareDoneCallBack)
                     }
 
-                    override fun onIndicateFailure(exception: BleException?) {
+                    override fun onIndicateFailure(
+                        bleDevice: BleDevice,
+                        characteristic: BluetoothGattCharacteristic?,
+                        exception: BleException
+                    ) {
                         if (isNeedLoading) sendEventMsg(
                             MsgEvent(
                                 MSG_EVENT_LOADING, LoadingMsg(false, null, false)
@@ -444,7 +496,11 @@ object BleConnectionManager {
                         }
                     }
 
-                    override fun onCharacteristicChanged(data: ByteArray?) {
+                    override fun onCharacteristicChanged(
+                        bleDevice: BleDevice,
+                        characteristic: BluetoothGattCharacteristic,
+                        data: ByteArray?
+                    ) {
                         LogUtil.i("蓝牙连接-onCharacteristicChanged : ${data?.toHexStrings()}")
                         data?.let { itData ->
                             BusinessManager.handleRsp(
@@ -455,6 +511,13 @@ object BleConnectionManager {
                             )
                         }
                     }
+
+                    override fun onIndicateCancel(
+                        bleDevice: BleDevice,
+                        characteristic: BluetoothGattCharacteristic
+                    ) {
+                        LogUtil.i("蓝牙连接-onIndicateCancel")
+                    }
                 })
         }
     }
@@ -478,7 +541,14 @@ object BleConnectionManager {
         )
         bleBean?.let {
             BleCmdManager.getToken(it.bleDevice.mac, object : CustomBleWriteCallback() {
-                override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
+                override fun onWriteSuccess(
+                    bleDevice: BleDevice,
+                    characteristic: BluetoothGattCharacteristic,
+                    current: Int,
+                    total: Int,
+                    justWrite: ByteArray,
+                    data: ByteArray
+                ) {
                     if (isNeedLoading) sendEventMsg(
                         MsgEvent(
                             MSG_EVENT_LOADING, LoadingMsg(false, "token获取成功", null)
@@ -487,7 +557,16 @@ object BleConnectionManager {
                     LogUtil.i("蓝牙连接-getToken success : ${bleBean.bleDevice.mac}")
                 }
 
-                override fun onWriteFailure(exception: BleException?) {
+                override fun onWriteFailure(
+                    bleDevice: BleDevice,
+                    characteristic: BluetoothGattCharacteristic?,
+                    exception: BleException,
+                    current: Int,
+                    total: Int,
+                    justWrite: ByteArray?,
+                    data: ByteArray?,
+                    isTotalFail: Boolean
+                ) {
                     if (isNeedLoading) sendEventMsg(
                         MsgEvent(
                             MSG_EVENT_LOADING, LoadingMsg(false, "token获取失败", false)
@@ -505,34 +584,12 @@ object BleConnectionManager {
      *   1. 先尝试不充电连接,若成功就返回 true;
      *   2. 否则开启“充电”,等 500ms,再尝试一次连接,连接成功后断电并返回 true;否则返回 false。
      */
-    suspend fun tryConnectWithOptionalCharge(mac: String, withOpenCharge: Boolean = true): Boolean =
+    suspend fun tryConnectWithOptionalCharge(
+        mac: String,
+        withOpenCharge: Boolean = true,
+        isSend: Boolean = true
+    ): Boolean =
         withContext(Dispatchers.IO) {
-            // -------- 第一次尝试 --------
-//            LogUtil.i("蓝牙连接-第一次尝试")
-//            val firstTry = suspendCancellableCoroutine<Boolean> { cont ->
-//                // 1. 定义一个 flag,确保只 resume 一次
-//                var isCalled = false
-//                BusinessManager.registerConnectListener(mac, true) { isDone, _ ->
-//                    if (isCalled) {
-//                        return@registerConnectListener
-//                    }
-//                    isCalled = true
-//                    if (isDone && cont.isActive) {
-//                        // 连接成功后,把电关掉(以防万一)
-//                        controlKeyCharge(false, mac) { }
-//                        cont.resume(true)
-//                    } else {
-//                        cont.resume(false)
-//                    }
-//                }
-//            }
-//            LogUtil.i("蓝牙连接-第一次连接:${firstTry},是否继续尝试上电连接${withOpenCharge}")
-//            if (firstTry) {
-//                return@withContext true
-//            }
-//            if (!withOpenCharge) {
-//                return@withContext false
-//            }
             // -------- 第二次尝试:先开电,再连 --------
             // 开电,并等待回调
             suspendCoroutine<Unit> { unitCont ->
@@ -552,13 +609,13 @@ object BleConnectionManager {
             // 再次注册连接监听
             val secondTry = suspendCancellableCoroutine<Boolean> { cont ->
                 var isCalled = false
-                BusinessManager.registerConnectListener(mac, true) { isDone, _ ->
+                BusinessManager.registerConnectListener(mac, true, isSend) { isDone, _ ->
                     if (isCalled) {
                         return@registerConnectListener
                     }
                     isCalled = true
                     // 无论成功或失败,都先把电关掉
-//                    controlKeyCharge(false, mac) { }
+                    controlKeyCharge(false, mac) { }
                     if (cont.isActive) {
                         cont.resume(isDone)
                     }
@@ -576,7 +633,6 @@ object BleConnectionManager {
                 override fun onPrompt(promptStr: String?) {
                     // 蓝牙未启动重试
                     LogUtil.i("设备录入-参数:${promptStr}")
-                    BleManager.getInstance().enableBluetooth()
                     ThreadUtils.runOnMainDelayed(300) {
                         scanOnlineKeyLockMacAndSwitchModeToClose()
                     }
@@ -591,12 +647,16 @@ object BleConnectionManager {
                     }
                 }
 
-                override fun onScanning(bleDevice: BleDevice?) {
-                    val mac = bleDevice?.mac ?: return
+                override fun onLeScan(
+                    oldDevice: BleDevice,
+                    newDevice: BleDevice,
+                    scannedBefore: Boolean
+                ) {
+                    val mac = newDevice?.mac ?: return
                     LogUtil.i("设备录入-onScanning:$mac")
                 }
 
-                override fun onScanFinished(scanResultList: MutableList<BleDevice>?) {
+                override fun onScanFinished(scanResultList: List<BleDevice>) {
                     val devicesSnapshot = scanResultList?.toList().orEmpty()
                     ThreadUtils.runOnIO {
                         val handlerDeviceSize = AtomicInteger(0)
@@ -615,6 +675,10 @@ object BleConnectionManager {
                         }
                     }
                 }
+
+                override fun onFilter(bleDevice: BleDevice): Boolean {
+                    return bleDevice.name == Constants.BLE_LOCAL_NAME
+                }
             })
         }
     }
@@ -629,9 +693,12 @@ object BleConnectionManager {
                 bleDevice = bleDevice,
                 callback = object : CustomBleWriteCallback() {
                     override fun onWriteSuccess(
+                        bleDevice: BleDevice,
+                        characteristic: BluetoothGattCharacteristic,
                         current: Int,
                         total: Int,
-                        justWrite: ByteArray?
+                        justWrite: ByteArray,
+                        data: ByteArray
                     ) {
                         ThreadUtils.runOnIO {
                             delay(3000)
@@ -639,7 +706,16 @@ object BleConnectionManager {
                         }
                     }
 
-                    override fun onWriteFailure(exception: BleException?) {
+                    override fun onWriteFailure(
+                        bleDevice: BleDevice,
+                        characteristic: BluetoothGattCharacteristic?,
+                        exception: BleException,
+                        current: Int,
+                        total: Int,
+                        justWrite: ByteArray?,
+                        data: ByteArray?,
+                        isTotalFail: Boolean
+                    ) {
                         ThreadUtils.runOnMainDelayed(300) {
                             cont.resume(sendEmptyTicketJson(bleDevice))
                         }
@@ -658,12 +734,14 @@ object BleConnectionManager {
                 bleDevice,
                 object : CustomBleWriteCallback() {
                     override fun onWriteSuccess(
+                        bleDevice: BleDevice,
+                        characteristic: BluetoothGattCharacteristic,
                         current: Int,
                         total: Int,
-                        justWrite: ByteArray?
+                        justWrite: ByteArray,
+                        data: ByteArray
                     ) {
-                        BleManager.getInstance().disconnect(bleDevice)
-                        deviceList.removeIf { device -> device.bleDevice.mac == bleDevice.mac }
+                        BleSendDispatcher.scheduleDisconnect(bleDevice.mac)
                         ThreadUtils.runOnIO {
                             delay(800)
                             cont.resume(true)
@@ -671,7 +749,16 @@ object BleConnectionManager {
                         LogUtil.i("设备录入-切换模式发送成功 : ${bleDevice.mac}")
                     }
 
-                    override fun onWriteFailure(exception: BleException?) {
+                    override fun onWriteFailure(
+                        bleDevice: BleDevice,
+                        characteristic: BluetoothGattCharacteristic?,
+                        exception: BleException,
+                        current: Int,
+                        total: Int,
+                        justWrite: ByteArray?,
+                        data: ByteArray?,
+                        isTotalFail: Boolean
+                    ) {
                         LogUtil.e("设备录入-切换模式发送失败 : ${bleDevice.mac}")
                         ThreadUtils.runOnMainDelayed(300) {
                             cont.resume(sendEmptyTicketJson(bleDevice))
@@ -681,39 +768,15 @@ object BleConnectionManager {
         }
     }
 
-    /**
-     * 切换待机模式
-     */
-    fun switchReadyMode(bleDevice: BleDevice) {
-        BleCmdManager.switchMode(
-            BleConst.STATUS_READY,
-            bleDevice,
-            object : CustomBleWriteCallback() {
-                override fun onWriteSuccess(
-                    current: Int,
-                    total: Int,
-                    justWrite: ByteArray?
-                ) {
-                    BleManager.getInstance().disconnect(bleDevice)
-                    deviceList.removeIf { device -> device.bleDevice.mac == bleDevice.mac }
-                    LogUtil.i("设备录入-切换模式发送成功 : ${bleDevice.mac}")
-                }
-
-                override fun onWriteFailure(exception: BleException?) {
-                    LogUtil.e("设备录入-切换模式发送失败 : ${bleDevice.mac}")
-                }
-            })
-    }
-
     /**
      * 扫描在线的蓝牙
      */
+    @SuppressLint("MissingPermission")
     fun scanOnlineKeyLockMac(existsMac: List<String>, callback: (BleDevice?) -> Unit) {
         BleUtil.instance?.scan(object : CustomBleScanCallback() {
             override fun onPrompt(promptStr: String?) {
                 // 蓝牙未启动重试
                 LogUtil.d("设备录入-参数:${promptStr}")
-                BleManager.getInstance().enableBluetooth()
                 ThreadUtils.runOnMainDelayed(300) {
                     scanOnlineKeyLockMac(existsMac, callback)
                 }
@@ -728,18 +791,26 @@ object BleConnectionManager {
                 }
             }
 
-            override fun onScanning(bleDevice: BleDevice?) {
-                val mac = bleDevice?.mac ?: return
+            override fun onLeScan(
+                oldDevice: BleDevice,
+                newDevice: BleDevice,
+                scannedBefore: Boolean
+            ) {
+                val mac = newDevice?.mac ?: return
                 LogUtil.d("设备录入-onScanning:$mac")
                 if (mac !in existsMac) {
-                    callback(bleDevice)
-                    BleManager.getInstance().cancelScan()
+                    callback(newDevice)
+                    BleManager.cancelScan()
                 }
             }
 
-            override fun onScanFinished(scanResultList: MutableList<BleDevice>?) {
+            override fun onScanFinished(scanResultList: List<BleDevice>) {
                 LogUtil.d("设备录入-扫描完成:$scanResultList")
             }
+
+            override fun onFilter(bleDevice: BleDevice): Boolean {
+                return bleDevice.name == Constants.BLE_LOCAL_NAME
+            }
         })
     }
 

+ 125 - 0
app/src/main/java/com/grkj/iscs_mars/ble/BleQueueDispatcher.kt

@@ -0,0 +1,125 @@
+package com.grkj.iscs_mars.ble
+
+import android.annotation.SuppressLint
+import com.grkj.iscs_mars.BusinessManager
+import com.huyuhui.fastble.BleManager
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+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 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) {
+
+        if (activeMacs.containsKey(mac) || taskQueue.any { it.first == mac } || connectedMacs.contains(
+                mac
+            )) {
+            if (connectedMacs.contains(mac)) {
+                onResult(true)
+            }
+            // 如果已存在断连计划,取消它
+            pendingDisconnectJobs.remove(mac)?.cancel()
+            return
+        }
+        taskQueue.add(mac to onResult)
+        tryStartNext()
+    }
+
+    @Synchronized
+    private fun tryStartNext() {
+        if ((activeMacs.size + connectedMacs.size) >= maxConnections || taskQueue.isEmpty()) return
+        val (mac, callback) = taskQueue.removeFirst()
+        activeMacs[mac] = callback
+        doConnect(mac) { success ->
+            synchronized(this) {
+                activeMacs.remove(mac)
+                if (success) {
+                    connectedMacs.add(mac)
+                }
+                callback(success)
+                tryStartNext()
+            }
+        }
+    }
+
+    protected abstract fun doConnect(mac: String, callback: (Boolean) -> Unit)
+
+    @Synchronized
+    fun clear(mac: String) {
+        taskQueue.removeIf { it.first == mac }
+        activeMacs.remove(mac)
+        connectedMacs.remove(mac)
+        pendingDisconnectJobs.remove(mac)?.cancel()
+        if ((activeMacs.size + connectedMacs.size) < maxConnections && taskQueue.isNotEmpty()) {
+            tryStartNext()
+        }
+    }
+
+    @SuppressLint("MissingPermission")
+    @Synchronized
+    fun scheduleDisconnect(mac: String, delayMillis: Long = 0) {
+        if (!connectedMacs.contains(mac)) return
+        pendingDisconnectJobs[mac]?.cancel()
+        val job = dispatcherScope.launch {
+            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 }
+                    }
+                    logger.info("当前线程:${Thread.currentThread().name}")
+                    clear(mac)
+                    tryStartNext()
+                }
+                pendingDisconnectJobs.remove(mac)
+            }
+        }
+        pendingDisconnectJobs[mac] = job
+    }
+
+    @SuppressLint("MissingPermission")
+    private fun disconnectDeviceByMac(mac: String) {
+        val device = BleManager.getAllConnectedDevice().find { it.mac == mac }
+        if (device != null) {
+            BleManager.disconnect(device)
+        }
+    }
+
+    @Synchronized
+    fun disconnectAll(delayMillis: Long = 0) {
+        val allMacs = connectedMacs.toList()
+        for (mac in allMacs) {
+            scheduleDisconnect(mac, delayMillis)
+        }
+    }
+
+
+    fun isConnecting(mac: String): Boolean = activeMacs.containsKey(mac)
+    fun isQueued(mac: String): Boolean = taskQueue.any { it.first == mac }
+    fun isConnected(mac: String): Boolean = connectedMacs.contains(mac)
+
+    fun getConnectedMacs(): List<String> = connectedMacs.toList()
+
+    fun getActiveMacs(): List<String> = activeMacs.keys.toList()
+
+    fun canConnect(): Boolean = (activeMacs.size + connectedMacs.size) <= maxConnections
+
+    fun shouldDisconnect(mac: String): Boolean =
+        isConnecting(mac) || isQueued(mac) || isConnected(mac)
+}

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

@@ -0,0 +1,14 @@
+package com.grkj.iscs_mars.ble
+
+import com.sik.sikcore.thread.ThreadUtils
+
+object BleReturnDispatcher : BleQueueDispatcher() {
+    override val maxConnections = 1
+
+    override fun doConnect(mac: String, callback: (Boolean) -> Unit) {
+        ThreadUtils.runOnIO {
+            val isConnected = BleConnectionManager.tryConnectWithOptionalCharge(mac, isSend = false)
+            callback(isConnected)
+        }
+    }
+}

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

@@ -0,0 +1,14 @@
+package com.grkj.iscs_mars.ble
+
+import com.sik.sikcore.thread.ThreadUtils
+
+object BleSendDispatcher : BleQueueDispatcher() {
+    override val maxConnections = 1
+
+    override fun doConnect(mac: String, callback: (Boolean) -> Unit) {
+        ThreadUtils.runOnIO {
+            val isConnected = BleConnectionManager.tryConnectWithOptionalCharge(mac, isSend = true)
+            callback(isConnected)
+        }
+    }
+}

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

@@ -1,21 +1,27 @@
 package com.grkj.iscs_mars.ble
 
+import android.Manifest
+import android.annotation.SuppressLint
 import android.app.Application
 import android.bluetooth.BluetoothGatt
+import android.bluetooth.le.ScanSettings
 import android.os.Build
 import android.util.Log
-import com.clj.fastble.BleManager
-import com.clj.fastble.callback.BleGattCallback
-import com.clj.fastble.callback.BleMtuChangedCallback
-import com.clj.fastble.data.BleDevice
-import com.clj.fastble.exception.BleException
-import com.clj.fastble.scan.BleScanRuleConfig
+import androidx.annotation.RequiresPermission
 import com.grkj.iscs_mars.model.Constants.BLE_LOCAL_NAME
 import com.grkj.iscs_mars.ble.BleConst.INDICATE_UUID
 import com.grkj.iscs_mars.ble.BleConst.MTU
 import com.grkj.iscs_mars.ble.BleConst.SERVICE_UUID
 import com.grkj.iscs_mars.extentions.toHexStrings
+import com.grkj.iscs_mars.model.Constants
 import com.grkj.iscs_mars.util.log.LogUtil
+import com.huyuhui.fastble.BleManager
+import com.huyuhui.fastble.callback.BleGattCallback
+import com.huyuhui.fastble.callback.BleMtuChangedCallback
+import com.huyuhui.fastble.data.BleDevice
+import com.huyuhui.fastble.exception.BleException
+import com.huyuhui.fastble.scan.BleScanRuleConfig
+import com.sik.sikcore.SIKCore
 import com.sik.sikcore.thread.ThreadUtils
 
 /**
@@ -31,37 +37,43 @@ class BleUtil private constructor() {
             }
             private set
 
-        const val OPERATE_TIMEOUT = 10 * 1000
+        const val OPERATE_TIMEOUT = 10 * 1000L
     }
 
-    fun initBle(application: Application?) {
+    fun initBle(application: Application) {
         try {
-            BleManager.getInstance().init(application)
-            BleManager.getInstance().enableLog(false)
-                .setConnectOverTime(5 * 1000L)
-                .setReConnectCount(0, 0)
-                .setSplitWriteNum(500)
-                .operateTimeout =
-                OPERATE_TIMEOUT // 设置操作readRssi、setMtu、write、read、notify、indicate的超时时间(毫秒)
+            BleManager.init(application)
+            BleManager.enableLog(false)
+                .apply {
+                    maxConnectCount = 0
+                    splitWriteNum = 500
+                    operateTimeout = OPERATE_TIMEOUT
+                }
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
                 //Android 12及以上不允许添加过滤器
                 val bleScanRuleConfig = BleScanRuleConfig.Builder()
-//                .setServiceUuids(arrayOf(UUID.fromString(BLUETOOTH_SERVICEUUID)))
-                    .setAutoConnect(false)
                     .setScanTimeOut(3_000L)
-                    .setDeviceName(true, BLE_LOCAL_NAME)
+                    .setDeviceName(Constants.BLE_LOCAL_NAME)
+                    .apply {
+                        setScanSettings(ScanSettings.Builder().apply {
+                            this.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
+                            this.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
+                            this.setNumOfMatches(ScanSettings.MATCH_NUM_ONE_ADVERTISEMENT)
+                        }.build())
+                    }
                     .build()
-                BleManager.getInstance().initScanRule(bleScanRuleConfig)
+                BleManager.bleScanRuleConfig = bleScanRuleConfig
             }
         } catch (e: Exception) {
             Log.d("initBlueTooth", "蓝牙初始化:${e.message}")
         }
     }
 
+    @SuppressLint("MissingPermission")
     fun scan(bleScanCallback: CustomBleScanCallback) {
-        if (BleManager.getInstance().isSupportBle) {
-            if (BleManager.getInstance().isBlueEnable) {
-                BleManager.getInstance().scan(bleScanCallback)
+        if (BleManager.isSupportBle(SIKCore.getApplication())) {
+            if (BleManager.isBleEnable(SIKCore.getApplication())) {
+                BleManager.scan(bleScanCallback)
             } else {
                 bleScanCallback.onPrompt("请打开您的蓝牙后重试")
             }
@@ -70,22 +82,11 @@ class BleUtil private constructor() {
         }
     }
 
-    fun connectBySelect(bleDevice: BleDevice?, bleGattCallback: CustomBleGattCallback) {
-        if (BleManager.getInstance().isSupportBle) {
-            if (BleManager.getInstance().isBlueEnable) {
-                BleManager.getInstance().connect(bleDevice, bleGattCallback)
-            } else {
-                bleGattCallback.onPrompt("请打开您的蓝牙后重试")
-            }
-        } else {
-            bleGattCallback.onPrompt("您的设备不支持蓝牙设备")
-        }
-    }
-
-    fun connectByMac(mac: String?, bleGattCallback: CustomBleGattCallback) {
-        if (BleManager.getInstance().isSupportBle) {
-            if (BleManager.getInstance().isBlueEnable) {
-                BleManager.getInstance().connect(mac, bleGattCallback)
+    @SuppressLint("MissingPermission")
+    fun connectBySelect(bleDevice: BleDevice, bleGattCallback: CustomBleGattCallback) {
+        if (BleManager.isSupportBle(SIKCore.getApplication())) {
+            if (BleManager.isBleEnable(SIKCore.getApplication())) {
+                BleManager.connect(bleDevice, bleGattCallback)
             } else {
                 bleGattCallback.onPrompt("请打开您的蓝牙后重试")
             }
@@ -94,18 +95,20 @@ class BleUtil private constructor() {
         }
     }
 
+    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
     fun setMtu(bleDevice: BleDevice) {
-        BleManager.getInstance().setMtu(bleDevice, MTU, object : BleMtuChangedCallback() {
-            override fun onSetMTUFailure(exception: BleException?) {
-//                indicate()
+        BleManager.setMtu(bleDevice, MTU, object : BleMtuChangedCallback() {
+            override fun onSetMTUFailure(bleDevice: BleDevice, exception: BleException) {
+                LogUtil.i("setMtu failure")
             }
 
-            override fun onMtuChanged(mtu: Int) {
-//                indicate()
+            override fun onMtuChanged(bleDevice: BleDevice, mtu: Int) {
+                LogUtil.i("setMtu success")
             }
         })
     }
 
+    @SuppressLint("MissingPermission")
     fun indicate(
         bleDevice: BleDevice,
         serviceUUID: String = SERVICE_UUID,
@@ -114,55 +117,62 @@ class BleUtil private constructor() {
         indicateCallback: CustomBleIndicateCallback?
     ) {
         // stopIndicate包含removeIndicateCallback
-//        BleManager.getInstance().removeIndicateCallback(bleDevice, indicateUUID)
-        BleManager.getInstance().stopIndicate(bleDevice, serviceUUID, indicateUUID)
+//        BleManager.removeIndicateCallback(bleDevice, indicateUUID)
+        BleManager.stopIndicate(bleDevice, serviceUUID, indicateUUID)
         if (!isStart) {
             return
         }
-        if (!BleManager.getInstance().isSupportBle) {
+        if (!BleManager.isSupportBle(SIKCore.getApplication())) {
             indicateCallback?.onPrompt("该设备不支持蓝牙BLE")
             return
         }
 
-        if (!BleManager.getInstance().isBlueEnable) {
+        if (!BleManager.isBleEnable(SIKCore.getApplication())) {
             indicateCallback?.onPrompt("蓝牙已关闭,请打开蓝牙后重试")
             return
         }
-        if (BleManager.getInstance().isConnected(bleDevice.mac)) {
-            BleManager.getInstance()
-                .indicate(bleDevice, serviceUUID, indicateUUID, indicateCallback)
+        if (BleManager.isConnected(bleDevice.mac)) {
+            BleManager.indicate(bleDevice, serviceUUID, indicateUUID, indicateCallback)
         } else {
-            BleManager.getInstance().connect(bleDevice.mac, object : BleGattCallback() {
-                override fun onStartConnect() {}
-                override fun onConnectFail(bleDevice: BleDevice, exception: BleException) {
-                    BleManager.getInstance().removeConnectGattCallback(bleDevice)
+            BleManager.connect(bleDevice.mac, object : BleGattCallback() {
+                override fun onStartConnect(bleDevice: BleDevice) {
+                    indicateCallback?.onConnectPrompt("正在连接设备 : ${bleDevice.name}")
+                }
+
+                override fun onConnectFail(bleDevice: BleDevice?, exception: BleException) {
+                    BleManager.removeConnectGattCallback(bleDevice)
                     indicateCallback?.onConnectPrompt("连接失败!请检查设备是否打开,并尝试重新连接 : $exception")
                 }
 
                 override fun onConnectSuccess(
                     bleDevice: BleDevice,
-                    gatt: BluetoothGatt,
+                    gatt: BluetoothGatt?,
                     status: Int
                 ) {
-                    BleManager.getInstance().removeConnectGattCallback(bleDevice)
-                    BleManager.getInstance()
-                        .indicate(bleDevice, serviceUUID, indicateUUID, indicateCallback)
+                    BleManager.removeConnectGattCallback(bleDevice)
+                    BleManager.indicate(bleDevice, serviceUUID, indicateUUID, indicateCallback)
                 }
 
                 override fun onDisConnected(
                     isActiveDisConnected: Boolean,
                     device: BleDevice,
-                    gatt: BluetoothGatt,
+                    gatt: BluetoothGatt?,
                     status: Int
                 ) {
-                    BleManager.getInstance().removeConnectGattCallback(device)
+                    BleManager.removeConnectGattCallback(device)
                     indicateCallback?.onDisConnectPrompt("连接断开!请检查硬件状态,并尝试重新连接!")
                 }
+
+                override fun onConnectCancel(bleDevice: BleDevice, skip: Boolean) {
+                    BleManager.removeConnectGattCallback(bleDevice)
+                    indicateCallback?.onConnectPrompt("连接取消!")
+                }
             })
         }
     }
 
 
+    @SuppressLint("MissingPermission")
     fun write(
         bleDevice: BleDevice,
         serviceUUID: String = SERVICE_UUID,
@@ -172,26 +182,32 @@ class BleUtil private constructor() {
     ) {
         LogUtil.i("ble_write : ${cmd?.toHexStrings()}")
         cmd ?: return
-        if (!BleManager.getInstance().isSupportBle) {
+        if (!BleManager.isSupportBle(SIKCore.getApplication())) {
             writeCallback?.onPrompt("该设备不支持蓝牙BLE")
             return
         }
 
-        if (!BleManager.getInstance().isBlueEnable) {
+        if (!BleManager.isBleEnable(SIKCore.getApplication())) {
             writeCallback?.onPrompt("蓝牙已关闭,请打开蓝牙后重试")
             return
         }
-        if (BleManager.getInstance().isConnected(bleDevice.mac)) {
-            BleManager.getInstance().write(bleDevice, serviceUUID, writeUUID, cmd, writeCallback)
+        if (BleManager.isConnected(bleDevice.mac)) {
+            BleManager.write(bleDevice, serviceUUID, writeUUID, cmd, callback = writeCallback)
         } else {
             fun checkAndWrite() {
                 ThreadUtils.runOnIO {
-                    val isConnect = BleConnectionManager.tryConnectWithOptionalCharge(bleDevice.mac)
-                    if (isConnect) {
-                        BleManager.getInstance()
-                            .write(bleDevice, serviceUUID, writeUUID, cmd, writeCallback)
-                    } else {
-                        checkAndWrite()
+                    BleSendDispatcher.submit(bleDevice.mac) { isConnect ->
+                        if (isConnect) {
+                            BleManager.write(
+                                bleDevice,
+                                serviceUUID,
+                                writeUUID,
+                                cmd,
+                                callback = writeCallback
+                            )
+                        } else {
+                            checkAndWrite()
+                        }
                     }
                 }
             }

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

@@ -1,6 +1,6 @@
 package com.grkj.iscs_mars.ble
 
-import com.clj.fastble.callback.BleGattCallback
+import com.huyuhui.fastble.callback.BleGattCallback
 
 abstract class CustomBleGattCallback : BleGattCallback() {
     abstract fun onPrompt(promptStr: String?)

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

@@ -1,6 +1,6 @@
 package com.grkj.iscs_mars.ble
 
-import com.clj.fastble.callback.BleIndicateCallback
+import com.huyuhui.fastble.callback.BleIndicateCallback
 
 abstract class CustomBleIndicateCallback : BleIndicateCallback() {
     abstract fun onPrompt(promptStr: String?)

+ 2 - 2
app/src/main/java/com/grkj/iscs_mars/ble/CustomBleScanCallback.kt

@@ -1,7 +1,7 @@
 package com.grkj.iscs_mars.ble
 
-import com.clj.fastble.callback.BleScanCallback
+import com.huyuhui.fastble.callback.BleScanCallback
 
-abstract class CustomBleScanCallback : BleScanCallback() {
+abstract class CustomBleScanCallback : BleScanCallback {
     abstract fun onPrompt(promptStr: String?)
 }

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

@@ -1,6 +1,6 @@
 package com.grkj.iscs_mars.ble
 
-import com.clj.fastble.callback.BleWriteCallback
+import com.huyuhui.fastble.callback.BleWriteCallback
 
 abstract class CustomBleWriteCallback : BleWriteCallback() {
     open fun onPrompt(promptStr: String?) {}

+ 53 - 15
app/src/main/java/com/grkj/iscs_mars/modbus/ModBusController.kt

@@ -1,11 +1,13 @@
 package com.grkj.iscs_mars.modbus
 
+import android.annotation.SuppressLint
 import android.content.Context
-import com.clj.fastble.BleManager
 import com.grkj.iscs_mars.BusinessManager
 import com.grkj.iscs_mars.BusinessManager.CAN_RETURN
 import com.grkj.iscs_mars.R
 import com.grkj.iscs_mars.ble.BleConnectionManager
+import com.grkj.iscs_mars.ble.BleReturnDispatcher
+import com.grkj.iscs_mars.ble.BleSendDispatcher
 import com.grkj.iscs_mars.extentions.removeLeadingZeros
 import com.grkj.iscs_mars.extentions.toHexStrings
 import com.grkj.iscs_mars.model.DeviceConst
@@ -26,10 +28,14 @@ import com.grkj.iscs_mars.util.Executor
 import com.grkj.iscs_mars.util.NetApi
 import com.grkj.iscs_mars.util.ToastUtils
 import com.grkj.iscs_mars.util.log.LogUtil
+import com.huyuhui.fastble.BleManager
 import com.sik.sikcore.thread.ThreadUtils
 import kotlinx.coroutines.delay
+import kotlinx.coroutines.isActive
 import java.util.concurrent.atomic.AtomicInteger
 import java.util.stream.Collectors
+import kotlin.coroutines.resume
+import kotlin.coroutines.suspendCoroutine
 
 
 /**
@@ -894,8 +900,12 @@ object ModBusController {
         } else {
             return status
         }
-        if (BleManager.getInstance()
-                .isConnected(BusinessManager.getBleDeviceByMac(key.mac)?.bleDevice)
+        if (BleSendDispatcher.isConnected(
+                BusinessManager.getBleDeviceByMac(key.mac)?.bleDevice?.mac ?: ""
+            ) ||
+            BleReturnDispatcher.isConnected(
+                BusinessManager.getBleDeviceByMac(key.mac)?.bleDevice?.mac ?: ""
+            )
         ) {
             status = 4
         } else {
@@ -1029,6 +1039,7 @@ object ModBusController {
      *
      * @return 底座地址,钥匙
      */
+    @SuppressLint("MissingPermission")
     suspend fun getOneKey(
         exceptionSlots: List<CabinetSlotsRecord>,
         exceptionKeysRfid: List<String>,
@@ -1044,7 +1055,9 @@ object ModBusController {
             LogUtil.i("keyStatus:${this}")
         }.filterIsInstance<DockBean.KeyBean>()
             .filterIndexed { idx, _ -> (idx + 1) !in slotCols }.filter { kb ->
-                !kb.rfid.isNullOrEmpty() && kb.rfid !in exceptionKeysRfid && kb.mac !in exceptionKeysMac && !kb.mac.isNullOrEmpty() && kb.isExist
+                !kb.rfid.isNullOrEmpty() && kb.rfid !in exceptionKeysRfid && kb.mac !in exceptionKeysMac && !kb.mac.isNullOrEmpty() && kb.isExist && !BleReturnDispatcher.isConnected(
+                    kb.mac ?: ""
+                ) && !BleReturnDispatcher.isConnecting(kb.mac ?: "")
             }.shuffled()
 
         LogUtil.i("蓝牙连接-获取到钥匙信息:${keyList}")
@@ -1054,7 +1067,9 @@ object ModBusController {
         }
         keyList = keyList.sortedWith(
             compareByDescending<DockBean.KeyBean> {
-                BleManager.getInstance().isConnected(it.mac)
+                BleSendDispatcher.isConnected(it.mac ?: "") || BleSendDispatcher.isConnecting(
+                    it.mac ?: ""
+                )
             }    // 主键:在线优先
                 .thenByDescending { BusinessManager.getBleDeviceByMac(it.mac)?.token != null } // 次键:有 token 优先
                 .thenByDescending { it.power }
@@ -1063,16 +1078,30 @@ object ModBusController {
         for (kb in keyList) {
             val mac = kb.mac ?: continue
 
-            val connected = BleConnectionManager.tryConnectWithOptionalCharge(mac)
-            if (connected) {
-                LogUtil.i("蓝牙连接完成 :${mac}")
-                // 找到第一个能连的:从 keyDockList 里拿同 rfid 的 addr
-                val addr =
-                    keyDockList.firstOrNull { it.getKeyList().any { it.rfid == kb.rfid } }?.addr
-                if (addr != null) {
-                    return addr to kb
+            val result = suspendCoroutine<Pair<Byte, DockBean.KeyBean>?> { cont ->
+                BleSendDispatcher.submit(mac) { connected ->
+                    if (connected) {
+                        LogUtil.i("蓝牙连接完成 :${mac}")
+                        // 找到第一个能连的:从 keyDockList 里拿同 rfid 的 addr
+                        val addr =
+                            keyDockList.firstOrNull {
+                                it.getKeyList().any { it.rfid == kb.rfid }
+                            }?.addr
+                        if (addr != null) {
+                            if (cont.context.isActive) {
+                                cont.resume(addr to kb)
+                            }
+                        } else {
+                            null
+                        }
+                    } else {
+                        null
+                    }
                 }
             }
+            if (result != null) {
+                return result
+            }
         }
 
         // 一个都没成功
@@ -1150,13 +1179,22 @@ object ModBusController {
     /**
      * 获取最多电量的钥匙
      */
-    fun getMaxPowerKey(): DockBean.KeyBean {
+    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>().maxBy { it.power }
+            .flatMap { it.deviceList }.filterIsInstance<DockBean.KeyBean>().filter { it.mac != mac }
+            .maxBy { it.power }
+    }
+
+    /**
+     * 更新钥匙电量
+     */
+    fun updateKeyPower(power: Int, keyMac: String) {
+        val keyBean = getKeyByMac(keyMac)
+        keyBean?.power = power
     }
 }

+ 1 - 1
app/src/main/java/com/grkj/iscs_mars/model/eventmsg/GetTicketStatusMsg.kt

@@ -1,6 +1,6 @@
 package com.grkj.iscs_mars.model.eventmsg
 
-import com.clj.fastble.data.BleDevice
+import com.huyuhui.fastble.data.BleDevice
 
 data class GetTicketStatusMsg(
     val isSuccess: Boolean,

+ 17 - 55
app/src/main/java/com/grkj/iscs_mars/service/CheckKeyInfoTask.kt

@@ -1,17 +1,13 @@
 package com.grkj.iscs_mars.service
 
-import com.clj.fastble.BleManager
 import com.grkj.iscs_mars.BusinessManager
-import com.grkj.iscs_mars.ble.BleBean
-import com.grkj.iscs_mars.ble.BleConnectionManager
-import com.grkj.iscs_mars.ble.BleConst
-import com.grkj.iscs_mars.ble.BleIndicateListener
-import com.grkj.iscs_mars.extentions.startsWith
+import com.grkj.iscs_mars.ble.BleSendDispatcher
 import com.grkj.iscs_mars.modbus.ModBusController
 import com.grkj.iscs_mars.util.log.LogUtil
 import com.sik.cronjob.annotations.CronJob
 import com.sik.sikcore.thread.ThreadUtils
-import kotlinx.coroutines.delay
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
 
 /**
  * 检查钥匙信息任务
@@ -19,58 +15,24 @@ import kotlinx.coroutines.delay
 
 class CheckKeyInfoTask {
 
-    /**
-     * 是检查信息
-     */
-    private var isCheckInfo: Boolean = false
-
-    /**
-     * 已经检查的钥匙
-     */
-    private var checkedKey: MutableList<String> = mutableListOf()
-
     /**
      * 检查钥匙信息
      */
     @CronJob(intervalMillis = 30 * 60_000L, initialDelay = 0, runOnMainThread = false)
     fun checkKeyInfo() {
-        LogUtil.i("开始检查钥匙信息")
-        val existsKey = ModBusController.getExistsKey()
-        BleConnectionManager.addBLeIndicateListener(this, object : BleIndicateListener {
-            override fun handleRsp(
-                bleBean: BleBean,
-                byteArray: ByteArray,
-                isNeedLoading: Boolean,
-                prepareDoneCallBack: ((Boolean, BleBean?) -> Unit)?
-            ) {
-                when {
-                    byteArray.startsWith(BleConst.RSP_POWER_STATUS) -> {
-                        if (isCheckInfo) {
-                            BleManager.getInstance().disconnect(bleBean.bleDevice)
-                            BusinessManager.deviceList.removeIf { it.bleDevice.mac == bleBean.bleDevice.mac }
-                            LogUtil.i("断开连接检查信息:${bleBean.bleDevice.mac}")
-                            checkedKey.add(bleBean.bleDevice.mac)
-                            if (checkedKey.joinToString(",") == existsKey.joinToString(",") {
-                                    it.mac ?: ""
-                                }) {
-                                BleConnectionManager.removeBLeIndicateListener(this)
-                                isCheckInfo = false
-                            }
-                        }
-                    }
-                }
-            }
-        })
-        checkedKey.clear()
-        isCheckInfo = true
-        ThreadUtils.runOnIO {
-            existsKey.forEach {
-                it.mac?.let {
-                    BleConnectionManager.tryConnectWithOptionalCharge(it)
-                    delay(2000)
-                }
-            }
-        }
-
+//        LogUtil.i("开始检查钥匙信息")
+//        val existsKey = ModBusController.getExistsKey()
+//        ThreadUtils.runOnIO {
+//            for (bean in existsKey) {
+//                bean.mac?.let { mac ->
+//                    BleSendDispatcher.submit(mac) {
+//                        LogUtil.i("信息获取完成,检查是否立即断开")
+//                        ThreadUtils.runOnIO {
+//                            BusinessManager.checkMyTodoForHandleKey(mac, 0)
+//                        }
+//                    }
+//                }
+//            }
+//        }
     }
 }

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

@@ -6,7 +6,6 @@ import com.grkj.iscs_mars.view.base.BaseActivity
 import com.grkj.iscs_mars.databinding.ActivityMainBinding
 import com.grkj.iscs_mars.presentation.PresentationActivity
 import com.grkj.iscs_mars.presentation.PresentationLoginActivity
-import com.grkj.iscs_mars.view.activity.test.BleActivity
 import com.grkj.iscs_mars.view.activity.test.RfidActivity
 import com.grkj.iscs_mars.view.activity.test.ModbusActivity
 import com.grkj.iscs_mars.view.activity.test.WidgetTestActivity
@@ -20,10 +19,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
         get() = ActivityMainBinding.inflate(layoutInflater)
 
     override fun initView() {
-        mBinding?.ble?.setOnClickListener {
-            startActivity(Intent(this, BleActivity::class.java))
-        }
-
         mBinding?.modbus?.setOnClickListener {
             startActivity(Intent(this, ModbusActivity::class.java))
         }

+ 0 - 363
app/src/main/java/com/grkj/iscs_mars/view/activity/test/BleActivity.kt

@@ -1,363 +0,0 @@
-package com.grkj.iscs_mars.view.activity.test
-
-import android.app.Activity
-import android.bluetooth.BluetoothGatt
-import android.content.Intent
-import android.os.Build
-import android.util.Log
-import com.clj.fastble.BleManager
-import com.clj.fastble.data.BleDevice
-import com.clj.fastble.exception.BleException
-import com.grkj.iscs_mars.BusinessManager
-import com.grkj.iscs_mars.R
-import com.grkj.iscs_mars.view.base.BaseActivity
-import com.grkj.iscs_mars.ble.BleBean
-import com.grkj.iscs_mars.ble.BleCmdManager
-import com.grkj.iscs_mars.ble.BleConst.INDICATE_UUID
-import com.grkj.iscs_mars.ble.BleConst.SERVICE_UUID
-import com.grkj.iscs_mars.ble.BleConst.STATUS_READY
-import com.grkj.iscs_mars.ble.BleConst.STATUS_WORK
-import com.grkj.iscs_mars.ble.BleUtil
-import com.grkj.iscs_mars.ble.CustomBleGattCallback
-import com.grkj.iscs_mars.ble.CustomBleIndicateCallback
-import com.grkj.iscs_mars.ble.CustomBleScanCallback
-import com.grkj.iscs_mars.ble.CustomBleWriteCallback
-import com.grkj.iscs_mars.databinding.ActivityBleBinding
-import com.grkj.iscs_mars.extentions.toHexStrings
-import com.grkj.iscs_mars.model.Constants.BLE_LOCAL_NAME
-import com.grkj.iscs_mars.model.Constants.PERMISSION_REQUEST_CODE
-import com.grkj.iscs_mars.util.CommonUtils
-import com.grkj.iscs_mars.util.Executor
-import com.grkj.iscs_mars.util.ToastUtils
-import com.grkj.iscs_mars.util.log.LogUtil
-import com.leon.lfilepickerlibrary.LFilePicker
-import com.zhy.adapter.recyclerview.CommonAdapter
-import com.zhy.adapter.recyclerview.base.ViewHolder
-import pub.devrel.easypermissions.AfterPermissionGranted
-import java.io.File
-
-class BleActivity : BaseActivity<ActivityBleBinding>() {
-
-    private val FILE_CODE = 1000
-    private var fileMac: String? = null
-    // TODO 重新指向数据,但是调试完必须重启防止数据干扰
-    var mBleList: MutableList<BleBean> = BusinessManager.deviceList
-
-    override val viewBinding: ActivityBleBinding
-        get() = ActivityBleBinding.inflate(layoutInflater)
-
-    override fun initView() {
-        mBleList.clear()
-        BleManager.getInstance().disconnectAllDevice()
-        mBinding?.srl?.setEnableRefresh(true)
-        mBinding?.srl?.setEnableLoadMore(false)
-        mBinding?.srl?.autoRefresh()
-        mBinding?.srl?.setOnRefreshListener {
-            CommonUtils.checkBlePermission(this) {
-                doScan()
-            }
-        }
-
-        mBinding?.rvBle?.adapter =
-            object : CommonAdapter<BleBean>(this, R.layout.item_ble, mBleList) {
-                override fun convert(holder: ViewHolder, item: BleBean?, position: Int) {
-                    holder.setText(R.id.ble_name, "Name:${item?.bleDevice?.name}")
-                    holder.setText(R.id.ble_mac, "Mac:${item?.bleDevice?.mac}")
-                    holder.setText(R.id.blc_connection, if (BleManager.getInstance().isConnected(item?.bleDevice)) "已连接" else "未连接")
-                    holder.setOnClickListener(R.id.connect) { doConnect(position) }
-                    holder.setOnClickListener(R.id.disconnect) {
-                        BleUtil.instance?.indicate(mBleList[position].bleDevice, isStart = false, indicateCallback = null)
-                        BleManager.getInstance().disconnect(item?.bleDevice)
-                        Executor.delayOnMain(200) {
-                            mBinding?.rvBle?.adapter?.notifyItemChanged(position)
-                        }
-                    }
-
-                    holder.setOnClickListener(R.id.mtu) {
-                        BleUtil.instance?.setMtu(mBleList[position].bleDevice)
-                    }
-
-                    holder.setOnClickListener(R.id.indicate) {
-                        item?.let {
-                            BleUtil.instance?.indicate(it.bleDevice, indicateCallback = object : CustomBleIndicateCallback() {
-                                override fun onPrompt(promptStr: String?) {
-                                    LogUtil.i("监听onPrompt : $promptStr")
-                                }
-
-                                override fun onConnectPrompt(promptStr: String?) {
-                                    LogUtil.i("监听onConnectPrompt : $promptStr")
-                                }
-
-                                override fun onDisConnectPrompt(promptStr: String?) {
-                                    LogUtil.i("监听onDisConnectPrompt : $promptStr")
-                                }
-
-                                override fun onIndicateSuccess() {
-                                    LogUtil.i("监听成功")
-                                }
-
-                                override fun onIndicateFailure(exception: BleException?) {
-                                    LogUtil.i("监听失败")
-                                }
-
-                                override fun onCharacteristicChanged(data: ByteArray?) {
-                                    LogUtil.i("******************* : ${data?.toHexStrings()}")
-                                    data?.let { itData ->
-                                        BleCmdManager.handleRsp(it, itData)
-                                    }
-                                }
-                            })
-                        }
-                    }
-
-                    holder.setOnClickListener(R.id.stopIndicate) {
-                        item?.let {
-                            BleUtil.instance?.indicate(it.bleDevice, isStart = false, indicateCallback = null)
-                        }
-                    }
-
-                    holder.setOnClickListener(R.id.exit) { finish() }
-
-                    holder.setOnClickListener(R.id.token) {
-                        BleCmdManager.getToken(item?.bleDevice?.mac, object : CustomBleWriteCallback() {
-                            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
-                                LogUtil.i("getToken success")
-                            }
-
-                            override fun onWriteFailure(exception: BleException?) {
-                                LogUtil.e("getToken fail")
-                            }
-                        })
-                    }
-
-                    holder.setOnClickListener(R.id.version) {
-                        BleCmdManager.getVersion(item?.bleDevice?.mac, object : CustomBleWriteCallback() {
-                            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
-                                LogUtil.i("getVersion success")
-                            }
-
-                            override fun onWriteFailure(exception: BleException?) {
-                                LogUtil.e("getVersion fail")
-                            }
-                        })
-                    }
-
-                    holder.setOnClickListener(R.id.power) {
-                        BleCmdManager.getPower(item?.bleDevice?.mac, object : CustomBleWriteCallback() {
-                            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
-                                LogUtil.i("getPower success")
-                            }
-
-                            override fun onWriteFailure(exception: BleException?) {
-                                LogUtil.e("getPower fail")
-                            }
-                        })
-                    }
-
-                    holder.setOnClickListener(R.id.device) {
-                        BleCmdManager.getCurrentStatus(item?.bleDevice!!, object : CustomBleWriteCallback() {
-                            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
-                                LogUtil.i("getCurrentStatus success")
-                            }
-                            override fun onWriteFailure(exception: BleException?) {
-                                LogUtil.e("getCurrentStatus fail")}
-                        })
-                    }
-
-                    holder.setOnClickListener(R.id.work_mode) {
-                        BleCmdManager.switchMode(STATUS_WORK, item?.bleDevice!!, object : CustomBleWriteCallback() {
-                            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
-                                LogUtil.i("switch mode work success")}
-                            override fun onWriteFailure(exception: BleException?) {
-                                LogUtil.i("switch mode work fail")}
-                        })
-                    }
-
-                    holder.setOnClickListener(R.id.standby_mode) {
-                        BleCmdManager.switchMode(STATUS_READY, item?.bleDevice!!, object : CustomBleWriteCallback() {
-                            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
-                                LogUtil.i("switch mode ready success")}
-                            override fun onWriteFailure(exception: BleException?) {
-                                LogUtil.e("switch mode ready fail")}
-                        })
-                    }
-
-                    holder.setOnClickListener(R.id.ticketStatus) {
-                        BleCmdManager.getTicketStatus(item?.bleDevice!!, object : CustomBleWriteCallback() {
-                            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
-                                LogUtil.i("getTicketStatus success")}
-                            override fun onWriteFailure(exception: BleException?) {
-                                LogUtil.e("getTicketStatus fail")}
-                        })
-                    }
-
-                    // 上锁工作票
-                    holder.setOnClickListener(R.id.sendTicket) {
-                        val testStr = "{\"cardNo\":\"267747D5\",\"data\":[{\"codeId\":1,\"dataList\":[{\"dataId\":17,\"equipName\":\"E-17\",\"equipRfidNo\":\"1DCAD26D031080\",\"target\":0},{\"dataId\":18,\"equipName\":\"E-18\",\"equipRfidNo\":\"1DA0C66D031080\",\"target\":0}],\"taskCode\":\"243\"}],\"lockList\":[{\"lockId\":1,\"rfid\":\"0089D495\"},{\"lockId\":2,\"rfid\":\"B05AD495\"}],\"password\":\"123456\"}"
-                        BleCmdManager.sendWorkTicket(testStr, bleDevice = item?.bleDevice!!, callback = object : CustomBleWriteCallback() {
-                            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
-                                LogUtil.i("sendTicket lock success")
-                            }
-
-                            override fun onWriteFailure(exception: BleException?) {
-                                LogUtil.e("sendTicket lock fail")
-                            }
-                        })
-                    }
-
-                    // 解锁工作票
-                    holder.setOnLongClickListener(R.id.sendTicket) {
-                        val testStr = "{\"cardNo\":\"267747D5\",\"data\":[{\"codeId\":1,\"dataList\":[{\"dataId\":17,\"equipName\":\"E-17\",\"equipRfidNo\":\"1DCAD26D031080\",\"target\":1,\"infoRfidNo\":\"0089D495\"},{\"dataId\":18,\"equipName\":\"E-18\",\"equipRfidNo\":\"1DA0C66D031080\",\"target\":1,\"infoRfidNo\":\"B05AD495\"}],\"taskCode\":\"243\"}],\"password\":\"123456\"}"
-                        BleCmdManager.sendWorkTicket(testStr, bleDevice = item?.bleDevice!!, callback = object : CustomBleWriteCallback() {
-                            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
-                                LogUtil.i("sendTicket unlock success")
-                            }
-
-                            override fun onWriteFailure(exception: BleException?) {
-                                LogUtil.e("sendTicket unlock fail")
-                            }
-                        })
-                        return@setOnLongClickListener true
-                    }
-
-                    holder.setOnClickListener(R.id.sendFile) {
-                        fileMac = item?.bleDevice?.mac
-
-                        LFilePicker()
-                            .withActivity(this@BleActivity)
-                            .withRequestCode(FILE_CODE)
-//                            .withStartPath("${FileUtil.getRootFolder(this)?.absolutePath}")
-                            .start()
-
-                    }
-                }
-            }
-
-        BleManager.getInstance().init(application)
-    }
-
-    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
-        super.onActivityResult(requestCode, resultCode, data)
-        when (requestCode) {
-            FILE_CODE -> {
-                if (resultCode == Activity.RESULT_OK && data != null) {
-                    val list: List<String>? = data.getStringArrayListExtra("paths")
-                    LogUtil.d("选择的文件为: $list")
-                    if (list.isNullOrEmpty()) {
-                        ToastUtils.tip("请选择文件!")
-                        return
-                    }
-                    BleCmdManager.sendFile(2, File(list[0]), mac = fileMac, callback = object : CustomBleWriteCallback() {
-                        override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
-                            LogUtil.i("sendFile success")
-                        }
-
-                        override fun onWriteFailure(exception: BleException?) {
-                            LogUtil.e("sendFile fail")
-                        }
-                    })
-                }
-            }
-        }
-    }
-
-    @AfterPermissionGranted(PERMISSION_REQUEST_CODE)
-    fun doScan() {
-        Log.d("doScanBle", "扫描开始:$")
-        BleUtil.instance?.scan(object : CustomBleScanCallback() {
-            override fun onPrompt(promptStr: String?) {
-                ToastUtils.tip(promptStr)
-                mBinding?.srl?.finishRefresh()
-                BleManager.getInstance().enableBluetooth()
-            }
-
-            override fun onScanStarted(success: Boolean) {
-                Log.d("doScanBle", "扫描开始:${success}")
-                mBleList.clear()
-                mBinding?.rvBle?.adapter?.notifyDataSetChanged()
-            }
-
-            override fun onScanning(bleDevice: BleDevice?) {
-                bleDevice?.let {
-                    Log.d("doScanBle", "扫描到的设备:${it.mac}")
-                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
-                        if (!it.name.isNullOrBlank() && it.name == BLE_LOCAL_NAME) {
-                            mBleList.add(BleBean(it))
-                            mBinding?.rvBle?.adapter?.notifyDataSetChanged()
-                        } else {
-
-                        }
-                    } else {
-                        mBleList.add(BleBean(it))
-                        mBinding?.rvBle?.adapter?.notifyDataSetChanged()
-                    }
-                }
-            }
-
-            override fun onScanFinished(scanResultList: MutableList<BleDevice>?) {
-                mBinding?.srl?.finishRefresh()
-                if (mBleList.isEmpty()) {
-                    ToastUtils.tip("没有扫描到设备,请下拉刷新重试!")
-                }
-            }
-        })
-    }
-
-    fun doConnect(position: Int) {
-        handleLoading(true)
-        BleManager.getInstance().disconnect(mBleList[position].bleDevice)
-        BleUtil.instance?.connectBySelect(mBleList[position].bleDevice,
-            object : CustomBleGattCallback() {
-                override fun onPrompt(promptStr: String?) {
-                    handleLoading(false)
-                    ToastUtils.tip(promptStr)
-                }
-
-                override fun onStartConnect() {
-                    LogUtil.i("onStartConnect : ${mBleList[position].bleDevice.mac}")
-                }
-
-                override fun onConnectFail(bleDevice: BleDevice?, exception: BleException?) {
-                    LogUtil.e("onConnectFail : ${bleDevice?.mac} - ${exception?.code} - ${exception?.description}")
-                    handleLoading(false)
-                    ToastUtils.tip("连接失败,请重试!")
-                }
-
-                override fun onConnectSuccess(
-                    bleDevice: BleDevice?,
-                    gatt: BluetoothGatt?,
-                    status: Int
-                ) {
-                    handleLoading(false)
-                    LogUtil.i("onConnectSuccess : ${bleDevice?.mac}")
-                    bleDevice?.let {
-                        mBinding?.rvBle?.adapter?.notifyItemChanged(position)
-                        LogUtil.i("Add BleBean : $mBleList")
-                    }
-                }
-
-                override fun onDisConnected(
-                    isActiveDisConnected: Boolean,
-                    device: BleDevice?,
-                    gatt: BluetoothGatt?,
-                    status: Int
-                ) {
-                    LogUtil.i("onDisConnected : ${device?.mac} - $isActiveDisConnected")
-                    handleLoading(false)
-                    ToastUtils.tip("连接断开了,请重试!")
-                    mBinding?.rvBle?.adapter?.notifyItemChanged(position)
-//                    mBleList.removeAt(position)
-                }
-            })
-    }
-
-    override fun onDestroy() {
-        super.onDestroy()
-
-        mBleList.forEach {
-            BleManager.getInstance().stopIndicate(it.bleDevice, SERVICE_UUID, INDICATE_UUID)
-        }
-        mBleList.clear()
-        BleManager.getInstance().disconnectAllDevice()
-    }
-}

+ 0 - 57
app/src/main/java/com/grkj/iscs_mars/view/dialog/KeyReturnConfirmDialog.kt

@@ -1,57 +0,0 @@
-package com.grkj.iscs_mars.view.dialog
-
-import android.content.Context
-import com.clj.fastble.BleManager
-import com.clj.fastble.data.BleDevice
-import com.clj.fastble.exception.BleException
-import com.grkj.iscs_mars.view.base.BaseDialog
-import com.grkj.iscs_mars.ble.BleCmdManager
-import com.grkj.iscs_mars.ble.BleConst.STATUS_READY
-import com.grkj.iscs_mars.ble.CustomBleWriteCallback
-import com.grkj.iscs_mars.databinding.DialogKeyReturnConfirmBinding
-import com.grkj.iscs_mars.util.log.LogUtil
-
-/**
- * 钥匙归还工作票未完成提示弹框
- */
-class KeyReturnConfirmDialog(ctx: Context): BaseDialog<DialogKeyReturnConfirmBinding>(ctx) {
-
-    private var bleDevice: BleDevice? = null
-
-    override val viewBinding: DialogKeyReturnConfirmBinding
-        get() = DialogKeyReturnConfirmBinding.inflate(layoutInflater)
-
-    override fun initView() {
-        mBinding?.tvCancel?.setOnClickListener {
-            // TODO 打开钥匙卡扣、断开连接
-            dismiss()
-        }
-
-        mBinding?.tvConfirm?.setOnClickListener {
-            // TODO 设置待机模式、断开连接
-            dismiss()
-        }
-    }
-
-    fun setDataAndShow(bleDevice: BleDevice) {
-        this.bleDevice = bleDevice
-        show()
-    }
-
-    fun setKeyModeReady() {
-        BleCmdManager.switchMode(STATUS_READY, bleDevice!!, object : CustomBleWriteCallback() {
-            override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
-                LogUtil.i("switch mode ready success")}
-            override fun onWriteFailure(exception: BleException?) {
-                LogUtil.e("switch mode ready fail")}
-        })
-    }
-
-    override fun dismiss() {
-        super.dismiss()
-        bleDevice?.let {
-            BleManager.getInstance().disconnect(it)
-            bleDevice = null
-        }
-    }
-}

+ 5 - 3
app/src/main/java/com/grkj/iscs_mars/view/presenter/DeviceStatusPresenter.kt

@@ -1,7 +1,7 @@
 package com.grkj.iscs_mars.view.presenter
 
+import android.annotation.SuppressLint
 import android.graphics.Bitmap
-import com.clj.fastble.BleManager
 import com.google.gson.Gson
 import com.google.gson.reflect.TypeToken
 import com.grkj.iscs_mars.BusinessManager
@@ -25,6 +25,7 @@ import com.grkj.iscs_mars.util.log.LogUtil
 import com.grkj.iscs_mars.view.base.BasePresenter
 import com.grkj.iscs_mars.view.fragment.DockTestFragment.DockTestBean
 import com.grkj.iscs_mars.view.iview.IDeviceStatusView
+import com.huyuhui.fastble.BleManager
 import com.sik.sikcore.thread.ThreadUtils
 
 class DeviceStatusPresenter : BasePresenter<IDeviceStatusView>() {
@@ -87,6 +88,7 @@ class DeviceStatusPresenter : BasePresenter<IDeviceStatusView>() {
         return Pair(status == 6, text)
     }
 
+    @SuppressLint("MissingPermission")
     fun repairKey(dockAddr: Byte?, isLeft: Boolean) {
         val status = ModBusController.getKeyStatus(dockAddr, isLeft)
         LogUtil.i("repairKey Key status : $dockAddr - $isLeft - $status")
@@ -104,10 +106,10 @@ class DeviceStatusPresenter : BasePresenter<IDeviceStatusView>() {
                 mac ?: return
                 BusinessManager.unregisterConnectListener(mac)
                 BusinessManager.getBleDeviceByMac(mac)?.bleDevice?.let {
-                    BleManager.getInstance().disconnect(it)
+                    BleManager.disconnect(it)
                 }
                 Executor.delayOnMain(2000) {
-                    BusinessManager.registerConnectListener(mac) { isDone, bleBean ->
+                    BusinessManager.registerConnectListener(mac, true) { isDone, bleBean ->
                         if (isDone && bleBean != null) {
                             Executor.delayOnMain(300) {
                                 getCurrentStatus(7, bleBean.bleDevice)

+ 20 - 22
app/src/main/java/com/grkj/iscs_mars/view/presenter/HomePresenter.kt

@@ -4,6 +4,7 @@ import com.grkj.iscs_mars.BusinessManager
 import com.grkj.iscs_mars.MyApplication
 import com.grkj.iscs_mars.R
 import com.grkj.iscs_mars.ble.BleConnectionManager
+import com.grkj.iscs_mars.ble.BleReturnDispatcher
 import com.grkj.iscs_mars.extentions.serialNo
 import com.grkj.iscs_mars.modbus.DockBean
 import com.grkj.iscs_mars.modbus.ModBusController
@@ -37,31 +38,28 @@ class HomePresenter : BasePresenter<IHomeView>() {
                                         BusinessManager.sendLoadingEventMsg(mContext?.getString(R.string.loading_msg_return_key_start))
                                     }
                                     ThreadUtils.runOnIO {
-                                        suspend fun readJobTicket(mac: String) {
+                                        fun readJobTicket(mac: String) {
                                             val isConnect =
-                                                BleConnectionManager.tryConnectWithOptionalCharge(
-                                                    mac
-                                                )
-                                            if (isConnect) {
-                                                val bleBean = BusinessManager.getBleDeviceByMac(mac)
-                                                Executor.delayOnMain(300) {
-                                                    bleBean?.let {
-                                                        BusinessManager.sendLoadingEventMsg(
-                                                            mContext?.getString(
-                                                                R.string.loading_msg_get_ticket_status_start
-                                                            )
-                                                        )
-                                                        BusinessManager.getCurrentStatus(
-                                                            4,
-                                                            it.bleDevice
-                                                        )
-                                                        BusinessManager.getBatteryPower(it.bleDevice)
+                                                BleReturnDispatcher.submit(mac){isConnect->
+                                                    if (isConnect) {
+                                                        val bleBean = BusinessManager.getBleDeviceByMac(mac)
+                                                        Executor.delayOnMain(300) {
+                                                            bleBean?.let {
+                                                                BusinessManager.sendLoadingEventMsg(
+                                                                    mContext?.getString(
+                                                                        R.string.loading_msg_get_ticket_status_start
+                                                                    )
+                                                                )
+                                                                BusinessManager.getCurrentStatus(
+                                                                    4,
+                                                                    it.bleDevice
+                                                                )
+                                                            }
+                                                        }
+                                                    } else {
+                                                        readJobTicket(mac)
                                                     }
                                                 }
-                                            } else {
-                                                delay(500)
-                                                readJobTicket(mac)
-                                            }
                                         }
                                         if (!ISCSDomainData.isDeviceRegistration) {
                                             readJobTicket(mac)

+ 2 - 3
app/src/main/java/com/grkj/iscs_mars/view/viewmodel/DeviceRegistrationKeyAndLockViewModel.kt

@@ -3,12 +3,12 @@ package com.grkj.iscs_mars.view.viewmodel
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.liveData
-import com.clj.fastble.BleManager
 import com.google.gson.Gson
 import com.google.gson.reflect.TypeToken
 import com.grkj.iscs_mars.BusinessManager
 import com.grkj.iscs_mars.MyApplication
 import com.grkj.iscs_mars.ble.BleConnectionManager
+import com.grkj.iscs_mars.ble.BleSendDispatcher
 import com.grkj.iscs_mars.modbus.DockBean
 import com.grkj.iscs_mars.modbus.ModBusController
 import com.grkj.iscs_mars.model.DeviceConst
@@ -97,8 +97,7 @@ class DeviceRegistrationKeyAndLockViewModel : BaseViewModel() {
 //            val allDeviceCloseCmdSend =
 //                BleConnectionManager.scanOnlineKeyLockMacAndSwitchModeToClose()
 //            LogUtil.i("设备录入-是否所有关闭命令发送成功:${allDeviceCloseCmdSend}")
-            BleManager.getInstance().disconnectAllDevice()
-            BusinessManager.deviceList.clear()
+            BleSendDispatcher.disconnectAll()
             BusinessManager.registerInitListener {
                 if (isStartCheckKey) {
                     return@registerInitListener

+ 0 - 36
app/src/main/res/layout/activity_ble.xml

@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/main"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@color/white"
-    android:orientation="vertical"
-    tools:context=".view.activity.test.BleActivity">
-
-    <com.scwang.smart.refresh.layout.SmartRefreshLayout
-        android:id="@+id/srl"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-        <com.scwang.smart.refresh.header.ClassicsHeader
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            app:srlTextRefreshing="正在扫描..." />
-
-        <androidx.recyclerview.widget.RecyclerView
-            android:id="@+id/rv_ble"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:overScrollMode="never"
-            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
-            tools:itemCount="100"
-            tools:listitem="@layout/item_ble" />
-
-        <com.scwang.smart.refresh.footer.ClassicsFooter
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
-    </com.scwang.smart.refresh.layout.SmartRefreshLayout>
-
-</LinearLayout>

+ 2 - 2
gradle/libs.versions.toml

@@ -13,7 +13,7 @@ mvvmhabit = "4.0.0"
 okhttps = "4.1.0"
 log-interceptor = "3.14.9"
 autosize = "v1.2.1"
-fastble = "2.4.0"
+fastble = "1.4.2"
 lifecycle-version = "2.9.0"
 nav_version = "2.9.0"
 kotlin_serialization_json = "1.7.3"
@@ -33,7 +33,7 @@ okhttps = { group = "cn.zhxu", name = "okhttps-gson", version.ref = "okhttps" }
 okhttps-stomp = { group = "cn.zhxu", name = "okhttps-stomp", version.ref = "okhttps" }
 log-interceptor = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "log-interceptor" }
 autosize = { group = "com.github.JessYanCoding", name = "AndroidAutoSize", version.ref = "autosize" }
-fastble = { group = "com.github.Jasonchenlijian", name = "FastBle", version.ref = "fastble" }
+fastble = { group = "com.github.kanshenmekan", name = "FastBle", version.ref = "fastble" }
 
 viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle-version" }
 viewmodel-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycle-version" }