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.
518 lines
15 KiB
518 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';
|
|
import '../../../data/services/voice_interaction_service.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 _deviceBattery = Rx<int?>(null);
|
|
|
|
int? get deviceBattery => _deviceBattery.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();
|
|
|
|
// 立即加载缓存的设备信息并显示
|
|
_loadCachedDeviceInfo();
|
|
|
|
// 先进行简单初始化,避免立即进行蓝牙操作
|
|
_initBasicServices();
|
|
|
|
// 延迟初始化蓝牙相关功能,让UI先渲染完成
|
|
Future.delayed(const Duration(milliseconds: 1200), () {
|
|
_initBluetoothService();
|
|
});
|
|
}
|
|
|
|
// 立即加载缓存的设备信息
|
|
void _loadCachedDeviceInfo() {
|
|
try {
|
|
// 1. 首先检查是否有传入的设备信息(从PairingController传入)
|
|
if (Get.arguments != null && Get.arguments is Map<String, dynamic>) {
|
|
Logger.info('使用传入的设备信息');
|
|
_deviceInfo.assignAll(Get.arguments);
|
|
_updateConnectionStatus();
|
|
update(); // 立即更新UI
|
|
return;
|
|
}
|
|
|
|
// 2. 如果没有传入信息,尝试从BluetoothService获取上次连接的设备信息
|
|
if (Get.isRegistered<BluetoothService>()) {
|
|
BluetoothService bluetoothService = Get.find<BluetoothService>();
|
|
if (bluetoothService.lastConnectedDeviceInfo.isNotEmpty) {
|
|
Logger.info('使用BluetoothService中存储的上次连接设备信息');
|
|
_deviceInfo.assignAll(bluetoothService.lastConnectedDeviceInfo);
|
|
_updateConnectionStatus();
|
|
update(); // 立即更新UI
|
|
return;
|
|
}
|
|
}
|
|
|
|
// 3. 如果上述都没有,显示未连接状态
|
|
Logger.info('没有找到缓存的设备信息,显示未连接状态');
|
|
_connectionStatus.value = ConnectionStatus.disconnected;
|
|
_isConnected.value = false;
|
|
update(); // 立即更新UI
|
|
} catch (e) {
|
|
Logger.error('加载缓存设备信息失败: $e');
|
|
}
|
|
}
|
|
|
|
// 基础服务初始化,不涉及蓝牙等耗时操作
|
|
void _initBasicServices() {
|
|
try {
|
|
// 初始化语音交互服务并启动服务
|
|
Future.microtask(() async {
|
|
// 先初始化服务
|
|
await VoiceInteractionService.to.initialize();
|
|
|
|
// 启动服务
|
|
bool serviceStarted = await VoiceInteractionService.to.startService();
|
|
if (serviceStarted) {
|
|
Logger.info('语音交互服务已成功启动');
|
|
} else {
|
|
Logger.error('语音交互服务启动失败');
|
|
}
|
|
});
|
|
|
|
// 检查是否有传入的蓝牙设备信息
|
|
if (Get.arguments != null && Get.arguments is Map<String, dynamic>) {
|
|
_deviceInfo.assignAll(Get.arguments);
|
|
_updateConnectionStatus();
|
|
}
|
|
|
|
// 模拟电池状态更新
|
|
_simulateBatteryUpdates();
|
|
} catch (e) {
|
|
Logger.error('初始化基础服务失败: $e');
|
|
}
|
|
}
|
|
|
|
// 初始化蓝牙服务
|
|
void _initBluetoothService() {
|
|
try {
|
|
if (Get.isRegistered<BluetoothService>()) {
|
|
_bluetoothService = Get.find<BluetoothService>();
|
|
|
|
// 直接获取当前设备信息
|
|
_updateDeviceInfoFromService();
|
|
|
|
// 监听连接状态变化
|
|
ever(_bluetoothService!.connectionStateObs, (state) {
|
|
Logger.info('蓝牙连接状态变化: $state');
|
|
_processConnectionStateChange(state);
|
|
});
|
|
|
|
// 监听选中设备变化
|
|
ever(_bluetoothService!.selectedDeviceObs, (device) {
|
|
Logger.info('蓝牙选中设备变化: ${device?.platformName ?? "无设备"}');
|
|
_updateDeviceInfoFromService();
|
|
});
|
|
|
|
// 监听最后连接的设备信息变化
|
|
ever(_bluetoothService!.lastConnectedDeviceInfoObs, (info) {
|
|
Logger.info('最后连接的设备信息变化');
|
|
if (info.isNotEmpty) {
|
|
_deviceInfo.assignAll(info);
|
|
_updateConnectionStatus();
|
|
update(); // 通知UI刷新
|
|
}
|
|
});
|
|
}
|
|
} catch (e) {
|
|
Logger.error('获取蓝牙服务失败: $e');
|
|
_connectionErrorMsg.value = '获取蓝牙服务失败';
|
|
update(); // 通知UI刷新
|
|
}
|
|
}
|
|
|
|
// 从蓝牙服务更新设备信息
|
|
void _updateDeviceInfoFromService() {
|
|
if (_bluetoothService != null) {
|
|
// 获取当前设备信息
|
|
Map<String, dynamic> info = _bluetoothService!.lastConnectedDeviceInfo;
|
|
if (info.isNotEmpty) {
|
|
_deviceInfo.assignAll(info);
|
|
_updateConnectionStatus();
|
|
update(); // 通知UI刷新
|
|
} else if (_bluetoothService!.selectedDevice != null) {
|
|
// 如果最后连接的设备信息为空,但有选中的设备,获取当前连接的设备信息
|
|
_deviceInfo.assignAll(_bluetoothService!.getConnectedDeviceInfo());
|
|
_updateConnectionStatus();
|
|
update(); // 通知UI刷新
|
|
}
|
|
}
|
|
}
|
|
|
|
// 检查并更新当前连接状态
|
|
void _checkAndUpdateCurrentConnectionState() {
|
|
if (_bluetoothService != null) {
|
|
_updateDeviceInfoFromService();
|
|
}
|
|
}
|
|
|
|
// 处理连接状态变化
|
|
void _processConnectionStateChange(BluetoothConnectionState state) {
|
|
// 从蓝牙服务获取最新设备信息
|
|
_updateDeviceInfoFromService();
|
|
|
|
switch (state) {
|
|
case BluetoothConnectionState.connected:
|
|
_connectionStatus.value = ConnectionStatus.connected;
|
|
_connectionErrorMsg.value = '';
|
|
_isConnected.value = true;
|
|
break;
|
|
case BluetoothConnectionState.disconnected:
|
|
_connectionStatus.value = ConnectionStatus.disconnected;
|
|
_isConnected.value = false;
|
|
break;
|
|
case BluetoothConnectionState.connecting:
|
|
_connectionStatus.value = ConnectionStatus.connecting;
|
|
break;
|
|
default:
|
|
// 其他状态暂不处理
|
|
break;
|
|
}
|
|
|
|
update(); // 通知UI刷新
|
|
}
|
|
|
|
// 显示连接成功消息
|
|
void _showConnectionSuccessMessage() {
|
|
if (_deviceInfo.isNotEmpty && _deviceInfo['device'] != null) {
|
|
String deviceName = _deviceInfo['device']['name'] ?? '未命名设备';
|
|
Get.snackbar(
|
|
'连接成功',
|
|
'已成功连接到设备: $deviceName',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.green[100],
|
|
colorText: Colors.green[800],
|
|
duration: const Duration(seconds: 2),
|
|
);
|
|
}
|
|
}
|
|
|
|
// 更新连接状态
|
|
void _updateConnectionStatus() {
|
|
if (_deviceInfo.containsKey('connected') || _deviceInfo.containsKey('paired')) {
|
|
// 检查是否已连接
|
|
bool isConnected = _deviceInfo['connected'] ?? false;
|
|
// 检查是否已配对
|
|
bool isPaired = _deviceInfo['paired'] ?? false;
|
|
|
|
// 如果已连接,设置为已连接状态
|
|
if (isConnected) {
|
|
_isConnected.value = true;
|
|
_connectionStatus.value = ConnectionStatus.connected;
|
|
}
|
|
// 如果已配对但未连接,也视为已连接状态(简化处理)
|
|
else if (isPaired) {
|
|
_isConnected.value = true;
|
|
_connectionStatus.value = ConnectionStatus.connected;
|
|
}
|
|
// 如果既未连接也未配对,设置为未连接状态
|
|
else {
|
|
_isConnected.value = false;
|
|
_connectionStatus.value = ConnectionStatus.disconnected;
|
|
}
|
|
} else {
|
|
_isConnected.value = false;
|
|
_connectionStatus.value = ConnectionStatus.disconnected;
|
|
}
|
|
}
|
|
|
|
// 模拟电池状态更新
|
|
void _simulateBatteryUpdates() {
|
|
// 不再获取设备电量
|
|
_deviceBattery.value = 0;
|
|
Logger.info('不再获取设备电量');
|
|
}
|
|
|
|
// 获取设备电量
|
|
Future<void> _fetchBatteryLevel() async {
|
|
// 不再获取设备电量
|
|
_deviceBattery.value = 0;
|
|
Logger.info('不再获取设备电量');
|
|
}
|
|
|
|
// 更新设备电量信息(提供给UI手动刷新使用)
|
|
Future<void> refreshBatteryLevel() async {
|
|
await _fetchBatteryLevel();
|
|
Get.snackbar(
|
|
'提示',
|
|
'电量信息已更新',
|
|
snackPosition: SnackPosition.TOP,
|
|
duration: const Duration(seconds: 1),
|
|
);
|
|
}
|
|
|
|
// 获取格式化后的电量显示文本
|
|
String getBatteryText() {
|
|
if (_deviceBattery.value == null) {
|
|
return '电量未知';
|
|
} else {
|
|
return '${_deviceBattery.value}%';
|
|
}
|
|
}
|
|
|
|
// 探索AI功能
|
|
void exploreAIFeatures() {
|
|
Get.toNamed(Routes.chat, arguments: {'agentId': 'personal_assistant'});
|
|
}
|
|
|
|
// 更新固件
|
|
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;
|
|
update(); // 立即更新UI状态
|
|
|
|
// 从BluetoothService获取最新设备信息
|
|
_updateDeviceInfoFromService();
|
|
|
|
// 刷新电量信息
|
|
await _fetchBatteryLevel();
|
|
|
|
// 根据当前状态给出提示
|
|
if (_isConnected.value) {
|
|
Get.snackbar(
|
|
'提示',
|
|
'设备信息已更新',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.green[100],
|
|
colorText: Colors.green[800],
|
|
);
|
|
} else {
|
|
Get.snackbar(
|
|
'提示',
|
|
'无法获取设备信息,请确保设备已连接',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.amber[100],
|
|
colorText: Colors.amber[800],
|
|
);
|
|
}
|
|
} catch (e) {
|
|
Logger.error('刷新设备信息失败: $e');
|
|
_connectionErrorMsg.value = '刷新设备信息失败: ${e.toString()}';
|
|
update(); // 确保状态更新
|
|
|
|
Get.snackbar(
|
|
'提示',
|
|
'刷新设备信息失败',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.red[100],
|
|
colorText: Colors.red[800],
|
|
);
|
|
}
|
|
}
|
|
|
|
// 获取设备状态文本
|
|
String getConnectionStatusText() {
|
|
// 检查是否已配对但未连接
|
|
if (_deviceInfo.containsKey('paired') && _deviceInfo['paired'] == true &&
|
|
(_deviceInfo['connected'] == false || _deviceInfo['connected'] == null)) {
|
|
return "已配对";
|
|
}
|
|
|
|
switch (_connectionStatus.value) {
|
|
case ConnectionStatus.connected:
|
|
return "已连接";
|
|
case ConnectionStatus.connecting:
|
|
return "连接中...";
|
|
case ConnectionStatus.disconnected:
|
|
return "未连接";
|
|
case ConnectionStatus.failed:
|
|
return "连接失败";
|
|
}
|
|
}
|
|
|
|
// 获取连接状态颜色
|
|
Color getConnectionStatusColor() {
|
|
// 检查是否已配对但未连接
|
|
if (_deviceInfo.containsKey('paired') && _deviceInfo['paired'] == true &&
|
|
(_deviceInfo['connected'] == false || _deviceInfo['connected'] == null)) {
|
|
return Colors.orange; // 已配对但未连接使用橙色
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
// 快捷入口方法
|
|
|
|
// 打开同声翻译页面
|
|
void openTranslation() {
|
|
Get.toNamed(Routes.translation);
|
|
}
|
|
|
|
// 打开AI女友页面
|
|
void openAIGirlfriend() {
|
|
Get.toNamed(Routes.chat, arguments: {'agentId': 'cyber_girlfriend'});
|
|
}
|
|
|
|
// 打开AI助理(已有方法 exploreAIFeatures)
|
|
}
|