Browse Source

add

newdev_shunjiawei
wolfplus 1 year ago
parent
commit
102fb4e4b4
  1. 125
      lib/modules/home/controllers/home_controller.dart
  2. 81
      lib/modules/pairing/controllers/pairing_controller.dart
  3. 8
      lib/modules/pairing/views/pairing_view.dart
  4. 5
      lib/modules/pairing/views/pairing_view_new.dart

125
lib/modules/home/controllers/home_controller.dart

@ -22,6 +22,10 @@ class HomeController extends GetxController {
// 连接状态相关 // 连接状态相关
final _isFullyConnected = false.obs; final _isFullyConnected = false.obs;
// 缓存最后连接的设备信息,用于断开后短暂显示
String? _lastConnectedDeviceName;
String? _lastConnectedDeviceAddress;
// Getter方法 // Getter方法
bool get isFullyConnected => _isFullyConnected.value; bool get isFullyConnected => _isFullyConnected.value;
RxBool get isFullyConnectedRx => _isFullyConnected; // 响应式getter供UI使用 RxBool get isFullyConnectedRx => _isFullyConnected; // 响应式getter供UI使用
@ -82,10 +86,8 @@ class HomeController extends GetxController {
// 设置监听器 // 设置监听器
_setupStateListeners(); _setupStateListeners();
// 延迟检查初始连接状态,确保监听器已经设置 // 立即检查初始连接状态
Future.delayed(const Duration(milliseconds: 100), () { _checkConnectionStatus();
_checkConnectionStatus();
});
} }
/// 设置状态监听器 /// 设置状态监听器
@ -102,29 +104,26 @@ class HomeController extends GetxController {
// 经典蓝牙连接监听 // 经典蓝牙连接监听
_classicBluetoothWorker = ever(_bluetoothManager.currentDeviceRx, (BluetoothDevice? device) { _classicBluetoothWorker = ever(_bluetoothManager.currentDeviceRx, (BluetoothDevice? device) {
Logger.d(_tag, '经典蓝牙: ${device != null ? "已连接" : "已断开"}'); Logger.d(_tag, '经典蓝牙: ${device != null ? "已连接" : "已断开"}');
// 保存设备信息用于断开后显示
if (device != null) {
_lastConnectedDeviceName = device.name;
_lastConnectedDeviceAddress = device.address;
}
// 立即检查状态,不使用延迟
_checkConnectionStatus(); _checkConnectionStatus();
// 额外的刷新确保UI更新
Future.delayed(const Duration(milliseconds: 50), () {
_isFullyConnected.refresh();
update();
});
}); });
// BLE连接监听 // BLE连接监听
_bleConnectionWorker = ever(_bleManager.connectionStateRx, (int state) { _bleConnectionWorker = ever(_bleManager.connectionStateRx, (int state) {
Logger.d(_tag, 'BLE状态变化: $state (${state == 2 ? "已连接" : "未连接"})'); Logger.d(_tag, 'BLE状态变化: $state (${state == 2 ? "已连接" : "未连接"})');
// 立即检查状态,不使用延迟
_checkConnectionStatus(); _checkConnectionStatus();
// 额外的刷新确保UI更新
Future.delayed(const Duration(milliseconds: 50), () {
_isFullyConnected.refresh();
update();
});
}); });
} }
/// 刷新设备连接状态 /// 刷新设备连接状态
Future<void> refreshDeviceConnection() async { Future<void> refreshDeviceConnection() async {
_checkConnectionStatus(); await _checkConnectionStatus();
} }
// 导航和功能方法 // 导航和功能方法
@ -147,47 +146,53 @@ class HomeController extends GetxController {
// UI辅助方法 // UI辅助方法
/// 检查连接状态 /// 检查连接状态
void _checkConnectionStatus() { Future<void> _checkConnectionStatus() async {
// 直接检查,不使用延迟 try {
bool hasClassicBluetooth = currentDevice != null; // 主动从原生层获取最新的BLE状态
bool hasBleConnection = _bleManager.connectionState == 2; // 直接检查状态值,2 = connected final currentBleState = await _bleManager.getConnectionState();
Logger.d(_tag, '连接状态检查: 经典蓝牙=$hasClassicBluetooth, BLE=$hasBleConnection (状态值=${_bleManager.connectionState})'); bool hasClassicBluetooth = currentDevice != null;
bool hasBleConnection = currentBleState == 2; // 使用实时查询的状态
bool wasConnected = _isFullyConnected.value;
bool isNowConnected = hasClassicBluetooth && hasBleConnection;
// 只有状态真正改变时才更新
if (_isFullyConnected.value != isNowConnected) {
// 先更新状态
_isFullyConnected.value = isNowConnected;
Logger.d(_tag, '连接状态变更: ${wasConnected ? "已连接" : "未连接"} -> ${isNowConnected ? "已连接" : "未连接"}');
// 强制触发响应式更新 Logger.d(_tag, '连接状态检查: 经典蓝牙=$hasClassicBluetooth, BLE=$hasBleConnection (实时状态值=$currentBleState)');
_isFullyConnected.refresh();
// 如果从未连接变为连接,主动获取耳机信息 bool wasConnected = _isFullyConnected.value;
if (!wasConnected && isNowConnected) { bool isNowConnected = hasClassicBluetooth && hasBleConnection;
Logger.d(_tag, '设备连接成功,获取耳机信息');
_bleManager.fetchDeviceInfo(); // 状态一致性检查:如果声称已连接但没有设备信息,强制断开
if (isNowConnected && currentDevice == null) {
Logger.w(_tag, '状态不一致:已连接但无设备信息,强制更新为未连接');
isNowConnected = false;
} }
// 延迟一帧后再次刷新,确保UI更新 // 只有状态真正改变时才更新
Future.delayed(Duration.zero, () { if (_isFullyConnected.value != isNowConnected) {
update(); // 立即同步更新状态
// 再次强制刷新响应式变量 _isFullyConnected.value = isNowConnected;
Logger.d(_tag, '连接状态变更: ${wasConnected ? "已连接" : "未连接"} -> ${isNowConnected ? "已连接" : "未连接"}');
// 立即触发UI更新,不使用延迟
_isFullyConnected.refresh(); _isFullyConnected.refresh();
});
// 延迟稍长时间再刷新一次,处理某些特殊情况
Future.delayed(const Duration(milliseconds: 100), () {
update(); update();
// 如果从未连接变为连接,主动获取耳机信息
if (!wasConnected && isNowConnected) {
Logger.d(_tag, '设备连接成功,获取耳机信息');
await _bleManager.fetchDeviceInfo();
}
}
// 确保UI刷新
update();
} catch (e) {
Logger.e(_tag, '检查连接状态失败: $e');
// 出错时设置为未连接
if (_isFullyConnected.value) {
_isFullyConnected.value = false;
_isFullyConnected.refresh(); _isFullyConnected.refresh();
}); update();
}
} }
// 总是调用update确保UI刷新
update();
} }
/// 获取连接状态对应的颜色 /// 获取连接状态对应的颜色
@ -209,7 +214,29 @@ class HomeController extends GetxController {
/// 获取设备名称 /// 获取设备名称
String getDeviceName() { String getDeviceName() {
return currentDevice?.name ?? 'unknownEquipment'.tr; // 状态一致性检查
if (_isFullyConnected.value && currentDevice == null) {
Logger.w(_tag, '状态不一致:显示已连接但无设备信息');
// 立即重新检查状态
_checkConnectionStatus();
}
// 优先使用当前设备名称
if (currentDevice?.name != null && currentDevice!.name!.isNotEmpty) {
return currentDevice!.name!;
}
// 如果当前没有设备但有BLE设备信息,使用BLE的设备名
if (deviceInfo.value?.name != null && deviceInfo.value!.name.isNotEmpty) {
return deviceInfo.value!.name;
}
// 如果刚断开连接,使用缓存的设备名称(提供更好的用户体验)
if (!_isFullyConnected.value && _lastConnectedDeviceName != null && _lastConnectedDeviceName!.isNotEmpty) {
return _lastConnectedDeviceName!;
}
return 'unknownEquipment'.tr;
} }
/// 获取信号强度(模拟数据) /// 获取信号强度(模拟数据)

81
lib/modules/pairing/controllers/pairing_controller.dart

@ -15,6 +15,7 @@ enum PairingState {
checking, // 检查中(蓝牙、权限等) checking, // 检查中(蓝牙、权限等)
waitingClassic, // 等待经典蓝牙连接 waitingClassic, // 等待经典蓝牙连接
verifying, // 验证设备 verifying, // 验证设备
associating, // 正在进行BLE设备关联
waitingBle, // 等待BLE连接 waitingBle, // 等待BLE连接
completed, // 配对完成 completed, // 配对完成
error, // 错误状态 error, // 错误状态
@ -28,6 +29,7 @@ enum ErrorType {
noClassicDevice, // 无经典蓝牙设备 noClassicDevice, // 无经典蓝牙设备
deviceNotMatch, // 设备不匹配 deviceNotMatch, // 设备不匹配
deviceBound, // 设备已被绑定 deviceBound, // 设备已被绑定
associationFailed, // 关联失败
bleTimeout, // BLE连接超时 bleTimeout, // BLE连接超时
networkError, // 网络错误 networkError, // 网络错误
} }
@ -261,6 +263,15 @@ class PairingController extends GetxController {
isLoading.value = true; isLoading.value = true;
break; break;
case PairingState.associating:
statusText.value = '正在关联设备...';
isLoading.value = true;
// 延迟执行关联,确保状态已更新
Future.delayed(const Duration(milliseconds: 200), () {
_startDeviceAssociation();
});
break;
case PairingState.waitingBle: case PairingState.waitingBle:
statusText.value = '正在建立安全连接...'; statusText.value = '正在建立安全连接...';
isLoading.value = true; isLoading.value = true;
@ -295,6 +306,10 @@ class PairingController extends GetxController {
showRetryButton.value = true; showRetryButton.value = true;
retryButtonText.value = '授予权限'; retryButtonText.value = '授予权限';
break; break;
case ErrorType.associationFailed:
showRetryButton.value = true;
retryButtonText.value = '重新关联';
break;
default: default:
showRetryButton.value = true; showRetryButton.value = true;
retryButtonText.value = '重试'; retryButtonText.value = '重试';
@ -394,16 +409,27 @@ class PairingController extends GetxController {
Logger.i(_tag, '设备验证通过'); Logger.i(_tag, '设备验证通过');
_verifiedDeviceAddress = device.address; _verifiedDeviceAddress = device.address;
// 检查BLE状态 - 直接从原生层获取 // 检查是否已有BLE关联
final currentBleState = await _bleManager.getConnectionState(); final pairedMacAddress = await _bleManager.getPairedMacAddress();
Logger.i(_tag, '验证时BLE状态: $currentBleState'); Logger.i(_tag, '已关联的MAC地址: $pairedMacAddress');
if (currentBleState == 2) { // BleConnectionState.connected if (pairedMacAddress != null && pairedMacAddress.toUpperCase() == device.address.toUpperCase()) {
Logger.i(_tag, 'BLE已连接,直接完成配对'); // 已有关联,检查BLE连接状态
_transition(PairingState.completed); Logger.i(_tag, '设备已关联,检查BLE连接状态');
final currentBleState = await _bleManager.getConnectionState();
Logger.i(_tag, '验证时BLE状态: $currentBleState');
if (currentBleState == 2) { // BleConnectionState.connected
Logger.i(_tag, 'BLE已连接,直接完成配对');
_transition(PairingState.completed);
} else {
Logger.i(_tag, 'BLE未连接,等待BLE连接');
_transition(PairingState.waitingBle);
}
} else { } else {
Logger.i(_tag, 'BLE未连接,等待BLE连接'); // 没有关联或关联的是其他设备,需要进行关联
_transition(PairingState.waitingBle); Logger.i(_tag, '需要进行BLE设备关联');
_transition(PairingState.associating);
} }
} else { } else {
_setError(ErrorType.deviceNotMatch, '请连接 DeepSound 设备'); _setError(ErrorType.deviceNotMatch, '请连接 DeepSound 设备');
@ -414,6 +440,35 @@ class PairingController extends GetxController {
} }
} }
/// 开始设备关联
void _startDeviceAssociation() async {
try {
if (_verifiedDeviceAddress == null) {
_setError(ErrorType.associationFailed, '设备地址无效');
return;
}
Logger.i(_tag, '开始BLE设备关联: $_verifiedDeviceAddress');
// 调用BLE管理器的关联方法
final success = await _bleManager.startDeviceAssociation(
deviceNamePattern: 'DeapSound', // 或者使用 _currentClassicDevice?.name
macAddress: _verifiedDeviceAddress!,
);
if (success) {
Logger.i(_tag, 'BLE设备关联成功');
// 关联成功后,转到等待BLE连接状态
_transition(PairingState.waitingBle);
} else {
_setError(ErrorType.associationFailed, 'BLE设备关联失败');
}
} catch (e) {
Logger.e(_tag, 'BLE设备关联异常: $e');
_setError(ErrorType.associationFailed, '设备关联失败,请重试');
}
}
/// 开始BLE连接 /// 开始BLE连接
void _startBleConnection() async { void _startBleConnection() async {
try { try {
@ -517,4 +572,14 @@ class PairingController extends GetxController {
void openBluetoothSettings() { void openBluetoothSettings() {
AppSettings.openAppSettings(type: AppSettingsType.bluetooth); AppSettings.openAppSettings(type: AppSettingsType.bluetooth);
} }
/// 清除设备关联(在需要重新配对时调用)
Future<void> clearDeviceAssociation() async {
try {
Logger.i(_tag, '清除设备关联');
await _bleManager.clearPairedDevices();
} catch (e) {
Logger.e(_tag, '清除设备关联失败: $e');
}
}
} }

8
lib/modules/pairing/views/pairing_view.dart

@ -234,6 +234,8 @@ class PairingView extends GetView<PairingController> {
switch (state) { switch (state) {
case PairingState.completed: case PairingState.completed:
return Icons.check_circle; return Icons.check_circle;
case PairingState.associating:
return Icons.link;
case PairingState.error: case PairingState.error:
final errorType = controller.errorType; final errorType = controller.errorType;
switch (errorType) { switch (errorType) {
@ -243,6 +245,8 @@ class PairingView extends GetView<PairingController> {
case ErrorType.noClassicDevice: case ErrorType.noClassicDevice:
case ErrorType.deviceNotMatch: case ErrorType.deviceNotMatch:
return Icons.headphones_outlined; return Icons.headphones_outlined;
case ErrorType.associationFailed:
return Icons.link_off;
default: default:
return Icons.error_outline; return Icons.error_outline;
} }
@ -307,6 +311,8 @@ class PairingView extends GetView<PairingController> {
return '请先通过系统蓝牙连接DeapSound设备'; return '请先通过系统蓝牙连接DeapSound设备';
case PairingState.verifying: case PairingState.verifying:
return '正在验证设备...'; return '正在验证设备...';
case PairingState.associating:
return '正在建立设备关联...';
case PairingState.waitingBle: case PairingState.waitingBle:
return '请稍候,正在完成配对...'; return '请稍候,正在完成配对...';
case PairingState.completed: case PairingState.completed:
@ -324,6 +330,8 @@ class PairingView extends GetView<PairingController> {
return '请确保连接的是DeapSound设备'; return '请确保连接的是DeapSound设备';
case ErrorType.deviceBound: case ErrorType.deviceBound:
return '该设备已被其他账号绑定'; return '该设备已被其他账号绑定';
case ErrorType.associationFailed:
return '设备关联失败,请重试';
case ErrorType.bleTimeout: case ErrorType.bleTimeout:
return '扫描超时,请确保设备在附近'; return '扫描超时,请确保设备在附近';
case ErrorType.networkError: case ErrorType.networkError:

5
lib/modules/pairing/views/pairing_view_new.dart

@ -153,6 +153,11 @@ class PairingView extends GetView<PairingController> {
iconColor = Colors.orange; iconColor = Colors.orange;
break; break;
case PairingState.associating:
iconData = Icons.link;
iconColor = Colors.blue;
break;
case PairingState.waitingBle: case PairingState.waitingBle:
iconData = Icons.sync; iconData = Icons.sync;
iconColor = Colors.blue; iconColor = Colors.blue;

Loading…
Cancel
Save