MainActivity.kt 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package com.iscs.comm
  2. import android.Manifest
  3. import android.os.Bundle
  4. import android.util.Log
  5. import androidx.activity.ComponentActivity
  6. import androidx.activity.compose.rememberLauncherForActivityResult
  7. import androidx.activity.compose.setContent
  8. import androidx.activity.enableEdgeToEdge
  9. import androidx.activity.result.contract.ActivityResultContracts
  10. import androidx.compose.foundation.layout.Arrangement
  11. import androidx.compose.foundation.layout.Column
  12. import androidx.compose.foundation.layout.PaddingValues
  13. import androidx.compose.foundation.layout.aspectRatio
  14. import androidx.compose.foundation.layout.fillMaxSize
  15. import androidx.compose.foundation.layout.fillMaxWidth
  16. import androidx.compose.foundation.layout.padding
  17. import androidx.compose.foundation.lazy.grid.GridCells
  18. import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
  19. import androidx.compose.foundation.lazy.grid.items
  20. import androidx.compose.material3.Card
  21. import androidx.compose.material3.Scaffold
  22. import androidx.compose.material3.Text
  23. import androidx.compose.runtime.Composable
  24. import androidx.compose.runtime.DisposableEffect
  25. import androidx.compose.runtime.LaunchedEffect
  26. import androidx.compose.runtime.mutableStateListOf
  27. import androidx.compose.runtime.remember
  28. import androidx.compose.ui.Modifier
  29. import androidx.compose.ui.unit.dp
  30. import androidx.compose.ui.unit.sp
  31. import androidx.lifecycle.lifecycleScope
  32. import com.iscs.comm.entity.BleTicketDataPackage
  33. import com.iscs.comm.entity.device.Device
  34. import com.iscs.comm.entity.device.DeviceKeySlot
  35. import com.iscs.comm.entity.device.status.DeviceStatusKeySlot
  36. import com.iscs.comm.enums.CommType
  37. import com.iscs.comm.extension.BleFrameExt
  38. import com.iscs.comm.extension.BleFrameExt.buildBLEGetPowerCMD
  39. import com.iscs.comm.extension.BleFrameExt.buildBLEGetStatusCMD
  40. import com.iscs.comm.extension.BleFrameExt.buildBLEGetTicketInfoCMD
  41. import com.iscs.comm.extension.BleFrameExt.getPower
  42. import com.iscs.comm.extension.BleFrameExt.getRunMode
  43. import com.iscs.comm.extension.BleFrameExt.getTicketPackageInfo
  44. import com.iscs.comm.extension.BleFrameExt.getToken
  45. import com.iscs.comm.extension.byteArrayToHexString
  46. import com.iscs.comm.intf.IDeviceListener
  47. import com.iscs.comm.manager.BleManager
  48. import com.iscs.comm.ui.theme.CommDemoTheme
  49. import com.iscs.comm.utils.ISCSLog
  50. import kotlinx.coroutines.delay
  51. import kotlinx.coroutines.launch
  52. class MainActivity : ComponentActivity() {
  53. val testJobJson =
  54. "{\"cardNo\":\"D2931A25\",\"data\":[{\"codeId\":1,\"dataList\":[{\"dataId\":87,\"equipName\":\"E_29\",\"equipRfidNo\":\"1B9105AF\",\"target\":0},{\"dataId\":88,\"equipName\":\"E_30\",\"equipRfidNo\":\"FB9091E5\",\"target\":0}],\"taskCode\":\"165\"}],\"lockList\":[{\"lockId\":1,\"rfid\":\"C097D395\"},{\"lockId\":2,\"rfid\":\"A04AD495\"}],\"password\":\"123456\"}"
  55. override fun onCreate(savedInstanceState: Bundle?) {
  56. super.onCreate(savedInstanceState)
  57. enableEdgeToEdge()
  58. setContent {
  59. CommDemoTheme {
  60. Scaffold(modifier = Modifier.fillMaxSize()) { pv ->
  61. BuildDeviceList(pv)
  62. }
  63. }
  64. }
  65. }
  66. @Composable
  67. fun BuildDeviceList(pv: PaddingValues) {
  68. val list = remember { mutableStateListOf<Device>() }
  69. val listener = object : IDeviceListener() {
  70. override fun onDeviceList(devices: List<Device>) {
  71. list.clear()
  72. list.addAll(devices.sortedBy { it.frame.cmd })
  73. }
  74. override fun onDeviceChanged(device: Device) {
  75. super.onDeviceChanged(device)
  76. if (device is DeviceKeySlot) {
  77. val slots = (device.deviceStatus as DeviceStatusKeySlot).slotList
  78. slots.forEach { slot ->
  79. if (slot.isChanged()) Log.d("xiaoming", "slot -> ${slot.ch} isUsed:${slot.isUsedChanged()} isRfid:${slot.isRfidChanged()}")
  80. }
  81. }
  82. }
  83. }
  84. LaunchedEffect("") {
  85. // 设置设备变化监听
  86. CommManager.addOnDeviceListener(listener)
  87. // SDK初始化
  88. CommManager.init(CommConfig().setCommType(CommType.CAN).setPort("can0").setBitrate(1000000))
  89. }
  90. DisposableEffect("") {
  91. // 移除页面监听
  92. CommManager.removeOnDeviceListener(listener)
  93. onDispose { }
  94. }
  95. RequestMultiplePermissions()
  96. LazyVerticalGrid(
  97. columns = GridCells.Adaptive(minSize = 100.dp),
  98. contentPadding = PaddingValues(10.dp, pv.calculateTopPadding() + 10.dp),
  99. horizontalArrangement = Arrangement.spacedBy(8.dp),
  100. verticalArrangement = Arrangement.spacedBy(8.dp),
  101. ) {
  102. items(list) { device ->
  103. Card(onClick = { openCtrlActivity(device.frame.cmd) }) {
  104. Column(
  105. modifier = Modifier
  106. .padding(5.dp)
  107. .aspectRatio(1.2f)
  108. .fillMaxWidth()
  109. ) {
  110. Text(device.frame.cmd.toString(16).uppercase())
  111. Text("${device.deviceType}", fontSize = 12.sp)
  112. }
  113. }
  114. }
  115. }
  116. }
  117. @Composable
  118. fun RequestMultiplePermissions() {
  119. // 定义要请求的多个权限
  120. val permissions = listOf(
  121. Manifest.permission.BLUETOOTH_CONNECT,
  122. Manifest.permission.BLUETOOTH_SCAN,
  123. Manifest.permission.ACCESS_FINE_LOCATION
  124. )
  125. // 创建权限请求的 launcher
  126. val permissionLauncher = rememberLauncherForActivityResult(
  127. contract = ActivityResultContracts.RequestMultiplePermissions(),
  128. onResult = { permissionsResult ->
  129. // 检查所有权限是否都被授予
  130. if (permissionsResult.all { it.value }) {
  131. lifecycleScope.launch { bleKeyTest("CC:BA:97:21:72:0A") }
  132. } else {
  133. // 有权限被拒绝
  134. }
  135. }
  136. )
  137. // 请求权限
  138. LaunchedEffect(Unit) {
  139. permissionLauncher.launch(permissions.toTypedArray())
  140. }
  141. }
  142. private suspend fun bleKeyTest(mac: String) {
  143. // 测试蓝牙扫描
  144. val bm = BleManager(this@MainActivity.application, mac = mac)
  145. val result = bm.connect()
  146. if (result.connected) {
  147. // 获取设备token
  148. val token = bm.writeByResponse(BleFrameExt.buildBLEGetTokenCMD()).getToken()
  149. ISCSLog.i("xiaoming $mac", "获取设备token ${token.byteArrayToHexString()}")
  150. // 获取设备电量
  151. val power = bm.writeByResponse(token.buildBLEGetPowerCMD()).getPower()
  152. ISCSLog.i("xiaoming $mac", "当前设备电量:$power")
  153. // 获取当前设备运行模式
  154. val runMode = bm.writeByResponse(token.buildBLEGetStatusCMD()).getRunMode()
  155. ISCSLog.i("xiaoming $mac", "当前工作模式:$runMode")
  156. // 切换当前设备运行模式
  157. // val switch = bm.writeByResponse(token.buildBLESwitchRunModeCMD(RunMode.STBY)).getSwitchRunModeResult()
  158. // ISCSLog.i("xiaoming $mac", "切换工作模式:$switch")
  159. // 下发作业票
  160. // val tickets = token.buildBLETicketDataCMDList(testJobJson)
  161. // var ticketSendOk = true
  162. // tickets.forEach {
  163. // val ticket = bm.writeByResponse(it).getSendTicketResult()
  164. // ISCSLog.i("xiaoming $mac", "下发作业票:分包${it.data[4].toInt()}发送结果:$ticket")
  165. // if (ticket != 0) {
  166. // ticketSendOk = false
  167. // return@forEach
  168. // }
  169. // }
  170. // ISCSLog.i("xiaoming $mac", "下发作业票:$ticketSendOk")
  171. // // 作业票下发成功,修改设备运行模式为工作模式
  172. // val switch = bm.writeByResponse(token.buildBLESwitchRunModeCMD(RunMode.WORK)).getSwitchRunModeResult()
  173. // ISCSLog.i("xiaoming $mac", "切换工作模式:$switch")
  174. // 读取作业票信息
  175. val pkgList = ArrayList<BleTicketDataPackage>()
  176. val ticketInfo = bm.writeByResponse(token.buildBLEGetTicketInfoCMD()).getTicketPackageInfo()
  177. pkgList.add(ticketInfo)
  178. ISCSLog.i("xiaoming $mac", "读取作业票:首包信息:$ticketInfo")
  179. // 校验是否有子包,如果有,继续读取子包数据
  180. for (idx in 1 until ticketInfo.pkgTotal) {
  181. delay(100)
  182. val ticketSubPackageInfo = bm.writeByResponse(token.buildBLEGetTicketInfoCMD(idx, ticketInfo.pkgTotal)).getTicketPackageInfo()
  183. pkgList.add(ticketSubPackageInfo)
  184. ticketSubPackageInfo.pkgIdx
  185. ISCSLog.i("xiaoming $mac", "读取作业票:子包信息:$ticketSubPackageInfo")
  186. }
  187. var datas = byteArrayOf()
  188. pkgList.forEach { datas += it.pkgData }
  189. ISCSLog.i("xiaoming $mac", "读取作业票:${String(datas)}")
  190. // val powerOff = bm.writeByResponse(token.buildBLEPowerOffCMD())
  191. // ISCSLog.i("xiaoming $mac", "设备关机结果:$powerOff")
  192. } else {
  193. // 进行重连,这里可以封装尝试次数
  194. bleKeyTest(mac)
  195. }
  196. bm.disconnect()
  197. }
  198. }