225 lines
8.3 KiB
Dart
225 lines
8.3 KiB
Dart
import 'dart:convert';
|
||
|
||
import 'package:starwork_flutter/base/app_logger.dart';
|
||
import 'package:starwork_flutter/ble/ble_service.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/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/common/sm4_encipher/sm4.dart';
|
||
|
||
/// ✨✨✨ 蓝牙命令管理器 - 统一管理所有命令解析器 ✨✨✨
|
||
class BleCommandManager {
|
||
// 私有构造函数
|
||
BleCommandManager._() {
|
||
// ✅ 这里就是单例初始化的地方
|
||
// 只会执行一次(第一次获取实例时)
|
||
_initialize();
|
||
}
|
||
|
||
// 单例实例
|
||
static final BleCommandManager _instance = BleCommandManager._();
|
||
|
||
// 工厂构造函数,提供全局访问点
|
||
factory BleCommandManager() => _instance;
|
||
|
||
/// 所有已注册的命令解析器
|
||
final Map<int, BaseBleResponseParser> _parsers = {};
|
||
|
||
/// ✨✨✨ 初始化命令管理器 ✨✨✨
|
||
void _initialize() {
|
||
AppLogger.highlight('✨✨✨ 🚀 初始化蓝牙命令管理器 ✨✨✨');
|
||
|
||
// 注册所有命令解析器
|
||
_registerParsers();
|
||
|
||
AppLogger.info('📋 已注册命令解析器数量: ${_parsers.length}');
|
||
_parsers.forEach((commandId, parser) {
|
||
AppLogger.debug(' • 0x${commandId.toRadixString(16).padLeft(4, '0')}: ${parser.commandName}');
|
||
});
|
||
|
||
AppLogger.highlight('✨✨✨ ✅ 蓝牙命令管理器初始化完成 ✨✨✨');
|
||
}
|
||
|
||
/// ✨✨✨ 注册所有命令解析器 ✨✨✨
|
||
void _registerParsers() {
|
||
// 注册获取公钥命令解析器
|
||
registerParser(BleCmdGetPublicKeyParser());
|
||
registerParser(BleCmdGetPrivateKeyParser());
|
||
|
||
// TODO: 在这里注册其他命令解析器
|
||
// registerParser(BleCmdSetPasswordParser());
|
||
// registerParser(BleCmdUnlockParser());
|
||
// 等等...
|
||
}
|
||
|
||
/// ✨✨✨ 注册命令解析器 ✨✨✨
|
||
void registerParser(BaseBleResponseParser parser) {
|
||
_parsers[parser.commandId] = parser;
|
||
AppLogger.debug('📝 注册命令解析器: 0x${parser.commandId.toRadixString(16).padLeft(4, '0')} - ${parser.commandName}');
|
||
}
|
||
|
||
/// ✨✨✨ 移除命令解析器 ✨✨✨
|
||
void unregisterParser(int commandId) {
|
||
BaseBleResponseParser? removed = _parsers.remove(commandId);
|
||
if (removed != null) {
|
||
AppLogger.debug('🗑️ 移除命令解析器: 0x${commandId.toRadixString(16).padLeft(4, '0')} - ${removed.commandName}');
|
||
}
|
||
}
|
||
|
||
/// ✨✨✨ 处理接收到的应答数据包 ✨✨✨
|
||
/// [rawPacketData] 完整的原始数据包
|
||
/// 返回解析后的业务数据,如果没有匹配的解析器则返回null
|
||
dynamic handleResponse(List<int> rawPacketData) {
|
||
AppLogger.debug('📊 收到蓝牙数据 (${rawPacketData.length}字节): ${rawPacketData.map((b) => '0x${b.toRadixString(16).padLeft(2, '0')}').join(' ')}');
|
||
|
||
try {
|
||
// ✨✨✨ 首先解析数据包以获取命令ID ✨✨✨
|
||
var parsedPacket = BaseBleCommand.parsePacket(rawPacketData);
|
||
|
||
// 检查数据包是否有效
|
||
if (!parsedPacket.isValid) {
|
||
AppLogger.warn('⚠️ 数据包无效: ${parsedPacket.errorMessage}');
|
||
return null;
|
||
}
|
||
|
||
// 检查数据长度是否足够包含命令ID
|
||
if (parsedPacket.data.length < 2) {
|
||
AppLogger.warn('⚠️ 应答数据长度不足,无法包含命令ID: ${parsedPacket.data.length}字节');
|
||
return null;
|
||
}
|
||
|
||
// ✨✨✨ 根据加密类型进行解密处理 ✨✨✨
|
||
List<int> processedData = _decryptDataIfNeeded(parsedPacket);
|
||
|
||
// ✨✨✨ 提取命令ID (大端序) ✨✨✨
|
||
int commandId = (processedData[0] << 8) | processedData[1];
|
||
AppLogger.debug('🔍 提取命令ID: 0x${commandId.toRadixString(16).padLeft(4, '0')}');
|
||
|
||
// ✨✨✨ 直接通过命令ID查找对应的解析器 ✨✨✨
|
||
BaseBleResponseParser? parser = _parsers[commandId];
|
||
if (parser != null) {
|
||
AppLogger.debug('🎯 找到匹配的解析器: ${parser.commandName}');
|
||
|
||
// 创建一个新的ParsedPacket对象,使用解密后的数据
|
||
ParsedPacket decryptedPacket = ParsedPacket(
|
||
isValid: parsedPacket.isValid,
|
||
packetType: parsedPacket.packetType,
|
||
packetSequence: parsedPacket.packetSequence,
|
||
version: parsedPacket.version,
|
||
encryptType: parsedPacket.encryptType,
|
||
encryptedDataLength: parsedPacket.encryptedDataLength,
|
||
originalDataLength: parsedPacket.originalDataLength,
|
||
data: processedData,
|
||
crc16: parsedPacket.crc16,
|
||
errorMessage: parsedPacket.errorMessage,
|
||
);
|
||
|
||
// 传递解密后的数据给解析器
|
||
dynamic result = parser.parseResponse(decryptedPacket, processedData);
|
||
return result;
|
||
} else {
|
||
// 没有找到匹配的解析器
|
||
AppLogger.warn('⚠️ 未找到命令ID 0x${commandId.toRadixString(16).padLeft(4, '0')} 对应的解析器');
|
||
_logUnknownPacket(rawPacketData);
|
||
return null;
|
||
}
|
||
} catch (e, stackTrace) {
|
||
AppLogger.error('❌ 处理蓝牙应答异常', error: e, stackTrace: stackTrace);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/// ✨✨✨ 根据加密类型解密数据 ✨✨✨
|
||
/// [parsedPacket] 已解析的数据包
|
||
/// 返回解密后的数据或原始数据(如果不需要解密)
|
||
List<int> _decryptDataIfNeeded(ParsedPacket parsedPacket) {
|
||
// 如果是明文,直接返回原始数据
|
||
if (parsedPacket.encryptType == BaseBleCommand.ENCRYPT_TYPE_PLAIN) {
|
||
AppLogger.debug('🔓 数据未加密,直接使用原始数据');
|
||
return parsedPacket.data;
|
||
}
|
||
|
||
switch (parsedPacket.encryptType) {
|
||
case BaseBleCommand.ENCRYPT_TYPE_AES128:
|
||
return _decryptAES128(parsedPacket.data);
|
||
|
||
case BaseBleCommand.ENCRYPT_TYPE_SM4_PRESET:
|
||
var decrypt = SM4.decrypt(
|
||
parsedPacket.data,
|
||
key: utf8.encode('TMH_190068d76ae8'),
|
||
mode: SM4CryptoMode.ECB,
|
||
);
|
||
return decrypt;
|
||
case BaseBleCommand.ENCRYPT_TYPE_SM4_DEVICE:
|
||
return _decryptSM4(parsedPacket.data);
|
||
default:
|
||
AppLogger.warn('⚠️ 未知的加密类型: ${parsedPacket.encryptType},使用原始数据');
|
||
return parsedPacket.data;
|
||
}
|
||
}
|
||
|
||
/// ✨✨✨ AES128解密 ✨✨✨
|
||
/// [encryptedData] 加密数据
|
||
/// 返回解密后的数据
|
||
List<int> _decryptAES128(List<int> encryptedData) {
|
||
// TODO: 实现AES128解密逻辑
|
||
|
||
return encryptedData;
|
||
}
|
||
|
||
/// ✨✨✨ SM4解密 ✨✨✨
|
||
/// [encryptedData] 加密数据
|
||
/// 返回解密后的数据
|
||
List<int> _decryptSM4(List<int> encryptedData) {
|
||
return encryptedData;
|
||
}
|
||
|
||
/// ✨✨✨ 根据命令ID获取解析器 ✨✨✨
|
||
BaseBleResponseParser? getParser(int commandId) {
|
||
return _parsers[commandId];
|
||
}
|
||
|
||
/// ✨✨✨ 获取所有已注册的命令ID ✨✨✨
|
||
List<int> getRegisteredCommandIds() {
|
||
return _parsers.keys.toList();
|
||
}
|
||
|
||
/// ✨✨✨ 获取所有已注册的解析器信息 ✨✨✨
|
||
Map<int, String> getRegisteredParsersInfo() {
|
||
return _parsers.map((commandId, parser) => MapEntry(commandId, parser.commandName));
|
||
}
|
||
|
||
/// ✨✨✨ 记录未知数据包信息 ✨✨✨
|
||
void _logUnknownPacket(List<int> rawPacketData) {
|
||
try {
|
||
// 尝试基本解析以获取更多信息
|
||
var parsedPacket = BaseBleCommand.parsePacket(rawPacketData);
|
||
|
||
if (parsedPacket.isValid && parsedPacket.data.length >= 2) {
|
||
int commandId = (parsedPacket.data[0] << 8) | parsedPacket.data[1];
|
||
AppLogger.warn('🔍 未知命令应答: 命令ID=0x${commandId.toRadixString(16).padLeft(4, '0')}, ' +
|
||
'包类型=0x${parsedPacket.packetType.toRadixString(16).padLeft(2, '0')}, ' +
|
||
'数据长度=${parsedPacket.data.length}字节');
|
||
} else {
|
||
AppLogger.warn('🔍 无效或无法识别的数据包');
|
||
}
|
||
} catch (e) {
|
||
AppLogger.warn('🔍 无法解析的数据包: $e');
|
||
}
|
||
}
|
||
|
||
/// ✨✨✨ 清除所有解析器 ✨✨✨
|
||
void clear() {
|
||
AppLogger.info('🧹 清除所有命令解析器');
|
||
_parsers.clear();
|
||
}
|
||
|
||
/// ✨✨✨ 重新初始化 ✨✨✨
|
||
void reinitialize() {
|
||
AppLogger.info('🔄 重新初始化命令管理器');
|
||
clear();
|
||
_initialize();
|
||
}
|
||
}
|