# BOOT按键新实现方案测试指南 ## 概述 本文档描述了BOOT按键新实现方案的测试验证流程。新方案创建了专门的 `AbortSpeakingAndReturnToIdle()` 函数来处理从说话状态到空闲状态的切换,而不是修改原有的 `AbortSpeaking()` 函数。 ## 新实现方案特点 ### 1. 专门函数设计 - **函数名称**: `AbortSpeakingAndReturnToIdle()` - **专门用途**: 处理BOOT按键在说话状态下的切换需求 - **独立性**: 不影响其他场景下的 `AbortSpeaking()` 调用 ### 2. 核心功能 - ✅ 状态检查:确保当前处于说话状态 - ✅ 安全性检查:防止重复操作和竞态条件 - ✅ 发送中止消息:通知服务器停止TTS - ✅ 主动关闭连接:100ms延迟后强制关闭WebSocket - ✅ 完整日志:详细记录每个操作步骤 ### 3. 调用路径 ``` BOOT按键点击 → InitializeButtons() → AbortSpeakingAndReturnToIdle() → OnAudioChannelClosed() → SetDeviceState(kDeviceStateIdle) → 播放待机音 ``` ## 测试场景 ### 场景1:正常说话状态下的BOOT按键操作 **测试步骤**: 1. 启动设备,确保连接正常 2. 触发语音对话,让设备进入说话状态(播放TTS) 3. 在TTS播放过程中按下BOOT按键 4. 观察设备行为和日志输出 **预期结果**: ``` 🔴 BOOT按键:设备处于说话状态,启动专门的中止和切换流程 🔴 AbortSpeakingAndReturnToIdle: Starting transition from speaking to idle state 🔴 AbortSpeakingAndReturnToIdle: Sending abort message to server 🔴 AbortSpeakingAndReturnToIdle: Abort message sent successfully 🔴 AbortSpeakingAndReturnToIdle: Actively closing audio channel 🔴 CloseAudioChannel: Actively closing WebSocket connection 🔴 OnDisconnected: WebSocket connection disconnected 🔴 OnDisconnected: Audio processor stopped immediately 🔴 OnDisconnected: Triggering OnAudioChannelClosed callback 🔴 OnAudioChannelClosed: Audio channel closed, starting cleanup tasks 🔵 SetDeviceState: Entering idle state from speaking, playing standby sound 🔵 SetDeviceState: Standby sound playback initiated ``` **验证要点**: - [ ] TTS立即停止播放 - [ ] 设备状态切换到空闲(kDeviceStateIdle) - [ ] 播放待机音(daiming.p3) - [ ] 显示屏显示"待机"状态 - [ ] LED指示灯切换到空闲状态颜色 ### 场景2:非说话状态下的BOOT按键操作 **测试步骤**: 1. 确保设备处于空闲状态 2. 按下BOOT按键 3. 观察设备行为 **预期结果**: - 设备应该正常切换到聆听状态 - 不应该调用 `AbortSpeakingAndReturnToIdle()` 函数 - 应该播放"卡卡在呢"提示音 ### 场景3:快速连续按键测试 **测试步骤**: 1. 让设备进入说话状态 2. 快速连续按下BOOT按键多次(间隔小于500ms) 3. 观察防抖机制和安全检查 **预期结果**: ``` BOOT button clicked too frequently, ignoring this click 🔴 AbortSpeakingAndReturnToIdle: Operation not safe, scheduling retry ``` ### 场景4:网络异常情况测试 **测试步骤**: 1. 让设备进入说话状态 2. 断开网络连接 3. 按下BOOT按键 4. 观察错误处理 **预期结果**: ``` 🔴 AbortSpeakingAndReturnToIdle: Audio channel not available, forcing close ``` ## 关键改进点 ### 1. 函数职责分离 - **原方案**: 修改 `AbortSpeaking()` 函数,影响所有调用场景 - **新方案**: 创建专门函数,只处理BOOT按键的特定需求 ### 2. 代码维护性 - **独立性**: 新函数不影响现有的语音打断逻辑 - **可扩展性**: 未来可以为其他按键创建类似的专门函数 - **可测试性**: 单独测试BOOT按键功能,不影响其他功能 ### 3. 安全性增强 - 状态检查:确保只在说话状态下执行 - 操作安全性:防止重复调用和竞态条件 - 异常处理:网络异常时的降级处理 ## 日志监控要点 ### 成功流程日志序列 1. `🔴 BOOT按键:设备处于说话状态,启动专门的中止和切换流程` 2. `🔴 AbortSpeakingAndReturnToIdle: Starting transition from speaking to idle state` 3. `🔴 AbortSpeakingAndReturnToIdle: Sending abort message to server` 4. `🔴 AbortSpeakingAndReturnToIdle: Abort message sent successfully` 5. `🔴 AbortSpeakingAndReturnToIdle: Actively closing audio channel` 6. `🔴 OnAudioChannelClosed: Audio channel closed, starting cleanup tasks` 7. `🔵 SetDeviceState: Entering idle state from speaking, playing standby sound` ### 异常情况日志 - `🔴 AbortSpeakingAndReturnToIdle: Device not in speaking state` - 状态不匹配 - `🔴 AbortSpeakingAndReturnToIdle: Operation not safe, scheduling retry` - 操作不安全 - `🔴 AbortSpeakingAndReturnToIdle: Failed to send abort message` - 发送失败 - `🔴 AbortSpeakingAndReturnToIdle: Audio channel not available, forcing close` - 连接不可用 ## 性能验证 ### 响应时间测试 - **目标**: BOOT按键按下到TTS停止 < 200ms - **目标**: 完整状态切换到播放待机音 < 500ms ### 资源使用测试 - 监控内存使用情况 - 检查是否有内存泄漏 - 验证任务调度的效率 ## 故障排除 ### 问题1:待机音不播放 **可能原因**: - 音频输出未正确初始化 - 状态切换未完成 - 音频文件损坏 **排查方法**: - 检查 `SetDeviceState` 日志 - 验证音频编解码器状态 - 测试其他音频播放功能 ### 问题2:连接未正确关闭 **可能原因**: - WebSocket关闭失败 - 网络异常 - 协议层错误 **排查方法**: - 检查 `CloseAudioChannel` 日志 - 监控网络连接状态 - 验证协议层实现 ### 问题3:状态转换异常 **可能原因**: - 竞态条件 - 重复调用 - 安全检查失败 **排查方法**: - 检查 `IsSafeToOperate` 返回值 - 监控操作时间戳 - 验证防抖机制 ## 总结 新实现方案通过创建专门的 `AbortSpeakingAndReturnToIdle()` 函数,实现了: 1. **功能独立性**: 不影响现有的 `AbortSpeaking()` 逻辑 2. **代码清晰性**: 专门处理BOOT按键的特定需求 3. **维护便利性**: 易于测试和调试 4. **扩展性**: 为其他类似需求提供了模板 这种设计方式更符合单一职责原则,提高了代码的可维护性和可靠性。