|
|
|
@ -9,13 +9,15 @@ import 'package:deep_voice/data/models/appconfig_model.dart'; |
|
|
|
import 'dart:convert'; |
|
|
|
import 'package:flutter/services.dart' show rootBundle; |
|
|
|
import 'package:agent_service/agent_service.dart'; |
|
|
|
import 'package:classic_bluetooth/classic_bluetooth.dart'; |
|
|
|
|
|
|
|
/// 命令类型常量(与原生层保持一致) |
|
|
|
class BleCommands { |
|
|
|
static const int GET_VERSION = 0x01; |
|
|
|
static const int GET_BATTERY_INFO = 0x02; |
|
|
|
static const int CONTROL_CODEC = 0x03; |
|
|
|
static const int PLAY_A2DP = 0x04; |
|
|
|
static const int GET_PRODUCT_ID = 0x02; |
|
|
|
static const int GET_PRODUCT_COLOR = 0x03; |
|
|
|
static const int GET_BATTERY_INFO = 0x04; |
|
|
|
static const int CONTROL_CODEC = 0x05; |
|
|
|
} |
|
|
|
|
|
|
|
/// 蓝牙设备信息缓存模型 |
|
|
|
@ -37,6 +39,8 @@ class DeviceInfo { |
|
|
|
final bool caseCharging; |
|
|
|
|
|
|
|
final String firmwareVersion; |
|
|
|
final String firmwareProductId; |
|
|
|
final String firmwareProductColor; |
|
|
|
final DateTime lastUpdated; |
|
|
|
|
|
|
|
DeviceInfo({ |
|
|
|
@ -50,6 +54,8 @@ class DeviceInfo { |
|
|
|
this.rightEarCharging = false, |
|
|
|
this.caseCharging = false, |
|
|
|
this.firmwareVersion = '', |
|
|
|
this.firmwareProductId = '', |
|
|
|
this.firmwareProductColor = '', |
|
|
|
DateTime? lastUpdated, |
|
|
|
}) : lastUpdated = lastUpdated ?? DateTime.now(); |
|
|
|
|
|
|
|
@ -65,6 +71,8 @@ class DeviceInfo { |
|
|
|
bool? rightEarCharging, |
|
|
|
bool? caseCharging, |
|
|
|
String? firmwareVersion, |
|
|
|
String? firmwareProductId, |
|
|
|
String? firmwareProductColor, |
|
|
|
}) { |
|
|
|
return DeviceInfo( |
|
|
|
address: address ?? this.address, |
|
|
|
@ -77,6 +85,8 @@ class DeviceInfo { |
|
|
|
rightEarCharging: rightEarCharging ?? this.rightEarCharging, |
|
|
|
caseCharging: caseCharging ?? this.caseCharging, |
|
|
|
firmwareVersion: firmwareVersion ?? this.firmwareVersion, |
|
|
|
firmwareProductId: firmwareProductId ?? this.firmwareProductId, |
|
|
|
firmwareProductColor: firmwareProductColor ?? this.firmwareProductColor, |
|
|
|
lastUpdated: DateTime.now(), |
|
|
|
); |
|
|
|
} |
|
|
|
@ -96,6 +106,7 @@ class BleManager extends GetxService { |
|
|
|
|
|
|
|
// BLE服务实例 |
|
|
|
final BleService _bleService = BleService(); |
|
|
|
// 经典蓝牙实例 |
|
|
|
|
|
|
|
// BLE连接状态 |
|
|
|
final _connectionState = BleConnectionState.disconnected.obs; |
|
|
|
@ -106,8 +117,7 @@ class BleManager extends GetxService { |
|
|
|
bool get isConnected => _isConnected.value; |
|
|
|
|
|
|
|
// 设备信息缓存 |
|
|
|
final Rx<DeviceInfo?> _deviceInfo = Rx<DeviceInfo?>(null); |
|
|
|
DeviceInfo? get deviceInfo => _deviceInfo.value; |
|
|
|
final deviceInfo = Rx<DeviceInfo?>(null); // 使用 Rx 包装 |
|
|
|
|
|
|
|
// 订阅 |
|
|
|
StreamSubscription<dynamic>? _statusSubscription; |
|
|
|
@ -145,8 +155,8 @@ class BleManager extends GetxService { |
|
|
|
|
|
|
|
if (event is Map) { |
|
|
|
// 处理连接状态更新 |
|
|
|
if (event.containsKey('connectionState')) { |
|
|
|
final state = event['connectionState'] as int; |
|
|
|
if (event['type'] == 'connectionStateChanged') { |
|
|
|
final state = event['state'] as int; |
|
|
|
_connectionState.value = state; |
|
|
|
|
|
|
|
// 连接状态转换 |
|
|
|
@ -154,8 +164,13 @@ class BleManager extends GetxService { |
|
|
|
Logger.info('BLE设备已连接'); |
|
|
|
_isConnected.value = true; |
|
|
|
|
|
|
|
// 在连接成功后获取设备信息 |
|
|
|
_fetchDeviceInfo(); |
|
|
|
// 在连接成功后延迟 300 毫秒获取设备信息(可根据需要调整时间) |
|
|
|
Future.delayed(const Duration(milliseconds: 300), () { |
|
|
|
// 可选:检查是否仍处于连接状态 |
|
|
|
if (_isConnected.value) { |
|
|
|
fetchDeviceInfo(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} else if (state == BleConnectionState.disconnected || |
|
|
|
state == BleConnectionState.error) { |
|
|
|
Logger.info('BLE设备已断开或发生错误'); |
|
|
|
@ -218,12 +233,18 @@ class BleManager extends GetxService { |
|
|
|
void _processDeviceInfoByCommandId( |
|
|
|
int commandId, Map<dynamic, dynamic> data) { |
|
|
|
switch (commandId) { |
|
|
|
case BleCommands.GET_BATTERY_INFO: |
|
|
|
_updateBatteryInfoFromData(data); |
|
|
|
break; |
|
|
|
case BleCommands.GET_VERSION: |
|
|
|
_updateVersionInfoFromData(data); |
|
|
|
break; |
|
|
|
case BleCommands.GET_PRODUCT_ID: |
|
|
|
_updateProductIdFromData(data); |
|
|
|
break; |
|
|
|
case BleCommands.GET_PRODUCT_COLOR: |
|
|
|
break; |
|
|
|
case BleCommands.GET_BATTERY_INFO: |
|
|
|
_updateBatteryInfoFromData(data); |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
Logger.info('未处理的命令ID: $commandId'); |
|
|
|
} |
|
|
|
@ -239,6 +260,11 @@ class BleManager extends GetxService { |
|
|
|
case 'versionInfo': |
|
|
|
_updateVersionInfoFromData(data); |
|
|
|
break; |
|
|
|
case 'productId': |
|
|
|
_updateProductIdFromData(data); |
|
|
|
break; |
|
|
|
case 'productColor': |
|
|
|
break; |
|
|
|
default: |
|
|
|
Logger.info('未处理的命令名称: $commandName'); |
|
|
|
} |
|
|
|
@ -307,6 +333,29 @@ class BleManager extends GetxService { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 更新设备id |
|
|
|
void _updateProductIdFromData(Map<dynamic, dynamic> data) { |
|
|
|
try { |
|
|
|
// 确保数据中包含版本信息 |
|
|
|
if (!data.containsKey('productId')) { |
|
|
|
Logger.warning('版本信息数据不完整'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 提取版本信息 |
|
|
|
final String productId = data['productId'] as String? ?? ''; |
|
|
|
|
|
|
|
// 更新设备信息 |
|
|
|
_updateDeviceInfoIfNeeded( |
|
|
|
firmwareProductId: productId, |
|
|
|
); |
|
|
|
|
|
|
|
Logger.info('设备设备id已更新: 设备id=$productId'); |
|
|
|
} catch (e) { |
|
|
|
Logger.error('更新设备id失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 更新设备信息(如果已存在设备) |
|
|
|
void _updateDeviceInfoIfNeeded({ |
|
|
|
int? batteryLevel, |
|
|
|
@ -317,31 +366,53 @@ class BleManager extends GetxService { |
|
|
|
bool? rightEarCharging, |
|
|
|
bool? caseCharging, |
|
|
|
String? firmwareVersion, |
|
|
|
String? firmwareProductId, |
|
|
|
String? firmwareProductColor, |
|
|
|
}) { |
|
|
|
// 如果设备信息已存在,则更新 |
|
|
|
if (_deviceInfo.value != null) { |
|
|
|
_deviceInfo.value = _deviceInfo.value!.copyWith( |
|
|
|
batteryLevel: batteryLevel, |
|
|
|
leftEarBattery: leftEarBattery, |
|
|
|
rightEarBattery: rightEarBattery, |
|
|
|
caseBattery: caseBattery, |
|
|
|
leftEarCharging: leftEarCharging, |
|
|
|
rightEarCharging: rightEarCharging, |
|
|
|
caseCharging: caseCharging, |
|
|
|
firmwareVersion: firmwareVersion, |
|
|
|
if (deviceInfo.value != null) { |
|
|
|
deviceInfo.value = deviceInfo.value!.copyWith( |
|
|
|
batteryLevel: batteryLevel ?? deviceInfo.value?.batteryLevel, |
|
|
|
leftEarBattery: leftEarBattery ?? deviceInfo.value?.leftEarBattery, |
|
|
|
rightEarBattery: rightEarBattery ?? deviceInfo.value?.rightEarBattery, |
|
|
|
caseBattery: caseBattery ?? deviceInfo.value?.caseBattery, |
|
|
|
leftEarCharging: leftEarCharging ?? deviceInfo.value!.leftEarCharging, |
|
|
|
rightEarCharging: |
|
|
|
rightEarCharging ?? deviceInfo.value!.rightEarCharging, |
|
|
|
caseCharging: caseCharging ?? deviceInfo.value!.caseCharging, |
|
|
|
firmwareVersion: firmwareVersion ?? deviceInfo.value!.firmwareVersion, |
|
|
|
firmwareProductId: |
|
|
|
firmwareProductId ?? deviceInfo.value!.firmwareProductId, |
|
|
|
firmwareProductColor: |
|
|
|
firmwareProductColor ?? deviceInfo.value!.firmwareProductColor, |
|
|
|
); |
|
|
|
} |
|
|
|
// 创建设备信息 |
|
|
|
// 如果设备信息不存在,但有地址和名称,则创建新的设备信息 |
|
|
|
else if (_deviceInfo.value == null && |
|
|
|
else if (deviceInfo.value == null && |
|
|
|
_isConnected.value && |
|
|
|
(firmwareVersion != null || batteryLevel != null)) { |
|
|
|
// 提示尝试创建设备信息但缺少必要信息 |
|
|
|
Logger.warning('尝试更新设备信息,但设备基本信息不存在'); |
|
|
|
deviceInfo.value = DeviceInfo( |
|
|
|
address: "", // 应确保从连接信息中获取真实值 |
|
|
|
name: "", |
|
|
|
batteryLevel: batteryLevel ?? 0, |
|
|
|
leftEarBattery: leftEarBattery ?? 0, |
|
|
|
rightEarBattery: rightEarBattery ?? 0, |
|
|
|
caseBattery: caseBattery ?? 0, |
|
|
|
leftEarCharging: leftEarCharging ?? false, |
|
|
|
rightEarCharging: rightEarCharging ?? false, |
|
|
|
caseCharging: caseCharging ?? false, |
|
|
|
firmwareVersion: firmwareVersion ?? '', |
|
|
|
firmwareProductId: firmwareProductId ?? '', |
|
|
|
firmwareProductColor: firmwareProductColor ?? '', |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 连接成功后获取设备信息 |
|
|
|
Future<void> _fetchDeviceInfo() async { |
|
|
|
Future<void> fetchDeviceInfo() async { |
|
|
|
Logger.info('开始获取BLE设备详细信息'); |
|
|
|
|
|
|
|
try { |
|
|
|
@ -360,6 +431,14 @@ class BleManager extends GetxService { |
|
|
|
} else { |
|
|
|
Logger.warning('版本信息获取指令发送失败'); |
|
|
|
} |
|
|
|
|
|
|
|
// 获取产品id |
|
|
|
final productIdResult = await _bleService.getProductId(); |
|
|
|
if (productIdResult) { |
|
|
|
Logger.info('产品id获取指令已发送'); |
|
|
|
} else { |
|
|
|
Logger.warning('产品id获取指令发送失败'); |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
Logger.error('获取BLE设备信息失败: $e'); |
|
|
|
} |
|
|
|
@ -450,9 +529,9 @@ class BleManager extends GetxService { |
|
|
|
_connectionState.value = BleConnectionState.connected; |
|
|
|
|
|
|
|
// 如果设备信息存在,则获取详细信息 |
|
|
|
if (_deviceInfo.value != null) { |
|
|
|
if (deviceInfo.value != null) { |
|
|
|
// 获取详细设备信息 |
|
|
|
_fetchDeviceInfo(); |
|
|
|
fetchDeviceInfo(); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
@ -486,7 +565,6 @@ class BleManager extends GetxService { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 获取电池电量 |
|
|
|
Future<int> getBatteryLevel() async { |
|
|
|
try { |
|
|
|
@ -507,6 +585,16 @@ class BleManager extends GetxService { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 主动产品id |
|
|
|
Future<bool> getProductId() async { |
|
|
|
try { |
|
|
|
return await _bleService.getProductId(); |
|
|
|
} catch (e) { |
|
|
|
Logger.error('获取设备版本失败: $e'); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 主动获取设备版本信息 |
|
|
|
Future<bool> fetchDeviceVersion() async { |
|
|
|
try { |
|
|
|
|