|
|
@ -183,8 +183,13 @@ class BleCommandSender { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 处理设备响应数据 - 从BleService移动过来 |
|
|
* 处理设备响应数据(统一兼容失败无长度的场景) |
|
|
* @param data 响应数据 |
|
|
* |
|
|
|
|
|
* 帧格式通常为: [HEADER(0)=0xBB][CMD(1)][LEN/STATUS(2)][DATA(len)][CRC(最后1字节)] |
|
|
|
|
|
* - 当 LEN/STATUS 为 0(例如收到 0xA2, 0x00),表示该命令执行失败,直接回调失败并返回。 |
|
|
|
|
|
* - 正常响应时进行 CRC 校验(若帧长度不足则跳过校验并告警),拷贝数据使用安全长度以避免越界。 |
|
|
|
|
|
* |
|
|
|
|
|
* @param data 设备返回的原始字节数组 |
|
|
*/ |
|
|
*/ |
|
|
@SuppressLint("StaticFieldLeak") |
|
|
@SuppressLint("StaticFieldLeak") |
|
|
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) |
|
|
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) |
|
|
@ -200,63 +205,64 @@ class BleCommandSender { |
|
|
|
|
|
|
|
|
val header = data[0] // 0xBB |
|
|
val header = data[0] // 0xBB |
|
|
val cmdType = data[1].toInt() and 0xFF |
|
|
val cmdType = data[1].toInt() and 0xFF |
|
|
|
|
|
val lenByte = data[2].toInt() and 0xFF |
|
|
// 判断命令失败响应(长度为0) |
|
|
|
|
|
if (data.size == 4 && data[2].toInt() and 0xFF == 0) { |
|
|
|
|
|
Log.w(TAG, "命令 0x${cmdType.toString(16)} 执行失败") |
|
|
|
|
|
// 创建失败结果Map |
|
|
// 正常响应处理:尽量进行 CRC 校验 |
|
|
val resultMap = mapOf( |
|
|
var crcOk = true |
|
|
"success" to false, |
|
|
if (data.size >= 4) { |
|
|
"command" to cmdType, |
|
|
val payload = data.sliceArray(0 until data.size - 1) |
|
|
"rawData" to byteArrayOf() |
|
|
val calculatedCrc = calculateCrc8Maxim(payload, payload.size) |
|
|
) |
|
|
val receivedCrc = data[data.size - 1].toInt() and 0xFF |
|
|
callback?.notifyDeviceInfoReceived(cmdType, resultMap) |
|
|
crcOk = (calculatedCrc.toInt() and 0xFF) == receivedCrc |
|
|
// 通知指令发送器处理响应 |
|
|
if (!crcOk) { |
|
|
onCommandResponse(cmdType) |
|
|
Log.e( |
|
|
return |
|
|
TAG, |
|
|
|
|
|
"设备响应CRC校验失败: 计算=${calculatedCrc.toInt() and 0xFF}, 接收=${receivedCrc}" |
|
|
|
|
|
) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
Log.w(TAG, "设备响应长度不足以包含CRC,跳过CRC校验") |
|
|
} |
|
|
} |
|
|
|
|
|
// 统一失败判定 |
|
|
|
|
|
if (lenByte != data.size-4) { |
|
|
|
|
|
Log.w(TAG, "命令 0x${cmdType.toString(16)} 执行失败(无数据长度)") |
|
|
|
|
|
val resultMap = mapOf( |
|
|
|
|
|
"success" to true, |
|
|
|
|
|
"command" to cmdType, |
|
|
|
|
|
"rawData" to byteArrayOf(data[2], data[data.size - 2]) // 取第二位和倒数第二位 |
|
|
|
|
|
) |
|
|
|
|
|
callback?.notifyDeviceInfoReceived(cmdType, resultMap) |
|
|
|
|
|
onCommandResponse(cmdType) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
// 安全提取响应数据,避免越界 |
|
|
|
|
|
val actualPayloadLen = (data.size - 4).coerceAtLeast(0) |
|
|
|
|
|
val copyLen = minOf(lenByte, actualPayloadLen) |
|
|
|
|
|
val responseData = if (copyLen > 0) ByteArray(copyLen) else ByteArray(0) |
|
|
|
|
|
|
|
|
// 正常响应处理 |
|
|
if (copyLen < lenByte) { |
|
|
val length = data[2].toInt() and 0xFF |
|
|
Log.w( |
|
|
|
|
|
|
|
|
// // 检查数据长度 |
|
|
|
|
|
// if (data.size != length + 4) { // 帧头 + 命令 + 长度 + 数据 + CRC |
|
|
|
|
|
// Log.e(TAG, "设备响应数据长度不匹配: 期望=${length + 4}, 实际=${data.size}") |
|
|
|
|
|
// return |
|
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
// 计算CRC校验 - 修正:计算除最后一个CRC字节外的所有字节 |
|
|
|
|
|
val payload = data.sliceArray(0 until data.size - 1) |
|
|
|
|
|
val calculatedCrc = calculateCrc8Maxim(payload, payload.size) |
|
|
|
|
|
val receivedCrc = data[data.size - 1].toInt() and 0xFF |
|
|
|
|
|
|
|
|
|
|
|
if (calculatedCrc.toInt() and 0xFF != receivedCrc) { |
|
|
|
|
|
Log.e( |
|
|
|
|
|
TAG, |
|
|
TAG, |
|
|
"设备响应CRC校验失败: 计算=${calculatedCrc.toInt() and 0xFF}, 接收=${receivedCrc}" |
|
|
"响应长度字段(${lenByte})与实际负载长度(${actualPayloadLen})不一致,按实际长度处理" |
|
|
) |
|
|
) |
|
|
return |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 提取响应数据 |
|
|
if (copyLen > 0) { |
|
|
val responseData = if (length > 0) ByteArray(length) else ByteArray(0) |
|
|
System.arraycopy(data, 3, responseData, 0, copyLen) |
|
|
if (length > 0) { |
|
|
|
|
|
System.arraycopy(data, 3, responseData, 0, length) |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Log.d( |
|
|
Log.d( |
|
|
TAG, |
|
|
TAG, |
|
|
"收到设备响应: CMD=0x${cmdType.toString(16)}, 数据=${ |
|
|
"收到设备响应: CMD=0x${cmdType.toString(16)}, 数据=${ |
|
|
responseData.joinToString(", ") { |
|
|
responseData.joinToString(", ") { "0x${(it.toInt() and 0xFF).toString(16)}" } |
|
|
"0x${ |
|
|
|
|
|
(it.toInt() and 0xFF).toString(16) |
|
|
|
|
|
}" |
|
|
|
|
|
} |
|
|
|
|
|
}" |
|
|
}" |
|
|
) |
|
|
) |
|
|
// 通知指令发送器处理响应 |
|
|
|
|
|
onCommandResponse(cmdType) |
|
|
onCommandResponse(cmdType) |
|
|
// 根据命令类型处理不同的响应 |
|
|
|
|
|
when (cmdType) { |
|
|
when (cmdType) { |
|
|
BleConst.CMD_GET_VERSION -> { |
|
|
BleConst.CMD_GET_VERSION -> { |
|
|
val resultMap = mutableMapOf<String, Any>( |
|
|
val resultMap = mutableMapOf<String, Any>( |
|
|
|