if self.mode() == VCMode.Realtime and getattr(self.vc, "Close_flag", 0) == 0:
k = getattr(self.vc, "_last_tts_kind", "") or ""
if k == "dialog":
- actions.append(("uplink_start", "local.play_end"))
+ # 用户短按打断(RequestToSpeak):等 canceled 再开麦,勿 play_end 抢跑
+ if getattr(self.vc, "_vc_pending_interrupt_uplink", 0) != 1:
+ actions.append(("uplink_start", "local.play_end"))
except Exception:
pass
self.on_local_audio_played()
return True
if getattr(self, "VC_Play_flag", 0) == 1:
return True
+ if self._vc_local_play_busy():
+ return True
+ except Exception:
+ pass
+ return False
+
+ def _vc_local_play_busy(self):
+ try:
+ if getattr(self, "_vc_local_play_active", 0) != 1:
+ return False
+ until = getattr(self, "_vc_local_play_until_ms", 0)
+ if until and utime.ticks_diff(until, utime.ticks_ms()) > 0:
+ return True
+ self._vc_local_play_active = 0
+ self._vc_local_play_until_ms = 0
except Exception:
pass
return False
+ def _vc_capture_allowed(self, reason=""):
+ """采集/上行开麦前:下行播放或本地短音未结束则禁止。"""
+ try:
+ if self._vc_tts_pipeline_busy():
+ return False
+ if self._vc_local_play_busy():
+ return False
+ except Exception:
+ return False
+ return True
+
+ def _vc_stop_downlink_for_interrupt(self, reason="interrupt"):
+ """详设 DES-SCN-003:打断/取消时先本地停播清队列,再允许开麦。"""
+ try:
+ if getattr(self, "AI_audio_queue", None) is not None:
+ if self.AI_audio_queue.empty() != True:
+ self.AI_audio_queue.clear()
+ except Exception:
+ pass
+ try:
+ if self._vc_tts_pipeline_busy() or getattr(self, "is_ruppt_tts", 0) == 1:
+ self._drop_tts_audio = 1
+ except Exception:
+ pass
+ try:
+ self._ptt_hard_mute_local_playback()
+ except Exception:
+ pass
+ try:
+ if getattr(self, "VC_Play_flag", 0) == 1 or getattr(self, "play_pcm", None) is not None:
+ self.VC_Play_End()
+ except Exception:
+ pass
+ try:
+ self._vc_local_play_active = 0
+ self._vc_local_play_until_ms = 0
+ except Exception:
+ pass
+ try:
+ self.fsm.await_played = False
+ self._need_audio_played_ack = 0
+ self._tts_pending = 0
+ self._tts_pending_ms = 0
+ except Exception:
+ pass
+ try:
+ pending_intr = getattr(self, "_vc_pending_interrupt_uplink", 0) == 1
+ if (
+ not pending_intr
+ and getattr(self, "VC_record_state_flag", 0) != 0
+ and getattr(self, "record_data_save_flag", 0) == 0
+ ):
+ self._uplink_request_stop("stop_downlink/" + str(reason))
+ except Exception:
+ pass
+
+ def _vc_local_play(self, path, play_mode=1, loop=1, hold_ms=650):
+ """本地 MP3 短音:播前停录/停流式 TTS,避免与麦克风采集叠用。"""
+ try:
+ if getattr(self, "record_data_save_flag", 0) == 0 and getattr(self, "VC_record_state_flag", 0) != 0:
+ self._uplink_request_stop("local_play")
+ utime.sleep_ms(30)
+ except Exception:
+ pass
+ try:
+ if self._vc_tts_playback_active():
+ self._ptt_hard_mute_local_playback()
+ try:
+ self.VC_Play_End()
+ except Exception:
+ pass
+ except Exception:
+ pass
+ try:
+ hold = int(hold_ms)
+ if hold < 200:
+ hold = 200
+ self._vc_local_play_active = 1
+ self._vc_local_play_until_ms = utime.ticks_add(utime.ticks_ms(), hold)
+ except Exception:
+ pass
+ try:
+ self.aud.play(play_mode, loop, path)
+ except Exception as e:
+ try:
+ self._vc_local_play_active = 0
+ self._vc_local_play_until_ms = 0
+ except Exception:
+ pass
+ usys.print_exception(e)
+
def _vc_tts_playback_active(self):
"""仅服务端 TTS/PCM 流在播(VC_Play_Start);aud.play 本地短音不算。"""
try:
playing = False
if playing or self._vc_tts_pipeline_busy():
self._ptt_short_press_stop = 1
+ try:
+ self._ptt_hard_mute_local_playback()
+ except Exception:
+ pass
try:
self.VC_Play_End()
except Exception:
self.fsm.await_played = False
except Exception:
pass
+ try:
+ self._ptt_led_lock_listening = 0
+ self._ptt_interrupt_active = 0
+ self.is_ruppt_tts = 0
+ except Exception:
+ pass
try:
self._vc_publish_led("idle", "ptt_short_press/stop_tts")
except Exception:
return False
print("[KEY] long interrupt -> RequestToSpeak (cancel then uplink)")
self.is_ruppt_tts = 1
+ try:
+ self._vc_pending_interrupt_uplink = 1
+ except Exception:
+ pass
EventMesh.publish("publish_AI_btnInfo", {"func": self.AI_client_VC_RequestToSpeak})
return True
# - 长按:无论当前处于 TTS/Thinking/任何中间态,立即打断并进入新一轮录音上行
# - 松开:停止录音并等待服务端返回(由 AI_client_VC_end_speech 触发)
def _ptt_end_led_suppress(self):
+ # 保持 _vc_play_end_suppress_idle_led / _ptt_led_lock_listening 直至真开录(VC_Speech_Start)
+ pass
+
+ def _ptt_should_drop_inbound_tts(self):
+ """单对话打断窗口:丢弃迟到 TTS 帧 / 禁止起播。"""
+ try:
+ if getattr(self, "VC_mode", -1) != 1:
+ return False
+ if getattr(self, "_drop_tts_audio", 0) == 1:
+ return True
+ if getattr(self, "is_ruppt_tts", 0) == 1:
+ return True
+ if getattr(self, "_ptt_interrupt_active", 0) == 1:
+ return True
+ if getattr(self, "_vc_serial_canceling", 0) == 1:
+ return True
+ if getattr(self, "_ptt_pending_arm", 0) == 1:
+ return True
+ except Exception:
+ pass
+ return False
+
+ def _ptt_should_skip_remote_playback(self):
+ return self._ptt_should_drop_inbound_tts()
+
+ def _ptt_enter_interrupt_arm(self):
+ try:
+ self._ptt_arm_epoch = int(getattr(self, "_ptt_arm_epoch", 0)) + 1
+ self._ptt_interrupt_active = 1
+ self._ptt_led_lock_listening = 1
+ self._vc_play_end_suppress_idle_led = 1
+ self._drop_tts_audio = 1
+ self.is_ruppt_tts = 1
+ except Exception:
+ pass
+
+ def _ptt_abort_interrupt_arm(self):
try:
+ self._ptt_interrupt_active = 0
+ self._ptt_led_lock_listening = 0
self._vc_play_end_suppress_idle_led = 0
+ self._drop_tts_audio = 0
+ self.is_ruppt_tts = 0
+ except Exception:
+ pass
+
+ def _ptt_on_record_hardware_started(self):
+ """真开录后:允许新 TTS、放开灯锁;旧 TTS 已在打断期丢弃。"""
+ try:
+ self._ptt_interrupt_active = 0
+ self._ptt_led_lock_listening = 0
+ self._vc_play_end_suppress_idle_led = 0
+ self._drop_tts_audio = 0
+ self.is_ruppt_tts = 0
+ except Exception:
+ pass
+
+ def _ptt_hard_mute_local_playback(self):
+ try:
+ self.VC_Play_flag = 0
+ if getattr(self, "VC_play_TYPE", None) == VC_play_TYPE_PCM:
+ if getattr(self, "play_pcm", None) is not None:
+ try:
+ self.play_pcm.stream_stop()
+ self.play_pcm.close()
+ except Exception:
+ pass
+ self.play_pcm = None
+ try:
+ self.aud.stopPlayStream()
+ self.aud.stopAll()
+ except Exception:
+ pass
+ if getattr(self, "AI_audio_queue", None) is not None:
+ try:
+ if self.AI_audio_queue.empty() != True:
+ self.AI_audio_queue.clear()
+ except Exception:
+ pass
+ except Exception:
+ pass
+ try:
+ gap = 0
+ if "vc_config" in globals() and vc_config:
+ gap = int(vc_config.get_int("PTT_POST_MUTE_MS", 30))
+ if gap > 0:
+ utime.sleep_ms(gap)
except Exception:
pass
self._vc_on_ptt_cancel_settled(via="canceled")
def _vc_dispatch_server_event(self, ev, jsload_data=None):
+ try:
+ if ev == "canceled":
+ self._vc_stop_downlink_for_interrupt("canceled")
+ except Exception:
+ pass
if getattr(self, "VC_mode", -1) == 1:
self._vc_enqueue_btn(self._vc_fsm_dispatch_cb, (ev, jsload_data))
else:
def _ptt_arm_uplink(self, t0=0):
"""btn 线程:cancel 已结束或无需 cancel 时,发 audio.create 并开麦。"""
+ try:
+ self.is_ruppt_tts = 0
+ except Exception:
+ pass
try:
self._ptt_audio_created = 0
except Exception:
self._ptt_await_server = 0
except Exception:
pass
- # 打断上一段 TTS 后可能仍有残留音频帧下发:短时间丢弃,避免“断断续续继续播”
- try:
- self._drop_tts_audio = 1
- except Exception:
- pass
t0 = 0
try:
except Exception:
t0 = 0
- # 先亮聆听灯,再停播;VC_init/VC_Play_End 全程抑制 idle,避免开录前灭灯
+ self._ptt_enter_interrupt_arm()
try:
- self._vc_play_end_suppress_idle_led = 1
+ self._vc_publish_led("listening", "ptt_begin/pre")
except Exception:
pass
+
+ # 本地先硬静音再 VC_init,避免 DMA/队列尾包漏播
try:
- self._vc_publish_led("listening", "ptt_begin/pre")
+ self._ptt_hard_mute_local_playback()
except Exception:
pass
-
- # 本地先停播并清空队列,避免“边播边录/回声触发/状态机乱跳”
try:
self.VC_init()
except Exception:
pass
-
- # 再强制停播一次(兼容:VC_init 未完全覆盖播放对象的场景)
try:
- if getattr(self, "VC_Play_flag", 0) == 1 or getattr(self, "play_pcm", None) != None:
+ if getattr(self, "VC_Play_flag", 0) == 1 or getattr(self, "play_pcm", None) is not None:
self.VC_Play_End()
except Exception:
pass
try:
- self._vc_publish_led("listening", "ptt_begin/armed")
+ self._ptt_hard_mute_local_playback()
except Exception:
pass
if getattr(self, "AI_client_VC_isconnect", 0) != 1:
self._ptt_force_record_on_started = 1
self.AI_VC_start()
- self._ptt_end_led_suppress()
return
except Exception:
self._ptt_force_record_on_started = 1
self.AI_VC_start()
except Exception:
pass
- self._ptt_end_led_suppress()
return
# 会话还没 initialized:先发 Start,请求服务端进入 started
self.AI_client_VC_start_requset()
except Exception:
pass
- self._ptt_end_led_suppress()
return
# 服务端仍在思考/TTS:先 cancel,在 btn 队列收到 canceled 后再开录(方案甲串行)
if self._vc_ptt_need_interrupt_wait():
self._vc_begin_ptt_cancel_wait("ptt_begin")
- self._ptt_end_led_suppress()
return
self._ptt_arm_uplink(t0)
+ def _vc_effective_asr_text(self):
+ try:
+ t = (getattr(self, "AI_ASR_str", "") or "").strip()
+ if t:
+ return t
+ return (getattr(self, "_last_asr_result_text", "") or "").strip()
+ except Exception:
+ return ""
+
+ def _vc_long_dialogue_auto_uplink_ok(self, reason):
+ """长对话 canceled/completed 自动开麦:须有有效 ASR,且防抖/勿在 LLM 无 TTS 后抢开。"""
+ try:
+ if reason not in ("canceled", "completed", "local.play_end", "audio.played"):
+ return True
+ if getattr(self, "Close_flag", 0) == 1:
+ return False
+ if reason == "canceled" and getattr(self, "_vc_pending_interrupt_uplink", 0) == 1:
+ pass
+ elif not self._vc_effective_asr_text():
+ try:
+ print("[VC][uplink_ctrl] Deny START by {} cause=empty_asr".format(reason))
+ except Exception:
+ pass
+ return False
+ if reason == "completed":
+ if getattr(self, "_turn_has_tts_started", 0) == 0:
+ try:
+ if getattr(self, "_llm_completed_ms", 0) or getattr(self.fsm, "turn", None) == VCTurnState.Thinking:
+ print("[VC][uplink_ctrl] Deny START by completed cause=llm_without_tts")
+ return False
+ except Exception:
+ pass
+ try:
+ now = utime.ticks_ms()
+ last = getattr(self, "_vc_last_auto_uplink_ms", 0)
+ if last and utime.ticks_diff(now, last) < 1200:
+ print("[VC][uplink_ctrl] Deny START by {} cause=auto_uplink_debounce".format(reason))
+ return False
+ self._vc_last_auto_uplink_ms = now
+ except Exception:
+ pass
+ except Exception:
+ pass
+ return True
+
def _vc_led_state_debug_enabled(self):
try:
if "vc_config" in globals() and vc_config:
return False
def _vc_publish_led(self, ai_state, reason=""):
+ try:
+ if getattr(self, "_ptt_led_lock_listening", 0) == 1:
+ if ai_state != "listening":
+ if self._vc_led_state_debug_enabled():
+ print("[LED] publish blocked ai={} reason={} (ptt_arm_lock)".format(
+ ai_state, reason))
+ return
+ except Exception:
+ pass
try:
if self._vc_led_state_debug_enabled():
print("[LED] publish ai={} reason={} VC_mode={} rec={} turn={}".format(
def _vc_led_sync_from_fsm(self):
"""按 FSM/真实 TTS 播放恢复 AI 灯;本地 aud.play 短音不参与。"""
+ try:
+ if getattr(self, "_ptt_led_lock_listening", 0) == 1:
+ if getattr(self, "VC_record_state_flag", 0) == 0:
+ return
+ except Exception:
+ pass
try:
if self._vc_led_should_standby_idle():
self._vc_publish_led("idle", "fsm_sync/standby_idle")
except Exception:
return
+ try:
+ if self.VC_mode == 0 and not self._vc_long_dialogue_auto_uplink_ok(reason):
+ return
+ except Exception:
+ pass
+
+ try:
+ if not self._vc_capture_allowed(reason):
+ try:
+ print("[VC][uplink_ctrl] Deny START by {} cause=playback_busy".format(reason))
+ except Exception:
+ pass
+ return
+ except Exception:
+ return
+
# ===== 业务门控(收敛到 FSM turn/session)=====
try:
if getattr(self.fsm, "session", VCSessionState.Disconnected) != VCSessionState.Started:
self._server_vad_silence = 0
print("[VC][uplink_ctrl] Request START by {}".format(reason))
+ try:
+ if reason == "canceled" and getattr(self, "_vc_pending_interrupt_uplink", 0) == 1:
+ self._vc_pending_interrupt_uplink = 0
+ print("[VC][uplink_ctrl] interrupt_uplink armed -> start (canceled)")
+ except Exception:
+ pass
self.VC_Speech_Start_now()
def _uplink_request_stop(self, reason="", *args, **kwargs):
self.request_uplink_start(a[1] if len(a) > 1 else "")
elif a[0] == "play_start":
if getattr(self, "VC_mode", -1) == 1:
- if getattr(self, "_vc_serial_canceling", 0) or getattr(self, "_ptt_pending_arm", 0):
+ if self._ptt_should_skip_remote_playback():
if self._vc_led_state_debug_enabled():
- print("[VC][serial] skip play_start (cancel_wait)")
+ print("[VC][serial] skip play_start (ptt_interrupt)")
continue
try:
self.fsm.on_local_play_start()
self._vc_serial_canceling = 0
self._ptt_pending_arm = 0
self._vc_cancel_deadline_ms = 0
+ # PTT 打断:轮次号 + 开录前丢弃旧 TTS / 灯只显示聆听
+ self._ptt_arm_epoch = 0
+ self._ptt_interrupt_active = 0
+ self._ptt_led_lock_listening = 0
# 端侧主动发 synthesis 后到收到 tts.started 之间的窗口标志,用于阻止误开下一轮录音上行
self._tts_pending = 0
self._tts_pending_ms = 0
self.VC_record_state_flag = 0
self.AI_key_long_press_flag = 0
self._asr_completed_tone_done = 0 # asr.completed 本地 think 提示每轮仅一次
+ self._last_asr_result_text = "" # 保留最近 asr.result,防 VC_Speech_End 早于 asr.completed 清空
+ self._vc_last_auto_uplink_ms = 0 # 长对话自动开麦防抖
+ self._vc_local_play_active = 0 # aud.play 本地短音占用(与采集互斥)
+ self._vc_local_play_until_ms = 0
+ self._vc_pending_interrupt_uplink = 0 # 长对话短按打断:等 canceled 再开麦
self.websocket_error_count = 0
self.AI_new_voice_url = "" #未读语音地址/音乐播放地址/闹钟播放标志
self.music_play_flag = 0 #音乐播放标志
return
except Exception:
pass
+ try:
+ if getattr(self, "_ptt_led_lock_listening", 0) == 1:
+ return
+ except Exception:
+ pass
self._vc_led_sync_from_fsm()
def set_tts_volume(self,event,msg):
EventMesh.publish("set_storage_config",["VC_TTS_volume",msg])#音量配置
if self.VC_record_state_flag == 0:
# 新一轮开始录音:允许上行(上一轮可能已置 silence 闸门)
self._server_vad_silence = 0
+ self.AI_ASR_str = ""
+ self.AI_ASR_str_tmp = ""
+ self._last_asr_result_text = ""
+ try:
+ self._asr_completed_tone_done = 0
+ except Exception:
+ pass
self.VC_record_thread_close()#关闭录音线程
_thread.stack_size(self.Audio_buf_size+8*1024)
self._vc_publish_led("listening", "VC_Speech_Start")
except Exception:
pass
+ try:
+ if getattr(self, "VC_mode", -1) == 1:
+ self._ptt_on_record_hardware_started()
+ except Exception:
+ pass
except Exception as e:
self.websocket_error()
self._uplink_mark_end("VC_Speech_End")
self.AI_ASR_flag = 0
self.AI_ASR_str_tmp = ""
- self.AI_ASR_str = ""
+ # 勿在此清空 AI_ASR_str:vad.silence 停麦常早于 asr.completed,清空会导致 check_text:len:0 连播 think 音
#EventMesh.publish("publish_AI_btnInfo",{"func":self.websocket_deconnect_asr})
if self.VC_record_state_flag == 0:
self._asr_completed_tone_done = 0
except Exception:
pass
+ # 单对话:_drop_tts_audio 在 VC_Speech_Start 真开录后再清 0,避免 canceled 后仍播旧 TTS
try:
- self._drop_tts_audio = 0
+ if getattr(self, "VC_mode", 0) != 1:
+ self._drop_tts_audio = 0
except Exception:
pass
# 单对话:勿在 asr.started 置 flag=2(未真开麦会僵死);由 VC_Speech_Start 维护
except Exception:
self.AI_ASR_str = ""
print("[VC][ASR] {}".format(self.AI_ASR_str))
+ try:
+ if (self.AI_ASR_str or "").strip():
+ self._last_asr_result_text = self.AI_ASR_str
+ except Exception:
+ pass
if self.AI_ASR_str == "":#没识别到
self.AI_TTS_str = "我没听清,请再说一遍"
self._vc_led_alert_rb_flash()
elif jsload_data["event"] == "asr.completed" :#asr 终止的标识
self._turn_has_asr_completed = 1
- # 本地 think 提示:每轮 ASR 最多一次,且不得与流式 TTS/PCM 播放竞态(避免长对话偶发连播「滴」)
+ try:
+ if not (self.AI_ASR_str or "").strip():
+ self.AI_ASR_str = getattr(self, "_last_asr_result_text", "") or ""
+ except Exception:
+ pass
+ # 本地 think 提示:仅在有有效 ASR 文本时播,避免空轮次连播「滴」
try:
if getattr(self, "_asr_completed_tone_done", 0) == 1:
pass
+ elif not self._vc_effective_asr_text():
+ try:
+ print("[VC][ASR] completed empty, skip think tone")
+ except Exception:
+ pass
else:
stream_on = False
try:
except Exception:
thinking = False
if (not stream_on) and (not pcm_busy) and (not playing) and (not thinking):
- self.aud.play(1, 1, 'U:/static/think.mp3')
+ self._vc_local_play('U:/static/think.mp3', 1, 1, 650)
self._asr_completed_tone_done = 1
except Exception:
pass
print("self.commands_mode:{}".format(self.commands_mode))
if self.commands_mode ==2:
- ret= self.check_text(self.AI_ASR_str)
+ ret= self.check_text(self._vc_effective_asr_text())
if ret == 0:#配置指令
if self.AI_VC_send_data_queue.empty()!=True:
pass
elif jsload_data["event"] == "canceled" :#打断
+ # 停播/清队列已在 _vc_dispatch_server_event(canceled) 完成;此处仅收尾标志
self.is_ruppt_tts = 0#设备上发中断tts,收到服务器返回的cancel后置为0
self._need_audio_played_ack = 0
self._tts_pending = 0
# PTT 打断后丢弃残留 TTS 音频帧,避免“断断续续继续播”
try:
- if getattr(self, "_drop_tts_audio", 0) == 1:
+ if self._ptt_should_drop_inbound_tts():
continue
except Exception:
pass
def set_recv_voice(self,event,msg):
return self.recv_voice
def put_record_data(self,data):
-
+ try:
+ if self._ptt_should_drop_inbound_tts():
+ return
+ except Exception:
+ pass
#print("下发音频数据1:{}".format(len(data[0])))
ret=self.AI_audio_queue.put(data)
try:
return self.VC_task_id
#开始播放声音
def VC_Play_Start(self):
+ try:
+ if self._ptt_should_skip_remote_playback():
+ if self._vc_led_state_debug_enabled():
+ print("[VC] VC_Play_Start skip (ptt_interrupt)")
+ return
+ except Exception:
+ pass
self.tts_in_data_len = 0
self.tts_out_data_len = 0
if self.VC_Play_flag == 0:
try:
+ _ptt_fast_open = False
+ try:
+ if getattr(self, "VC_mode", -1) == 1:
+ _ptt_fast_open = True
+ except Exception:
+ pass
# 本地提示音/文件播放可能占用同一音频通道,导致 TTS 流播放“写入成功但无声”;
# 在开启 TTS PCM 前先停掉本地播放,避免资源冲突。
try:
if self.play_pcm == None:
# 刚停采集时延后打开播音 PCM,且失败时重试,降低「pcm open write only fail」
last_err = None
- for i in range(3):
+ _open_retries = 1 if _ptt_fast_open else 3
+ for i in range(_open_retries):
try:
- utime.sleep_ms(80 + i * 60)
+ if not _ptt_fast_open:
+ utime.sleep_ms(80 + i * 60)
self.play_pcm = audio.Audio.PCM(0, 1, self.VC_play_samplerate, 1, 1, 2)
ret = self.play_pcm.stream_write_start()
print("self.record_pcm.stream_write_start:ret:{}".format(ret))
pass
self.VC_Play_flag = 1
try:
- self._vc_publish_led("playing", "VC_Play_Start/tts")
+ if not self._ptt_should_skip_remote_playback():
+ self._vc_publish_led("playing", "VC_Play_Start/tts")
except Exception:
pass
except Exception as e:
try:
if self.VC_mode == 0:
self.Close_flag = 0
+ self._vc_pending_interrupt_uplink = 1
self._vc_clear_stale_record_state("RequestToSpeak")
except Exception:
pass
#print("audio_queue:len:{}".format(len(data[0])))
if len(data[0]) > 10:
+ try:
+ if self._ptt_should_drop_inbound_tts():
+ continue
+ except Exception:
+ pass
for i in range(5):
if self.VC_Play_flag == 0:
self.VC_Play_Start()
self._tts_pending_ms = 0
self._vc_session_started = 0
self._ptt_audio_created = 0
+ self._vc_pending_interrupt_uplink = 0
try:
self._skip_started_uplink_once = 0
except Exception:
pass
+ try:
+ self._ptt_abort_interrupt_arm()
+ except Exception:
+ pass
# Power 短按停止对话后,再次按 AI 需要新建 dialog_id:清理本轮 dialog/session 标识
try:
self._cur_dialog_id = ""
-# 设备侧默认配置(freeze 内置)。\r
-#\r
-# 加载优先级(由 vc_config.py 执行):\r
-# 1) usr/default_config.py(或 usr/defualt_config.py)\r
-# 2) 本文件 default_config.py\r
-\r
-# 当前设备类型(编译期间确定;现场仅可用 usr/default_config.py 覆盖)\r
-DEV_TYPE = "7PIN"\r
-\r
-# 是否加载 quecgnss 并在定位管理器初始化时调用 gnssEnable(0)。\r
-# 无 GNSS 硬件的机型(如部分吊坠)可置 False,避免 import quecgnss 或底层驱动异常/阻塞。\r
-GNSS_ENABLED = False\r
-\r
-# 为 True 时,protocol 模块 import 过程会打印 [proto.import] 阶段标记(配合 qp 日志口排查卡点)。\r
-PROTOCOL_IMPORT_TRACE = True\r
-\r
-# 当前设备配置(仅保留“设备差异项”,不要放运行态变量)\r
-# led_gpio 使用 Pin 属性名(字符串),由 vc_config.py 转成 Pin.GPIOxx 常量。\r
-LED_GPIO = ("GPIO36", "GPIO44", "GPIO43") # (R, G, B)\r
-\r
-# LED 电平极性(是否“反向”点亮)。\r
-# - 默认 LED_ACTIVE_LOW=False:高电平点亮(write(1)=亮)\r
-# - 若你的硬件是低电平点亮(write(0)=亮),将 LED_ACTIVE_LOW=True\r
-# - 若仅某一路反相,用 LED_ACTIVE_LOW_RGB 单独配置(按 LED_GPIO 顺序 R/G/B)\r
-LED_ACTIVE_LOW = False\r
-LED_ACTIVE_LOW_RGB = None # 例如 (True, False, False) 表示仅红灯反相\r
-# LED_ACTIVE_LOW_RGB = (True, False, False)\r
-\r
-# idle 绿灯长慢闪:常亮 / 熄灭(ms);仅配 LED_IDLE_GREEN_BLINK_MS 时灭灯时长与常亮相同(对称慢闪)\r
-LED_IDLE_GREEN_BLINK_MS = 1000\r
-LED_IDLE_GREEN_BLINK_OFF_MS = 2000\r
-\r
-# 是否支持 UART 相关能力(例如 7PIN_1_5 才允许走串口)\r
-UART_SUPPORTED = False\r
-\r
-# 语言/地区(如 zh/en),用于少量文案/逻辑差异\r
-LANG = "zh"\r
-\r
-# --------------------\r
-# 硬件差异项(由每个设备的 default_config 固定)\r
-# --------------------\r
-LED_DEBUG = True\r
-LED_STATE_DEBUG = True\r
-KEY_LED_DEBUG = True\r
-HW_STATUS_DEBUG = True\r
-\r
-# --------------------\r
-# 电池 OCV / 硬件状态轮询(AI_hw_status,可在 usr/default_config.py 覆盖)\r
-# --------------------\r
-# True 时用三档电压门限估算 SoC,忽略 BATTERY_OCV_MAP\r
-USE_SIMPLE_VBATT_THRESH = False\r
-VBATT_CHARGE_FULL_MV = 4290 # USB 在位且电压≥此值视为充满(get_battery / AI_hw_status / AI_dev 共用)\r
-VBATT_LOW_MV = 3699 # 低电电压门限;simple 模式与 AI_dev 低电提示用\r
-VBATT_EMPTY_MV = 3629 # 空电电压门限;AI_dev 低电关机等\r
-BATTERY_LOW_SOC_PERCENT = 30 # OCV 模式:soc < 此值 → battery=low(REQ-BAT-02:10%~30%)\r
-BATTERY_EMPTY_SOC_PERCENT = 10 # OCV 模式:soc < 此值 → battery=empty(REQ-BAT-03:<10%)\r
-HW_STATUS_PERIOD_MS = 10000\r
-SIGNAL_WEAK_CSQ = 10\r
-\r
-# 开路电压(mV) -> SoC(%),按电压线性插值;None 则用 ai_VC 内置默认表\r
-BATTERY_OCV_MAP = {\r
- 4290: 100, 4237: 95, 4179: 90, 4123: 85, 4070: 80, 4020: 75, 3963: 70, 3919: 65, 3882: 60, 3847: 55,\r
- 3818: 50, 3794: 45, 3772: 40, 3752: 35, 3733: 30, 3716: 25, 3699: 20, 3677: 15, 3652: 10, 3629: 5, 3400: 0,\r
-}\r
-\r
-# 是否需要初始化蓝牙电源/马达/音频IIS配置等(原先仅 7PIN_1_5)\r
-BT_POWER_MOTOR_ENABLED = False\r
-PIN_BT_ON_GPIO = None # 例如 "GPIO31"\r
-PIN_MOT_GPIO = None\r
-# audio.set_qdai_cfg(...) 参数;若为 None 则不调用\r
-AUDIO_QDAI_CFG = None # 例如 (1,0,0,2,0,1,1,1)\r
-\r
-# motor.py(motorEventManager):马达输出脚与节拍。MOTOR_GPIO 为 None 时依次尝试 PIN_MOT_GPIO、默认 GPIO36。\r
-MOTOR_PIN_GPIO = "GPIO20" # 例如 "GPIO36";无马达硬件可保持 None\r
-MOTOR_TICK_MS = 100\r
-MOTOR_ACTIVE_LOW = False\r
-MOTOR_BOOT_VIBRATE_MS = 200 # 马达开机震动时间 200ms\r
-\r
-\r
-# AI 按键中断与电源键中断引脚(ExtInt.GPIOxx)\r
-EXTINT_AI_GPIO = "GPIO22" # ai按键\r
-PWK_KEY_GPIO = "GPIO26" # 侧边power按键 , 模式切换\r
-\r
-#btn_device_ec800m.py\r
-BTN_WECHAT_GPIO = None\r
-BTN_SOS_GPIO = None\r
-\r
-\r
-# 蓝牙唤醒 4G/4G 唤醒蓝牙相关(原先仅 7PIN_1_5)\r
-BT_WAKEUP_4G_ENABLED = False\r
-EXTINT_WAKEUP_CTA1_GPIO = None # 例如 "GPIO22"\r
-PIN_WAKEUP_BT_GPIO = None # 例如 "GPIO21"\r
-\r
-# --------------------\r
-# 按键/防抖差异\r
-# --------------------\r
-\r
-# 释放防抖阈值(KeyAI/pwk):原代码部分设备用 3,其他用 5\r
-KEY_RELEASE_DEBOUNCE_COUNT = 5\r
-\r
-# 是否允许 AI 键长按 8 秒触发关机逻辑(原 jswm/jswm_BOX)\r
-AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
-\r
-# 是否启用 SOS:False 时禁用 AI 键长按 3s 拨紧急号、以及按键板上的 SOS 长按拨号入口\r
-SOS_ENABLED = False\r
-\r
-# VC WebSocket 文本保活 ping 间隔(秒)。原逻辑约每 4 秒一次,空闲功耗偏高;拉大间隔可降低唤醒与发包频率\r
-VC_WS_PING_INTERVAL_SEC = 55\r
-\r
-# --------------------\r
-# VC 空闲/超时(ai_VC._1S_timer_cb_ 每秒累计)\r
-# --------------------\r
-# 长对话:无有效业务下行累计达此秒数后结束会话;代码侧最小 5\r
-VC_IDLE_AUTO_CLOSE_SEC = 20\r
-# 单对话侧预留(当前与 idle+深睡统一处理,与 7PIN_1_5 对齐)\r
-VC_IDLE_AUTO_CLOSE_SEC_PTT = 0\r
-# 业务 idle 累计达此秒数触发深睡断开;代码侧最小 10;0 关闭请改 ENABLE\r
-VC_IDLE_DEEP_SLEEP_SEC = 60\r
-VC_IDLE_DEEP_SLEEP_ENABLE = 1\r
-\r
-# --------------------\r
-# 开机提示/语音参数默认值(与具体产品绑定,编译期决定)\r
-# --------------------\r
-\r
-# 若为 None 或 POWER_ON_TONE_ENABLED=False,则不开机播报提示词\r
-POWER_ON_TONE_ENABLED = True\r
-POWER_ON_TONE_DEFAULT = "你好,我来了"\r
-\r
-# VAD 静音阈值默认值(ms)\r
-VAD_SILENCE_DEFAULT = 300\r
-\r
-# 默认音色配置(与 ai_VC.py 中格式保持一致)\r
-VC_TTS_VOICE_TYPE_DEFAULT = None # dict 或 None(None 表示沿用 ai_VC.py 内置兜底/存储值)\r
-VC_TTS_VOICE_KEY_DEFAULT = None # 例如 "男"/"童"\r
-\r
-# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
-VC_WS_PATH = "vc/agent"\r
-\r
-# 是否支持蓝牙 OTA(原先仅 7PIN_1_5 会检查 bt_ota)\r
-BT_OTA_ENABLED = False\r
-\r
-# 是否在“开始上传语音”时播放成功提示音(原逻辑:非 7PIN/7PIN_1_5/7PIN_coze 才播)\r
-UPLOAD_START_TONE_ENABLED = False\r
-\r
-# 正常待机 idle 灯效:off=灭灯(REQ-BAT-01);green_blink=旧工程绿灯慢闪\r
-LED_IDLE_MODE = "off"\r
-\r
-# LLM thinking 阶段 LED 策略:flicker_blue_green / open_red_green\r
-THINKING_LED_MODE = "flicker_blue_green"\r
-\r
-# 收到 vad.active 时是否强制切回蓝灯\r
-VAD_ACTIVE_BLUE_LED = True\r
-\r
-# 本地指令:切换对话模式时的提示语(是什么语言就写什么)\r
-CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
-CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
-\r
-# 蓝牙/语音留言类本地指令是否启用(原先仅 7PIN_1_5)\r
-BT_VOICE_FEATURES_ENABLED = False\r
-\r
-# “关机”语音指令是否仅关闭对话(不触发 Power_off)。原逻辑:7PIN/7PIN_coze/7PIN_1_5 只 Close\r
-POWEROFF_CMD_CLOSE_ONLY = True\r
-\r
-# 关键词唤醒时在 PTT 模式下播报的提示语\r
-KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
-\r
-# 对话智能体/工作流默认配置(编译期确定;可在 usr/default_config.py 覆盖)\r
-# 结构示例:\r
-# DIALOG_BOT_OPTION = {"bot_id":"...", "workflow_id":"...", "use_workflow":True}\r
-DIALOG_BOT_OPTION = None\r
-\r
-# VC Start 请求里 dialog_attributes.cfg.bot_option(与 DIALOG_BOT_OPTION 二选一或叠加:后者可再覆盖)\r
-# 允许空字符串 "";未定义键时沿用下方默认值;若两者都为空则自动 use_workflow=False\r
-VC_BOT_ID = "7462617881076351002"\r
-VC_WORKFLOW_ID = "7462621757327196187"\r
-\r
-# dialog_attributes.provider 覆盖(None 表示沿用存储配置 dialog_attributes_provider)\r
-DIALOG_PROVIDER_DEFAULT = None\r
-\r
-# 是否从 VC_TTS_voice_type 的 key 列表生成 ASR 热词\r
-KEYWORDS_FROM_VOICE_TYPE = False\r
-\r
-# --------------------\r
-# 按键音/提示音策略(设备差异项)\r
-# --------------------\r
-\r
-# AI 键按下时:若设置了该文件路径,则在“无 VC 流播放中”时播放该提示音(例如 "U:/static/start.mp3")\r
-KEY_PRESS_TONE_FILE = None\r
-\r
-# AI 键按下时:延迟播放按键音(ms),规避蓝牙刚连上不出声等(与 7PIN_1_5 一致)\r
-KEY_PRESS_TONE_DELAY_MS = 300\r
-\r
-# 单对话长按开麦:开录提示音(None=不播,流畅优先;可设 U:/static/start.mp3)\r
-RECORD_START_TONE_FILE = None\r
-RECORD_START_TONE_GAP_MS = 180\r
-# 单对话松手后延迟(ms)再发 audio.completed,利于尾包/ASR 收敛\r
-PTT_RELEASE_END_SPEECH_DELAY_MS = 200\r
-# 单对话打断:发 cancel 后等待 canceled 的最长时间(ms),超时仍开录\r
-PTT_CANCEL_WAIT_MS = 2500\r
-\r
-# PTT 提示语(单对话模式,未长按时的提示;是什么语言就写什么)\r
-PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
-\r
+# 设备侧默认配置(freeze 内置)。
+#
+# 加载优先级(由 vc_config.py 执行):
+# 1) usr/default_config.py(或 usr/defualt_config.py)
+# 2) 本文件 default_config.py
+
+# 当前设备类型(编译期间确定;现场仅可用 usr/default_config.py 覆盖)
+DEV_TYPE = "7PIN"
+
+# 是否加载 quecgnss 并在定位管理器初始化时调用 gnssEnable(0)。
+# 无 GNSS 硬件的机型(如部分吊坠)可置 False,避免 import quecgnss 或底层驱动异常/阻塞。
+GNSS_ENABLED = False
+
+# 为 True 时,protocol 模块 import 过程会打印 [proto.import] 阶段标记(配合 qp 日志口排查卡点)。
+PROTOCOL_IMPORT_TRACE = True
+
+# 当前设备配置(仅保留“设备差异项”,不要放运行态变量)
+# led_gpio 使用 Pin 属性名(字符串),由 vc_config.py 转成 Pin.GPIOxx 常量。
+LED_GPIO = ("GPIO36", "GPIO44", "GPIO43") # (R, G, B)
+
+# LED 电平极性(是否“反向”点亮)。
+# - 默认 LED_ACTIVE_LOW=False:高电平点亮(write(1)=亮)
+# - 若你的硬件是低电平点亮(write(0)=亮),将 LED_ACTIVE_LOW=True
+# - 若仅某一路反相,用 LED_ACTIVE_LOW_RGB 单独配置(按 LED_GPIO 顺序 R/G/B)
+LED_ACTIVE_LOW = False
+LED_ACTIVE_LOW_RGB = None # 例如 (True, False, False) 表示仅红灯反相
+# LED_ACTIVE_LOW_RGB = (True, False, False)
+
+# idle 绿灯长慢闪:常亮 / 熄灭(ms);仅配 LED_IDLE_GREEN_BLINK_MS 时灭灯时长与常亮相同(对称慢闪)
+LED_IDLE_GREEN_BLINK_MS = 1000
+LED_IDLE_GREEN_BLINK_OFF_MS = 2000
+
+# 是否支持 UART 相关能力(例如 7PIN_1_5 才允许走串口)
+UART_SUPPORTED = False
+
+# 语言/地区(如 zh/en),用于少量文案/逻辑差异
+LANG = "zh"
+
+# --------------------
+# 硬件差异项(由每个设备的 default_config 固定)
+# --------------------
+LED_DEBUG = True
+LED_STATE_DEBUG = True
+KEY_LED_DEBUG = True
+HW_STATUS_DEBUG = True
+
+# --------------------
+# 电池 OCV / 硬件状态轮询(AI_hw_status,可在 usr/default_config.py 覆盖)
+# --------------------
+# True 时用三档电压门限估算 SoC,忽略 BATTERY_OCV_MAP
+USE_SIMPLE_VBATT_THRESH = False
+VBATT_CHARGE_FULL_MV = 4290 # USB 在位且电压≥此值视为充满(get_battery / AI_hw_status / AI_dev 共用)
+VBATT_LOW_MV = 3699 # 低电电压门限;simple 模式与 AI_dev 低电提示用
+VBATT_EMPTY_MV = 3629 # 空电电压门限;AI_dev 低电关机等
+BATTERY_LOW_SOC_PERCENT = 30 # OCV 模式:soc < 此值 → battery=low(REQ-BAT-02:10%~30%)
+BATTERY_EMPTY_SOC_PERCENT = 10 # OCV 模式:soc < 此值 → battery=empty(REQ-BAT-03:<10%)
+HW_STATUS_PERIOD_MS = 10000
+SIGNAL_WEAK_CSQ = 10
+
+# 开路电压(mV) -> SoC(%),按电压线性插值;None 则用 ai_VC 内置默认表
+BATTERY_OCV_MAP = {
+ 4290: 100, 4237: 95, 4179: 90, 4123: 85, 4070: 80, 4020: 75, 3963: 70, 3919: 65, 3882: 60, 3847: 55,
+ 3818: 50, 3794: 45, 3772: 40, 3752: 35, 3733: 30, 3716: 25, 3699: 20, 3677: 15, 3652: 10, 3629: 5, 3400: 0,
+}
+
+# 是否需要初始化蓝牙电源/马达/音频IIS配置等(原先仅 7PIN_1_5)
+BT_POWER_MOTOR_ENABLED = False
+PIN_BT_ON_GPIO = None # 例如 "GPIO31"
+PIN_MOT_GPIO = None
+# audio.set_qdai_cfg(...) 参数;若为 None 则不调用
+AUDIO_QDAI_CFG = None # 例如 (1,0,0,2,0,1,1,1)
+
+# motor.py(motorEventManager):马达输出脚与节拍。MOTOR_GPIO 为 None 时依次尝试 PIN_MOT_GPIO、默认 GPIO36。
+MOTOR_PIN_GPIO = "GPIO20" # 例如 "GPIO36";无马达硬件可保持 None
+MOTOR_TICK_MS = 100
+MOTOR_ACTIVE_LOW = False
+MOTOR_BOOT_VIBRATE_MS = 200 # 马达开机震动时间 200ms
+
+
+# AI 按键中断与电源键中断引脚(ExtInt.GPIOxx)
+EXTINT_AI_GPIO = "GPIO22" # ai按键
+PWK_KEY_GPIO = "GPIO26" # 侧边power按键 , 模式切换
+
+#btn_device_ec800m.py
+BTN_WECHAT_GPIO = None
+BTN_SOS_GPIO = None
+
+
+# 蓝牙唤醒 4G/4G 唤醒蓝牙相关(原先仅 7PIN_1_5)
+BT_WAKEUP_4G_ENABLED = False
+EXTINT_WAKEUP_CTA1_GPIO = None # 例如 "GPIO22"
+PIN_WAKEUP_BT_GPIO = None # 例如 "GPIO21"
+
+# --------------------
+# 按键/防抖差异
+# --------------------
+
+# 释放防抖阈值(KeyAI/pwk):原代码部分设备用 3,其他用 5
+KEY_RELEASE_DEBOUNCE_COUNT = 5
+
+# 是否允许 AI 键长按 8 秒触发关机逻辑(原 jswm/jswm_BOX)
+AI_LONG_PRESS_POWER_OFF_ENABLED = False
+
+# 是否启用 SOS:False 时禁用 AI 键长按 3s 拨紧急号、以及按键板上的 SOS 长按拨号入口
+SOS_ENABLED = False
+
+# VC WebSocket 文本保活 ping 间隔(秒)。原逻辑约每 4 秒一次,空闲功耗偏高;拉大间隔可降低唤醒与发包频率
+VC_WS_PING_INTERVAL_SEC = 55
+
+# --------------------
+# VC 空闲/超时(ai_VC._1S_timer_cb_ 每秒累计)
+# --------------------
+# 长对话:无有效业务下行累计达此秒数后结束会话;代码侧最小 5
+VC_IDLE_AUTO_CLOSE_SEC = 20
+# 单对话侧预留(当前与 idle+深睡统一处理,与 7PIN_1_5 对齐)
+VC_IDLE_AUTO_CLOSE_SEC_PTT = 0
+# 业务 idle 累计达此秒数触发深睡断开;代码侧最小 10;0 关闭请改 ENABLE
+VC_IDLE_DEEP_SLEEP_SEC = 60
+VC_IDLE_DEEP_SLEEP_ENABLE = 1
+
+# --------------------
+# 开机提示/语音参数默认值(与具体产品绑定,编译期决定)
+# --------------------
+
+# 若为 None 或 POWER_ON_TONE_ENABLED=False,则不开机播报提示词
+POWER_ON_TONE_ENABLED = True
+POWER_ON_TONE_DEFAULT = "你好,我来了"
+
+# VAD 静音阈值默认值(ms)
+VAD_SILENCE_DEFAULT = 300
+
+# 默认音色配置(与 ai_VC.py 中格式保持一致)
+VC_TTS_VOICE_TYPE_DEFAULT = None # dict 或 None(None 表示沿用 ai_VC.py 内置兜底/存储值)
+VC_TTS_VOICE_KEY_DEFAULT = None # 例如 "男"/"童"
+
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)
+VC_WS_PATH = "vc/agent"
+
+# 是否支持蓝牙 OTA(原先仅 7PIN_1_5 会检查 bt_ota)
+BT_OTA_ENABLED = False
+
+# 是否在“开始上传语音”时播放成功提示音(原逻辑:非 7PIN/7PIN_1_5/7PIN_coze 才播)
+UPLOAD_START_TONE_ENABLED = False
+
+# 正常待机 idle 灯效:off=灭灯(REQ-BAT-01);green_blink=旧工程绿灯慢闪
+LED_IDLE_MODE = "off"
+
+# LLM thinking 阶段 LED 策略:flicker_blue_green / open_red_green
+THINKING_LED_MODE = "flicker_blue_green"
+
+# 收到 vad.active 时是否强制切回蓝灯
+VAD_ACTIVE_BLUE_LED = True
+
+# 本地指令:切换对话模式时的提示语(是什么语言就写什么)
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"
+
+# 蓝牙/语音留言类本地指令是否启用(原先仅 7PIN_1_5)
+BT_VOICE_FEATURES_ENABLED = False
+
+# “关机”语音指令是否仅关闭对话(不触发 Power_off)。原逻辑:7PIN/7PIN_coze/7PIN_1_5 只 Close
+POWEROFF_CMD_CLOSE_ONLY = True
+
+# 关键词唤醒时在 PTT 模式下播报的提示语
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "
+
+# 对话智能体/工作流默认配置(编译期确定;可在 usr/default_config.py 覆盖)
+# 结构示例:
+# DIALOG_BOT_OPTION = {"bot_id":"...", "workflow_id":"...", "use_workflow":True}
+DIALOG_BOT_OPTION = None
+
+# VC Start 请求里 dialog_attributes.cfg.bot_option(与 DIALOG_BOT_OPTION 二选一或叠加:后者可再覆盖)
+# 允许空字符串 "";未定义键时沿用下方默认值;若两者都为空则自动 use_workflow=False
+VC_BOT_ID = "7462617881076351002"
+VC_WORKFLOW_ID = "7462621757327196187"
+
+# dialog_attributes.provider 覆盖(None 表示沿用存储配置 dialog_attributes_provider)
+DIALOG_PROVIDER_DEFAULT = None
+
+# 是否从 VC_TTS_voice_type 的 key 列表生成 ASR 热词
+KEYWORDS_FROM_VOICE_TYPE = False
+
+# --------------------
+# 按键音/提示音策略(设备差异项)
+# --------------------
+
+# AI 键按下时:若设置了该文件路径,则在“无 VC 流播放中”时播放该提示音(例如 "U:/static/start.mp3")
+KEY_PRESS_TONE_FILE = None
+
+# AI 键按下时:延迟播放按键音(ms),规避蓝牙刚连上不出声等(与 7PIN_1_5 一致)
+KEY_PRESS_TONE_DELAY_MS = 300
+
+# 单对话长按开麦:开录提示音(None=不播,流畅优先;可设 U:/static/start.mp3)
+RECORD_START_TONE_FILE = None
+RECORD_START_TONE_GAP_MS = 180
+# 单对话松手后延迟(ms)再发 audio.completed,利于尾包/ASR 收敛
+PTT_RELEASE_END_SPEECH_DELAY_MS = 200
+# 单对话打断:发 cancel 后等待 canceled 的最长时间(ms),超时仍开录
+PTT_CANCEL_WAIT_MS = 2500
+# PTT 本地硬静音后等待 codec/DMA 收尾(ms),减轻打断尾音
+PTT_POST_MUTE_MS = 30
+
+# PTT 提示语(单对话模式,未长按时的提示;是什么语言就写什么)
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "
+
-# 设备侧默认配置(freeze 内置)。\r
-#\r
-# 加载优先级(由 vc_config.py 执行):\r
-# 1) usr/default_config.py(或 usr/defualt_config.py)\r
-# 2) 本文件 default_config.py\r
-\r
-# 当前设备类型(编译期间确定;现场仅可用 usr/default_config.py 覆盖)\r
-DEV_TYPE = "7PIN"\r
-\r
-# 是否加载 quecgnss 并在定位管理器初始化时调用 gnssEnable(0)。\r
-# 无 GNSS 硬件的机型(如部分吊坠)可置 False,避免 import quecgnss 或底层驱动异常/阻塞。\r
-GNSS_ENABLED = False\r
-\r
-# 为 True 时,protocol 模块 import 过程会打印 [proto.import] 阶段标记(配合 qp 日志口排查卡点)。\r
-PROTOCOL_IMPORT_TRACE = True\r
-\r
-# 当前设备配置(仅保留“设备差异项”,不要放运行态变量)\r
-# led_gpio 使用 Pin 属性名(字符串),由 vc_config.py 转成 Pin.GPIOxx 常量。\r
-LED_GPIO = ("GPIO36", "GPIO44", "GPIO43") # (R, G, B)\r
-\r
-# LED 电平极性(是否“反向”点亮)。\r
-# - 默认 LED_ACTIVE_LOW=False:高电平点亮(write(1)=亮)\r
-# - 若你的硬件是低电平点亮(write(0)=亮),将 LED_ACTIVE_LOW=True\r
-# - 若仅某一路反相,用 LED_ACTIVE_LOW_RGB 单独配置(按 LED_GPIO 顺序 R/G/B)\r
-LED_ACTIVE_LOW = False\r
-LED_ACTIVE_LOW_RGB = None # 例如 (True, False, False) 表示仅红灯反相\r
-# LED_ACTIVE_LOW_RGB = (True, False, False)\r
-\r
-# idle 绿灯长慢闪:常亮 / 熄灭(ms);仅配 LED_IDLE_GREEN_BLINK_MS 时灭灯时长与常亮相同(对称慢闪)\r
-LED_IDLE_GREEN_BLINK_MS = 1000\r
-LED_IDLE_GREEN_BLINK_OFF_MS = 2000\r
-\r
-# 是否支持 UART 相关能力(例如 7PIN_1_5 才允许走串口)\r
-UART_SUPPORTED = False\r
-\r
-# 语言/地区(如 zh/en),用于少量文案/逻辑差异\r
-LANG = "zh"\r
-\r
-# --------------------\r
-# 硬件差异项(由每个设备的 default_config 固定)\r
-# --------------------\r
-LED_DEBUG = True\r
-LED_STATE_DEBUG = True\r
-KEY_LED_DEBUG = True\r
-HW_STATUS_DEBUG = True\r
-\r
-# --------------------\r
-# 电池 OCV / 硬件状态轮询(AI_hw_status,可在 usr/default_config.py 覆盖)\r
-# --------------------\r
-# True 时用三档电压门限估算 SoC,忽略 BATTERY_OCV_MAP\r
-USE_SIMPLE_VBATT_THRESH = False\r
-VBATT_CHARGE_FULL_MV = 4290 # USB 在位且电压≥此值视为充满(get_battery / AI_hw_status / AI_dev 共用)\r
-VBATT_LOW_MV = 3699 # 低电电压门限;simple 模式与 AI_dev 低电提示用\r
-VBATT_EMPTY_MV = 3629 # 空电电压门限;AI_dev 低电关机等\r
-BATTERY_LOW_SOC_PERCENT = 30 # OCV 模式:soc < 此值 → battery=low(REQ-BAT-02:10%~30%)\r
-BATTERY_EMPTY_SOC_PERCENT = 10 # OCV 模式:soc < 此值 → battery=empty(REQ-BAT-03:<10%)\r
-HW_STATUS_PERIOD_MS = 10000\r
-SIGNAL_WEAK_CSQ = 10\r
-\r
-# 开路电压(mV) -> SoC(%),按电压线性插值;None 则用 ai_VC 内置默认表\r
-BATTERY_OCV_MAP = {\r
- 4290: 100, 4237: 95, 4179: 90, 4123: 85, 4070: 80, 4020: 75, 3963: 70, 3919: 65, 3882: 60, 3847: 55,\r
- 3818: 50, 3794: 45, 3772: 40, 3752: 35, 3733: 30, 3716: 25, 3699: 20, 3677: 15, 3652: 10, 3629: 5, 3400: 0,\r
-}\r
-\r
-# 是否需要初始化蓝牙电源/马达/音频IIS配置等(原先仅 7PIN_1_5)\r
-BT_POWER_MOTOR_ENABLED = False\r
-PIN_BT_ON_GPIO = None # 例如 "GPIO31"\r
-PIN_MOT_GPIO = None\r
-# audio.set_qdai_cfg(...) 参数;若为 None 则不调用\r
-AUDIO_QDAI_CFG = None # 例如 (1,0,0,2,0,1,1,1)\r
-\r
-# motor.py(motorEventManager):马达输出脚与节拍。MOTOR_GPIO 为 None 时依次尝试 PIN_MOT_GPIO、默认 GPIO36。\r
-MOTOR_PIN_GPIO = "GPIO20" # 例如 "GPIO36";无马达硬件可保持 None\r
-MOTOR_TICK_MS = 100\r
-MOTOR_ACTIVE_LOW = False\r
-MOTOR_BOOT_VIBRATE_MS = 200 # 马达开机震动时间 200ms\r
-\r
-\r
-# AI 按键中断与电源键中断引脚(ExtInt.GPIOxx)\r
-EXTINT_AI_GPIO = "GPIO22" # ai按键\r
-PWK_KEY_GPIO = "GPIO26" # 侧边power按键 , 模式切换\r
-\r
-#btn_device_ec800m.py\r
-BTN_WECHAT_GPIO = None\r
-BTN_SOS_GPIO = None\r
-\r
-\r
-# 蓝牙唤醒 4G/4G 唤醒蓝牙相关(原先仅 7PIN_1_5)\r
-BT_WAKEUP_4G_ENABLED = False\r
-EXTINT_WAKEUP_CTA1_GPIO = None # 例如 "GPIO22"\r
-PIN_WAKEUP_BT_GPIO = None # 例如 "GPIO21"\r
-\r
-# --------------------\r
-# 按键/防抖差异\r
-# --------------------\r
-\r
-# 释放防抖阈值(KeyAI/pwk):原代码部分设备用 3,其他用 5\r
-KEY_RELEASE_DEBOUNCE_COUNT = 5\r
-\r
-# 是否允许 AI 键长按 8 秒触发关机逻辑(原 jswm/jswm_BOX)\r
-AI_LONG_PRESS_POWER_OFF_ENABLED = False\r
-\r
-# 是否启用 SOS:False 时禁用 AI 键长按 3s 拨紧急号、以及按键板上的 SOS 长按拨号入口\r
-SOS_ENABLED = False\r
-\r
-# VC WebSocket 文本保活 ping 间隔(秒)。原逻辑约每 4 秒一次,空闲功耗偏高;拉大间隔可降低唤醒与发包频率\r
-VC_WS_PING_INTERVAL_SEC = 55\r
-\r
-# --------------------\r
-# VC 空闲/超时(ai_VC._1S_timer_cb_ 每秒累计)\r
-# --------------------\r
-# 长对话:无有效业务下行累计达此秒数后结束会话;代码侧最小 5\r
-VC_IDLE_AUTO_CLOSE_SEC = 20\r
-# 单对话侧预留(当前与 idle+深睡统一处理,与 7PIN_1_5 对齐)\r
-VC_IDLE_AUTO_CLOSE_SEC_PTT = 0\r
-# 业务 idle 累计达此秒数触发深睡断开;代码侧最小 10;0 关闭请改 ENABLE\r
-VC_IDLE_DEEP_SLEEP_SEC = 60\r
-VC_IDLE_DEEP_SLEEP_ENABLE = 1\r
-\r
-# --------------------\r
-# 开机提示/语音参数默认值(与具体产品绑定,编译期决定)\r
-# --------------------\r
-\r
-# 若为 None 或 POWER_ON_TONE_ENABLED=False,则不开机播报提示词\r
-POWER_ON_TONE_ENABLED = True\r
-POWER_ON_TONE_DEFAULT = "你好,我来了"\r
-\r
-# VAD 静音阈值默认值(ms)\r
-VAD_SILENCE_DEFAULT = 300\r
-\r
-# 默认音色配置(与 ai_VC.py 中格式保持一致)\r
-VC_TTS_VOICE_TYPE_DEFAULT = None # dict 或 None(None 表示沿用 ai_VC.py 内置兜底/存储值)\r
-VC_TTS_VOICE_KEY_DEFAULT = None # 例如 "男"/"童"\r
-\r
-# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)\r
-VC_WS_PATH = "vc/agent"\r
-\r
-# 是否支持蓝牙 OTA(原先仅 7PIN_1_5 会检查 bt_ota)\r
-BT_OTA_ENABLED = False\r
-\r
-# 是否在“开始上传语音”时播放成功提示音(原逻辑:非 7PIN/7PIN_1_5/7PIN_coze 才播)\r
-UPLOAD_START_TONE_ENABLED = False\r
-\r
-# 正常待机 idle 灯效:off=灭灯(REQ-BAT-01);green_blink=旧工程绿灯慢闪\r
-LED_IDLE_MODE = "off"\r
-\r
-# LLM thinking 阶段 LED 策略:flicker_blue_green / open_red_green\r
-THINKING_LED_MODE = "flicker_blue_green"\r
-\r
-# 收到 vad.active 时是否强制切回蓝灯\r
-VAD_ACTIVE_BLUE_LED = True\r
-\r
-# 本地指令:切换对话模式时的提示语(是什么语言就写什么)\r
-CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"\r
-CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"\r
-\r
-# 蓝牙/语音留言类本地指令是否启用(原先仅 7PIN_1_5)\r
-BT_VOICE_FEATURES_ENABLED = False\r
-\r
-# “关机”语音指令是否仅关闭对话(不触发 Power_off)。原逻辑:7PIN/7PIN_coze/7PIN_1_5 只 Close\r
-POWEROFF_CMD_CLOSE_ONLY = True\r
-\r
-# 关键词唤醒时在 PTT 模式下播报的提示语\r
-KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
-\r
-# 对话智能体/工作流默认配置(编译期确定;可在 usr/default_config.py 覆盖)\r
-# 结构示例:\r
-# DIALOG_BOT_OPTION = {"bot_id":"...", "workflow_id":"...", "use_workflow":True}\r
-DIALOG_BOT_OPTION = None\r
-\r
-# VC Start 请求里 dialog_attributes.cfg.bot_option(与 DIALOG_BOT_OPTION 二选一或叠加:后者可再覆盖)\r
-# 允许空字符串 "";未定义键时沿用下方默认值;若两者都为空则自动 use_workflow=False\r
-VC_BOT_ID = "7462617881076351002"\r
-VC_WORKFLOW_ID = "7462621757327196187"\r
-\r
-# dialog_attributes.provider 覆盖(None 表示沿用存储配置 dialog_attributes_provider)\r
-DIALOG_PROVIDER_DEFAULT = None\r
-\r
-# 是否从 VC_TTS_voice_type 的 key 列表生成 ASR 热词\r
-KEYWORDS_FROM_VOICE_TYPE = False\r
-\r
-# --------------------\r
-# 按键音/提示音策略(设备差异项)\r
-# --------------------\r
-\r
-# AI 键按下时:若设置了该文件路径,则在“无 VC 流播放中”时播放该提示音(例如 "U:/static/start.mp3")\r
-KEY_PRESS_TONE_FILE = None\r
-\r
-# AI 键按下时:延迟播放按键音(ms),规避蓝牙刚连上不出声等(与 7PIN_1_5 一致)\r
-KEY_PRESS_TONE_DELAY_MS = 300\r
-\r
-# 单对话长按开麦:开录提示音(None=不播,流畅优先;可设 U:/static/start.mp3)\r
-RECORD_START_TONE_FILE = None\r
-RECORD_START_TONE_GAP_MS = 180\r
-# 单对话松手后延迟(ms)再发 audio.completed,利于尾包/ASR 收敛\r
-PTT_RELEASE_END_SPEECH_DELAY_MS = 200\r
-# 单对话打断:发 cancel 后等待 canceled 的最长时间(ms),超时仍开录\r
-PTT_CANCEL_WAIT_MS = 2500\r
-\r
-# PTT 提示语(单对话模式,未长按时的提示;是什么语言就写什么)\r
-PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "\r
-\r
+# 设备侧默认配置(freeze 内置)。
+#
+# 加载优先级(由 vc_config.py 执行):
+# 1) usr/default_config.py(或 usr/defualt_config.py)
+# 2) 本文件 default_config.py
+
+# 当前设备类型(编译期间确定;现场仅可用 usr/default_config.py 覆盖)
+DEV_TYPE = "7PIN"
+
+# 是否加载 quecgnss 并在定位管理器初始化时调用 gnssEnable(0)。
+# 无 GNSS 硬件的机型(如部分吊坠)可置 False,避免 import quecgnss 或底层驱动异常/阻塞。
+GNSS_ENABLED = False
+
+# 为 True 时,protocol 模块 import 过程会打印 [proto.import] 阶段标记(配合 qp 日志口排查卡点)。
+PROTOCOL_IMPORT_TRACE = True
+
+# 当前设备配置(仅保留“设备差异项”,不要放运行态变量)
+# led_gpio 使用 Pin 属性名(字符串),由 vc_config.py 转成 Pin.GPIOxx 常量。
+LED_GPIO = ("GPIO36", "GPIO44", "GPIO43") # (R, G, B)
+
+# LED 电平极性(是否“反向”点亮)。
+# - 默认 LED_ACTIVE_LOW=False:高电平点亮(write(1)=亮)
+# - 若你的硬件是低电平点亮(write(0)=亮),将 LED_ACTIVE_LOW=True
+# - 若仅某一路反相,用 LED_ACTIVE_LOW_RGB 单独配置(按 LED_GPIO 顺序 R/G/B)
+LED_ACTIVE_LOW = False
+LED_ACTIVE_LOW_RGB = None # 例如 (True, False, False) 表示仅红灯反相
+# LED_ACTIVE_LOW_RGB = (True, False, False)
+
+# idle 绿灯长慢闪:常亮 / 熄灭(ms);仅配 LED_IDLE_GREEN_BLINK_MS 时灭灯时长与常亮相同(对称慢闪)
+LED_IDLE_GREEN_BLINK_MS = 1000
+LED_IDLE_GREEN_BLINK_OFF_MS = 2000
+
+# 是否支持 UART 相关能力(例如 7PIN_1_5 才允许走串口)
+UART_SUPPORTED = False
+
+# 语言/地区(如 zh/en),用于少量文案/逻辑差异
+LANG = "zh"
+
+# --------------------
+# 硬件差异项(由每个设备的 default_config 固定)
+# --------------------
+LED_DEBUG = True
+LED_STATE_DEBUG = True
+KEY_LED_DEBUG = True
+HW_STATUS_DEBUG = True
+
+# --------------------
+# 电池 OCV / 硬件状态轮询(AI_hw_status,可在 usr/default_config.py 覆盖)
+# --------------------
+# True 时用三档电压门限估算 SoC,忽略 BATTERY_OCV_MAP
+USE_SIMPLE_VBATT_THRESH = False
+VBATT_CHARGE_FULL_MV = 4290 # USB 在位且电压≥此值视为充满(get_battery / AI_hw_status / AI_dev 共用)
+VBATT_LOW_MV = 3699 # 低电电压门限;simple 模式与 AI_dev 低电提示用
+VBATT_EMPTY_MV = 3629 # 空电电压门限;AI_dev 低电关机等
+BATTERY_LOW_SOC_PERCENT = 30 # OCV 模式:soc < 此值 → battery=low(REQ-BAT-02:10%~30%)
+BATTERY_EMPTY_SOC_PERCENT = 10 # OCV 模式:soc < 此值 → battery=empty(REQ-BAT-03:<10%)
+HW_STATUS_PERIOD_MS = 10000
+SIGNAL_WEAK_CSQ = 10
+
+# 开路电压(mV) -> SoC(%),按电压线性插值;None 则用 ai_VC 内置默认表
+BATTERY_OCV_MAP = {
+ 4290: 100, 4237: 95, 4179: 90, 4123: 85, 4070: 80, 4020: 75, 3963: 70, 3919: 65, 3882: 60, 3847: 55,
+ 3818: 50, 3794: 45, 3772: 40, 3752: 35, 3733: 30, 3716: 25, 3699: 20, 3677: 15, 3652: 10, 3629: 5, 3400: 0,
+}
+
+# 是否需要初始化蓝牙电源/马达/音频IIS配置等(原先仅 7PIN_1_5)
+BT_POWER_MOTOR_ENABLED = False
+PIN_BT_ON_GPIO = None # 例如 "GPIO31"
+PIN_MOT_GPIO = None
+# audio.set_qdai_cfg(...) 参数;若为 None 则不调用
+AUDIO_QDAI_CFG = None # 例如 (1,0,0,2,0,1,1,1)
+
+# motor.py(motorEventManager):马达输出脚与节拍。MOTOR_GPIO 为 None 时依次尝试 PIN_MOT_GPIO、默认 GPIO36。
+MOTOR_PIN_GPIO = "GPIO20" # 例如 "GPIO36";无马达硬件可保持 None
+MOTOR_TICK_MS = 100
+MOTOR_ACTIVE_LOW = False
+MOTOR_BOOT_VIBRATE_MS = 200 # 马达开机震动时间 200ms
+
+
+# AI 按键中断与电源键中断引脚(ExtInt.GPIOxx)
+EXTINT_AI_GPIO = "GPIO22" # ai按键
+PWK_KEY_GPIO = "GPIO26" # 侧边power按键 , 模式切换
+
+#btn_device_ec800m.py
+BTN_WECHAT_GPIO = None
+BTN_SOS_GPIO = None
+
+
+# 蓝牙唤醒 4G/4G 唤醒蓝牙相关(原先仅 7PIN_1_5)
+BT_WAKEUP_4G_ENABLED = False
+EXTINT_WAKEUP_CTA1_GPIO = None # 例如 "GPIO22"
+PIN_WAKEUP_BT_GPIO = None # 例如 "GPIO21"
+
+# --------------------
+# 按键/防抖差异
+# --------------------
+
+# 释放防抖阈值(KeyAI/pwk):原代码部分设备用 3,其他用 5
+KEY_RELEASE_DEBOUNCE_COUNT = 5
+
+# 是否允许 AI 键长按 8 秒触发关机逻辑(原 jswm/jswm_BOX)
+AI_LONG_PRESS_POWER_OFF_ENABLED = False
+
+# 是否启用 SOS:False 时禁用 AI 键长按 3s 拨紧急号、以及按键板上的 SOS 长按拨号入口
+SOS_ENABLED = False
+
+# VC WebSocket 文本保活 ping 间隔(秒)。原逻辑约每 4 秒一次,空闲功耗偏高;拉大间隔可降低唤醒与发包频率
+VC_WS_PING_INTERVAL_SEC = 55
+
+# --------------------
+# VC 空闲/超时(ai_VC._1S_timer_cb_ 每秒累计)
+# --------------------
+# 长对话:无有效业务下行累计达此秒数后结束会话;代码侧最小 5
+VC_IDLE_AUTO_CLOSE_SEC = 20
+# 单对话侧预留(当前与 idle+深睡统一处理,与 7PIN_1_5 对齐)
+VC_IDLE_AUTO_CLOSE_SEC_PTT = 0
+# 业务 idle 累计达此秒数触发深睡断开;代码侧最小 10;0 关闭请改 ENABLE
+VC_IDLE_DEEP_SLEEP_SEC = 60
+VC_IDLE_DEEP_SLEEP_ENABLE = 1
+
+# --------------------
+# 开机提示/语音参数默认值(与具体产品绑定,编译期决定)
+# --------------------
+
+# 若为 None 或 POWER_ON_TONE_ENABLED=False,则不开机播报提示词
+POWER_ON_TONE_ENABLED = True
+POWER_ON_TONE_DEFAULT = "你好,我来了"
+
+# VAD 静音阈值默认值(ms)
+VAD_SILENCE_DEFAULT = 300
+
+# 默认音色配置(与 ai_VC.py 中格式保持一致)
+VC_TTS_VOICE_TYPE_DEFAULT = None # dict 或 None(None 表示沿用 ai_VC.py 内置兜底/存储值)
+VC_TTS_VOICE_KEY_DEFAULT = None # 例如 "男"/"童"
+
+# VC WebSocket 路径(ws://{AMP_SERVER}/{VC_WS_PATH}...)
+VC_WS_PATH = "vc/agent"
+
+# 是否支持蓝牙 OTA(原先仅 7PIN_1_5 会检查 bt_ota)
+BT_OTA_ENABLED = False
+
+# 是否在“开始上传语音”时播放成功提示音(原逻辑:非 7PIN/7PIN_1_5/7PIN_coze 才播)
+UPLOAD_START_TONE_ENABLED = False
+
+# 正常待机 idle 灯效:off=灭灯(REQ-BAT-01);green_blink=旧工程绿灯慢闪
+LED_IDLE_MODE = "off"
+
+# LLM thinking 阶段 LED 策略:flicker_blue_green / open_red_green
+THINKING_LED_MODE = "flicker_blue_green"
+
+# 收到 vad.active 时是否强制切回蓝灯
+VAD_ACTIVE_BLUE_LED = True
+
+# 本地指令:切换对话模式时的提示语(是什么语言就写什么)
+CMD_TOGGLE_MODE_TO_PTT_TTS = "已切换到单对话模式"
+CMD_TOGGLE_MODE_TO_LONG_TTS = "已切换到长对话模式"
+
+# 蓝牙/语音留言类本地指令是否启用(原先仅 7PIN_1_5)
+BT_VOICE_FEATURES_ENABLED = False
+
+# “关机”语音指令是否仅关闭对话(不触发 Power_off)。原逻辑:7PIN/7PIN_coze/7PIN_1_5 只 Close
+POWEROFF_CMD_CLOSE_ONLY = True
+
+# 关键词唤醒时在 PTT 模式下播报的提示语
+KWS_PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "
+
+# 对话智能体/工作流默认配置(编译期确定;可在 usr/default_config.py 覆盖)
+# 结构示例:
+# DIALOG_BOT_OPTION = {"bot_id":"...", "workflow_id":"...", "use_workflow":True}
+DIALOG_BOT_OPTION = None
+
+# VC Start 请求里 dialog_attributes.cfg.bot_option(与 DIALOG_BOT_OPTION 二选一或叠加:后者可再覆盖)
+# 允许空字符串 "";未定义键时沿用下方默认值;若两者都为空则自动 use_workflow=False
+VC_BOT_ID = "7462617881076351002"
+VC_WORKFLOW_ID = "7462621757327196187"
+
+# dialog_attributes.provider 覆盖(None 表示沿用存储配置 dialog_attributes_provider)
+DIALOG_PROVIDER_DEFAULT = None
+
+# 是否从 VC_TTS_voice_type 的 key 列表生成 ASR 热词
+KEYWORDS_FROM_VOICE_TYPE = False
+
+# --------------------
+# 按键音/提示音策略(设备差异项)
+# --------------------
+
+# AI 键按下时:若设置了该文件路径,则在“无 VC 流播放中”时播放该提示音(例如 "U:/static/start.mp3")
+KEY_PRESS_TONE_FILE = None
+
+# AI 键按下时:延迟播放按键音(ms),规避蓝牙刚连上不出声等(与 7PIN_1_5 一致)
+KEY_PRESS_TONE_DELAY_MS = 300
+
+# 单对话长按开麦:开录提示音(None=不播,流畅优先;可设 U:/static/start.mp3)
+RECORD_START_TONE_FILE = None
+RECORD_START_TONE_GAP_MS = 180
+# 单对话松手后延迟(ms)再发 audio.completed,利于尾包/ASR 收敛
+PTT_RELEASE_END_SPEECH_DELAY_MS = 200
+# 单对话打断:发 cancel 后等待 canceled 的最长时间(ms),超时仍开录
+PTT_CANCEL_WAIT_MS = 2500
+# PTT 本地硬静音后等待 codec/DMA 收尾(ms),减轻打断尾音
+PTT_POST_MUTE_MS = 30
+
+# PTT 提示语(单对话模式,未长按时的提示;是什么语言就写什么)
+PTT_HINT = "请您按住圆形的按钮开始讲话,讲完松开即可 "
+
Version="V1.2" \r
-Build_Time="2026-05-17 20:20:17" \r
+Build_Time="2026-05-17 23:56:53" \r