import 'dart:convert'; import 'dart:typed_data'; import 'package:app_settings/app_settings.dart'; import 'package:deep_voice/data/models/appconfig.dart'; import 'package:deep_voice/data/models/user_Info.dart'; import 'package:deep_voice/data/services/network/api.dart'; import 'package:flutter/material.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'; import '../../../core/utils/permission_util.dart'; /// 配对状态枚举 - 简化版本 enum PairingState { idle, // 空闲/初始状态 checking, // 检查中(蓝牙、权限等) waitingClassic, // 等待经典蓝牙连接 verifying, // 验证设备 binding, //确认绑定设备 manualbinding, //手动绑定设备 associating, // 正在进行BLE设备关联 waitingBle, //等待BLE连接 completed, //配对完成 error, // 错误状态 } /// 错误类型枚举 enum ErrorType { none, bluetoothOff, // 蓝牙关闭 noPermission, // 无权限 noClassicDevice, // 无经典蓝牙设备 deviceNotMatch, // 设备不匹配 deviceBound, // 设备已被绑定 associationFailed, // 关联失败 bleTimeout, // BLE连接超时 authnFailed, // 授权失败 networkError, // 网络错误 } /// 配对控制器 - 基于简化状态机的实现 class PairingController extends GetxController { static const String _tag = 'PairingCtrl'; static PairingController get to => Get.find(); // ========== 状态管理 ========== final _currentState = PairingState.idle.obs; final _errorType = ErrorType.none.obs; final _errorMessage = ''.obs; PairingState get currentState => _currentState.value; ErrorType get errorType => _errorType.value; String get errorMessage => _errorMessage.value; // ========== UI状态 ========== final statusText = ''.obs; final isLoading = false.obs; final showConnectButton = false.obs; final showRetryButton = false.obs; final showBindButton = false.obs; final showRetryChectButton = false.obs; final showAutoCodeInput = false.obs; final showSkipButton = false.obs; // 增加临时跳过绑定按钮状态 final showSkipBindingButton = false.obs; // 新增临时跳过绑定按钮 final connectButtonText = '连接设备'.obs; final retryButtonText = '重试'.obs; final deviceCode = ''.obs; // ========== 监听器管理 ========== final List _workers = []; Timer? _bleTimeoutTimer; // ========== 依赖服务 ========== late final BluetoothManager _bluetoothManager; late final BleManager _bleManager; // ========== 当前设备信息 ========== BluetoothDevice? _currentClassicDevice; String? _verifiedDeviceAddress; TextEditingController codeInputController = TextEditingController(); // Public getter for view access BluetoothDevice? get currentDevice => _currentClassicDevice; @override void onInit() { super.onInit(); Logger.i(_tag, '配对控制器初始化'); // 确保服务已初始化 _bluetoothManager = Get.find(); _bleManager = Get.find(); // 集中设置所有监听器 _setupAllListeners(); // 开始初始状态检查 // 延迟稍长时间,确保BluetoothManager有足够时间获取已连接设备 Future.delayed(const Duration(milliseconds: 300), () { _startInitialCheck(); }); } @override void onClose() { Logger.i(_tag, '配对控制器销毁'); // 清理所有Worker for (var worker in _workers) { worker.dispose(); } _workers.clear(); // 清理定时器 _bleTimeoutTimer?.cancel(); super.onClose(); } // ==================== 监听器设置 ==================== /// 集中设置所有监听器 void _setupAllListeners() { // 1. 监听蓝牙开关状态 _setupBluetoothStateListener(); // 2. 监听经典蓝牙连接状态 _setupClassicConnectionListener(); // 3. 监听BLE连接状态 _setupBleConnectionListener(); } /// 监听蓝牙开关状态 void _setupBluetoothStateListener() { _workers.add(ever(_bluetoothManager.bluetoothStateRx, (String state) { Logger.d(_tag, '蓝牙状态变化: $state'); _handleBluetoothStateChange(state); })); } /// 监听经典蓝牙连接状态 void _setupClassicConnectionListener() { _workers .add(ever(_bluetoothManager.currentDeviceRx, (BluetoothDevice? device) { Logger.d(_tag, '经典蓝牙设备变化: ${device?.name}'); _handleClassicDeviceChange(device); })); } /// 监听BLE连接状态 void _setupBleConnectionListener() { _workers.add(ever(_bleManager.connectionStateRx, (int state) { Logger.d(_tag, 'BLE连接状态变化: $state'); _handleBleStateChange(state); })); } // ==================== 状态处理 ==================== /// 处理蓝牙开关状态变化 void _handleBluetoothStateChange(String state) { if (state == 'off') { // 蓝牙关闭,进入错误状态 _setError(ErrorType.bluetoothOff, '请开启蓝牙'); } else if (state == 'on' && _errorType.value == ErrorType.bluetoothOff) { // 蓝牙重新开启,恢复流程 Logger.i(_tag, '检测到蓝牙已开启,自动恢复配对流程'); _clearError(); // 延迟一下确保蓝牙服务完全就绪 Future.delayed(const Duration(milliseconds: 500), () { _checkCurrentStatus(); }); } } /// 处理经典蓝牙设备变化 void _handleClassicDeviceChange(BluetoothDevice? device) { _currentClassicDevice = device; switch (_currentState.value) { case PairingState.waitingClassic: if (device != null) { // 有设备连接,进入验证阶段 Logger.i(_tag, '检测到经典蓝牙设备连接,开始验证'); _transition(PairingState.verifying); _verifyDevice(device); } break; case PairingState.error: // 如果在错误状态下检测到设备连接,且错误是无设备连接,则自动恢复 if (device != null && _errorType.value == ErrorType.noClassicDevice) { Logger.i(_tag, '检测到设备重新连接,自动恢复配对流程'); _clearError(); _transition(PairingState.verifying); _verifyDevice(device); } break; case PairingState.verifying: case PairingState.waitingBle: case PairingState.completed: if (device == null) { // 设备断开,返回等待连接状态 _setError(ErrorType.noClassicDevice, '设备已断开'); } break; default: break; } } /// 处理BLE状态变化 void _handleBleStateChange(int state) { if (_currentState.value == PairingState.waitingBle) { if (state == 2) { // BLE已连接 _bleTimeoutTimer?.cancel(); _transition(PairingState.completed); } } // 如果在完成状态下BLE断开,显示警告但不改变状态 if (_currentState.value == PairingState.completed && state != 2) { Logger.w(_tag, 'BLE连接已断开,但配对流程已完成'); } } // ==================== 状态转换 ==================== /// 状态转换 void _transition(PairingState newState) { final oldState = _currentState.value; _currentState.value = newState; Logger.i(_tag, '状态转换: $oldState -> $newState'); // 根据新状态执行相应操作 _onStateChanged(newState); } /// 状态变化处理 void _onStateChanged(PairingState state) { // 重置UI状态 isLoading.value = false; showConnectButton.value = false; showRetryButton.value = false; showSkipBindingButton.value = false; // 重置临时跳过绑定按钮 showSkipButton.value = false; showAutoCodeInput.value = false; showBindButton.value = false; showRetryChectButton.value = false; switch (state) { case PairingState.idle: statusText.value = '准备开始配对'; break; case PairingState.checking: statusText.value = '正在检查环境...'; isLoading.value = true; break; case PairingState.waitingClassic: statusText.value = '请确保耳机已开启并进入配对模式'; showConnectButton.value = true; showSkipButton.value = true; connectButtonText.value = '前往蓝牙设置'; break; case PairingState.verifying: statusText.value = '正在验证设备...'; isLoading.value = true; break; case PairingState.binding: statusText.value = '确认绑定'; isLoading.value = true; showBindButton.value = true; showRetryChectButton.value = true; break; case PairingState.associating: statusText.value = '正在关联设备...'; isLoading.value = true; // 延迟执行关联,确保状态已更新 Future.delayed(const Duration(milliseconds: 200), () { _startDeviceAssociation(); }); break; case PairingState.waitingBle: statusText.value = '正在建立安全连接...'; isLoading.value = true; // 延迟一下再调用,给BLE管理器时间更新状态 Future.delayed(const Duration(milliseconds: 200), () { _startBleConnection(); }); break; case PairingState.manualbinding: statusText.value = '需要手动绑定授权码...'; isLoading.value = false; showAutoCodeInput.value = true; // showSkipButton.value = true; showSkipBindingButton.value = true; // 显示临时跳过绑定按钮 break; case PairingState.completed: statusText.value = '配对成功!'; isLoading.value = false; _navigateToHome(); break; case PairingState.error: statusText.value = _errorMessage.value; isLoading.value = false; showSkipButton.value = true; // 根据错误类型决定显示哪个按钮和按钮文本 switch (_errorType.value) { case ErrorType.bluetoothOff: showConnectButton.value = true; connectButtonText.value = '开启蓝牙'; break; case ErrorType.noClassicDevice: showConnectButton.value = true; connectButtonText.value = '前往蓝牙设置'; break; case ErrorType.noPermission: showRetryButton.value = true; retryButtonText.value = '授予权限'; break; case ErrorType.associationFailed: showRetryButton.value = true; retryButtonText.value = '重新关联'; break; case ErrorType.authnFailed: showRetryButton.value = true; retryButtonText.value = '重新授权'; break; default: showRetryButton.value = true; retryButtonText.value = '重试'; break; } break; } } // ==================== 错误处理 ==================== /// 设置错误状态 void _setError(ErrorType type, String message) { _errorType.value = type; _errorMessage.value = message; _transition(PairingState.error); } /// 清除错误状态 void _clearError() { _errorType.value = ErrorType.none; _errorMessage.value = ''; } // ==================== 核心流程 ==================== /// 开始初始检查 void _startInitialCheck() { _transition(PairingState.checking); _checkCurrentStatus(); } /// 检查当前状态并决定下一步 void _checkCurrentStatus() async { try { // 1. 检查蓝牙状态 if (_bluetoothManager.bluetoothState == 'off') { _setError(ErrorType.bluetoothOff, '请开启蓝牙'); return; } // 2. 检查权限 if (!await _checkPermissions()) { _setError(ErrorType.noPermission, '请授予必要权限'); return; } // 3. 先刷新设备连接状态,确保获取最新的连接信息 await _bluetoothManager.refreshDeviceConnection(); // 4. 检查经典蓝牙连接 final classicDevice = _bluetoothManager.currentDevice; if (classicDevice == null) { _transition(PairingState.waitingClassic); return; } // 5. 如果有设备,进行验证 _currentClassicDevice = classicDevice; _transition(PairingState.verifying); await _verifyDevice(classicDevice); } catch (e) { Logger.e(_tag, '状态检查失败: $e'); _setError(ErrorType.networkError, '检查失败,请重试'); } } /// 检查权限 Future _checkPermissions() async { // Android权限检查 if (Platform.isAndroid) { // 检查蓝牙相关权限 final bluetoothScan = await Permission.bluetoothScan.request(); final bluetoothConnect = await Permission.bluetoothConnect.request(); final location = await Permission.locationWhenInUse.request(); return bluetoothScan.isGranted && bluetoothConnect.isGranted && location.isGranted; } return true; } /// 验证设备 Future _verifyDevice(BluetoothDevice device) async { try { Logger.i(_tag, '开始验证设备: ${device.name} (${device.address})'); final result = await authbindingDevice(device); if (result == 10) { //验证失败 进入手动授权 await connectble(device); } else if (result == 9) { Logger.i(_tag, 'BLE已连接,直接完成配对'); _transition(PairingState.completed); } else if (result == 1) { //跳转绑定界面 //验证失败 进入手动授权 if (currentDevice != null) { _transition(PairingState.binding); } else { _transition(PairingState.checking); _checkCurrentStatus(); } } else { final authcode_open = AppConfig.env("APP_AUTHCODE_OPEN") ?? ""; if (authcode_open == "true") { //验证失败 进入手动授权 _transition(PairingState.manualbinding); } else { _setError(ErrorType.deviceNotMatch, '请连接 DeepSound 设备'); } } } catch (e) { Logger.e(_tag, '设备验证异常: $e'); _setError(ErrorType.networkError, '验证失败,请重试'); } } //连接ble Future connectble(BluetoothDevice device) async { Logger.i(_tag, '设备验证通过'); _verifiedDeviceAddress = device.address; // 检查是否已有BLE关联 final pairedMacAddress = await _bleManager.getPairedMacAddress(); Logger.i(_tag, '已关联的MAC地址: $pairedMacAddress'); if (pairedMacAddress != null && pairedMacAddress.toUpperCase() == device.address.toUpperCase()) { // 已有关联,检查BLE连接状态 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 { // 没有关联或关联的是其他设备,需要进行关联 Logger.i(_tag, '需要进行BLE设备关联'); _transition(PairingState.associating); } return; } /// 开始设备关联 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连接 void _startBleConnection() async { try { // 设置超时定时器 _bleTimeoutTimer?.cancel(); _bleTimeoutTimer = Timer(const Duration(seconds: 30), () { if (_currentState.value == PairingState.waitingBle) { _setError(ErrorType.bleTimeout, 'BLE连接超时,请重试'); } }); // 检查是否已连接 - 直接从原生层获取最新状态 final currentBleState = await _bleManager.getConnectionState(); Logger.i(_tag, 'BLE当前连接状态: $currentBleState'); if (currentBleState == 2) { // BleConnectionState.connected Logger.i(_tag, 'BLE已经连接,直接完成配对'); _bleTimeoutTimer?.cancel(); _transition(PairingState.completed); return; } // 注册后台扫描以开始BLE配对 if (_verifiedDeviceAddress != null) { final success = await _bleManager.registerBackgroundScan( macAddress: _verifiedDeviceAddress); if (!success && _currentState.value == PairingState.waitingBle) { _setError(ErrorType.bleTimeout, 'BLE配对启动失败'); } } } catch (e) { Logger.e(_tag, 'BLE连接失败: $e'); _setError(ErrorType.bleTimeout, 'BLE连接失败'); } } //自动绑定设备 0 未合作商 1 合作商 2,已绑定 Future authbindingDevice(BluetoothDevice device) async { if (User.instance.earphonelicense != "" && User.instance.earphonemac == device.address) { // 已经绑定 return 10; } if (User.instance.earphoneauthcode != "" && User.instance.earphonemac == device.address) { // 已经绑定 return 9; } // 检查设备名称是否包含 DeepSound 或 DeapSound final deviceName = device.name; final names = AppConfig.allproductNames(); print('获取到 deviceName: $deviceName names:$names'); if (names.contains(deviceName)) { await _bleManager.startScan(deviceName); await Future.delayed(const Duration(seconds: 1)); // 尝试最多读取 3 次设备信息,每次间隔 1 秒 Map? deviceinfo; for (int i = 0; i < 3; i++) { deviceinfo = await _bleManager.getDeviceInfo(device.address); print('获取到 deviceinfo: $deviceinfo'); if (deviceinfo != null) { break; } await Future.delayed(Duration(seconds: 1)); } print('获取到 deviceinfo: $deviceinfo'); if (deviceinfo != null) { // final code = processHex(deviceinfo["hex"]!, 15, 25); String code = extractAndReverseBytes(deviceinfo["hex"]!, 15, 24); print('获取到 code: $code'); // 安全检查长度 if (code != "") { deviceCode.value = code; return 1; } else { return 0; } } return 0; // 调用BLE管理器的自动绑定方法 } else { return 0; } } //确认绑定设备 void confirmBindDevice() async { final response = await Api.bindearphone({ "code": deviceCode.value, "earphonname": currentDevice?.name, "earphonemac": currentDevice?.address, }); Logger.i(_tag, '手动授权结果 ${response}'); if (response != null) { Logger.i(_tag, '绑定设备成功'); User.instance.earphonemac = currentDevice?.address ?? ''; User.instance.earphonename = currentDevice?.name ?? ''; User.instance.earphonelicense = deviceCode.value; _transition(PairingState.verifying); _verifyDevice(_currentClassicDevice!); return; } else { Logger.e(_tag, '绑定设备失败!'); return; } } int reverseBits(int byte) { // 这里是 nibble swap 还是 bit 反转?看你需求,先保持 nibble swap return ((byte & 0x0F) << 4) | ((byte & 0xF0) >> 4); } String extractAndReverseBytes(String hex, int start, int end) { List bytes = []; for (int i = 0; i < hex.length; i += 2) { bytes.add(int.parse(hex.substring(i, i + 2), radix: 16)); } List slice = bytes.sublist(start, end + 1); List reversed = slice.reversed.toList(); return reversed .map((b) => b.toRadixString(16).padLeft(2, '0')) .join() .toUpperCase(); } /// 用户点击授权码输入框 void onAutoCodeInputTap() async { // 调用BLE管理器的自动绑定方法 final response = await Api.bindauthcode({ "code": codeInputController.text.trim(), "earphonname": currentDevice?.name, "earphonemac": currentDevice?.address, }); Logger.i(_tag, '手动授权结果 ${response}'); if (response != null) { User.instance.earphonemac = currentDevice?.address ?? ''; User.instance.earphonename = currentDevice?.name ?? ''; User.instance.earphoneauthcode = codeInputController.text.trim(); _transition(PairingState.verifying); _verifyDevice(_currentClassicDevice!); } else { Logger.e(_tag, '手动绑定失败!'); _setError(ErrorType.authnFailed, '设备授权失败,请检查授权码'); } } /// 导航到主页 void _navigateToHome() { Future.delayed(const Duration(seconds: 1), () async { // 启动AgentService服务 try { Logger.i(_tag, '启动AgentService服务'); await _bleManager.startAgentService(); } catch (e) { Logger.e(_tag, '启动AgentService失败: $e'); } Get.offAllNamed(Routes.home); }); } // ==================== 用户操作 ==================== /// 用户点击连接按钮 void onConnectTap() { Logger.i(_tag, '用户点击连接按钮'); // 根据当前状态或错误类型决定行为 if (_currentState.value == PairingState.error) { switch (_errorType.value) { case ErrorType.bluetoothOff: // 引导用户去开启蓝牙 Logger.i(_tag, '引导用户开启蓝牙'); AppSettings.openAppSettings(type: AppSettingsType.bluetooth); break; case ErrorType.noClassicDevice: // 引导用户去蓝牙设置连接设备 Logger.i(_tag, '引导用户去蓝牙设置'); AppSettings.openAppSettings(type: AppSettingsType.bluetooth); break; default: // 其他错误情况,刷新并重试 _bluetoothManager.refreshDeviceConnection(); _checkCurrentStatus(); break; } } else if (_currentState.value == PairingState.waitingClassic) { // 等待经典蓝牙连接状态,引导去设置 Logger.i(_tag, '等待经典蓝牙连接,引导用户去蓝牙设置'); AppSettings.openAppSettings(type: AppSettingsType.bluetooth); } else { // 其他情况,刷新设备连接 _bluetoothManager.refreshDeviceConnection(); _checkCurrentStatus(); } } /// 用户点击重试按钮 void onRetryTap() { Logger.i(_tag, '用户点击重试按钮'); // 如果是权限问题,引导去设置 if (_errorType.value == ErrorType.noPermission) { Logger.i(_tag, '引导用户去应用设置授予权限'); AppSettings.openAppSettings(); } else { // 其他情况,清除错误并重试 _clearError(); _startInitialCheck(); } } /// 用户点击跳过绑定按钮 void onSkipBindingTap() { Logger.i(_tag, '用户选择临时跳过手动绑定'); User.instance.earphonemac = currentDevice?.address ?? ''; _transition(PairingState.verifying); _verifyDevice(_currentClassicDevice!); } /// 用户点击跳过按钮 void onSkipTap() async { Logger.i(_tag, '用户选择跳过配对'); // 启动AgentService服务 try { Logger.i(_tag, '启动AgentService服务'); await _bleManager.startAgentService(); } catch (e) { Logger.e(_tag, '启动AgentService失败: $e'); } Get.offAllNamed(Routes.home); } /// 打开蓝牙设置 void openBluetoothSettings() { AppSettings.openAppSettings(type: AppSettingsType.bluetooth); } /// 清除设备关联(在需要重新配对时调用) Future clearDeviceAssociation() async { try { Logger.i(_tag, '清除设备关联'); await _bleManager.clearPairedDevices(); } catch (e) { Logger.e(_tag, '清除设备关联失败: $e'); } } }