import 'package:app_settings/app_settings.dart'; import 'package:get/get.dart'; import 'dart:async'; import 'package:permission_handler/permission_handler.dart'; import '../../../routes/app_routes.dart'; import '../../../core/utils/logger.dart'; import 'dart:io'; import '../../../data/services/bluetooth_manager.dart'; import '../../../data/services/ble_manager.dart'; /// 配对状态枚举 enum PairingState { init, // 初始状态 btReady, // 蓝牙已就绪 classicOk, // 经典蓝牙已连接 serverVerify, // 服务器验证中 pairing, // 配对中 paired, // 已配对 // 错误/退出状态 exitNoPermission, // 无权限 exitBtOff, // 蓝牙关闭 exitNoClassic, // 无经典蓝牙连接 exitNotMatch, // 设备不匹配 exitIllegal, // 非法设备 exitBound, // 已被他人绑定 exitPairFailed, // 配对失败 exitTimeout, // 超时 } /// 配对控制器 - 基于有限状态机的实现 class PairingController extends GetxController { static PairingController get to => Get.find(); // ==================== 状态管理 ==================== final _state = PairingState.init.obs; PairingState get state => _state.value; // ==================== 状态数据 ==================== final statusDescription = ''.obs; final actionButtonText = ''.obs; final isLoading = false.obs; // 当前设备信息 BluetoothDevice? _currentClassicDevice; // 计时器和异步操作管理 Timer? _stateTimer; StreamSubscription? _bluetoothStateSubscription; StreamSubscription? _deviceSubscription; StreamSubscription? _bleStatusSubscription; // 常量定义 static const _tag = 'PairingController'; static const _validDeviceNamePattern = 'DeapSound'; // ==================== 生命周期 ==================== @override void onInit() { super.onInit(); _setupStateObserver(); start(); } @override void onClose() { _cancelAllOperations(); _bluetoothStateSubscription?.cancel(); _deviceSubscription?.cancel(); _bleStatusSubscription?.cancel(); super.onClose(); } // ==================== 公共 API ==================== /// 启动配对流程 Future start() async { _transition(PairingState.init); } /// 重新开始配对流程 Future restart() async { _cancelAllOperations(); _transition(PairingState.init); } /// 处理按钮点击 void handleActionButtonTap() { switch (state) { case PairingState.exitNoPermission: _openAppSettings(); break; case PairingState.exitBtOff: _openBluetoothSettings(); break; case PairingState.exitNoClassic: case PairingState.exitNotMatch: _openBluetoothSettings(); break; case PairingState.exitTimeout: restart(); break; case PairingState.exitPairFailed: case PairingState.exitBound: _retryPairing(); break; default: break; } } /// 跳过配对 void skipPairing() { Logger.i(_tag, '用户选择跳过配对'); _navigateToHome(); } // ==================== FSM 核心实现 ==================== /// 状态转换 void _transition(PairingState next) { final current = state; // 允许init状态重复执行,其他状态避免重复转换 if (current == next && next != PairingState.init) return; Logger.d(_tag, 'FSM: ${current.name} → ${next.name}'); _cancelStateTimer(); _state.value = next; // 根据新状态执行对应的进入方法 switch (next) { case PairingState.init: _enterInit(); break; case PairingState.btReady: _enterBtReady(); break; case PairingState.classicOk: _enterClassicOk(); break; case PairingState.serverVerify: _enterServerVerify(); break; case PairingState.pairing: _enterPairing(); break; case PairingState.paired: _enterPaired(); break; // 错误状态 case PairingState.exitNoPermission: case PairingState.exitBtOff: case PairingState.exitNoClassic: case PairingState.exitNotMatch: case PairingState.exitIllegal: case PairingState.exitBound: case PairingState.exitPairFailed: case PairingState.exitTimeout: _handleErrorState(next); break; } } /// 设置状态观察器 void _setupStateObserver() { ever(_state, (PairingState state) { _updateUI(); }); } // ==================== 状态处理方法 ==================== /// INIT: 初始化,检查权限 Future _enterInit() async { Logger.i(_tag, '开始执行初始化流程'); isLoading.value = true; statusDescription.value = '正在检查权限...'; try { // iOS平台跳过权限检查 if (!Platform.isIOS) { final hasPermission = await _checkAndRequestPermissions(); if (!hasPermission) { _transition(PairingState.exitNoPermission); return; } } // 设置蓝牙状态监听 _setupBluetoothListener(); // 检查蓝牙状态 final btState = BluetoothManager.to.bluetoothState; Logger.i(_tag, '当前蓝牙状态: $btState'); if (btState == 'on' || btState == 'unknown') { _transition(PairingState.btReady); } else { _transition(PairingState.exitBtOff); } } catch (e) { Logger.e(_tag, 'Init failed: $e'); _transition(PairingState.exitNoPermission); } finally { isLoading.value = false; } } /// BT_READY: 蓝牙已就绪,检查经典蓝牙连接 Future _enterBtReady() async { isLoading.value = true; statusDescription.value = '正在检查设备连接...'; try { // 刷新设备连接 await BluetoothManager.to.refreshDeviceConnection(); // 获取当前连接的经典蓝牙设备 final device = BluetoothManager.to.currentDevice; if (device == null) { _transition(PairingState.exitNoClassic); return; } _currentClassicDevice = device; _transition(PairingState.classicOk); } catch (e) { Logger.e(_tag, 'BT ready check failed: $e'); _transition(PairingState.exitNoClassic); } finally { isLoading.value = false; } } /// CLASSIC_OK: 经典蓝牙已连接,检查是否需要BLE配对 Future _enterClassicOk() async { if (_currentClassicDevice == null) { _transition(PairingState.exitNoClassic); return; } statusDescription.value = '已连接: ${_currentClassicDevice!.name}'; // 检查设备名称是否合规 if (!_isValidDeviceName(_currentClassicDevice!.name)) { _transition(PairingState.exitNotMatch); return; } // 检查是否已有BLE配对记录 try { // 1. 检查平台是否支持Companion功能 final isSupported = await BleManager.to.isCompanionSupported(); if (!isSupported) { Logger.i(_tag, '设备不支持Companion功能,跳过BLE配对'); _transition(PairingState.paired); return; } // 2. 获取已配对的MAC地址 final pairedMac = await BleManager.to.getPairedMacAddress(); // 3. 检查是否已经配对且是同一设备 if (pairedMac != null && pairedMac == _currentClassicDevice!.address) { Logger.i(_tag, '设备已完成BLE配对: $pairedMac'); // 4. 检查BLE连接状态 final isBleConnected = await BleManager.to.isBleConnected(); if (isBleConnected) { Logger.i(_tag, 'BLE已连接,跳转到配对成功'); _transition(PairingState.paired); } else { Logger.i(_tag, 'BLE未连接,尝试重新配对'); _transition(PairingState.pairing); } return; } // 5. 如果没有配对或配对的是其他设备,进入验证流程 _transition(PairingState.serverVerify); } catch (e) { Logger.e(_tag, 'Classic OK check failed: $e'); // 出错时直接尝试配对 _transition(PairingState.pairing); } } /// SERVER_VERIFY: 服务器验证 Future _enterServerVerify() async { isLoading.value = true; statusDescription.value = '正在验证设备...'; try { if (_currentClassicDevice == null) { _transition(PairingState.exitNotMatch); return; } // 验证设备是否可以配对 final canPair = await BleManager.to.verifyDeviceCanPair( _currentClassicDevice!.address ); if (canPair) { Logger.i(_tag, '设备验证通过,可以配对'); _transition(PairingState.pairing); } else { Logger.e(_tag, '设备验证失败,不能配对'); _transition(PairingState.exitIllegal); } } catch (e) { Logger.e(_tag, 'Server verify failed: $e'); _transition(PairingState.exitIllegal); } finally { isLoading.value = false; } } /// PAIRING: 执行配对 Future _enterPairing() async { isLoading.value = true; statusDescription.value = '正在配对设备...'; try { if (_currentClassicDevice == null) { _transition(PairingState.exitPairFailed); return; } // 启动BLE状态监听 _setupBleStatusListener(); // 检查当前BLE连接状态,防止错过已经连接的事件 final isBleConnected = await BleManager.to.isBleConnected(); if (isBleConnected) { Logger.i(_tag, 'BLE已经连接,直接完成配对'); _onBleConnected(); return; } // 设置配对超时保护 _stateTimer = Timer(const Duration(seconds: 30), () { if (state == PairingState.pairing) { Logger.e(_tag, 'BLE配对超时'); _transition(PairingState.exitTimeout); } }); // 使用系统配对框架执行BLE配对 // iOS: AccessorySetupKit // Android: Companion Device Manager final success = await BleManager.to.startDeviceAssociation( deviceNamePattern: _currentClassicDevice!.name, macAddress: _currentClassicDevice!.address, ); if (success) { Logger.i(_tag, 'BLE配对启动成功,等待连接完成...'); // 配对结果将通过BLE状态监听回调处理 } else { Logger.e(_tag, 'BLE配对启动失败'); _transition(PairingState.exitPairFailed); } } catch (e) { Logger.e(_tag, 'Pairing failed: $e'); _transition(PairingState.exitPairFailed); } } /// 设置BLE状态监听 void _setupBleStatusListener() { Logger.d(_tag, '🎯 开始设置BLE状态监听器...'); _bleStatusSubscription?.cancel(); Logger.d(_tag, '📱 当前BLE连接状态: ${BleManager.to.connectionState}'); Logger.d(_tag, '🔗 开始监听BleManager.connectionStateRx...'); // 监听BleManager的连接状态变化,而不是直接监听BleService _bleStatusSubscription = BleManager.to.connectionStateRx.listen( (bleState) { // 只在配对状态下处理BLE连接事件 if (state == PairingState.pairing) { if (bleState == BleConnectionState.connected) { Logger.i(_tag, 'BLE连接成功,处理配对完成'); _onBleConnected(); } else if (bleState == BleConnectionState.error) { Logger.e(_tag, 'BLE连接错误'); _transition(PairingState.exitPairFailed); } else { Logger.d(_tag, 'BLE状态变化,但非关键状态: $bleState'); } } else { Logger.d(_tag, '当前状态为${state.name},忽略BLE连接事件'); } }, onError: (error) { Logger.e(_tag, 'BLE状态监听错误: $error'); }, onDone: () { Logger.w(_tag, 'BLE状态监听流已关闭'); }, ); Logger.d(_tag, 'BLE状态监听器已设置完成'); } /// 处理BLE连接成功 Future _onBleConnected() async { Logger.i(_tag, 'BLE连接成功'); // 取消超时计时器 _cancelStateTimer(); // BLE连接成功即表示配对完成 // iOS使用UUID,Android使用MAC地址,但连接成功都表示配对验证通过 Logger.i(_tag, 'BLE配对验证成功,经典蓝牙和BLE均已连接'); _transition(PairingState.paired); } /// PAIRED: 配对成功 Future _enterPaired() async { isLoading.value = false; statusDescription.value = '配对成功!'; try { if (_currentClassicDevice != null) { // Android平台注册后台扫描 if (Platform.isAndroid) { await BleManager.to.registerBackgroundScan( macAddress: _currentClassicDevice!.address ); Logger.i(_tag, '已注册后台扫描'); } } // 启动BLE后台服务 await BleManager.to.startAgentService(); Logger.i(_tag, 'BLE后台服务已启动'); // 延迟后跳转到主页 await Future.delayed(const Duration(milliseconds: 500)); _navigateToHome(); } catch (e) { Logger.e(_tag, 'Post pairing setup failed: $e'); // 即使失败也跳转到主页 // _navigateToHome(); } } /// 处理错误状态 void _handleErrorState(PairingState errorState) { isLoading.value = false; switch (errorState) { case PairingState.exitNoPermission: statusDescription.value = '需要蓝牙权限'; actionButtonText.value = '去设置'; break; case PairingState.exitBtOff: statusDescription.value = '请开启蓝牙'; actionButtonText.value = '去设置'; break; case PairingState.exitNoClassic: statusDescription.value = '请先连接DeapSound设备'; actionButtonText.value = '去设置'; break; case PairingState.exitNotMatch: statusDescription.value = '请连接DeapSound设备'; actionButtonText.value = '去设置'; break; case PairingState.exitTimeout: statusDescription.value = '扫描超时'; actionButtonText.value = '重试'; break; case PairingState.exitPairFailed: statusDescription.value = '配对失败'; actionButtonText.value = '重新配对'; break; case PairingState.exitBound: statusDescription.value = '设备已被其他用户绑定'; actionButtonText.value = '联系客服'; break; case PairingState.exitIllegal: statusDescription.value = '设备验证失败'; actionButtonText.value = '重试'; break; default: break; } } // ==================== 辅助方法 ==================== /// 检查并请求权限 Future _checkAndRequestPermissions() async { try { if (Platform.isIOS) { // iOS权限由系统自动处理 return true; } // Android权限检查 final permissions = []; permissions.add(Permission.locationWhenInUse); if (Platform.isAndroid && await _getAndroidSdkVersion() >= 31) { permissions.add(Permission.bluetoothScan); permissions.add(Permission.bluetoothConnect); } final statuses = await permissions.request(); return statuses.values.every((status) => status.isGranted); } catch (e) { Logger.e(_tag, '权限检查失败: $e'); return false; } } /// 设置蓝牙状态监听 void _setupBluetoothListener() { _bluetoothStateSubscription?.cancel(); _bluetoothStateSubscription = BluetoothManager.to.bluetoothState.obs.listen((btState) { Logger.d(_tag, '蓝牙状态变化: $btState'); // 根据当前状态决定如何响应蓝牙状态变化 if (btState == 'off' && state != PairingState.exitBtOff) { _transition(PairingState.exitBtOff); } else if (btState == 'on' && state == PairingState.exitBtOff) { _transition(PairingState.btReady); } }); // 监听设备连接状态 _deviceSubscription?.cancel(); _deviceSubscription = BluetoothManager.to.currentDeviceRx.listen((device) { Logger.d(_tag, '设备连接状态变化: ${device?.name}'); // 根据当前状态决定如何响应设备变化 if (device != null && state == PairingState.exitNoClassic) { _currentClassicDevice = device; _transition(PairingState.classicOk); } else if (device == null && (state == PairingState.classicOk || state == PairingState.pairing || state == PairingState.serverVerify)) { _transition(PairingState.exitNoClassic); } }); } /// 检查设备名称是否合规 bool _isValidDeviceName(String deviceName) { return deviceName.contains(_validDeviceNamePattern); } /// 获取Android SDK版本 Future _getAndroidSdkVersion() async { // 简化处理,实际应该通过platform channel获取 return 31; } /// 更新UI void _updateUI() { // 根据状态更新UI文本 switch (state) { case PairingState.init: statusDescription.value = '初始化中...'; break; case PairingState.btReady: statusDescription.value = '蓝牙已就绪'; break; case PairingState.classicOk: if (_currentClassicDevice != null) { statusDescription.value = '已连接: ${_currentClassicDevice!.name}'; } break; case PairingState.serverVerify: statusDescription.value = '正在验证设备...'; break; case PairingState.pairing: statusDescription.value = '正在配对...'; break; case PairingState.paired: statusDescription.value = '配对成功!'; break; default: // 错误状态在_handleErrorState中处理 break; } } /// 取消所有异步操作 void _cancelAllOperations() { _stateTimer?.cancel(); } /// 取消状态计时器 void _cancelStateTimer() { _stateTimer?.cancel(); } /// 重试配对 void _retryPairing() { if (_currentClassicDevice != null) { _transition(PairingState.pairing); } else { restart(); } } /// 打开应用设置 void _openAppSettings() { AppSettings.openAppSettings(); } /// 打开蓝牙设置 void _openBluetoothSettings() { if (Platform.isAndroid) { AppSettings.openAppSettings(type: AppSettingsType.bluetooth); } else { AppSettings.openAppSettings(); } } /// 导航到主页 void _navigateToHome() { Logger.i(_tag, '跳转到主页'); Get.offAllNamed(Routes.home); } // ==================== 公共属性 ==================== /// 当前连接的经典蓝牙设备 BluetoothDevice? get currentDevice => _currentClassicDevice; /// 是否可以跳过配对 bool get canSkip => !isLoading.value && (state == PairingState.exitNoClassic || state == PairingState.exitNotMatch || state == PairingState.exitTimeout); /// 是否显示操作按钮 bool get showActionButton => state == PairingState.exitNoPermission || state == PairingState.exitBtOff || state == PairingState.exitNoClassic || state == PairingState.exitNotMatch || state == PairingState.exitTimeout || state == PairingState.exitPairFailed || state == PairingState.exitBound || state == PairingState.exitIllegal; }