Prechádzať zdrojové kódy

蓝牙通信优化,防止频繁扫描被系统主动停止

bjb 1 týždeň pred
rodič
commit
e5a1ebae25

+ 8 - 1
app/src/main/java/com/iscs/comm/CtrlActivity.kt

@@ -108,6 +108,7 @@ class CtrlActivity : ComponentActivity() {
                 verticalArrangement = Arrangement.spacedBy(8.dp),
             ) {
                 items(ArrayList(status.slotList.sortedBy { it.ch })) { state ->
+                    var lastRFID = state.rfid
                     val rfid = remember { mutableStateOf(state.rfid) }
                     val isLock = remember { mutableStateOf(state.isSlotLock) }
                     val isUsed = remember { mutableStateOf(state.isUsed) }
@@ -119,6 +120,12 @@ class CtrlActivity : ComponentActivity() {
                                     isLock.value = it.isSlotLock
                                     isUsed.value = it.isUsed
                                     rfid.value = it.rfid
+                                    if (it.isChanged && rfid.value.isNotEmpty() && rfid.value != lastRFID) {
+                                        lastRFID = rfid.value
+                                        dev.ctrlSlotLock(state.ch, true).writeByFrame()
+                                    } else if (rfid.value.isEmpty()) {
+                                        lastRFID = ""
+                                    }
                                 }
                             }
                         }
