fix: 增加获取锁状态接口

This commit is contained in:
liyi 2025-09-08 18:16:48 +08:00
parent 067489b37b
commit e07e30f598
4 changed files with 196 additions and 11 deletions

View File

@ -47,6 +47,17 @@ class BleService {
// 访
factory BleService() => _instance;
/// SharedPreferences
static List<int>? _cachedPrivateKey;
///
static List<int>? get cachedPrivateKey => _cachedPrivateKey;
///
static void setCachedPrivateKey(List<int> privateKey) {
_cachedPrivateKey = List.from(privateKey);
}
///
final Map<String, ScanResult> _discoveredDevices = {};
@ -281,23 +292,146 @@ class BleService {
BaseBleCommand.MAX_PACKET_DATA_SIZE = mtu;
}
///
final Map<int, List<int>> _pendingPackets = {};
///
void _handleListenCharacteristicData(List<int> data) async {
void _handleListenCharacteristicData(List<int> data) {
AppLogger.highlight('✨✨✨ 📨 收到订阅数据:$data (长度: ${data.length}) ✨✨✨');
//
if (data.isNotEmpty) {
dynamic result = await bleCommandManager.handleResponse(data);
if (result != null) {
//
_triggerCommandResponseWaiters(result);
} else {
AppLogger.warn('⚠️ 数据包解析失败或不匹配任何命令');
//
List<int>? completePacket = _reassemblePacket(data);
if (completePacket != null) {
//
dynamic result = bleCommandManager.handleResponse(completePacket);
if (result != null) {
//
_triggerCommandResponseWaiters(result);
} else {
AppLogger.warn('⚠️ 数据包解析失败或不匹配任何命令');
}
}
} else {
AppLogger.warn('✨✨✨ ⚠️ 收到空数据 ✨✨✨');
}
}
///
/// [data]
/// null
List<int>? _reassemblePacket(List<int> data) {
try {
// 1.
if (data.length >= 4 &&
data[0] == BaseBleCommand.PACKET_HEADER[0] &&
data[1] == BaseBleCommand.PACKET_HEADER[1] &&
data[2] == BaseBleCommand.PACKET_HEADER[2] &&
data[3] == BaseBleCommand.PACKET_HEADER[3]) {
//
//
if (_pendingPackets.isNotEmpty) {
AppLogger.warn('⚠️ 检测到新包开始,丢弃未完成的包');
_pendingPackets.clear();
}
//
if (data.length >= 12) {
// ()
int packetSequence = (data[5] << 8) | data[6];
// (: 16 + 16)
int combinedLength = (data[8] << 24) | (data[9] << 16) | (data[10] << 8) | data[11];
int encryptedDataLength = (combinedLength >> 16) & 0xFFFF;
int originalDataLength = combinedLength & 0xFFFF;
//
int encryptType = data[7] & 0x0F;
int actualDataLength = (encryptType == BaseBleCommand.ENCRYPT_TYPE_PLAIN) ? originalDataLength : encryptedDataLength;
//
int expectedTotalLength = 12 + actualDataLength + 2; // (12) + + CRC(2)
AppLogger.debug('📦 新包开始: 序号=$packetSequence, 预期长度=$expectedTotalLength, 实际长度=${data.length}');
if (data.length == expectedTotalLength) {
//
AppLogger.debug('✅ 数据包完整,无需重组');
return data;
} else if (data.length < expectedTotalLength) {
//
AppLogger.debug('📥 数据包不完整,开始重组: 已接收${data.length}/$expectedTotalLength字节');
_pendingPackets[packetSequence] = List.from(data);
return null;
} else {
//
AppLogger.warn('⚠️ 数据包长度异常: 实际${data.length}字节 > 预期$expectedTotalLength字节');
return data;
}
} else {
//
AppLogger.warn('⚠️ 包头信息不完整,无法解析包长度');
return data;
}
} else {
//
if (_pendingPackets.isNotEmpty) {
//
int packetSequence = _pendingPackets.keys.first;
List<int> pendingData = _pendingPackets[packetSequence]!;
//
pendingData.addAll(data);
_pendingPackets[packetSequence] = pendingData;
AppLogger.debug('📥 追加数据片段: 当前长度${pendingData.length}字节');
//
if (pendingData.length >= 12) {
//
int combinedLength = (pendingData[8] << 24) | (pendingData[9] << 16) | (pendingData[10] << 8) | pendingData[11];
int encryptedDataLength = (combinedLength >> 16) & 0xFFFF;
int originalDataLength = combinedLength & 0xFFFF;
//
int encryptType = pendingData[7] & 0x0F;
int actualDataLength = (encryptType == BaseBleCommand.ENCRYPT_TYPE_PLAIN) ? originalDataLength : encryptedDataLength;
//
int expectedTotalLength = 12 + actualDataLength + 2; // (12) + + CRC(2)
if (pendingData.length == expectedTotalLength) {
//
AppLogger.debug('✅ 数据包重组完成: 序号=$packetSequence, 长度=$expectedTotalLength字节');
List<int> completePacket = _pendingPackets.remove(packetSequence)!;
return completePacket;
} else if (pendingData.length > expectedTotalLength) {
//
AppLogger.warn('⚠️ 重组后数据包长度异常: 实际${pendingData.length}字节 > 预期$expectedTotalLength字节');
_pendingPackets.clear();
return pendingData;
}
//
}
//
return null;
} else {
//
AppLogger.warn('⚠️ 收到无法关联的数据片段');
return data;
}
}
} catch (e, stackTrace) {
AppLogger.error('❌ 数据包重组异常', error: e, stackTrace: stackTrace);
_pendingPackets.clear(); //
return data; //
}
}
///
void _triggerCommandResponseWaiters(dynamic response) {
//

View File

@ -6,6 +6,7 @@ import 'package:starwork_flutter/ble/command/base/base_ble_command.dart';
import 'package:starwork_flutter/ble/command/base/base_ble_response_parser.dart';
import 'package:starwork_flutter/ble/command/response/ble_cmd_get_private_key_parser.dart';
import 'package:starwork_flutter/ble/command/response/ble_cmd_get_public_key_parser.dart';
import 'package:starwork_flutter/ble/command/response/ble_cmd_read_lock_status_parser.dart';
import 'package:starwork_flutter/common/constant/cache_keys.dart';
import 'package:starwork_flutter/common/sm4_encipher/sm4.dart';
import 'package:starwork_flutter/common/utils/shared_preferences_utils.dart';
@ -48,6 +49,7 @@ class BleCommandManager {
//
registerParser(BleCmdGetPublicKeyParser());
registerParser(BleCmdGetPrivateKeyParser());
registerParser(BleCmdReadLockStatusParser());
// TODO:
// registerParser(BleCmdSetPasswordParser());
@ -72,7 +74,7 @@ class BleCommandManager {
///
/// [rawPacketData]
/// null
dynamic handleResponse(List<int> rawPacketData) async {
dynamic handleResponse(List<int> rawPacketData) {
AppLogger.debug('📊 收到蓝牙数据 (${rawPacketData.length}字节): ${rawPacketData.map((b) => '0x${b.toRadixString(16).padLeft(2, '0')}').join(' ')}');
try {
@ -92,7 +94,7 @@ class BleCommandManager {
}
//
List<int> processedData = await _decryptDataIfNeeded(parsedPacket);
List<int> processedData = _decryptDataIfNeededSync(parsedPacket);
// ID ()
int commandId = (processedData[0] << 8) | processedData[1];
@ -132,6 +134,51 @@ class BleCommandManager {
}
}
///
/// [parsedPacket]
///
List<int> _decryptDataIfNeededSync(ParsedPacket parsedPacket) {
//
if (parsedPacket.encryptType == BaseBleCommand.ENCRYPT_TYPE_PLAIN) {
AppLogger.debug('🔓 数据未加密,直接使用原始数据');
return parsedPacket.data;
}
switch (parsedPacket.encryptType) {
case BaseBleCommand.ENCRYPT_TYPE_AES128:
return parsedPacket.data;
case BaseBleCommand.ENCRYPT_TYPE_SM4_PRESET:
var connectedDevice = BleService().connectedDevice;
var platformName = connectedDevice?.platformName ?? '';
if (platformName.isEmpty) {
AppLogger.warn('⚠️ 解密数据时未找到设备名称');
return parsedPacket.data;
}
var decrypt = SM4.decrypt(
parsedPacket.data,
key: utf8.encode(platformName),
mode: SM4CryptoMode.ECB,
);
return decrypt;
case BaseBleCommand.ENCRYPT_TYPE_SM4_DEVICE:
// 使
var cachedPrivateKey = BleService.cachedPrivateKey;
if (cachedPrivateKey == null || cachedPrivateKey.isEmpty) {
AppLogger.warn('⚠️ 解密数据时未找到缓存的私钥');
return parsedPacket.data;
}
var decrypt = SM4.decrypt(
parsedPacket.data,
key: cachedPrivateKey,
mode: SM4CryptoMode.ECB,
);
return decrypt;
default:
AppLogger.warn('⚠️ 未知的加密类型: ${parsedPacket.encryptType},使用原始数据');
return parsedPacket.data;
}
}
///
/// [parsedPacket]
///

View File

@ -2,6 +2,7 @@ import 'package:starwork_flutter/base/app_logger.dart';
import 'package:starwork_flutter/ble/command/base/base_ble_command.dart';
import 'package:starwork_flutter/ble/command/base/base_ble_response_parser.dart';
import 'package:starwork_flutter/ble/command/request/ble_cmd_get_public_key.dart';
import 'package:starwork_flutter/ble/command/request/ble_cmd_read_lock_status.dart';
///
class ReadLockStatusResponse {
@ -94,7 +95,7 @@ class ReadLockStatusResponse {
///
class BleCmdReadLockStatusParser extends BaseBleResponseParser {
@override
int get commandId => BleCmdGetPublicKey.cmdId; // 0x3090
int get commandId => BleCmdReadLockStatus.cmdId;
@override
String get commandName => '读取锁状态命令';

View File

@ -207,6 +207,9 @@ class SearchDeviceController extends BaseController {
await SharedPreferencesUtils.saveIntList(CacheKeys.lockCommKey, privateKeyResponse.commKey);
await SharedPreferencesUtils.saveIntList(CacheKeys.lockSignKey, privateKeyResponse.signKey);
AppLogger.info('🎯 获取私钥成功: ${privateKeyResponse.toString()}');
// 便使
BleService.setCachedPrivateKey(privateKeyResponse.commKey);
//
BleCmdReadLockStatus readLockStatusCmd = BleCmdReadLockStatus(