You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
249 lines
7.8 KiB
249 lines
7.8 KiB
import 'dart:async';
|
|
import 'dart:math' as math;
|
|
import 'package:get/get.dart';
|
|
import 'package:classic_bluetooth/classic_bluetooth.dart';
|
|
import 'package:deep_voice/core/utils/logger.dart';
|
|
import 'package:flutter/services.dart';
|
|
|
|
/// 蓝牙设备信息缓存模型
|
|
class DeviceInfo {
|
|
final String address;
|
|
final String name;
|
|
|
|
// 整体电池电量
|
|
final int batteryLevel;
|
|
|
|
// 详细电池信息
|
|
final int leftEarBattery;
|
|
final int rightEarBattery;
|
|
final int caseBattery;
|
|
|
|
// 充电状态
|
|
final bool leftEarCharging;
|
|
final bool rightEarCharging;
|
|
final bool caseCharging;
|
|
|
|
final String firmwareVersion;
|
|
final String productId;
|
|
final String colorId;
|
|
final DateTime lastUpdated;
|
|
|
|
DeviceInfo({
|
|
required this.address,
|
|
required this.name,
|
|
this.batteryLevel = 0,
|
|
this.leftEarBattery = 0,
|
|
this.rightEarBattery = 0,
|
|
this.caseBattery = 0,
|
|
this.leftEarCharging = false,
|
|
this.rightEarCharging = false,
|
|
this.caseCharging = false,
|
|
this.firmwareVersion = '',
|
|
this.productId = '',
|
|
this.colorId = '',
|
|
DateTime? lastUpdated,
|
|
}) : lastUpdated = lastUpdated ?? DateTime.now();
|
|
|
|
/// 创建更新后的设备信息副本
|
|
DeviceInfo copyWith({
|
|
String? address,
|
|
String? name,
|
|
int? batteryLevel,
|
|
int? leftEarBattery,
|
|
int? rightEarBattery,
|
|
int? caseBattery,
|
|
bool? leftEarCharging,
|
|
bool? rightEarCharging,
|
|
bool? caseCharging,
|
|
String? firmwareVersion,
|
|
String? productId,
|
|
String? colorId,
|
|
}) {
|
|
return DeviceInfo(
|
|
address: address ?? this.address,
|
|
name: name ?? this.name,
|
|
batteryLevel: batteryLevel ?? this.batteryLevel,
|
|
leftEarBattery: leftEarBattery ?? this.leftEarBattery,
|
|
rightEarBattery: rightEarBattery ?? this.rightEarBattery,
|
|
caseBattery: caseBattery ?? this.caseBattery,
|
|
leftEarCharging: leftEarCharging ?? this.leftEarCharging,
|
|
rightEarCharging: rightEarCharging ?? this.rightEarCharging,
|
|
caseCharging: caseCharging ?? this.caseCharging,
|
|
firmwareVersion: firmwareVersion ?? this.firmwareVersion,
|
|
productId: productId ?? this.productId,
|
|
colorId: colorId ?? this.colorId,
|
|
lastUpdated: DateTime.now(),
|
|
);
|
|
}
|
|
|
|
@override
|
|
String toString() {
|
|
return 'DeviceInfo(address: $address, name: $name, '
|
|
'battery: $batteryLevel%, L: $leftEarBattery%, R: $rightEarBattery%, Case: $caseBattery%, '
|
|
'charging: L:$leftEarCharging, R:$rightEarCharging, C:$caseCharging, '
|
|
'version: $firmwareVersion, productId: $productId, colorId: $colorId)';
|
|
}
|
|
}
|
|
|
|
/// 蓝牙服务 - 管理经典蓝牙服务,提供设备信息缓存
|
|
class BluetoothService extends GetxService {
|
|
static BluetoothService get to => Get.find<BluetoothService>();
|
|
|
|
// 蓝牙状态
|
|
final _bluetoothState = 'unknown'.obs;
|
|
String get bluetoothState => _bluetoothState.value;
|
|
|
|
// 当前经典蓝牙设备
|
|
final Rx<BluetoothDevice?> currentDeviceRx = Rx<BluetoothDevice?>(null);
|
|
BluetoothDevice? get currentDevice => currentDeviceRx.value;
|
|
|
|
// 设备信息缓存
|
|
final Rx<DeviceInfo?> _deviceInfo = Rx<DeviceInfo?>(null);
|
|
DeviceInfo? get deviceInfo => _deviceInfo.value;
|
|
|
|
// 表明当前连接类型,本服务只处理经典蓝牙
|
|
bool get isBleConnection => false;
|
|
|
|
// 订阅
|
|
StreamSubscription<BluetoothEvent>? _bluetoothSubscription;
|
|
|
|
/// 初始化
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
Logger.info('蓝牙服务初始化');
|
|
|
|
// 设置蓝牙事件监听
|
|
_setupBluetoothListener();
|
|
}
|
|
|
|
/// 释放资源
|
|
@override
|
|
void onClose() {
|
|
_bluetoothSubscription?.cancel();
|
|
super.onClose();
|
|
}
|
|
|
|
/// 设置经典蓝牙事件监听
|
|
void _setupBluetoothListener() {
|
|
_bluetoothSubscription?.cancel();
|
|
|
|
try {
|
|
_bluetoothSubscription = ClassicBluetooth.events.listen(
|
|
(event) {
|
|
if (event.type == 'stateChanged' && event.state != null) {
|
|
_bluetoothState.value = event.state!;
|
|
Logger.info('蓝牙状态变更: ${event.state}');
|
|
|
|
// 如果蓝牙关闭,清除设备
|
|
if (event.state == 'off') {
|
|
currentDeviceRx.value = null;
|
|
_deviceInfo.value = null;
|
|
}
|
|
} else if (event.type == 'deviceConnected' && event.device != null) {
|
|
// 直接从事件中获取设备信息
|
|
final newDevice = event.device!;
|
|
|
|
// 更新当前设备
|
|
currentDeviceRx.value = newDevice;
|
|
|
|
Logger.info('经典蓝牙设备已连接: ${newDevice.name} (${newDevice.address})');
|
|
|
|
// 创建基本设备信息
|
|
if (_deviceInfo.value == null || _deviceInfo.value!.address != newDevice.address) {
|
|
_deviceInfo.value = DeviceInfo(
|
|
address: newDevice.address,
|
|
name: newDevice.name,
|
|
);
|
|
Logger.info('创建设备信息缓存: ${_deviceInfo.value}');
|
|
}
|
|
} else if (event.type == 'deviceDisconnected' && event.device != null) {
|
|
// 直接从事件中获取设备信息
|
|
final disconnectedDevice = event.device!;
|
|
|
|
Logger.info('经典蓝牙设备已断开: ${disconnectedDevice.name} (${disconnectedDevice.address})');
|
|
|
|
// 如果断开的是当前设备,清除当前设备
|
|
if (currentDeviceRx.value?.address == disconnectedDevice.address) {
|
|
currentDeviceRx.value = null;
|
|
// 不清除设备信息缓存,保留最后状态
|
|
Logger.info('已清除当前设备引用,保留最后设备信息缓存');
|
|
}
|
|
}
|
|
},
|
|
onError: (error) {
|
|
Logger.error('蓝牙事件流错误: $error');
|
|
},
|
|
);
|
|
} catch (e) {
|
|
Logger.error('设置蓝牙事件监听器失败: $e');
|
|
}
|
|
}
|
|
|
|
/// 刷新设备连接状态
|
|
Future<void> refreshDeviceConnection() async {
|
|
try {
|
|
// 检查经典蓝牙连接
|
|
final devices = await ClassicBluetooth.getConnectedDevices();
|
|
|
|
if (devices.isNotEmpty) {
|
|
final newDevice = devices.first;
|
|
|
|
// 更新当前设备
|
|
currentDeviceRx.value = newDevice;
|
|
|
|
Logger.info('已连接经典蓝牙设备: ${newDevice.name} (${newDevice.address})');
|
|
|
|
// 创建基本设备信息
|
|
if (_deviceInfo.value == null || _deviceInfo.value!.address != newDevice.address) {
|
|
_deviceInfo.value = DeviceInfo(
|
|
address: newDevice.address,
|
|
name: newDevice.name,
|
|
);
|
|
Logger.info('创建设备信息缓存: ${_deviceInfo.value}');
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// 没有任何连接
|
|
currentDeviceRx.value = null;
|
|
Logger.info('未找到已连接的蓝牙设备');
|
|
|
|
} catch (e) {
|
|
Logger.error('刷新设备连接失败: $e');
|
|
}
|
|
}
|
|
|
|
/// 检查蓝牙是否已启用
|
|
Future<bool> isBluetoothEnabled() async {
|
|
try {
|
|
final isEnabled = await ClassicBluetooth.isBluetoothEnabled();
|
|
_bluetoothState.value = isEnabled ? 'on' : 'off';
|
|
return isEnabled;
|
|
} catch (e) {
|
|
Logger.error('检查蓝牙状态失败: $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// 启动BLE服务(不适用于此服务,仅为接口兼容)
|
|
Future<bool> startBleService(Map<String, dynamic> config) async {
|
|
Logger.warning('BluetoothService不支持BLE服务,请使用BleService');
|
|
return false;
|
|
}
|
|
|
|
/// 停止BLE服务(不适用于此服务,仅为接口兼容)
|
|
Future<bool> stopBleService() async {
|
|
Logger.warning('BluetoothService不支持BLE服务,请使用BleService');
|
|
return false;
|
|
}
|
|
|
|
/// 注册服务
|
|
static Future<BluetoothService> init() async {
|
|
if (!Get.isRegistered<BluetoothService>()) {
|
|
Get.put(BluetoothService(), permanent: true);
|
|
}
|
|
return Future.value(Get.find<BluetoothService>());
|
|
}
|
|
}
|