@@ -197,7 +204,7 @@ class CtrlActivity : ComponentActivity() {
                                     isLock.value = it.isSlotLock
                                     isUsed.value = it.isUsed
                                     rfid.value = it.rfid
-                                    Log.d("xiaoming", "${state.ch} ${it.isChanged} ${rfid.value} ${lastRFID}")
+                                    // Log.d("xiaoming", "${state.ch} ${it.isChanged} ${rfid.value} ${lastRFID}")
                                     // 这里可以做一些其他逻辑,比如如果当前有锁存在,但是没上锁,这里可执行上锁操作
                                     if (it.isChanged && rfid.value.isNotEmpty() && rfid.value != lastRFID) {
                                         lastRFID = rfid.value

+ 64 - 39
app/src/main/java/com/iscs/comm/MainActivity.kt

@@ -24,17 +24,25 @@ import androidx.compose.runtime.mutableStateListOf
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
-import com.iscs.comm.entity.BleTicketDataPackage
 import com.iscs.comm.entity.device.Device
+import com.iscs.comm.enums.CommType
+import com.iscs.comm.enums.RunMode
 import com.iscs.comm.extension.BleFrameExt
-import com.iscs.comm.extension.BleFrameExt.buildBLEGetTicketInfoCMD
-import com.iscs.comm.extension.BleFrameExt.getTicketPackageInfo
+import com.iscs.comm.extension.BleFrameExt.buildBLEGetPowerCMD
+import com.iscs.comm.extension.BleFrameExt.buildBLEGetStatusCMD
+import com.iscs.comm.extension.BleFrameExt.buildBLESwitchRunModeCMD
+import com.iscs.comm.extension.BleFrameExt.buildBLETicketDataCMDList
+import com.iscs.comm.extension.BleFrameExt.getPower
+import com.iscs.comm.extension.BleFrameExt.getRunMode
+import com.iscs.comm.extension.BleFrameExt.getSendTicketResult
+import com.iscs.comm.extension.BleFrameExt.getSwitchRunModeResult
 import com.iscs.comm.extension.BleFrameExt.getToken
 import com.iscs.comm.extension.byteArrayToHexString
 import com.iscs.comm.intf.IDeviceListener
 import com.iscs.comm.manager.BleManager
 import com.iscs.comm.ui.theme.CommDemoTheme
 import com.iscs.comm.utils.ISCSLog
+import kotlinx.coroutines.delay
 
 class MainActivity : ComponentActivity() {
 
@@ -68,9 +76,16 @@ class MainActivity : ComponentActivity() {
             // 设置设备变化监听
             CommManager.addOnDeviceListener(listener)
             // SDK初始化
-            CommManager.init()
+            CommManager.init(CommConfig().setCommType(CommType.CAN).setPort("can0").setBitrate(1000000))
             // 蓝牙钥匙功能测试
-            // bleKeyTest()
+            repeat(10) {
+                ISCSLog.i("xiaoming", "------------ start ------------")
+                bleKeyTest("CC:BA:97:21:71:E6")
+                bleKeyTest("CC:BA:97:21:72:0A")
+                bleKeyTest("CC:BA:97:21:71:CA")
+                ISCSLog.i("xiaoming", "------------- end -----------")
+                delay(10000)
+            }
         }
         DisposableEffect("") {
             // 移除页面监听
@@ -100,47 +115,57 @@ class MainActivity : ComponentActivity() {
 
     }
 
-    private suspend fun bleKeyTest() {
+    private suspend fun bleKeyTest(mac: String) {
         // 测试蓝牙扫描
-        val bm = BleManager(this@MainActivity.application, mac = "CC:BA:97:21:71:E6")
+        val bm = BleManager(this@MainActivity.application, mac = mac)
         val result = bm.connect()
         if (result.connected) {
+            // 获取设备token
             val token = bm.writeByResponse(BleFrameExt.buildBLEGetTokenCMD()).getToken()
-            ISCSLog.i("xiaoming", "获取设备token ${token.byteArrayToHexString()}")
-//                val power = bm.writeByResponse(token.buildBLEGetPowerCMD()).getPower()
-//                ISCSLog.i("xiaoming", "当前设备电量:$power")
-//                val runMode = bm.writeByResponse(token.buildBLEGetStatusCMD()).getRunMode()
-//                ISCSLog.i("xiaoming", "当前工作模式:$runMode")
+            ISCSLog.i("xiaoming $mac", "获取设备token ${token.byteArrayToHexString()}")
+            // 获取设备电量
+            val power = bm.writeByResponse(token.buildBLEGetPowerCMD()).getPower()
+            ISCSLog.i("xiaoming $mac", "当前设备电量:$power")
+            // 获取当前设备运行模式
+            val runMode = bm.writeByResponse(token.buildBLEGetStatusCMD()).getRunMode()
+            ISCSLog.i("xiaoming $mac", "当前工作模式:$runMode")
+            // 切换当前设备运行模式
 //                val switch = bm.writeByResponse(token.buildBLESwitchRunModeCMD(RunMode.STBY)).getSwitchRunModeResult()
-//                ISCSLog.i("xiaoming", "切换工作模式:$switch")
-//                val tickets = token.buildBLETicketDataCMDList(testJobJson)
-//                var ticketSendOk = true
-//                tickets.forEach {
-//                    val ticket = bm.writeByResponse(it).getSendTicketResult()
-//                    ISCSLog.i("xiaoming", "下发作业票:分包${it.data[4].toInt()}发送结果:$ticket")
-//                    if (ticket != 0) {
-//                        ticketSendOk = false
-//                        return@forEach
-//                    }
-//                }
-//                ISCSLog.i("xiaoming", "下发作业票:$ticketSendOk")
-//                val switch = bm.writeByResponse(token.buildBLESwitchRunModeCMD(RunMode.WORK)).getSwitchRunModeResult()
-//                ISCSLog.i("xiaoming", "切换工作模式:$switch")
-            // 读取作业票信息
-            val pkgList = ArrayList<BleTicketDataPackage>()
-            val ticketInfo = bm.writeByResponse(token.buildBLEGetTicketInfoCMD()).getTicketPackageInfo()
-            pkgList.add(ticketInfo)
-            ISCSLog.i("xiaoming", "读取作业票:首包信息:$ticketInfo")
-            // 校验是否有子包,如果有,继续读取子包数据
-            for (idx in 1 until ticketInfo.pkgTotal) {
-                val ticketSubPackageInfo = bm.writeByResponse(token.buildBLEGetTicketInfoCMD(idx, ticketInfo.pkgTotal)).getTicketPackageInfo()
-                pkgList.add(ticketSubPackageInfo)
-                ISCSLog.i("xiaoming", "读取作业票:子包信息:$ticketSubPackageInfo")
+//                ISCSLog.i("xiaoming $mac", "切换工作模式:$switch")
+            // 下发作业票
+            val tickets = token.buildBLETicketDataCMDList(testJobJson)
+            var ticketSendOk = true
+            tickets.forEach {
+                val ticket = bm.writeByResponse(it).getSendTicketResult()
+                ISCSLog.i("xiaoming $mac", "下发作业票:分包${it.data[4].toInt()}发送结果:$ticket")
+                if (ticket != 0) {
+                    ticketSendOk = false
+                    return@forEach
+                }
             }
-            var datas = byteArrayOf()
-            pkgList.forEach { datas += it.pkgData }
-            ISCSLog.i("xiaoming", "读取作业票:${String(datas)}")
+            ISCSLog.i("xiaoming $mac", "下发作业票:$ticketSendOk")
+            // 作业票下发成功,修改设备运行模式为工作模式
+            val switch = bm.writeByResponse(token.buildBLESwitchRunModeCMD(RunMode.WORK)).getSwitchRunModeResult()
+            ISCSLog.i("xiaoming $mac", "切换工作模式:$switch")
+            // 读取作业票信息
+//            val pkgList = ArrayList<BleTicketDataPackage>()
+//            val ticketInfo = bm.writeByResponse(token.buildBLEGetTicketInfoCMD()).getTicketPackageInfo()
+//            pkgList.add(ticketInfo)
+//            ISCSLog.i("xiaoming $mac", "读取作业票:首包信息:$ticketInfo")
+//            // 校验是否有子包,如果有,继续读取子包数据
+//            for (idx in 1 until ticketInfo.pkgTotal) {
+//                val ticketSubPackageInfo = bm.writeByResponse(token.buildBLEGetTicketInfoCMD(idx, ticketInfo.pkgTotal)).getTicketPackageInfo()
+//                pkgList.add(ticketSubPackageInfo)
+//                ISCSLog.i("xiaoming $mac", "读取作业票:子包信息:$ticketSubPackageInfo")
+//            }
+//            var datas = byteArrayOf()
+//            pkgList.forEach { datas += it.pkgData }
+//            ISCSLog.i("xiaoming $mac", "读取作业票:${String(datas)}")
+        } else {
+            // 进行重连,这里可以封装尝试次数
+            bleKeyTest(mac)
         }
+        bm.disconnect()
     }
 
 }

+ 70 - 0
transport/src/main/java/com/iscs/comm/CommConfig.kt

@@ -0,0 +1,70 @@
+package com.iscs.comm
+
+import com.iscs.comm.enums.CommType
+
+class CommConfig {
+
+    /**
+     * 配置通信类型
+     */
+    private var commType = CommType.NONE
+
+    /**
+     * 配置通信端口
+     */
+    private var port = ""
+
+    /**
+     * 配置通信传输速率
+     */
+    private var bitrate = 0
+
+    fun setCommType(type: CommType): CommConfig {
+        this.commType = type
+        return this
+    }
+
+    /**
+     * 获取通信类型
+     */
+    fun getCommType(): CommType {
+        return commType
+    }
+
+    /**
+     * 设置通信端口
+     *
+     * @param port CAN - can0/can1
+     *             485 - dev/ttys0 dev/ttys1
+     */
+    fun setPort(port: String): CommConfig {
+        this.port = port
+        return this
+    }
+
+    /**
+     * 获取当前通信端口
+     */
+    fun getPort(): String {
+        return port
+    }
+
+    /**
+     * 设置传输速率
+     *
+     * @param bitrate CAN - 1000000
+     *                485/serial - 115200/9600
+     */
+    fun setBitrate(bitrate: Int): CommConfig {
+        this.bitrate = bitrate
+        return this
+    }
+
+    /**
+     * 获取当前通信速率
+     */
+    fun getBitrate(): Int {
+        return bitrate
+    }
+
+}

+ 6 - 2
transport/src/main/java/com/iscs/comm/CommManager.kt

@@ -2,6 +2,7 @@ package com.iscs.comm
 
 import com.iscs.comm.entity.Frame
 import com.iscs.comm.entity.device.Device
+import com.iscs.comm.enums.CommType
 import com.iscs.comm.extension.buildReadDeviceInfo
 import com.iscs.comm.extension.factoryDevice
 import com.iscs.comm.intf.AbsCommBase
@@ -30,11 +31,14 @@ object CommManager {
     // 设备变化监听
     private val deviceChangeListeners = ConcurrentLinkedQueue<IDeviceListener>()
 
-    fun init() {
+    fun init(config: CommConfig) {
         // 初始化前释放资源
         release()
         // 连接之前先对已连接进行断开连接处理
-        manager = CanManager("can0")
+        manager = when (config.getCommType()) {
+            CommType.CAN -> CanManager(config.getPort(), config.getBitrate())
+            else -> null
+        }
         manager?.open()
         initDeviceList()
     }

+ 12 - 3
transport/src/main/java/com/iscs/comm/manager/BleManager.kt

@@ -84,6 +84,8 @@ class BleManager(
         override fun onScanFailed(errorCode: Int) {
             super.onScanFailed(errorCode)
             ISCSLog.i(TAG, "scan() onScanFailed() $errorCode")
+            // 扫描失败重新执行扫描
+            scan()
         }
 
     }
@@ -101,6 +103,9 @@ class BleManager(
                 gatt.discoverServices()
             } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                 ISCSLog.i(TAG, "gattCallback onConnectionStateChange() gatt disconnected")
+                if (!(this@BleManager.doneConnect?.isCompleted ?: false)) {
+                    this@BleManager.doneConnect?.resume(BleConnectResult(false), null)
+                }
             }
         }
 
@@ -118,7 +123,7 @@ class BleManager(
             ISCSLog.i(TAG, "gattCallback onMtuChanged() mtu $mtu")
             Thread {
                 val indicateOk = enableIndicate()
-                SystemClock.sleep(2000)
+                SystemClock.sleep(1000)
                 if (needIndicate) {
                     if (!(this@BleManager.doneConnect?.isCompleted ?: false)) this@BleManager.doneConnect?.resume(BleConnectResult(indicateOk), null)
                 } else {
@@ -217,7 +222,8 @@ class BleManager(
         // 设置扫描过滤
         val filters = ArrayList<ScanFilter>()
         if (mac.isNotEmpty()) filters.add(ScanFilter.Builder().setDeviceAddress(mac).build())
-        // 设置蓝牙扫描频率高
+        // 设置蓝牙扫描频率高 SCAN_MODE_LOW_LATENCY
+        // 设置蓝牙扫描频率中 SCAN_MODE_BALANCED
         val settings = ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build()
         scan.startScan(filters, settings, scanCallback)
     }
@@ -250,7 +256,10 @@ class BleManager(
      */
     @SuppressLint("MissingPermission")
     fun disconnect() {
-        device?.let { gatt?.close() }
+        device?.let {
+            gatt?.disconnect()
+            gatt?.close()
+        }
     }
 
     /**

+ 2 - 2
transport/src/main/java/com/iscs/comm/manager/CanManager.kt

@@ -20,7 +20,7 @@ import java.util.concurrent.ConcurrentHashMap
  *
  * @author GrayCarbon
  */
-class CanManager(private val port: String) : AbsCommBase() {
+class CanManager(private val port: String = "can0", private val bitrate: Int = 1000000) : AbsCommBase() {
 
     companion object {
 
@@ -44,7 +44,7 @@ class CanManager(private val port: String) : AbsCommBase() {
      */
     override fun open() {
         // 打开CAN口之前需要先对CAN口进行操作
-        ShellTools.execAsync(listOf("ip link set $port down", "ip link set $port up type can bitrate 1000000"), true) {
+        ShellTools.execAsync(listOf("ip link set $port down", "ip link set $port up type can bitrate $bitrate"), true) {
             openListener()
             portId = NativeCan.canOpen(port)
             isOpened = portId > 0