|
|
@ -1,4 +1,7 @@ |
|
|
import 'package:app_settings/app_settings.dart'; |
|
|
import 'package:app_settings/app_settings.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 'package:get/get.dart'; |
|
|
import 'dart:async'; |
|
|
import 'dart:async'; |
|
|
import 'package:permission_handler/permission_handler.dart'; |
|
|
import 'package:permission_handler/permission_handler.dart'; |
|
|
@ -15,9 +18,10 @@ enum PairingState { |
|
|
checking, // 检查中(蓝牙、权限等) |
|
|
checking, // 检查中(蓝牙、权限等) |
|
|
waitingClassic, // 等待经典蓝牙连接 |
|
|
waitingClassic, // 等待经典蓝牙连接 |
|
|
verifying, // 验证设备 |
|
|
verifying, // 验证设备 |
|
|
|
|
|
manualbinding, //手动绑定设备 |
|
|
associating, // 正在进行BLE设备关联 |
|
|
associating, // 正在进行BLE设备关联 |
|
|
waitingBle, // 等待BLE连接 |
|
|
waitingBle, //等待BLE连接 |
|
|
completed, // 配对完成 |
|
|
completed, //配对完成 |
|
|
error, // 错误状态 |
|
|
error, // 错误状态 |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -31,6 +35,7 @@ enum ErrorType { |
|
|
deviceBound, // 设备已被绑定 |
|
|
deviceBound, // 设备已被绑定 |
|
|
associationFailed, // 关联失败 |
|
|
associationFailed, // 关联失败 |
|
|
bleTimeout, // BLE连接超时 |
|
|
bleTimeout, // BLE连接超时 |
|
|
|
|
|
authnFailed, // 授权失败 |
|
|
networkError, // 网络错误 |
|
|
networkError, // 网络错误 |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -53,6 +58,7 @@ class PairingController extends GetxController { |
|
|
final isLoading = false.obs; |
|
|
final isLoading = false.obs; |
|
|
final showConnectButton = false.obs; |
|
|
final showConnectButton = false.obs; |
|
|
final showRetryButton = false.obs; |
|
|
final showRetryButton = false.obs; |
|
|
|
|
|
final showAutoCodeInput = false.obs; |
|
|
final showSkipButton = false.obs; |
|
|
final showSkipButton = false.obs; |
|
|
final connectButtonText = '连接设备'.obs; |
|
|
final connectButtonText = '连接设备'.obs; |
|
|
final retryButtonText = '重试'.obs; |
|
|
final retryButtonText = '重试'.obs; |
|
|
@ -68,6 +74,7 @@ class PairingController extends GetxController { |
|
|
// ========== 当前设备信息 ========== |
|
|
// ========== 当前设备信息 ========== |
|
|
BluetoothDevice? _currentClassicDevice; |
|
|
BluetoothDevice? _currentClassicDevice; |
|
|
String? _verifiedDeviceAddress; |
|
|
String? _verifiedDeviceAddress; |
|
|
|
|
|
TextEditingController codeInputController = TextEditingController(); |
|
|
|
|
|
|
|
|
// Public getter for view access |
|
|
// Public getter for view access |
|
|
BluetoothDevice? get currentDevice => _currentClassicDevice; |
|
|
BluetoothDevice? get currentDevice => _currentClassicDevice; |
|
|
@ -236,6 +243,7 @@ class PairingController extends GetxController { |
|
|
showConnectButton.value = false; |
|
|
showConnectButton.value = false; |
|
|
showRetryButton.value = false; |
|
|
showRetryButton.value = false; |
|
|
showSkipButton.value = false; |
|
|
showSkipButton.value = false; |
|
|
|
|
|
showAutoCodeInput.value = false; |
|
|
|
|
|
|
|
|
switch (state) { |
|
|
switch (state) { |
|
|
case PairingState.idle: |
|
|
case PairingState.idle: |
|
|
@ -276,7 +284,12 @@ class PairingController extends GetxController { |
|
|
_startBleConnection(); |
|
|
_startBleConnection(); |
|
|
}); |
|
|
}); |
|
|
break; |
|
|
break; |
|
|
|
|
|
case PairingState.manualbinding: |
|
|
|
|
|
statusText.value = '需要手动版定授权码...'; |
|
|
|
|
|
isLoading.value = false; |
|
|
|
|
|
showAutoCodeInput.value = true; |
|
|
|
|
|
showSkipButton.value = true; |
|
|
|
|
|
break; |
|
|
case PairingState.completed: |
|
|
case PairingState.completed: |
|
|
statusText.value = '配对成功!'; |
|
|
statusText.value = '配对成功!'; |
|
|
isLoading.value = false; |
|
|
isLoading.value = false; |
|
|
@ -306,6 +319,10 @@ class PairingController extends GetxController { |
|
|
showRetryButton.value = true; |
|
|
showRetryButton.value = true; |
|
|
retryButtonText.value = '重新关联'; |
|
|
retryButtonText.value = '重新关联'; |
|
|
break; |
|
|
break; |
|
|
|
|
|
case ErrorType.authnFailed: |
|
|
|
|
|
showRetryButton.value = true; |
|
|
|
|
|
retryButtonText.value = '重新授权'; |
|
|
|
|
|
break; |
|
|
default: |
|
|
default: |
|
|
showRetryButton.value = true; |
|
|
showRetryButton.value = true; |
|
|
retryButtonText.value = '重试'; |
|
|
retryButtonText.value = '重试'; |
|
|
@ -393,44 +410,48 @@ class PairingController extends GetxController { |
|
|
Future<void> _verifyDevice(BluetoothDevice device) async { |
|
|
Future<void> _verifyDevice(BluetoothDevice device) async { |
|
|
try { |
|
|
try { |
|
|
Logger.i(_tag, '开始验证设备: ${device.name} (${device.address})'); |
|
|
Logger.i(_tag, '开始验证设备: ${device.name} (${device.address})'); |
|
|
|
|
|
|
|
|
// TODO: 实现API验证逻辑 |
|
|
// TODO: 实现API验证逻辑 |
|
|
// 暂时模拟验证通过 |
|
|
// 暂时模拟验证通过 |
|
|
await Future.delayed(const Duration(seconds: 2)); |
|
|
// await Future.delayed(const Duration(seconds: 2));; |
|
|
|
|
|
if (await authbindingDevice()) { |
|
|
// 检查设备名称是否包含 DeepSound 或 DeapSound |
|
|
// 检查设备名称是否包含 DeepSound 或 DeapSound |
|
|
final deviceName = device.name ?? ''; |
|
|
final deviceName = device.name ?? ''; |
|
|
if (deviceName.contains('DeepSound') || |
|
|
if (deviceName.contains('DeepSound') || |
|
|
deviceName.contains('DeapSound')) { |
|
|
deviceName.contains('DeapSound')) { |
|
|
Logger.i(_tag, '设备验证通过'); |
|
|
Logger.i(_tag, '设备验证通过'); |
|
|
_verifiedDeviceAddress = device.address; |
|
|
_verifiedDeviceAddress = device.address; |
|
|
|
|
|
|
|
|
// 检查是否已有BLE关联 |
|
|
// 检查是否已有BLE关联 |
|
|
final pairedMacAddress = await _bleManager.getPairedMacAddress(); |
|
|
final pairedMacAddress = await _bleManager.getPairedMacAddress(); |
|
|
Logger.i(_tag, '已关联的MAC地址: $pairedMacAddress'); |
|
|
Logger.i(_tag, '已关联的MAC地址: $pairedMacAddress'); |
|
|
|
|
|
|
|
|
if (pairedMacAddress != null && |
|
|
if (pairedMacAddress != null && |
|
|
pairedMacAddress.toUpperCase() == device.address.toUpperCase()) { |
|
|
pairedMacAddress.toUpperCase() == device.address.toUpperCase()) { |
|
|
// 已有关联,检查BLE连接状态 |
|
|
// 已有关联,检查BLE连接状态 |
|
|
Logger.i(_tag, '设备已关联,检查BLE连接状态'); |
|
|
Logger.i(_tag, '设备已关联,检查BLE连接状态'); |
|
|
final currentBleState = await _bleManager.getConnectionState(); |
|
|
final currentBleState = await _bleManager.getConnectionState(); |
|
|
Logger.i(_tag, '验证时BLE状态: $currentBleState'); |
|
|
Logger.i(_tag, '验证时BLE状态: $currentBleState'); |
|
|
|
|
|
|
|
|
if (currentBleState == 2) { |
|
|
if (currentBleState == 2) { |
|
|
// BleConnectionState.connected |
|
|
// BleConnectionState.connected |
|
|
Logger.i(_tag, 'BLE已连接,直接完成配对'); |
|
|
Logger.i(_tag, 'BLE已连接,直接完成配对'); |
|
|
_transition(PairingState.completed); |
|
|
_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 设备'); |
|
|
Logger.i(_tag, '需要进行BLE设备关联'); |
|
|
_transition(PairingState.completed); |
|
|
_transition(PairingState.associating); |
|
|
|
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
_setError(ErrorType.deviceNotMatch, '请连接 DeepSound 设备'); |
|
|
//验证失败 进入手动授权 |
|
|
|
|
|
_transition(PairingState.manualbinding); |
|
|
} |
|
|
} |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
Logger.e(_tag, '设备验证异常: $e'); |
|
|
Logger.e(_tag, '设备验证异常: $e'); |
|
|
@ -504,6 +525,46 @@ class PairingController extends GetxController { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//自动绑定设备 |
|
|
|
|
|
Future<bool> authbindingDevice() async { |
|
|
|
|
|
if (User.instance.earphonemac == currentDevice?.address) { |
|
|
|
|
|
// 已经绑定 |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 调用BLE管理器的自动绑定方法 |
|
|
|
|
|
final response = await Api.bindearphone({ |
|
|
|
|
|
"earphonemac": currentDevice?.address, |
|
|
|
|
|
"earphoneauthcode": "", |
|
|
|
|
|
}); |
|
|
|
|
|
Logger.i(_tag, '手动授权结果 ${response}'); |
|
|
|
|
|
if (response != null) { |
|
|
|
|
|
Logger.i(_tag, '设备自动绑定成功'); |
|
|
|
|
|
User.instance.earphonemac = currentDevice?.address ?? ''; |
|
|
|
|
|
return true; |
|
|
|
|
|
} else { |
|
|
|
|
|
Logger.e(_tag, '手动绑定失败!'); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 用户点击授权码输入框 |
|
|
|
|
|
void onAutoCodeInputTap() async { |
|
|
|
|
|
// 调用BLE管理器的自动绑定方法 |
|
|
|
|
|
final response = await Api.bindearphone({ |
|
|
|
|
|
"earphonemac": currentDevice?.address, |
|
|
|
|
|
"earphoneauthcode": codeInputController.text.trim(), |
|
|
|
|
|
}); |
|
|
|
|
|
Logger.i(_tag, '手动授权结果 ${response}'); |
|
|
|
|
|
if (response != null) { |
|
|
|
|
|
_transition(PairingState.verifying); |
|
|
|
|
|
_verifyDevice(_currentClassicDevice!); |
|
|
|
|
|
} else { |
|
|
|
|
|
Logger.e(_tag, '手动绑定失败!'); |
|
|
|
|
|
_setError(ErrorType.authnFailed, '设备授权失败,请检查授权码'); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/// 导航到主页 |
|
|
/// 导航到主页 |
|
|
void _navigateToHome() { |
|
|
void _navigateToHome() { |
|
|
Future.delayed(const Duration(seconds: 1), () async { |
|
|
Future.delayed(const Duration(seconds: 1), () async { |
|
|
|