From 5a395c7c2e952fd77e41130a5e2ffe6954981d72 Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Thu, 11 Sep 2025 15:57:26 +0800 Subject: [PATCH 1/3] =?UTF-8?q?refactor(=E6=96=B0=E6=89=8B=E5=BC=95?= =?UTF-8?q?=E5=AF=BC):=20=E4=BD=BF=E7=94=A8=E6=9C=8D=E5=8A=A1=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=9B=BF=E4=BB=A3=E6=9C=AC=E5=9C=B0=E5=AD=98=E5=82=A8?= =?UTF-8?q?=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将新手引导完成状态的检查从本地存储改为直接使用NoviceGuideService中的状态变量,提高代码一致性和可维护性 --- lib/data/services/novice_guide_service.dart | 2 +- lib/modules/home/controllers/home_controller.dart | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/data/services/novice_guide_service.dart b/lib/data/services/novice_guide_service.dart index 17d9f0a35..f7617114f 100644 --- a/lib/data/services/novice_guide_service.dart +++ b/lib/data/services/novice_guide_service.dart @@ -14,7 +14,7 @@ class NoviceGuideService extends GetxService { final BleService _bleService = BleService(); StreamSubscription? _statusSubscription; - bool isHomeGuide = false; + bool isHomeGuide = false; //false代表未完成新手引导,true代表已经完成 bool isAIGuide = false; RxBool isWakeup = false.obs; diff --git a/lib/modules/home/controllers/home_controller.dart b/lib/modules/home/controllers/home_controller.dart index 518726b18..a031c0b97 100644 --- a/lib/modules/home/controllers/home_controller.dart +++ b/lib/modules/home/controllers/home_controller.dart @@ -177,7 +177,7 @@ class HomeController extends GetxController { bool wasConnected = _isFullyConnected.value; bool isNowConnected = hasClassicBluetooth && hasBleConnection; - bool isGuideCompleted = _storage.read('home_guide') ?? false; + //bool isGuideCompleted = _storage.read('home_guide') ?? false; if (isNowConnected && currentDevice == null) { isNowConnected = false; @@ -197,7 +197,7 @@ class HomeController extends GetxController { // 移除了连接成功后的电池信息刷新 // 连接成功后检查OTA升级 - if (isGuideCompleted) { + if (noviceGuideService.isHomeGuide) { Future.delayed(const Duration(seconds: 2), () { _checkOtaUpgrade(); }); @@ -338,7 +338,7 @@ class HomeController extends GetxController { if (deviceName == 'unknownEquipment'.tr) { return DeviceType.unknown; } - + // 通过AppConfig获取产品信息 final product = AppConfig.getproduct(deviceName); if (product != null) { @@ -358,7 +358,7 @@ class HomeController extends GetxController { return DeviceType.unknown; } } - + return DeviceType.unknown; } catch (e) { Logger.e(_tag, '获取设备类型失败: $e'); From 53dabd4ef47c33e009220a69c8f9f2cfcb370eb9 Mon Sep 17 00:00:00 2001 From: fdp <1286779656@qq.com> Date: Thu, 11 Sep 2025 20:11:11 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dtts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/azure_speech/AzureTtsHelper.swift | 113 +++++++++++++----- 1 file changed, 86 insertions(+), 27 deletions(-) diff --git a/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureTtsHelper.swift b/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureTtsHelper.swift index 30dfd7464..6689f5138 100644 --- a/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureTtsHelper.swift +++ b/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureTtsHelper.swift @@ -264,44 +264,77 @@ public class AzureTtsHelper: NSObject, ITtsService { pendingTasks.removeAll() taskLock.unlock() - do { - print("liwei-------------停止语音合成播放") - try self.synthesizer?.stopSpeaking() - self.notifyEvent(eventType: .synthesisCanceled) - - if !micCapture.isCapturing{ - // 停止时设置音频会话为非活跃状态 - // try AVAudioSession.sharedInstance().setActive(false) - } - - print("音频会话已设置为非活跃状态") - } catch { - os_log("停止语音合成失败: %{public}@", log: self.log, type: .error, error.localizedDescription) - self.notifyEvent(eventType: .error, params: [ - "errorCode": "STOP_FAILED", - "errorMessage": error.localizedDescription - ]) - } + // 使用异步停止方法并等待完成 + let stopGroup = DispatchGroup() + stopGroup.enter() - synthesisQueue.async { + synthesisQueue.async { [weak self] in + guard let self = self else { + stopGroup.leave() + return + } + do { + print("liwei-------------停止语音合成播放") + // 使用异步停止方法 + if let synthesizer = self.synthesizer { + let stopFuture = synthesizer.stopSpeakingAsync() + // 等待停止操作完成 + _ = stopFuture.get() + } + + self.notifyEvent(eventType: .synthesisCanceled) + + if !self.micCapture.isCapturing { + // 停止时设置音频会话为非活跃状态 + // try AVAudioSession.sharedInstance().setActive(false) + } + + print("音频会话已设置为非活跃状态") + + // 等待所有合成操作完成后再重新创建 + self.synthesisGroup.wait() + + // 安全地销毁和重新创建合成器 self.synthesizer = nil try self.recreateSynthesizer() - }catch { - os_log("重置语音合成失败: %{public}@", log: self.log, type: .error, error.localizedDescription) + + } catch { + os_log("停止语音合成失败: %{public}@", log: self.log, type: .error, error.localizedDescription) + self.notifyEvent(eventType: .error, params: [ + "errorCode": "STOP_FAILED", + "errorMessage": error.localizedDescription + ]) } + + stopGroup.leave() } + // 等待停止操作完成 + stopGroup.wait() return true } /** * 释放资源 */ public func dispose() { + // 先停止所有操作 _ = stop() + + // 等待所有异步操作完成 synthesisGroup.wait() synthesisQueue.sync { + // 确保合成器完全停止后再销毁 + if let synthesizer = self.synthesizer { + do { + let stopFuture = synthesizer.stopSpeakingAsync() + _ = try stopFuture.get() + } catch { + os_log("停止合成器失败: %{public}@", log: self.log, type: .error, error.localizedDescription) + } + } + synthesizer = nil speechConfig = nil customAudioOutputStream = nil @@ -441,29 +474,55 @@ public class AzureTtsHelper: NSObject, ITtsService { /** * 执行语音合成 */ - private func performSynthesis(sessionid:String,text: String) { + private func performSynthesis(sessionid: String, text: String) { if (self.sessionid != sessionid) { return } + + // 进入合成组 + synthesisGroup.enter() + speaking = true -// lastSpokenText = text // 生成SSML let ssml = generateOptimizedSsml(text) do { if (self.sessionid != sessionid) { + synthesisGroup.leave() return } os_log("开始合成: %{public}@", log: log, type: .debug, ssml) - let result = try synthesizer?.startSpeakingSsml(ssml) - if let result = result { - os_log("合成完成,结果: %{public}@", log: log, type: .debug, String(describing: result.reason)) + // 使用异步合成方法 + if let synthesizer = self.synthesizer { + let future = synthesizer.speakSsmlAsync(ssml) + + // 在后台等待合成完成 + DispatchQueue.global(qos: .userInitiated).async { [weak self] in + defer { + self?.synthesisGroup.leave() + } + + do { + let result = try future.get() + os_log("合成完成,结果: %{public}@", log: self?.log ?? OSLog.default, type: .debug, String(describing: result.reason)) + } catch { + self?.speaking = false + self?.pendingTextCount = max(0, (self?.pendingTextCount ?? 0) - text.count) + os_log("异步语音合成失败: %{public}@", log: self?.log ?? OSLog.default, type: .error, error.localizedDescription) + self?.notifyEvent(eventType: .error, params: [ + "errorCode": "ASYNC_SYNTHESIS_FAILED", + "errorMessage": error.localizedDescription + ]) + } + } } + } catch { speaking = false - // 减少待处理文本计数 pendingTextCount = max(0, pendingTextCount - text.count) + synthesisGroup.leave() + os_log("语音合成失败: %{public}@", log: log, type: .error, error.localizedDescription) notifyEvent(eventType: .error, params: [ "errorCode": "SYNTHESIS_FAILED", From 36a190729d49ba74e16d050045272e1b91424cc1 Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Thu, 11 Sep 2025 20:24:31 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E6=96=B0=E6=89=8B?= =?UTF-8?q?=E5=BC=95=E5=AF=BC=E7=82=B9=E5=87=BB=E4=BA=8B=E4=BB=B6=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在home_view和agent_view中添加onTap事件处理,确保点击时执行onNext回调并启动唤醒监听 --- lib/modules/agent/views/agent_view.dart | 8 ++++++++ lib/modules/home/views/home_view.dart | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/lib/modules/agent/views/agent_view.dart b/lib/modules/agent/views/agent_view.dart index b3a5846b1..76edfeca9 100644 --- a/lib/modules/agent/views/agent_view.dart +++ b/lib/modules/agent/views/agent_view.dart @@ -521,6 +521,14 @@ class _AgentViewState extends State with WidgetsBindingObserver { controller.noviceGuideService .aiStep]['input']; }, + onTap: () { + controller.textController.text = + controller.noviceGuideService + .aiStepsList[ + controller.noviceGuideService + .aiStep]['input']; + params.onNext!(); + }, ); }, onWidgetLoad: () { diff --git a/lib/modules/home/views/home_view.dart b/lib/modules/home/views/home_view.dart index 440db691a..34156f114 100644 --- a/lib/modules/home/views/home_view.dart +++ b/lib/modules/home/views/home_view.dart @@ -105,6 +105,10 @@ class HomeView extends GetView { onNext: () { controller.noviceGuideService.startWakeupListen(); }, + onTap: () { + params.onNext!(); + controller.noviceGuideService.startWakeupListen(); + }, ); }, builder: (BuildContext context, GlobalKey key) => SizedBox(