package com.iscs.comm import android.Manifest import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items import androidx.compose.material3.Card import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.lifecycleScope import com.iscs.comm.entity.BleTicketDataPackage import com.iscs.comm.entity.device.Device import com.iscs.comm.entity.device.DeviceKeySlot import com.iscs.comm.entity.device.status.DeviceStatusKeySlot import com.iscs.comm.enums.CommType import com.iscs.comm.extension.BleFrameExt import com.iscs.comm.extension.BleFrameExt.buildBLEGetPowerCMD import com.iscs.comm.extension.BleFrameExt.buildBLEGetStatusCMD import com.iscs.comm.extension.BleFrameExt.buildBLEGetTicketInfoCMD import com.iscs.comm.extension.BleFrameExt.getPower import com.iscs.comm.extension.BleFrameExt.getRunMode import com.iscs.comm.extension.BleFrameExt.getTicketPackageInfo 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 import kotlinx.coroutines.launch class MainActivity : ComponentActivity() { val testJobJson = "{\"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\"}" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { CommDemoTheme { Scaffold(modifier = Modifier.fillMaxSize()) { pv -> BuildDeviceList(pv) } } } } @Composable fun BuildDeviceList(pv: PaddingValues) { val list = remember { mutableStateListOf() } val listener = object : IDeviceListener() { override fun onDeviceList(devices: List) { list.clear() list.addAll(devices.sortedBy { it.frame.cmd }) } override fun onDeviceChanged(device: Device) { super.onDeviceChanged(device) if (device is DeviceKeySlot) { val slots = (device.deviceStatus as DeviceStatusKeySlot).slotList slots.forEach { slot -> if (slot.isChanged()) Log.d("xiaoming", "slot -> ${slot.ch} isUsed:${slot.isUsedChanged()} isRfid:${slot.isRfidChanged()}") } } } } LaunchedEffect("") { // 设置设备变化监听 CommManager.addOnDeviceListener(listener) // SDK初始化 CommManager.init(CommConfig().setCommType(CommType.CAN).setPort("can0").setBitrate(1000000)) } DisposableEffect("") { // 移除页面监听 CommManager.removeOnDeviceListener(listener) onDispose { } } RequestMultiplePermissions() LazyVerticalGrid( columns = GridCells.Adaptive(minSize = 100.dp), contentPadding = PaddingValues(10.dp, pv.calculateTopPadding() + 10.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp), ) { items(list) { device -> Card(onClick = { openCtrlActivity(device.frame.cmd) }) { Column( modifier = Modifier .padding(5.dp) .aspectRatio(1.2f) .fillMaxWidth() ) { Text(device.frame.cmd.toString(16).uppercase()) Text("${device.deviceType}", fontSize = 12.sp) } } } } } @Composable fun RequestMultiplePermissions() { // 定义要请求的多个权限 val permissions = listOf( Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.ACCESS_FINE_LOCATION ) // 创建权限请求的 launcher val permissionLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.RequestMultiplePermissions(), onResult = { permissionsResult -> // 检查所有权限是否都被授予 if (permissionsResult.all { it.value }) { lifecycleScope.launch { bleKeyTest("CC:BA:97:21:72:0A") } } else { // 有权限被拒绝 } } ) // 请求权限 LaunchedEffect(Unit) { permissionLauncher.launch(permissions.toTypedArray()) } } private suspend fun bleKeyTest(mac: String) { // 测试蓝牙扫描 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 $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 $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 // } // } // ISCSLog.i("xiaoming $mac", "下发作业票:$ticketSendOk") // // 作业票下发成功,修改设备运行模式为工作模式 // val switch = bm.writeByResponse(token.buildBLESwitchRunModeCMD(RunMode.WORK)).getSwitchRunModeResult() // ISCSLog.i("xiaoming $mac", "切换工作模式:$switch") // 读取作业票信息 val pkgList = ArrayList() val ticketInfo = bm.writeByResponse(token.buildBLEGetTicketInfoCMD()).getTicketPackageInfo() pkgList.add(ticketInfo) ISCSLog.i("xiaoming $mac", "读取作业票:首包信息:$ticketInfo") // 校验是否有子包,如果有,继续读取子包数据 for (idx in 1 until ticketInfo.pkgTotal) { delay(100) val ticketSubPackageInfo = bm.writeByResponse(token.buildBLEGetTicketInfoCMD(idx, ticketInfo.pkgTotal)).getTicketPackageInfo() pkgList.add(ticketSubPackageInfo) ticketSubPackageInfo.pkgIdx ISCSLog.i("xiaoming $mac", "读取作业票:子包信息:$ticketSubPackageInfo") } var datas = byteArrayOf() pkgList.forEach { datas += it.pkgData } ISCSLog.i("xiaoming $mac", "读取作业票:${String(datas)}") // val powerOff = bm.writeByResponse(token.buildBLEPowerOffCMD()) // ISCSLog.i("xiaoming $mac", "设备关机结果:$powerOff") } else { // 进行重连,这里可以封装尝试次数 bleKeyTest(mac) } bm.disconnect() } }