Browse Source

唤醒开关支持

weicu
liwei1dao 7 months ago
parent
commit
fed996403d
  1. 96
      lib/data/services/ble_manager.dart
  2. 74
      lib/modules/settings/controllers/settings_controller.dart
  3. 35
      lib/modules/settings/views/settings_view.dart
  4. 2
      local_plugins/azure_speech/ios/azure_speech/Sources/tools/SimpleAudioReceiver.swift
  5. 33
      local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleCommandSender.kt
  6. 11
      local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleConst.kt
  7. 21
      local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt
  8. 9
      local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleServicePlugin.kt
  9. 10
      local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleConst.swift
  10. 41
      local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift
  11. 8
      local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftBleServicePlugin.swift
  12. 26
      local_plugins/ble_service/lib/ble_service.dart

96
lib/data/services/ble_manager.dart

@ -27,6 +27,8 @@ class BleCommands {
static const int GET_BATTERY_INFO = 0x04; static const int GET_BATTERY_INFO = 0x04;
static const int CONTROL_CODEC = 0x05; static const int CONTROL_CODEC = 0x05;
static const int GET_WAKEUP_VERSION = 0x08; static const int GET_WAKEUP_VERSION = 0x08;
static const int GET_VOICE_WAKEUP_STATUS = 0x14;
static const int SET_VOICE_WAKEUP_STATUS = 0x15;
} }
/// 判断编解码控制指令是否成功 /// 判断编解码控制指令是否成功
@ -216,6 +218,15 @@ class BleManager extends GetxService {
bool _awaitingCodecOpen = false; //是否正在等待编码器打开的成功应答 bool _awaitingCodecOpen = false; //是否正在等待编码器打开的成功应答
bool _awaitingCodecClose = false; //是否正在等待编码器关闭的成功应答 bool _awaitingCodecClose = false; //是否正在等待编码器关闭的成功应答
// 语音唤醒状态
final _voiceWakeupEnabled = true.obs; // 唤醒开关状态,默认开启
bool get voiceWakeupEnabled => _voiceWakeupEnabled.value;
RxBool get voiceWakeupEnabledRx => _voiceWakeupEnabled;
final _voiceWakeupSupported = false.obs; // 耳机是否支持语音唤醒功能
bool get voiceWakeupSupported => _voiceWakeupSupported.value;
RxBool get voiceWakeupSupportedRx => _voiceWakeupSupported;
// 订阅 // 订阅
StreamSubscription<dynamic>? _statusSubscription; StreamSubscription<dynamic>? _statusSubscription;
StreamSubscription<dynamic>? _dataSubscription; StreamSubscription<dynamic>? _dataSubscription;
@ -275,14 +286,7 @@ class BleManager extends GetxService {
Logger.info('lxm--BLE设备已连接'); Logger.info('lxm--BLE设备已连接');
_isConnected.value = true; _isConnected.value = true;
// 在连接成功后延迟 300 毫秒获取设备信息(可根据需要调整时间) // 设备信息(含唤醒状态)由 HomeController.fetchDeviceInfo() 统一查询
Future.delayed(const Duration(milliseconds: 300), () {
// 可选:检查是否仍处于连接状态
if (_isConnected.value) {
Logger.info('lxm--连接后延迟获取设备信息(当前被注释)');
// fetchDeviceInfo();
}
});
} else if (state == BleConnectionState.disconnected || } else if (state == BleConnectionState.disconnected ||
state == BleConnectionState.error) { state == BleConnectionState.error) {
Logger.info('lxm--BLE设备已断开或发生错误'); Logger.info('lxm--BLE设备已断开或发生错误');
@ -290,6 +294,9 @@ class BleManager extends GetxService {
_awaitingCodecOpen = false; _awaitingCodecOpen = false;
_awaitingCodecClose = false; _awaitingCodecClose = false;
_isCodecActive.value = false; _isCodecActive.value = false;
_voiceWakeupSupported.value = false;
_voiceWakeupEnabled.value = true;
Logger.info('[VoiceWakeup] 断开连接,重置 supported=false, enabled=true');
Logger.info('lxm--断开连接时重置设备信息为0'); Logger.info('lxm--断开连接时重置设备信息为0');
_updateDeviceInfoIfNeeded( _updateDeviceInfoIfNeeded(
batteryLevel: 0, batteryLevel: 0,
@ -447,6 +454,14 @@ class BleManager extends GetxService {
Logger.info('lxm--处理唤醒语音版本命令'); Logger.info('lxm--处理唤醒语音版本命令');
_updateWakeupVersionFromData(data); _updateWakeupVersionFromData(data);
break; break;
case BleCommands.GET_VOICE_WAKEUP_STATUS:
Logger.info('[VoiceWakeup] 收到查询响应(0x14), data: $data');
_updateVoiceWakeupStatusFromData(data);
break;
case BleCommands.SET_VOICE_WAKEUP_STATUS:
Logger.info('[VoiceWakeup] 收到设置响应(0x15), data: $data');
_updateVoiceWakeupSetResultFromData(data);
break;
default: default:
Logger.warning('lxm--未处理的命令ID: $commandId,数据: $data'); Logger.warning('lxm--未处理的命令ID: $commandId,数据: $data');
print(" 未处理的命令ID: $commandId,$data"); print(" 未处理的命令ID: $commandId,$data");
@ -636,6 +651,64 @@ class BleManager extends GetxService {
} }
} }
/// 更新语音唤醒状态(0x14 查询响应)
void _updateVoiceWakeupStatusFromData(Map<dynamic, dynamic> data) {
try {
if (!data.containsKey('voiceWakeupEnabled')) {
Logger.warning('[VoiceWakeup] 查询响应数据不完整,缺少 voiceWakeupEnabled');
return;
}
final bool enabled = data['voiceWakeupEnabled'] as bool? ?? true;
_voiceWakeupEnabled.value = enabled;
_voiceWakeupSupported.value = true;
Logger.info('[VoiceWakeup] 查询成功 → supported=true, enabled=${enabled ? "开启" : "关闭"}');
} catch (e) {
Logger.error('[VoiceWakeup] 解析查询响应异常: ${e.toString()}');
}
}
/// 处理设置语音唤醒的响应(0x15 设置响应)
void _updateVoiceWakeupSetResultFromData(Map<dynamic, dynamic> data) {
try {
final bool setSuccess = data['voiceWakeupSetSuccess'] as bool? ?? false;
if (setSuccess) {
Logger.info('[VoiceWakeup] 设置成功 → enabled=${_voiceWakeupEnabled.value ? "开启" : "关闭"}');
} else {
Logger.warning('[VoiceWakeup] 设置失败 → supported=false,开关置灰');
_voiceWakeupSupported.value = false;
}
} catch (e) {
Logger.error('[VoiceWakeup] 解析设置响应异常: ${e.toString()}');
}
}
/// 查询语音唤醒状态
Future<bool> queryVoiceWakeupStatus() async {
Logger.info('[VoiceWakeup] 发送查询命令(0x14)...');
final result = await _bleService.getVoiceWakeupStatus();
if (!result) {
_voiceWakeupSupported.value = false;
Logger.warning('[VoiceWakeup] 查询命令发送失败 → supported=false,设备可能不支持');
} else {
Logger.info('[VoiceWakeup] 查询命令发送成功,等待设备响应...');
}
return result;
}
/// 设置语音唤醒状态
Future<bool> setVoiceWakeupStatus(bool enabled) async {
Logger.info('[VoiceWakeup] 发送设置命令(0x15), enabled=${enabled ? "开启" : "关闭"}...');
_voiceWakeupEnabled.value = enabled; // 乐观更新
final result = await _bleService.setVoiceWakeupStatus(enabled);
if (!result) {
_voiceWakeupSupported.value = false;
Logger.warning('[VoiceWakeup] 设置命令发送失败 → supported=false,开关置灰');
} else {
Logger.info('[VoiceWakeup] 设置命令发送成功,等待设备响应...');
}
return result;
}
/// 更新设备信息(如果已存在设备) /// 更新设备信息(如果已存在设备)
void _updateDeviceInfoIfNeeded({ void _updateDeviceInfoIfNeeded({
int? batteryLevel, int? batteryLevel,
@ -783,10 +856,11 @@ class BleManager extends GetxService {
_bleService.getBatteryInfo(), _bleService.getBatteryInfo(),
_bleService.getDeviceVersion(), _bleService.getDeviceVersion(),
_bleService.getProductId(), _bleService.getProductId(),
_bleService.getVoiceWakeupStatus(),
]); ]);
Logger.info( Logger.info(
'设备信息获取结果: 电池=${results[0]}, 版本=${results[1]}, 产品ID=${results[2]}'); '设备信息获取结果: 电池=${results[0]}, 版本=${results[1]}, 产品ID=${results[2]}, 唤醒状态=${results[3]}');
if (!results[0]) { if (!results[0]) {
Logger.warning('电池信息获取指令发送失败'); Logger.warning('电池信息获取指令发送失败');
@ -797,6 +871,10 @@ class BleManager extends GetxService {
if (!results[2]) { if (!results[2]) {
Logger.warning('产品ID获取指令发送失败'); Logger.warning('产品ID获取指令发送失败');
} }
if (!results[3]) {
Logger.warning('语音唤醒状态获取指令发送失败');
_voiceWakeupSupported.value = false;
}
} catch (e) { } catch (e) {
Logger.error('获取BLE设备信息失败: ${e.toString()}'); Logger.error('获取BLE设备信息失败: ${e.toString()}');
} }

74
lib/modules/settings/controllers/settings_controller.dart

@ -16,6 +16,7 @@ import '../models/language_model.dart';
import '../models/app_supported_languages.dart'; import '../models/app_supported_languages.dart';
import '../../../data/services/language_manager.dart'; import '../../../data/services/language_manager.dart';
import '../../../data/services/version_update_service.dart'; import '../../../data/services/version_update_service.dart';
import '../../../data/services/ble_manager.dart';
import '../../common/widgets/version_update_dialog.dart'; import '../../common/widgets/version_update_dialog.dart';
class SettingsController extends GetxController { class SettingsController extends GetxController {
@ -44,6 +45,12 @@ class SettingsController extends GetxController {
DateTime? _lastClickTime; // 上次点击时间 DateTime? _lastClickTime; // 上次点击时间
final RxBool showDebugInfo = false.obs; // 是否显示调试信息 final RxBool showDebugInfo = false.obs; // 是否显示调试信息
// 语音唤醒相关
late final BleManager _bleManager;
final RxBool isVoiceWakeupEnabled = true.obs;
final RxBool isBleConnected = false.obs;
final RxBool isVoiceWakeupSupported = false.obs;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
@ -59,6 +66,73 @@ class SettingsController extends GetxController {
// 获取应用版本信息 // 获取应用版本信息
getAppVersion(); getAppVersion();
// 语音唤醒相关初始化
_initVoiceWakeup();
}
/// 初始化语音唤醒功能
void _initVoiceWakeup() {
_bleManager = Get.find<BleManager>();
// 同步初始连接状态
isBleConnected.value = _bleManager.isConnected;
isVoiceWakeupSupported.value = _bleManager.voiceWakeupSupported;
isVoiceWakeupEnabled.value = _bleManager.voiceWakeupEnabled;
// 监听BLE连接状态变化
// 注意:ever 回调同步触发,此时 _isConnected 可能尚未更新,
// 因此直接用 state 参数判断连接状态
ever<int>(_bleManager.connectionStateRx, (state) {
final connected = state == BleConnectionState.connected;
isBleConnected.value = connected;
if (connected) {
// 连接后延迟查询唤醒状态
Future.delayed(const Duration(milliseconds: 500), () {
if (_bleManager.isConnected) {
_queryVoiceWakeupStatus();
}
});
}
});
// 监听语音唤醒状态变化
ever<bool>(_bleManager.voiceWakeupEnabledRx, (enabled) {
isVoiceWakeupEnabled.value = enabled;
});
// 监听语音唤醒支持状态变化
ever<bool>(_bleManager.voiceWakeupSupportedRx, (supported) {
isVoiceWakeupSupported.value = supported;
});
// 如果当前已连接,立即查询
if (_bleManager.isConnected) {
_queryVoiceWakeupStatus();
}
}
/// 查询语音唤醒状态
Future<void> _queryVoiceWakeupStatus() async {
try {
await _bleManager.queryVoiceWakeupStatus();
} catch (e) {
Logger().e('查询语音唤醒状态失败: $e');
}
}
/// 切换语音唤醒状态
Future<void> toggleVoiceWakeup(bool enabled) async {
try {
final success = await _bleManager.setVoiceWakeupStatus(enabled);
if (!success) {
// 命令发送失败,BleManager 已将 supported 设为 false
Logger().w('语音唤醒设置命令发送失败');
}
} catch (e) {
Logger().e('设置语音唤醒状态失败: $e');
_bleManager.voiceWakeupSupportedRx.value = false;
}
} }
// 获取应用版本信息的方法 // 获取应用版本信息的方法

35
lib/modules/settings/views/settings_view.dart

@ -437,6 +437,39 @@ class SettingsView extends GetView<SettingsController> {
? const Color(0xFF2C2C2C) ? const Color(0xFF2C2C2C)
: Colors.grey[200]), : Colors.grey[200]),
// 语音唤醒开关
Obx(
() {
final connected = controller.isBleConnected.value;
final supported = controller.isVoiceWakeupSupported.value;
final canToggle = connected && supported;
return _buildToggleSetting(
title: '语音唤醒',
subtitle: !connected
? '请先连接耳机'
: !supported
? '当前设备不支持此功能'
: '控制耳机语音唤醒功能的开关',
icon: Icons.mic,
iconBgColor: isDarkMode
? Colors.teal[900]!.withValues(alpha: 0.3)
: Colors.teal[100]!,
iconColor:
isDarkMode ? Colors.teal[300]! : Colors.teal[600]!,
value: controller.isVoiceWakeupEnabled.value,
onChanged: canToggle
? (enabled) => controller.toggleVoiceWakeup(enabled)
: null,
isDarkMode: isDarkMode,
);
},
),
Divider(
height: 1,
color: isDarkMode
? const Color(0xFF2C2C2C)
: Colors.grey[200]),
// 用户反馈 // 用户反馈
_buildSimpleNavigationSetting( _buildSimpleNavigationSetting(
title: 'feedback'.tr, // 用户反馈 title: 'feedback'.tr, // 用户反馈
@ -912,7 +945,7 @@ class SettingsView extends GetView<SettingsController> {
required Color iconBgColor, required Color iconBgColor,
required Color iconColor, required Color iconColor,
required bool value, required bool value,
required Function(bool) onChanged, Function(bool)? onChanged,
required bool isDarkMode, required bool isDarkMode,
}) { }) {
return Padding( return Padding(

2
local_plugins/azure_speech/ios/azure_speech/Sources/tools/SimpleAudioReceiver.swift

@ -203,6 +203,8 @@ public class SimpleAudioReceiver: NSObject {
// 仅在需要时更新会话,避免不必要的中断 // 仅在需要时更新会话,避免不必要的中断
if audioSession.category != desiredCategory || audioSession.mode != desiredMode || audioSession.categoryOptions != desiredOptions { if audioSession.category != desiredCategory || audioSession.mode != desiredMode || audioSession.categoryOptions != desiredOptions {
// 音频路由真正变更时,等待 UI 动画完成再执行,避免 mediaserverd XPC 路由通知与动画竞争导致卡顿
Thread.sleep(forTimeInterval: 0.25)
try audioSession.setCategory(desiredCategory, mode: desiredMode, options: desiredOptions) try audioSession.setCategory(desiredCategory, mode: desiredMode, options: desiredOptions)
} }

33
local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleCommandSender.kt

@ -192,7 +192,7 @@ class BleCommandSender {
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
fun processDeviceResponse(data: ByteArray) { fun processDeviceResponse(data: ByteArray) {
Log.d( Log.i(
TAG, TAG,
"收到设备响应: ${data.joinToString(", ") { "0x${(it.toInt() and 0xFF).toString(16)}" }}" "收到设备响应: ${data.joinToString(", ") { "0x${(it.toInt() and 0xFF).toString(16)}" }}"
) )
@ -435,6 +435,33 @@ class BleCommandSender {
Log.d(TAG, "获取唤醒词版本号:leftVersionDec: $leftVersionDec,rightVersionDec: $rightVersionDec") Log.d(TAG, "获取唤醒词版本号:leftVersionDec: $leftVersionDec,rightVersionDec: $rightVersionDec")
callback?.notifyDeviceInfoReceived(cmdType, resultMap) callback?.notifyDeviceInfoReceived(cmdType, resultMap)
} }
BleConst.CMD_GET_VOICE_WAKEUP_STATUS -> {
val resultMap = mutableMapOf<String, Any>(
"success" to true,
"command" to cmdType
)
if (responseData.isNotEmpty()) {
val status = responseData[0].toInt() and 0xFF
val wakeupEnabled = status == BleConst.VOICE_WAKEUP_ON
resultMap["voiceWakeupEnabled"] = wakeupEnabled
Log.i(TAG, "语音唤醒状态: ${if (wakeupEnabled) "开启" else "关闭"}")
}
callback?.notifyDeviceInfoReceived(cmdType, resultMap)
}
BleConst.CMD_SET_VOICE_WAKEUP_STATUS -> {
val resultMap = mutableMapOf<String, Any>(
"success" to true,
"command" to cmdType
)
if (responseData.size >= 2) {
val cmdStatus = responseData[0].toInt() and 0xFF
val setSuccess = (responseData[1].toInt() and 0xFF) == 0x01
resultMap["voiceWakeupSetSuccess"] = setSuccess
resultMap["voiceWakeupCmdStatus"] = cmdStatus
Log.i(TAG, "设置语音唤醒结果: ${if (setSuccess) "成功" else "失败"}")
}
callback?.notifyDeviceInfoReceived(cmdType, resultMap)
}
else -> { else -> {
// 对于未知命令,返回原始数据 // 对于未知命令,返回原始数据
val resultMap = mapOf( val resultMap = mapOf(
@ -651,11 +678,11 @@ class BleCommandSender {
*/ */
private fun logCommandDetails(cmdType: Byte, cmdData: ByteArray, cmdPacket: ByteArray) { private fun logCommandDetails(cmdType: Byte, cmdData: ByteArray, cmdPacket: ByteArray) {
val crc = cmdPacket[cmdPacket.size - 1] val crc = cmdPacket[cmdPacket.size - 1]
Log.d( Log.i(
TAG, TAG,
"发送命令: CMD=0x${(cmdType.toInt() and 0xFF).toString(16)}, 长度=${cmdData.size}, " + "发送命令: CMD=0x${(cmdType.toInt() and 0xFF).toString(16)}, 长度=${cmdData.size}, " +
"数据=${cmdData.joinToString(", ") { "0x${(it.toInt() and 0xFF).toString(16)}" }}, " + "数据=${cmdData.joinToString(", ") { "0x${(it.toInt() and 0xFF).toString(16)}" }}, " +
"CRC=0x${(crc.toInt() and 0xFF).toString(16)}" "完整包=${cmdPacket.joinToString(", ") { "0x${(it.toInt() and 0xFF).toString(16)}" }}"
) )
} }

11
local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleConst.kt

@ -97,6 +97,17 @@ object BleConst {
/** 唤醒指令 */ /** 唤醒指令 */
const val CMD_WAKE_UP = 0x11 const val CMD_WAKE_UP = 0x11
/** 查询语音唤醒状态 */
const val CMD_GET_VOICE_WAKEUP_STATUS = 0x14
/** 设置语音唤醒状态 */
const val CMD_SET_VOICE_WAKEUP_STATUS = 0x15
// ================== 语音唤醒状态值 ==================
/** 语音唤醒关闭 */
const val VOICE_WAKEUP_OFF = 0xE0
/** 语音唤醒开启 */
const val VOICE_WAKEUP_ON = 0xE1
// ================== 编解码控制值 ================== // ================== 编解码控制值 ==================
/** 关闭编解码指令 */ /** 关闭编解码指令 */
const val CODEC_CONTROL_CLOSE = 0x00 const val CODEC_CONTROL_CLOSE = 0x00

21
local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt

@ -1680,6 +1680,27 @@ object BleService {
return commandSender.sendCommand(BleConst.CMD_GET_WAKEUP_VERSION.toByte(),cmdData) return commandSender.sendCommand(BleConst.CMD_GET_WAKEUP_VERSION.toByte(),cmdData)
} }
/**
* 查询语音唤醒状态
* @return 是否成功发送命令
*/
fun getVoiceWakeupStatus(): Boolean {
Log.i(TAG, "查询语音唤醒状态...")
val cmdData = byteArrayOf(0xFF.toByte())
return commandSender.sendCommand(BleConst.CMD_GET_VOICE_WAKEUP_STATUS.toByte(), cmdData)
}
/**
* 设置语音唤醒状态
* @param enabled 是否开启语音唤醒
* @return 是否成功发送命令
*/
fun setVoiceWakeupStatus(enabled: Boolean): Boolean {
val status = if (enabled) BleConst.VOICE_WAKEUP_ON.toByte() else BleConst.VOICE_WAKEUP_OFF.toByte()
Log.i(TAG, "设置语音唤醒状态: ${if (enabled) "开启" else "关闭"}")
return commandSender.sendCommand(BleConst.CMD_SET_VOICE_WAKEUP_STATUS.toByte(), byteArrayOf(status))
}
// ====================================================================================================== // ======================================================================================================
// 连接状态和工具方法 // 连接状态和工具方法
// ====================================================================================================== // ======================================================================================================

9
local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleServicePlugin.kt

@ -197,6 +197,15 @@ class BleServicePlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
val success = BleService.getBatteryInfo() val success = BleService.getBatteryInfo()
result.success(success) result.success(success)
} }
"getVoiceWakeupStatus" -> {
val success = BleService.getVoiceWakeupStatus()
result.success(success)
}
"setVoiceWakeupStatus" -> {
val enabled = call.argument<Boolean>("enabled") ?: true
val success = BleService.setVoiceWakeupStatus(enabled)
result.success(success)
}
"openEncoder" -> { "openEncoder" -> {
val success = BleService.openEncoder() val success = BleService.openEncoder()
result.success(success) result.success(success)

10
local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleConst.swift

@ -92,6 +92,16 @@ class BleConst {
/** 唤醒指令 */ /** 唤醒指令 */
static let CMD_WAKE_UP: UInt8 = 0x11 static let CMD_WAKE_UP: UInt8 = 0x11
/** 查询语音唤醒状态 */
static let CMD_GET_VOICE_WAKEUP_STATUS: UInt8 = 0x14
/** 设置语音唤醒状态 */
static let CMD_SET_VOICE_WAKEUP_STATUS: UInt8 = 0x15
// ================== 语音唤醒状态值 ==================
/** 语音唤醒关闭 */
static let VOICE_WAKEUP_OFF: UInt8 = 0xE0
/** 语音唤醒开启 */
static let VOICE_WAKEUP_ON: UInt8 = 0xE1
// ================== 编解码控制值 ================== // ================== 编解码控制值 ==================
/** 关闭编解码指令 */ /** 关闭编解码指令 */

41
local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift

@ -654,6 +654,20 @@ private var cmdReplyType: UInt8 = 0
return sendCommand(BleConst.CMD_GET_BATTERY_INFO, data: paramData) return sendCommand(BleConst.CMD_GET_BATTERY_INFO, data: paramData)
} }
/// 查询语音唤醒状态
func getVoiceWakeupStatus() -> Bool {
os_log("查询语音唤醒状态...", log: logger, type: .info)
let paramData = Data([0xFF])
return sendCommand(BleConst.CMD_GET_VOICE_WAKEUP_STATUS, data: paramData)
}
/// 设置语音唤醒状态
func setVoiceWakeupStatus(enabled: Bool) -> Bool {
let status: UInt8 = enabled ? BleConst.VOICE_WAKEUP_ON : BleConst.VOICE_WAKEUP_OFF
os_log("设置语音唤醒状态: %@", log: logger, type: .info, enabled ? "开启" : "关闭")
return sendCommand(BleConst.CMD_SET_VOICE_WAKEUP_STATUS, data: Data([status]))
}
// MARK: - 编解码控制 // MARK: - 编解码控制
public func writeExternalAudioData(data: Data) { public func writeExternalAudioData(data: Data) {
@ -1208,6 +1222,33 @@ private var cmdReplyType: UInt8 = 0
notifyDeviceInfoReceived(infoType: Int(cmd), infoData: resultMap) notifyDeviceInfoReceived(infoType: Int(cmd), infoData: resultMap)
case BleConst.CMD_GET_VOICE_WAKEUP_STATUS:
var resultMap: [String: Any] = [
"success": true,
"command": Int(cmd)
]
if !responseData.isEmpty {
let status = Int(responseData[0])
let wakeupEnabled = (status == Int(BleConst.VOICE_WAKEUP_ON))
resultMap["voiceWakeupEnabled"] = wakeupEnabled
os_log("语音唤醒状态: %@", log: logger, type: .info, wakeupEnabled ? "开启" : "关闭")
}
notifyDeviceInfoReceived(infoType: Int(cmd), infoData: resultMap)
case BleConst.CMD_SET_VOICE_WAKEUP_STATUS:
var resultMap: [String: Any] = [
"success": true,
"command": Int(cmd)
]
if responseData.count >= 2 {
let cmdStatus = Int(responseData[0])
let setSuccess = (Int(responseData[1]) == 0x01)
resultMap["voiceWakeupSetSuccess"] = setSuccess
resultMap["voiceWakeupCmdStatus"] = cmdStatus
os_log("设置语音唤醒结果: %@", log: logger, type: .info, setSuccess ? "成功" : "失败")
}
notifyDeviceInfoReceived(infoType: Int(cmd), infoData: resultMap)
default: default:
let resultMap: [String: Any] = [ let resultMap: [String: Any] = [
"success": true, "success": true,

8
local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftBleServicePlugin.swift

@ -92,6 +92,14 @@ public class SwiftBleServicePlugin: NSObject, FlutterPlugin {
case "getBatteryInfo": case "getBatteryInfo":
result(BleService.shared.getBatteryInfo()) result(BleService.shared.getBatteryInfo())
case "getVoiceWakeupStatus":
result(BleService.shared.getVoiceWakeupStatus())
case "setVoiceWakeupStatus":
let arguments = call.arguments as? [String: Any]
let enabled = (arguments?["enabled"] as? Bool) ?? true
result(BleService.shared.setVoiceWakeupStatus(enabled: enabled))
case "openEncoder": case "openEncoder":
result(BleService.shared.openEncoder()) result(BleService.shared.openEncoder())

26
local_plugins/ble_service/lib/ble_service.dart

@ -543,4 +543,30 @@ class BleService {
return false; return false;
} }
} }
/// 查询语音唤醒状态
Future<bool> getVoiceWakeupStatus() async {
try {
final result =
await _methodChannel.invokeMethod<bool>('getVoiceWakeupStatus');
return result ?? false;
} catch (e) {
print('查询语音唤醒状态失败: $e');
return false;
}
}
/// 设置语音唤醒状态
Future<bool> setVoiceWakeupStatus(bool enabled) async {
try {
final result = await _methodChannel.invokeMethod<bool>(
'setVoiceWakeupStatus',
{'enabled': enabled},
);
return result ?? false;
} catch (e) {
print('设置语音唤醒状态失败: $e');
return false;
}
}
} }

Loading…
Cancel
Save