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.
467 lines
15 KiB
467 lines
15 KiB
import 'package:get/get.dart';
|
|
import '../../../core/routes/app_routes.dart';
|
|
import '../../../data/services/bluetooth_service.dart';
|
|
import '../../../core/utils/logger.dart';
|
|
import 'package:flutter_blue_plus/flutter_blue_plus.dart' hide BluetoothService;
|
|
import 'package:flutter/material.dart';
|
|
|
|
// 连接状态枚举
|
|
enum ConnectionStatus {
|
|
disconnected, // 未连接
|
|
connecting, // 连接中
|
|
connected, // 已连接
|
|
failed // 连接失败
|
|
}
|
|
|
|
class HomeController extends GetxController {
|
|
static HomeController get to => Get.find();
|
|
|
|
// 设备连接状态
|
|
final _isConnected = false.obs;
|
|
bool get isConnected => _isConnected.value;
|
|
|
|
// 连接状态
|
|
final _connectionStatus = ConnectionStatus.disconnected.obs;
|
|
ConnectionStatus get connectionStatus => _connectionStatus.value;
|
|
|
|
// 电池状态
|
|
final _leftEarbudBattery = 75.obs;
|
|
final _rightEarbudBattery = 52.obs;
|
|
final _caseBattery = 92.obs;
|
|
|
|
int get leftEarbudBattery => _leftEarbudBattery.value;
|
|
int get rightEarbudBattery => _rightEarbudBattery.value;
|
|
int get caseBattery => _caseBattery.value;
|
|
|
|
// 固件版本
|
|
final String firmwareVersion = 'v2.4.1';
|
|
|
|
// 蓝牙设备信息
|
|
final _deviceInfo = <String, dynamic>{}.obs;
|
|
Map<String, dynamic> get deviceInfo => _deviceInfo.value;
|
|
|
|
// 蓝牙服务
|
|
BluetoothService? _bluetoothService;
|
|
|
|
// 连接错误信息
|
|
final _connectionErrorMsg = ''.obs;
|
|
String get connectionErrorMsg => _connectionErrorMsg.value;
|
|
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
// 检查是否有传入的蓝牙设备信息
|
|
if (Get.arguments != null && Get.arguments is Map<String, dynamic>) {
|
|
_deviceInfo.assignAll(Get.arguments);
|
|
_updateConnectionStatus();
|
|
}
|
|
|
|
// 获取蓝牙服务
|
|
_initBluetoothService();
|
|
|
|
// 模拟定期获取电池状态
|
|
_simulateBatteryUpdates();
|
|
}
|
|
|
|
// 初始化蓝牙服务
|
|
void _initBluetoothService() {
|
|
try {
|
|
if (Get.isRegistered<BluetoothService>()) {
|
|
_bluetoothService = Get.find<BluetoothService>();
|
|
|
|
// 如果已经有连接的设备但没有设备信息
|
|
if (_deviceInfo.isEmpty && _bluetoothService!.selectedDevice != null) {
|
|
_deviceInfo.assignAll(_bluetoothService!.getConnectedDeviceInfo());
|
|
_updateConnectionStatus();
|
|
} else if (_deviceInfo.isEmpty) {
|
|
// 如果没有设备信息,尝试获取已配对设备
|
|
_checkPairedDevices();
|
|
}
|
|
|
|
// 监听连接状态变化
|
|
ever(_bluetoothService!.connectionStateObs, (state) {
|
|
_processConnectionStateChange(state);
|
|
});
|
|
|
|
// 监听选中设备变化
|
|
ever(_bluetoothService!.selectedDeviceObs, (device) {
|
|
if (device != null) {
|
|
_deviceInfo.assignAll(_bluetoothService!.getConnectedDeviceInfo());
|
|
_updateConnectionStatus();
|
|
} else if (_isConnected.value) {
|
|
// 如果设备断开连接,更新状态
|
|
_isConnected.value = false;
|
|
_deviceInfo.clear();
|
|
_connectionStatus.value = ConnectionStatus.disconnected;
|
|
}
|
|
});
|
|
}
|
|
} catch (e) {
|
|
Logger.error('获取蓝牙服务失败: $e');
|
|
_connectionStatus.value = ConnectionStatus.failed;
|
|
_connectionErrorMsg.value = '获取蓝牙服务失败';
|
|
}
|
|
}
|
|
|
|
// 处理连接状态变化
|
|
void _processConnectionStateChange(BluetoothConnectionState state) {
|
|
_deviceInfo.assignAll(_bluetoothService!.getConnectedDeviceInfo());
|
|
|
|
switch (state) {
|
|
case BluetoothConnectionState.connected:
|
|
_connectionStatus.value = ConnectionStatus.connected;
|
|
_connectionErrorMsg.value = '';
|
|
_showConnectionSuccessMessage();
|
|
break;
|
|
case BluetoothConnectionState.disconnected:
|
|
_connectionStatus.value = ConnectionStatus.disconnected;
|
|
break;
|
|
case BluetoothConnectionState.connecting:
|
|
_connectionStatus.value = ConnectionStatus.connecting;
|
|
break;
|
|
default:
|
|
// 其他状态暂不处理
|
|
break;
|
|
}
|
|
|
|
_updateConnectionStatus();
|
|
}
|
|
|
|
// 显示连接成功消息
|
|
void _showConnectionSuccessMessage() {
|
|
if (_bluetoothService?.selectedDevice != null) {
|
|
String deviceName = _bluetoothService!.selectedDevice!.platformName.isEmpty ?
|
|
'未命名设备' : _bluetoothService!.selectedDevice!.platformName;
|
|
Get.snackbar(
|
|
'连接成功',
|
|
'已成功连接到设备: $deviceName',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.green[100],
|
|
colorText: Colors.green[800],
|
|
duration: const Duration(seconds: 2),
|
|
);
|
|
}
|
|
}
|
|
|
|
// 尝试查找并连接已配对设备
|
|
Future<void> _checkPairedDevices() async {
|
|
try {
|
|
if (_bluetoothService != null) {
|
|
// 更新状态为正在连接
|
|
_connectionStatus.value = ConnectionStatus.connecting;
|
|
|
|
// 如果已有选中的设备并且已连接,直接使用
|
|
if (_bluetoothService!.selectedDevice != null &&
|
|
_bluetoothService!.connectionState == BluetoothConnectionState.connected) {
|
|
Logger.info('使用已连接的设备: ${_bluetoothService!.selectedDevice!.platformName}');
|
|
_deviceInfo.assignAll(_bluetoothService!.getConnectedDeviceInfo());
|
|
_connectionStatus.value = ConnectionStatus.connected;
|
|
_updateConnectionStatus();
|
|
return;
|
|
}
|
|
|
|
// 获取已配对设备
|
|
final pairedDevices = await _bluetoothService!.getPairedDevices();
|
|
if (pairedDevices.isEmpty) {
|
|
Logger.info('没有找到已配对设备');
|
|
_connectionStatus.value = ConnectionStatus.disconnected;
|
|
return;
|
|
}
|
|
|
|
// 遍历配对设备,查找已连接的设备
|
|
for (var device in pairedDevices) {
|
|
try {
|
|
final state = await device.connectionState.first;
|
|
if (state == BluetoothConnectionState.connected) {
|
|
// 找到已连接的设备,更新UI
|
|
final success = await _bluetoothService!.connectToDevice(device);
|
|
if (success) {
|
|
Logger.info('使用已连接的已配对设备: ${device.platformName}');
|
|
_deviceInfo.assignAll(_bluetoothService!.getConnectedDeviceInfo());
|
|
_connectionStatus.value = ConnectionStatus.connected;
|
|
_updateConnectionStatus();
|
|
return;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// 忽略单个设备检查错误
|
|
Logger.error('检查设备连接状态失败: $e');
|
|
}
|
|
}
|
|
|
|
// 如果没有已连接的设备,尝试连接第一个配对设备
|
|
if (pairedDevices.isNotEmpty) {
|
|
Logger.info('尝试连接第一个配对设备: ${pairedDevices.first.platformName}');
|
|
final success = await _bluetoothService!.connectToDevice(pairedDevices.first);
|
|
if (success) {
|
|
Logger.info('自动连接到已配对设备: ${pairedDevices.first.platformName}');
|
|
_deviceInfo.assignAll(_bluetoothService!.getConnectedDeviceInfo());
|
|
_connectionStatus.value = ConnectionStatus.connected;
|
|
_updateConnectionStatus();
|
|
} else {
|
|
// 连接失败
|
|
_connectionStatus.value = ConnectionStatus.failed;
|
|
_connectionErrorMsg.value = '连接设备失败,请重试';
|
|
}
|
|
} else {
|
|
_connectionStatus.value = ConnectionStatus.disconnected;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
Logger.error('检查已配对设备失败: $e');
|
|
_connectionStatus.value = ConnectionStatus.failed;
|
|
_connectionErrorMsg.value = '检查设备失败: ${e.toString()}';
|
|
}
|
|
}
|
|
|
|
// 更新连接状态
|
|
void _updateConnectionStatus() {
|
|
if (_deviceInfo.containsKey('connected')) {
|
|
_isConnected.value = _deviceInfo['connected'] ?? false;
|
|
|
|
// 如果设备信息显示已连接,但状态不是已连接,则更新状态
|
|
if (_isConnected.value && _connectionStatus.value != ConnectionStatus.connected) {
|
|
_connectionStatus.value = ConnectionStatus.connected;
|
|
} else if (!_isConnected.value && _connectionStatus.value == ConnectionStatus.connected) {
|
|
// 如果设备显示未连接,但状态是已连接,则更新状态
|
|
_connectionStatus.value = ConnectionStatus.disconnected;
|
|
}
|
|
} else {
|
|
_isConnected.value = false;
|
|
if (_connectionStatus.value == ConnectionStatus.connected) {
|
|
_connectionStatus.value = ConnectionStatus.disconnected;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 模拟电池状态更新
|
|
void _simulateBatteryUpdates() {
|
|
// 在实际应用中,这里应该从设备获取真实的电池状态
|
|
// 这里只是模拟随机波动
|
|
}
|
|
|
|
// 探索AI功能
|
|
void exploreAIFeatures() {
|
|
Get.toNamed(Routes.explore);
|
|
}
|
|
|
|
// 更新固件
|
|
void updateFirmware() {
|
|
Get.snackbar(
|
|
'提示',
|
|
'开始下载固件更新...',
|
|
snackPosition: SnackPosition.TOP,
|
|
);
|
|
|
|
// 模拟更新过程
|
|
// 在真实应用中,这里应该有固件更新的实际逻辑
|
|
}
|
|
|
|
// 打开降噪功能
|
|
void toggleNoiseReduction() {
|
|
Get.snackbar(
|
|
'提示',
|
|
'降噪功能已开启',
|
|
snackPosition: SnackPosition.TOP,
|
|
);
|
|
}
|
|
|
|
// 音效设置
|
|
void openSoundEffects() {
|
|
Get.snackbar(
|
|
'提示',
|
|
'音效设置功能尚未实现',
|
|
snackPosition: SnackPosition.TOP,
|
|
);
|
|
}
|
|
|
|
// 环境音功能
|
|
void toggleAmbientSound() {
|
|
Get.snackbar(
|
|
'提示',
|
|
'环境音模式已开启',
|
|
snackPosition: SnackPosition.TOP,
|
|
);
|
|
}
|
|
|
|
// 收藏的设置
|
|
void openFavorites() {
|
|
Get.snackbar(
|
|
'提示',
|
|
'收藏功能尚未实现',
|
|
snackPosition: SnackPosition.TOP,
|
|
);
|
|
}
|
|
|
|
// 打开设置页面
|
|
void openSettings() {
|
|
Get.toNamed(Routes.settings);
|
|
}
|
|
|
|
// 重新扫描设备
|
|
void rescanDevices() {
|
|
if (_bluetoothService != null) {
|
|
Get.toNamed(Routes.pairing);
|
|
} else {
|
|
Get.snackbar(
|
|
'提示',
|
|
'蓝牙服务不可用',
|
|
snackPosition: SnackPosition.TOP,
|
|
);
|
|
}
|
|
}
|
|
|
|
// 获取设备名称
|
|
String getDeviceName() {
|
|
if (_deviceInfo.isEmpty || _deviceInfo['device'] == null) {
|
|
return '未连接设备';
|
|
}
|
|
|
|
final device = _deviceInfo['device'] as Map<String, dynamic>;
|
|
return device['name'] ?? '未命名设备';
|
|
}
|
|
|
|
// 获取设备ID
|
|
String getDeviceId() {
|
|
if (_deviceInfo.isEmpty || _deviceInfo['device'] == null) {
|
|
return '';
|
|
}
|
|
|
|
final device = _deviceInfo['device'] as Map<String, dynamic>;
|
|
return device['id'] ?? '';
|
|
}
|
|
|
|
// 获取设备信号强度
|
|
String getSignalStrength() {
|
|
if (_deviceInfo.isEmpty || _deviceInfo['device'] == null) {
|
|
return '无信号';
|
|
}
|
|
|
|
final device = _deviceInfo['device'] as Map<String, dynamic>;
|
|
final rssi = device['rssi'];
|
|
|
|
if (rssi == null) {
|
|
return '未知';
|
|
}
|
|
|
|
// RSSI通常在-100到0之间,值越大信号越强
|
|
if (rssi > -60) {
|
|
return '强';
|
|
} else if (rssi > -80) {
|
|
return '中';
|
|
} else {
|
|
return '弱';
|
|
}
|
|
}
|
|
|
|
// 刷新设备信息
|
|
Future<void> refreshDeviceInfo() async {
|
|
try {
|
|
// 检查蓝牙是否可用
|
|
if (_bluetoothService == null) {
|
|
Get.snackbar(
|
|
'提示',
|
|
'蓝牙服务不可用',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.red[100],
|
|
colorText: Colors.red[800],
|
|
);
|
|
return;
|
|
}
|
|
|
|
// 设置正在刷新状态
|
|
_connectionStatus.value = ConnectionStatus.connecting;
|
|
|
|
if (_bluetoothService!.selectedDevice != null) {
|
|
// 如果有选中的设备,刷新设备信息
|
|
_deviceInfo.assignAll(_bluetoothService!.getConnectedDeviceInfo());
|
|
_updateConnectionStatus();
|
|
|
|
// 检查刷新后的连接状态
|
|
if (_isConnected.value) {
|
|
Get.snackbar(
|
|
'提示',
|
|
'设备信息已更新',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.green[100],
|
|
colorText: Colors.green[800],
|
|
);
|
|
} else {
|
|
// 设备可能已断开连接
|
|
_connectionStatus.value = ConnectionStatus.disconnected;
|
|
Get.snackbar(
|
|
'提示',
|
|
'设备已断开连接',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.amber[100],
|
|
colorText: Colors.amber[800],
|
|
);
|
|
|
|
// 尝试重新连接
|
|
await _checkPairedDevices();
|
|
}
|
|
} else {
|
|
// 如果没有选中的设备,尝试连接已配对设备
|
|
await _checkPairedDevices();
|
|
|
|
if (_connectionStatus.value == ConnectionStatus.failed) {
|
|
Get.snackbar(
|
|
'提示',
|
|
_connectionErrorMsg.value.isNotEmpty ? _connectionErrorMsg.value : '连接设备失败',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.red[100],
|
|
colorText: Colors.red[800],
|
|
);
|
|
} else if (_connectionStatus.value == ConnectionStatus.disconnected) {
|
|
Get.snackbar(
|
|
'提示',
|
|
'未找到已连接设备,请连接设备',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.amber[100],
|
|
colorText: Colors.amber[800],
|
|
);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
Logger.error('刷新设备信息失败: $e');
|
|
_connectionStatus.value = ConnectionStatus.failed;
|
|
_connectionErrorMsg.value = '刷新设备信息失败: ${e.toString()}';
|
|
|
|
Get.snackbar(
|
|
'提示',
|
|
'刷新设备信息失败',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.red[100],
|
|
colorText: Colors.red[800],
|
|
);
|
|
}
|
|
}
|
|
|
|
// 处理连接失败
|
|
String getConnectionStatusText() {
|
|
switch (_connectionStatus.value) {
|
|
case ConnectionStatus.connected:
|
|
return "已连接";
|
|
case ConnectionStatus.connecting:
|
|
return "连接中...";
|
|
case ConnectionStatus.disconnected:
|
|
return "未连接";
|
|
case ConnectionStatus.failed:
|
|
return "连接失败";
|
|
}
|
|
}
|
|
|
|
// 获取连接状态颜色
|
|
Color getConnectionStatusColor() {
|
|
switch (_connectionStatus.value) {
|
|
case ConnectionStatus.connected:
|
|
return Colors.green;
|
|
case ConnectionStatus.connecting:
|
|
return Colors.blue;
|
|
case ConnectionStatus.disconnected:
|
|
return Colors.red;
|
|
case ConnectionStatus.failed:
|
|
return Colors.red;
|
|
}
|
|
}
|
|
}
|