Browse Source

Merge branch 'new_dev' of https://github.com/deepcloud2048/deep_voice into 唤醒优化

newdev_shunjiawei
fdp 1 year ago
parent
commit
025ac6b26d
  1. 39
      lib/data/models/appconfig_model.dart
  2. 11
      lib/data/services/ble_manager.dart
  3. 9
      lib/data/services/network/api.dart
  4. 19
      lib/modules/agent/views/message_bubble.dart
  5. 24
      lib/modules/devices/controllers/devices_controller.dart
  6. 43
      lib/modules/home/controllers/home_controller.dart
  7. 58
      lib/modules/home/views/home_view.dart
  8. 48
      lib/modules/ota_upgrade/controllers/ota_core_contropller.dart
  9. 36
      lib/modules/pairing/controllers/pairing_controller.dart
  10. 1
      lib/modules/translation/controllers/translation_audiohistory_controller.dart
  11. 6
      lib/modules/translation/controllers/translation_controller.dart
  12. 1
      lib/modules/translation/controllers/translation_detail_controller.dart
  13. 1
      lib/modules/translation/controllers/translation_list_controller.dart
  14. 1
      lib/modules/translation/views/translation_history_view.dart
  15. 1
      lib/modules/translation/views/translation_view.dart

39
lib/data/models/appconfig_model.dart

@ -95,3 +95,42 @@ class DBProduct {
_$DBProductFromJson(json); _$DBProductFromJson(json);
Map<String, dynamic> toJson() => _$DBProductToJson(this); Map<String, dynamic> toJson() => _$DBProductToJson(this);
} }
//设备类型
enum DeviceType {
/// 未知设备
/// @Description 未知设备
/// @example
unknown(0), //未知设备
/// 经典蓝牙耳机
/// @Description 经典蓝牙耳机
/// @example
classicBluetoothHeadset(1), //经典蓝牙耳机
/// Ble蓝牙耳机 双端
/// @Description Ble蓝牙耳机
/// @example
bleBluetoothDoubleHeadset(2), //Ble蓝牙耳机 双端
/// Ble蓝牙耳机 单端
/// @Description Ble蓝牙耳机
/// @example
bleBluetoothSingleHeadset(3), //Ble蓝牙耳机 单端
/// 智能录音笔
/// @Description 智能录音笔
/// @example
smartVoiceRecorder(4), //智能录音笔
/// 智能眼镜
/// @Description 智能眼镜
/// @example
smartEye(5); //智能眼镜
/// 构造函数
const DeviceType(this.value);
/// 设备类型对应的整数值
final int value;
}

11
lib/data/services/ble_manager.dart

@ -1,13 +1,14 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'dart:convert';
import '../../data/models/appconfig.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:get_storage/get_storage.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:ble_service/ble_service.dart'; import 'package:ble_service/ble_service.dart';
import '../../core/utils/logger.dart';
import 'package:get_storage/get_storage.dart';
import 'dart:convert';
import 'package:agent_service/agent_service.dart'; import 'package:agent_service/agent_service.dart';
import '../../data/models/appconfig.dart';
import '../../core/utils/logger.dart';
import 'bluetooth_manager.dart'; import 'bluetooth_manager.dart';
import 'language_manager.dart'; import 'language_manager.dart';

9
lib/data/services/network/api.dart

