185 lines
6.1 KiB
Markdown
185 lines
6.1 KiB
Markdown
# 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. **扩展性**: 为其他类似需求提供了模板
|
||
|
||
这种设计方式更符合单一职责原则,提高了代码的可维护性和可靠性。 |