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.
208 lines
5.8 KiB
208 lines
5.8 KiB
import 'package:get/get.dart';
|
|
import 'dart:async';
|
|
import 'package:flutter/material.dart';
|
|
import '../../../data/services/voice_interaction_service.dart';
|
|
|
|
enum ConnectStatus {
|
|
initial, // 初始状态,显示添加设备
|
|
searching, // 搜索中
|
|
connected, // 连接成功
|
|
failed // 连接失败
|
|
}
|
|
|
|
class HomeController extends GetxController {
|
|
static HomeController get to => Get.find();
|
|
|
|
final _connectStatus = ConnectStatus.initial.obs;
|
|
final _searchDots = ''.obs;
|
|
Timer? _animationTimer;
|
|
bool _isDisposed = false;
|
|
|
|
// 语音服务状态
|
|
final _voiceServiceRunning = false.obs;
|
|
bool get voiceServiceRunning => _voiceServiceRunning.value;
|
|
|
|
ConnectStatus get connectStatus => _connectStatus.value;
|
|
String get searchDots => _searchDots.value;
|
|
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
_connectStatus.value = ConnectStatus.initial;
|
|
|
|
// 获取语音服务状态
|
|
_updateVoiceServiceStatus();
|
|
}
|
|
|
|
@override
|
|
void onClose() {
|
|
_isDisposed = true;
|
|
stopSearchingAnimation();
|
|
super.onClose();
|
|
}
|
|
|
|
/// 更新语音服务状态
|
|
Future<void> _updateVoiceServiceStatus() async {
|
|
if (Get.isRegistered<VoiceInteractionService>()) {
|
|
_voiceServiceRunning.value = VoiceInteractionService.to.isRunning;
|
|
} else {
|
|
_voiceServiceRunning.value = false;
|
|
}
|
|
}
|
|
|
|
/// 启动语音交互服务
|
|
Future<void> startVoiceService() async {
|
|
// 确保 ConfigService 已初始化
|
|
|
|
|
|
// 确保 VoiceInteractionService 已初始化
|
|
if (!Get.isRegistered<VoiceInteractionService>()) {
|
|
await Get.putAsync(() => VoiceInteractionService().init());
|
|
}
|
|
|
|
final result = await VoiceInteractionService.to.startService();
|
|
await _updateVoiceServiceStatus();
|
|
|
|
if (result) {
|
|
Get.snackbar(
|
|
'成功',
|
|
'语音交互服务已启动',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.green.withOpacity(0.1),
|
|
colorText: Colors.green,
|
|
duration: const Duration(seconds: 2),
|
|
);
|
|
} else {
|
|
Get.snackbar(
|
|
'错误',
|
|
'启动语音交互服务失败',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.red.withOpacity(0.1),
|
|
colorText: Colors.red,
|
|
duration: const Duration(seconds: 2),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 停止语音交互服务
|
|
Future<void> stopVoiceService() async {
|
|
if (!Get.isRegistered<VoiceInteractionService>()) {
|
|
await Get.putAsync(() => VoiceInteractionService().init());
|
|
}
|
|
|
|
final result = await VoiceInteractionService.to.stopService();
|
|
await _updateVoiceServiceStatus();
|
|
|
|
if (result) {
|
|
Get.snackbar(
|
|
'成功',
|
|
'语音交互服务已停止',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.blue.withOpacity(0.1),
|
|
colorText: Colors.blue,
|
|
duration: const Duration(seconds: 2),
|
|
);
|
|
} else {
|
|
Get.snackbar(
|
|
'错误',
|
|
'停止语音交互服务失败',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.red.withOpacity(0.1),
|
|
colorText: Colors.red,
|
|
duration: const Duration(seconds: 2),
|
|
);
|
|
}
|
|
}
|
|
|
|
void startSearchingAnimation() {
|
|
stopSearchingAnimation(); // Clear any existing timer
|
|
|
|
if (_isDisposed) return;
|
|
|
|
int count = 0;
|
|
_animationTimer = Timer.periodic(const Duration(milliseconds: 500), (timer) {
|
|
if (_isDisposed || _connectStatus.value != ConnectStatus.searching) {
|
|
timer.cancel();
|
|
return;
|
|
}
|
|
count = (count + 1) % 4;
|
|
_searchDots.value = '.' * count;
|
|
});
|
|
}
|
|
|
|
void stopSearchingAnimation() {
|
|
_animationTimer?.cancel();
|
|
_animationTimer = null;
|
|
if (!_isDisposed) {
|
|
_searchDots.value = '';
|
|
}
|
|
}
|
|
|
|
Future<void> connectDevice() async {
|
|
if (_connectStatus.value == ConnectStatus.searching) return;
|
|
|
|
_connectStatus.value = ConnectStatus.searching;
|
|
startSearchingAnimation();
|
|
|
|
try {
|
|
// 模拟搜索和连接过程
|
|
await Future.delayed(const Duration(seconds: 3));
|
|
|
|
if (_isDisposed) return; // Check if controller is disposed
|
|
|
|
// 模拟随机成功或失败
|
|
if (DateTime.now().millisecondsSinceEpoch % 2 == 0) {
|
|
_connectStatus.value = ConnectStatus.connected;
|
|
if (!_isDisposed) {
|
|
await Future.delayed(const Duration(seconds: 2)); // 显示成功状态2秒
|
|
Get.snackbar(
|
|
'Success',
|
|
'Device connected successfully',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.green.withOpacity(0.1),
|
|
colorText: Colors.green,
|
|
duration: const Duration(seconds: 3),
|
|
);
|
|
}
|
|
} else {
|
|
_connectStatus.value = ConnectStatus.failed;
|
|
}
|
|
} catch (e) {
|
|
if (!_isDisposed) {
|
|
_connectStatus.value = ConnectStatus.failed;
|
|
Get.snackbar(
|
|
'Error',
|
|
'Failed to connect to device',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.red.withOpacity(0.1),
|
|
colorText: Colors.red,
|
|
duration: const Duration(seconds: 3),
|
|
);
|
|
}
|
|
} finally {
|
|
if (!_isDisposed && _connectStatus.value == ConnectStatus.searching) {
|
|
stopSearchingAnimation();
|
|
_connectStatus.value = ConnectStatus.failed;
|
|
}
|
|
}
|
|
}
|
|
|
|
void retryConnect() {
|
|
if (_isDisposed) return;
|
|
_connectStatus.value = ConnectStatus.initial;
|
|
connectDevice();
|
|
}
|
|
|
|
void disconnectDevice() {
|
|
if (_isDisposed) return;
|
|
_connectStatus.value = ConnectStatus.initial;
|
|
Get.snackbar(
|
|
'Disconnected',
|
|
'Device has been disconnected',
|
|
snackPosition: SnackPosition.TOP,
|
|
backgroundColor: Colors.blue.withOpacity(0.1),
|
|
colorText: Colors.blue,
|
|
duration: const Duration(seconds: 3),
|
|
);
|
|
}
|
|
}
|