@ -154,6 +154,15 @@ class Api {
); );
} }
// 获取验证码
static getdevices([params]) {
return DioManager().request(
NWMethod.post,
'/api/home/user_getdevices',
params: params,
);
}
//绑定设备 //绑定设备
static bindauthcode([params]) { static bindauthcode([params]) {
return DioManager().request( return DioManager().request(

19
lib/modules/agent/views/message_bubble.dart

@ -159,6 +159,10 @@ class MessageBubble extends GetView<AgentController> {
); );
} }
if (!isUser && message.isEmpty) {
return _buildTypingIndicator();
}
// 如果是图片消息,显示图片 // 如果是图片消息,显示图片
if (hasImage && imagePath != null) { if (hasImage && imagePath != null) {
// 如果消息是默认的[图片]标记,只显示图片 // 如果消息是默认的[图片]标记,只显示图片
@ -220,21 +224,6 @@ class MessageBubble extends GetView<AgentController> {
// 判断消息内容,显示特殊卡片 // 判断消息内容,显示特殊卡片
if (!isUser && meta != null) { if (!isUser && meta != null) {
// 判断消息类型,显示不同的卡片
// if (meta!.keys.contains('music_play')) {
// final card_music =
// meta!["music_play"]['card_music'] as Map<String, dynamic>?;
// if (card_music != null) {
// final musicId = card_music['id'];
// final musicName = card_music['name'] as String? ?? '未知歌曲';
// final musicUrl = card_music['url'] as String? ?? '';
// final musicSinger = card_music['sgener'] as String? ?? '未知歌手';
// final musicImage = card_music['image'] as String? ?? '';
// final ts = card_music['ts'] as int? ?? 0;
// //音乐卡片
// return buildMusicItem(context, musicId, musicName, musicUrl,
// musicSinger, musicImage, ts);
// }
if (meta!.keys.contains('music_searchandplay_songs')) { if (meta!.keys.contains('music_searchandplay_songs')) {
final music_search_songs = final music_search_songs =
meta!['music_searchandplay_songs'] as Map<String, dynamic>; meta!['music_searchandplay_songs'] as Map<String, dynamic>;

24
lib/modules/devices/controllers/devices_controller.dart

@ -1,5 +1,7 @@
import 'dart:ffi'; import 'dart:ffi';
import 'package:voitrans/data/models/appconfig_model.dart';
import '/core/utils/logger.dart'; import '/core/utils/logger.dart';
import '/data/models/user_Info.dart'; import '/data/models/user_Info.dart';
import '/data/services/ble_manager.dart'; import '/data/services/ble_manager.dart';
@ -29,8 +31,16 @@ class DevicesController extends GetxController {
} }
// 加载设备数据 // 加载设备数据
void _loadDevices() { void _loadDevices() async {
devices.clear(); devices.clear();
final response = await Api.getdevices();
if (response != null) {
var devices = (response['devices'] as List<dynamic>)
.map((e) => UserDevice.fromJson(e as Map<String, dynamic>))
.toList();
User.instance.devices = devices;
}
for (var device in User.instance.devices) { for (var device in User.instance.devices) {
if (!devices.containsKey(device.devicetype)) { if (!devices.containsKey(device.devicetype)) {
devices[device.devicetype] = []; devices[device.devicetype] = [];
@ -54,11 +64,13 @@ class DevicesController extends GetxController {
devices[device.devicetype]?.remove(device); devices[device.devicetype]?.remove(device);
devices.refresh(); // 触发UI更新 devices.refresh(); // 触发UI更新
User.instance.removeUserDevice(device.id); if (device.devicemac == _bleManager.deviceInfo.value?.address) {
_bleManager.clearPairedDevices(); User.instance.removeUserDevice(device.id);
_bleManager.disconnect(); _bleManager.clearPairedDevices();
await Future.delayed(const Duration(seconds: 1)); _bleManager.disconnect();
Get.toNamed(Routes.pairing); await Future.delayed(const Duration(seconds: 1));
Get.toNamed(Routes.pairing);
}
return; return;
} else { } else {
return; return;

43
lib/modules/home/controllers/home_controller.dart

@ -8,6 +8,8 @@ import 'package:flutter/material.dart';
import '../../../data/services/bluetooth_manager.dart'; import '../../../data/services/bluetooth_manager.dart';
import '../../../data/services/ble_manager.dart'; import '../../../data/services/ble_manager.dart';
import '../../../data/services/ota_check_service.dart'; import '../../../data/services/ota_check_service.dart';
import '../../../data/models/appconfig.dart';
import '../../../data/models/appconfig_model.dart';
/// 连接状态枚举 /// 连接状态枚举
enum ConnectionStatus { enum ConnectionStatus {
@ -328,6 +330,47 @@ class HomeController extends GetxController {
return isCharging ? 'charging'.tr : 'notCharging'.tr; return isCharging ? 'charging'.tr : 'notCharging'.tr;
} }
/// 获取当前设备类型
/// 返回设备类型,如果无法获取则返回未知类型
DeviceType getCurrentDeviceType() {
try {
final deviceName = getDeviceName();
if (deviceName == 'unknownEquipment'.tr) {
return DeviceType.unknown;
}
// 通过AppConfig获取产品信息
final product = AppConfig.getproduct(deviceName);
if (product != null) {
// 根据产品的devicetype字段返回对应的DeviceType
switch (product.devicetype) {
case 1:
return DeviceType.classicBluetoothHeadset;
case 2:
return DeviceType.bleBluetoothDoubleHeadset;
case 3:
return DeviceType.bleBluetoothSingleHeadset;
case 4:
return DeviceType.smartVoiceRecorder;
case 5:
return DeviceType.smartEye;
default:
return DeviceType.unknown;
}
}
return DeviceType.unknown;
} catch (e) {
Logger.e(_tag, '获取设备类型失败: $e');
return DeviceType.unknown;
}
}
/// 判断当前设备是否为单端耳机
bool isSingleHeadset() {
return getCurrentDeviceType() == DeviceType.bleBluetoothSingleHeadset;
}
String getVersionText() { String getVersionText() {
return deviceInfo.value?.firmwareVersion.isNotEmpty == true return deviceInfo.value?.firmwareVersion.isNotEmpty == true
? deviceInfo.value!.firmwareVersion ? deviceInfo.value!.firmwareVersion

58
lib/modules/home/views/home_view.dart

@ -462,6 +462,9 @@ class HomeView extends GetView<HomeController> {
final shouldShowCase = final shouldShowCase =
caseBattery.value > 0 && controller.isFullyConnectedRx.value; caseBattery.value > 0 && controller.isFullyConnectedRx.value;
// 判断是否为单端耳机
final isSingleHeadset = controller.isSingleHeadset();
// 使用更紧凑的布局 // 使用更紧凑的布局
return Container( return Container(
padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 4.w), padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 4.w),
@ -472,28 +475,43 @@ class HomeView extends GetView<HomeController> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
// 左耳机 // 单端耳机只显示一个电池信息(优先显示左耳,如果左耳电量为0则显示右耳)
_buildCompactBatteryItem( if (isSingleHeadset) ...[
label: 'left'.tr, // 左 _buildCompactBatteryItem(
batteryLevel: leftBattery.value, label: 'deviceTypeBleBluetoothHeadset'.tr,
isCharging: leftEarCharging.value, batteryLevel: (leftBattery.value > 0 || rightBattery.value == 0)
isDarkMode: isDarkMode, ? leftBattery.value
), : rightBattery.value,
isCharging: (leftBattery.value > 0 || rightBattery.value == 0)
? leftEarCharging.value
: rightEarCharging.value,
isDarkMode: isDarkMode,
),
] else ...[
// 双端耳机显示左右两个电池信息
// 左耳机
_buildCompactBatteryItem(
label: 'left'.tr, // 左
batteryLevel: leftBattery.value,
isCharging: leftEarCharging.value,
isDarkMode: isDarkMode,
),
// 分隔线 // 分隔线
Container( Container(
height: 30.h, height: 30.h,
width: 1, width: 1,
color: isDarkMode ? Colors.grey[800] : Colors.grey[300], color: isDarkMode ? Colors.grey[800] : Colors.grey[300],
), ),
// 右耳机 // 右耳机
_buildCompactBatteryItem( _buildCompactBatteryItem(
label: 'right'.tr, // 右 label: 'right'.tr, // 右
batteryLevel: rightBattery.value, batteryLevel: rightBattery.value,
isCharging: rightEarCharging.value, isCharging: rightEarCharging.value,
isDarkMode: isDarkMode, isDarkMode: isDarkMode,
), ),
],
// 只有在充电盒电量大于0且设备已连接时才显示充电盒 // 只有在充电盒电量大于0且设备已连接时才显示充电盒
if (shouldShowCase) ...[ if (shouldShowCase) ...[

48
lib/modules/ota_upgrade/controllers/ota_core_contropller.dart

@ -288,19 +288,51 @@ class OtaCoreService {
throw "获取设备信息失败,请检查连接"; throw "获取设备信息失败,请检查连接";
} }
// 验证固件版本格式 // 获取产品信息以确定设备类型
final firmwareParts = deviceInfo.firmwareVersion.split('.'); DBProduct? product = AppConfig.getproduct("DeapSound");
final firstPart = firmwareParts.sublist(0, 3).join('.'); if (product == null) {
final secondPart = firmwareParts.sublist(3).join('.'); throw "无法获取产品信息";
}
Logger().d("firstPart: $firstPart, secondPart: $secondPart"); // 根据设备类型进行不同的版本校验
String currentVersion;
if (product.devicetype == DeviceType.bleBluetoothSingleHeadset.value) {
// 单端耳机:固件版本只有三位数(如:1.2.3)
final firmwareParts = deviceInfo.firmwareVersion.split('.');
if (firmwareParts.length < 3) {
throw "单端耳机固件版本格式错误:${deviceInfo.firmwareVersion},应为三位数格式(如:1.2.3)";
}
currentVersion = firmwareParts.sublist(0, 3).join('.');
Logger().d("单端耳机版本: $currentVersion");
} else if (product.devicetype ==
DeviceType.bleBluetoothDoubleHeadset.value) {
// 双端耳机:固件版本有六位数(如:1.2.3.1.2.3)
final firmwareParts = deviceInfo.firmwareVersion.split('.');
if (firmwareParts.length < 6) {
throw "双端耳机固件版本格式错误:${deviceInfo.firmwareVersion},应为六位数格式(如:1.2.3.1.2.3)";
}
final firstPart = firmwareParts.sublist(0, 3).join('.');
final secondPart = firmwareParts.sublist(3, 6).join('.');
Logger().d("双端耳机版本 - firstPart: $firstPart, secondPart: $secondPart");
if (firstPart != secondPart) { if (firstPart != secondPart) {
throw "固件版本格式错误:${deviceInfo.firmwareVersion}"; throw "双端耳机固件版本格式错误:${deviceInfo.firmwareVersion},前三位和后三位应该相同";
}
currentVersion = firstPart;
} else {
// 其他设备类型,使用原有逻辑
final firmwareParts = deviceInfo.firmwareVersion.split('.');
if (firmwareParts.length >= 3) {
currentVersion = firmwareParts.sublist(0, 3).join('.');
} else {
currentVersion = deviceInfo.firmwareVersion;
}
Logger().d("其他设备类型版本: $currentVersion");
} }
return { return {
'currentVersion': firstPart, 'currentVersion': currentVersion,
'productId': deviceInfo.firmwareProductId, 'productId': deviceInfo.firmwareProductId,
'deviceInfo': deviceInfo, 'deviceInfo': deviceInfo,
}; };

36
lib/modules/pairing/controllers/pairing_controller.dart

@ -1,17 +1,18 @@
import 'dart:io';
import 'dart:async';
import 'package:app_settings/app_settings.dart'; import 'package:app_settings/app_settings.dart';
import 'package:voitrans/data/models/appconfig_model.dart';
import '/data/models/appconfig.dart';
import '/data/models/user_Info.dart';
import '/data/services/network/api.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'dart:async';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import '../../../routes/app_routes.dart'; import '../../../routes/app_routes.dart';
import '../../../core/utils/logger.dart'; import '../../../core/utils/logger.dart';
import 'dart:io'; import '/data/models/appconfig_model.dart';
import '/data/models/appconfig.dart';
import '/data/models/user_Info.dart';
import '/data/services/network/api.dart';
import '../../../data/services/bluetooth_manager.dart'; import '../../../data/services/bluetooth_manager.dart';
import '../../../data/services/ble_manager.dart'; import '../../../data/services/ble_manager.dart';
import '../../../core/utils/permission_util.dart'; import '../../../core/utils/permission_util.dart';
@ -347,7 +348,7 @@ class PairingController extends GetxController with WidgetsBindingObserver {
void _handleBleStateChange(int state) { void _handleBleStateChange(int state) {
if (_currentState.value == PairingState.waitingBle) { if (_currentState.value == PairingState.waitingBle) {
if (state == 2) { if (state == 2) {
// BLE已连接 // 2代表BLE已连接
_bleTimeoutTimer?.cancel(); _bleTimeoutTimer?.cancel();
_transition(PairingState.completed); _transition(PairingState.completed);
} }
@ -501,32 +502,33 @@ class PairingController extends GetxController with WidgetsBindingObserver {
/// 检查当前状态并决定下一步 /// 检查当前状态并决定下一步
void _checkCurrentStatus() async { void _checkCurrentStatus() async {
try { try {
// 1. 检查蓝牙状态 // 1. 并行检查蓝牙状态、权限、设备连接
final results = await Future.wait([ final results = await Future.wait([
_checkBluetoothState(), // 检查蓝牙状态 _checkBluetoothState(), // 检查蓝牙是否开启
_checkPermissions(), // 检查权限 _checkPermissions(), // 检查蓝牙相关权限
_bluetoothManager.refreshDeviceConnection(), // 刷新设备连接 _bluetoothManager.refreshDeviceConnection(), // 刷新设备连接状态
]); ]);
final isBluetoothOk = results[0] as bool; final isBluetoothOk = results[0] as bool;
final arePermissionsOk = results[1] as bool; final arePermissionsOk = results[1] as bool;
//蓝牙没开
if (!isBluetoothOk) { if (!isBluetoothOk) {
_setError( _setError(
ErrorType.bluetoothOff, 'connectDeepSoundViaSystemBluetooth'.tr); ErrorType.bluetoothOff, 'connectDeepSoundViaSystemBluetooth'.tr);
return; return;
} }
// 2. 检查权限 //权限不够
if (!arePermissionsOk) { if (!arePermissionsOk) {
_setError(ErrorType.noPermission, 'pleaseGrantNecessaryPermissions'.tr); _setError(ErrorType.noPermission, 'pleaseGrantNecessaryPermissions'.tr);
return; return;
} }
// 3. 先刷新设备连接状态,确保获取最新的连接信息 // 2. 先刷新设备连接状态,确保获取最新的连接信息
await _bluetoothManager.refreshDeviceConnection(); //await _bluetoothManager.refreshDeviceConnection();
// 4. 检查经典蓝牙连接 // 3. 检查经典蓝牙连接
final classicDevice = _bluetoothManager.currentDevice; final classicDevice = _bluetoothManager.currentDevice;
if (classicDevice == null) { if (classicDevice == null) {
_transition(PairingState.waitingClassic); _transition(PairingState.waitingClassic);
@ -543,7 +545,7 @@ class PairingController extends GetxController with WidgetsBindingObserver {
} }
} }
/// 新增一个辅助方法来检查蓝牙状态 /// 检查蓝牙状态是否开启
Future<bool> _checkBluetoothState() async { Future<bool> _checkBluetoothState() async {
return _bluetoothManager.bluetoothState != 'off'; return _bluetoothManager.bluetoothState != 'off';
} }
@ -727,7 +729,7 @@ class PairingController extends GetxController with WidgetsBindingObserver {
// 检查设备名称是否包含 DeepSound 或 DeapSound // 检查设备名称是否包含 DeepSound 或 DeapSound
final deviceName = device.name; final deviceName = device.name;
DBProduct? product; DBProduct? product;
// 检查是否已有BLE绑定的设备
/// 检查是否已有BLE绑定的设备 /// 检查是否已有BLE绑定的设备
if (AppConfig.config.products.isNotEmpty) { if (AppConfig.config.products.isNotEmpty) {
final match = AppConfig.config.products.where( final match = AppConfig.config.products.where(

1
lib/modules/translation/controllers/translation_audiohistory_controller.dart

@ -6,6 +6,7 @@ import 'dart:async';
import '../models/translation_models.dart'; // 添加异步支持 import '../models/translation_models.dart'; // 添加异步支持
//音频历史管理
class TranslationAudioHistoryController extends GetxController { class TranslationAudioHistoryController extends GetxController {
// 引用主翻译控制器,以访问历史记录数据 // 引用主翻译控制器,以访问历史记录数据
final TranslationController translationController = final TranslationController translationController =

6
lib/modules/translation/controllers/translation_controller.dart

@ -1,9 +1,8 @@
import 'dart:io'; import 'dart:io';
import 'dart:async';
import '../../../core/utils/permission_util.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'dart:async';
import 'package:get_storage/get_storage.dart'; import 'package:get_storage/get_storage.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
@ -16,6 +15,7 @@ import '../../../data/services/volcano_translation_service.dart';
import '../../../data/services/tts_service.dart'; import '../../../data/services/tts_service.dart';
import '../../../data/services/language_manager.dart'; import '../../../data/services/language_manager.dart';
import '../../../core/utils/logger.dart'; import '../../../core/utils/logger.dart';
import '../../../core/utils/permission_util.dart';
import '../../../data/services/asr_service.dart'; import '../../../data/services/asr_service.dart';
import '../../../data/services/translation_usage_service.dart'; import '../../../data/services/translation_usage_service.dart';
@ -31,7 +31,7 @@ enum AudioOutputDevice {
speaker, // 强制扬声器 speaker, // 强制扬声器
} }
/// 翻译控制器 - 负责管理语音识别、翻译和TTS功能 /// 翻译控制器 - 负责管理语音识别、翻译和TTS功能(主控制器)
class TranslationController extends GetxController with WidgetsBindingObserver { class TranslationController extends GetxController with WidgetsBindingObserver {
static const String TAG = 'TranslationController'; static const String TAG = 'TranslationController';

1
lib/modules/translation/controllers/translation_detail_controller.dart

@ -9,6 +9,7 @@ import 'dart:async';
import '../../../core/utils/logger.dart'; import '../../../core/utils/logger.dart';
import '../../../data/services/translation_usage_service.dart'; import '../../../data/services/translation_usage_service.dart';
//详情页管理
class TranslationDetailController extends GetxController { class TranslationDetailController extends GetxController {
// 依赖注入 // 依赖注入
final VolcanoAIService _aiService = Get.find<VolcanoAIService>(); final VolcanoAIService _aiService = Get.find<VolcanoAIService>();

1
lib/modules/translation/controllers/translation_list_controller.dart

@ -10,6 +10,7 @@ import '../../../core/utils/permission_util.dart';
import 'package:share_plus/share_plus.dart'; import 'package:share_plus/share_plus.dart';
//列表页管理
class TranslationListController extends GetxController { class TranslationListController extends GetxController {
// 是否还有更多数据 // 是否还有更多数据
bool isGetMore = true; bool isGetMore = true;

1
lib/modules/translation/views/translation_history_view.dart

@ -10,6 +10,7 @@ import 'translation_detail_view.dart';
import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_colors.dart';
import '../../../data/services/language_manager.dart'; import '../../../data/services/language_manager.dart';
//历史记录页面
class TranslationHistoryView class TranslationHistoryView
extends GetView<TranslationAudioHistoryController> { extends GetView<TranslationAudioHistoryController> {
const TranslationHistoryView({Key? key}) : super(key: key); const TranslationHistoryView({Key? key}) : super(key: key);

1
lib/modules/translation/views/translation_view.dart

@ -12,6 +12,7 @@ import '../../../core/theme/app_colors.dart';
import '../../../routes/app_routes.dart'; import '../../../routes/app_routes.dart';
// import 'package:intl/intl.dart'; // import 'package:intl/intl.dart';
//主页面
class TranslationView extends GetView<TranslationController> { class TranslationView extends GetView<TranslationController> {
const TranslationView({Key? key}) : super(key: key); const TranslationView({Key? key}) : super(key: key);

Loading…
Cancel
Save