T5_3.13.6版本,我在进入深度休眠状态之前播放了一段提示音,播放结束后再执行进入休眠。进入休眠时间设置为1分钟,但是目前的状况是第1分钟会播报提示音但无法进入休眠,且按键唤醒后无法正常对话,等到第2分钟才会进入休眠,奇怪的是第2分钟居然不会播报提示音,直接就休眠了。求解答!
T5_3.13.6版本在进入低功耗之前播放本地提示音,进入低功耗时间翻倍
Re: T5_3.13.6版本在进入低功耗之前播放本地提示音,进入低功耗时间翻倍
你好!
问题概述
进入深度休眠前播放提示音,设置1分钟超时变成2分钟才进入休眠。
根因分析
经代码排查,定位到tuya_ai_toy.c中__on_ai_toy_lowpower_timer回调的逻辑问题:
时序分析:
- idle状态启动lowpower_timer(60s)
- 用户播放本地提示音
- 第1分钟timer到期,但wukong_audio_player_is_playing()==TRUE
- 回调将timer重置为完整的TOY_LOWPOWER_TIMEOUT(60s),而非短间隔重试
- 按键唤醒后AI agent处于idle不可交互状态
- 第2分钟timer再次到期,提示音已播完,直接进入深度休眠
总等待时间=60s+60s=120s,翻倍。第2分钟不播提示音是因为音频播放已完成、状态已变迁。
关键代码(tuya_ai_toy.c:618):
if(wukong_audio_player_is_playing()) {
tal_sw_timer_start(s_ai_toy->lowpower_timer, TOY_LOWPOWER_TIMEOUT, TAL_TIMER_ONCE);
}
// 问题:重置为完整60s而非短间隔重试
解决方案
方案1(推荐):修改重置逻辑为短间隔重试
将重置间隔从TOY_LOWPOWER_TIMEOUT(60s)改为1s:
Code: Select all
// 修改前
tal_sw_timer_start(s_ai_toy->lowpower_timer, TOY_LOWPOWER_TIMEOUT, TAL_TIMER_ONCE);
// 修改后
tal_sw_timer_start(s_ai_toy->lowpower_timer, 1000, TAL_TIMER_ONCE);播放提示音场景下总等待时间从120s变为约61s。
方案2:播放提示音前停止lowpower_timer
在播放本地提示音前调用tuya_ai_toy_lowpower_timer_ctrl(FALSE),播放结束回调中调用tuya_ai_toy_lowpower_timer_ctrl(TRUE),休眠从提示音播完后重新计时60s。
验证方法
修改后播放提示音,总等待时间应为原超时+提示音剩余播放时间(约61s),不再翻倍。
Re: T5_3.13.6版本在进入低功耗之前播放本地提示音,进入低功耗时间翻倍
T5_3.13.6版本在进入低功耗之前播放本地提示音,进入低功耗时间翻倍
本地资料够了:svc_ai_agent 的输出会话/提示音机制和 T5 深睡唤醒机制都能对上这个「第一分钟播不睡、第二分钟不播直接睡」的现象,可以回答。
结论:大概率不是“时间翻倍”,而是第一次休眠尝试被自己的提示音否决了——提示音走音频输出通道播放时,系统处于“音频会话活跃”状态,休眠条件检查不通过,这一轮就放弃了;但休眠准备动作(停会话/关麦克风)已经做了一半且没有回滚,所以按键唤醒后无法对话;第二分钟提示音的 one-shot 标志已被消费、也没有音频再阻塞,就直接睡进去了。
逐分钟拆解(出处:components/svc_ai_agent/README_CN.md、vendor/T5/README_CN.md):
- 第 1 分钟:定时到点 → 业务先播提示音。音频输出会话进入
PLAYING,要等AI_EVENT_END才算空闲;休眠入口检查时音频未结束(或刚结束、I2S/DMA 还没排空),本轮休眠被跳过,等下一个周期 - 唤醒后不能对话:休眠流程里先执行的“退出 AI 会话/关麦克风”在休眠被否决后没有恢复,agent 状态机停在半关闭状态,按键说话送不进会话
- 第 2 分钟:播提示音的逻辑挂在“休眠流程入口”且只执行一次,标志已消费 → 不再播报;这次没有音频阻塞,休眠成功
- T5 平台侧:深睡只能靠
tkl_wakeup_source_set注册过的源唤醒,普通 GPIO IRQ 在 Deep Sleep 下不触发,这部分你们已验证能唤醒,说明平台配置本身没问题
建议改法:
| 问题点 | 修改 |
|---|---|
| 提示音阻塞休眠 | 先播提示音,在播放完成回调(AI_EVENT_END 或本地播放器完成事件)里再发起休眠,不要在休眠入口同步等 |
| 失败后状态不回滚 | 休眠失败分支要把麦克风/会话重新拉起,保证按键对话可用 |
| 提示音只播一次 | 挂到“每次真正进休眠前”的路径上,而不是一次性标志 |
Code: Select all
// 定时器到点:先播,播完再睡
STATIC VOID prompt_done_cb(VOID_T *arg)
{
// 用一次性软件_timer 延时 500ms,等 I2S/DMA 排空,别在回调里阻塞
tal_sw_timer_start(s_sleep_timer, 500, TAL_TIMER_ONCE);
}
STATIC VOID on_sleep_timer_expire(TAL_TIMER_CB cb, VOID_T *arg)
{
tkl_cpu_sleep_mode_set(TRUE, TUYA_CPU_SLEEP); // 唤醒源开机时已注册
}
void on_idle_timeout(void)
{
play_prompt_async(PROMPT_GOING_SLEEP, prompt_done_cb);
}细节行为(比如 3.13.6 里休眠前检查的具体条件)需要看你们 实现代码.txt 的实际流程才能确认,可以点「查代码」进一步对照。
以上内容由 AI 自动分析生成,如有疑问请回复补充。