# BOOT按键聆听状态切换实现测试指南

## 修改概述

本次修改实现了BOOT按键在说话状态下切换到聆听状态的功能，替代了原来切换到待命状态的行为。

### 核心变更

1. **新增函数**: `AbortSpeakingAndReturnToListening()`
   - 专门处理从说话状态到聆听状态的切换
   - 播放"卡卡在呢"语音提示（P3_KAKAZAINNE）
   - 保持与原有`AbortSpeakingAndReturnToIdle()`相同的安全机制

2. **BOOT按键行为修改**:
   - 说话状态下：从切换到待命状态 → 切换到聆听状态
   - 语音提示：从"卡卡正在待命" → "卡卡在呢"

3. **日志标识**:
   - 🔴: 切换到待命状态相关操作
   - 🔵: 切换到聆听状态相关操作

4. **状态保持优化**: 
   - 移除了聆听状态下音频通道不可用时自动回退到idle状态的逻辑
   - 添加了`is_switching_to_listening_`原子标志，防止OnAudioChannelClosed回调强制设置为idle状态
   - 确保设备在切换到聆听状态后能够稳定保持该状态，不被意外的回调函数干扰

## 实现细节

### 函数调用路径
```
BOOT按键按下 (说话状态)
↓
movecall_moji_esp32s3.cc: AbortSpeakingAndReturnToListening()
↓
application.cc: 发送中止消息 → 关闭连接 → 切换到聆听状态 → 播放"卡卡在呢"
```

### 关键特性

1. **状态验证**: 确保当前处于说话状态
2. **安全检查**: 通过`IsSafeToOperate()`防止频繁操作
3. **优雅中止**: 发送中止消息给服务器
4. **主动关闭**: 100ms延迟后关闭音频通道
5. **状态切换**: 200ms延迟后切换到聆听状态
6. **语音反馈**: 播放"卡卡在呢"确认进入聆听状态

## 测试场景

### 1. 正常说话状态下的BOOT按键操作

**测试步骤**:
1. 启动设备，确保网络连接正常
2. 触发语音对话，使设备进入说话状态
3. 在TTS播放过程中按下BOOT按键
4. 观察设备行为和日志输出

**预期结果**:
- TTS播放立即停止
- 日志显示🔵标记的聆听状态切换流程
- 设备状态切换到聆听状态（LED指示灯变化）
- 播放"卡卡在呢"语音提示
- 设备进入聆听模式，可以接收语音输入

**关键日志**:
```
🔵 BOOT按键：设备处于说话状态，启动专门的中止和切换到聆听状态流程
🔵 AbortSpeakingAndReturnToListening: Starting transition from speaking to listening state
🔵 AbortSpeakingAndReturnToListening: Switching to listening state and playing KAKAZAINNE sound
```

### 2. 非说话状态下的按键行为验证

**测试步骤**:
1. 在待命状态下按BOOT按键
2. 在聆听状态下按BOOT按键
3. 在其他状态下按BOOT按键

**预期结果**:
- 待命状态 → 聆听状态（原有行为保持不变）
- 聆听状态 → 待命状态（原有行为保持不变）
- 其他状态 → 设备唤醒（原有行为保持不变）

### 3. 快速连续按键测试

**测试步骤**:
1. 在说话状态下快速连续按BOOT按键
2. 观察安全机制是否生效

**预期结果**:
- 第一次按键触发正常切换流程
- 后续按键被安全机制阻止
- 日志显示"Operation not safe, scheduling retry"消息

### 4. 网络异常情况测试

**测试步骤**:
1. 在说话状态下断开网络连接
2. 按下BOOT按键
3. 观察设备处理异常情况的能力

**预期结果**:
- 即使网络异常，设备也能正常切换到聆听状态
- 播放"卡卡在呢"语音提示
- 日志显示"Audio channel not available"相关处理

## 性能验证

### 响应时间要求
- TTS停止响应时间: < 200ms
- 状态切换完成时间: < 500ms
- 语音提示播放延迟: < 300ms

### 资源使用
- 内存增量: 新函数增加约1KB代码空间
- CPU使用: 状态切换期间短暂增加

## 日志监控要点

### 正常流程日志
```
🔵 BOOT按键：设备处于说话状态，启动专门的中止和切换到聆听状态流程
🔵 AbortSpeakingAndReturnToListening: Starting transition from speaking to listening state
🔵 AbortSpeakingAndReturnToListening: Sending abort message to server
🔵 AbortSpeakingAndReturnToListening: Abort message sent successfully
🔵 AbortSpeakingAndReturnToListening: Actively closing audio channel
🔵 AbortSpeakingAndReturnToListening: Switching to listening state and playing KAKAZAINNE sound
STATE: listening
```

### 异常情况日志
```
🔵 AbortSpeakingAndReturnToListening: Device not in speaking state
🔵 AbortSpeakingAndReturnToListening: Operation not safe, scheduling retry
🔵 AbortSpeakingAndReturnToListening: Audio channel not available
```

## 故障排除

### 问题1: "卡卡在呢"语音不播放
**可能原因**: 音频队列阻塞或P3文件损坏
**解决方案**: 检查音频队列状态，验证P3_KAKAZAINNE文件完整性

### 问题2: 设备未切换到聆听状态
**可能原因**: 状态切换逻辑异常或延迟设置不当
**解决方案**: 检查SetDeviceState调用和Schedule延迟时间

### 问题3: 连接未正确关闭
**可能原因**: 协议层异常或网络问题
**解决方案**: 检查protocol_->CloseAudioChannel()调用和网络状态

## 兼容性说明

- **向后兼容**: 原有`AbortSpeakingAndReturnToIdle()`函数保持不变
- **其他状态**: 非说话状态下的BOOT按键行为完全不变
- **API稳定**: 不影响其他模块的接口调用

## 总结

本次修改通过新增专用函数的方式，实现了BOOT按键在说话状态下切换到聆听状态的需求，同时保持了代码的清晰性和可维护性。修改遵循了单一职责原则，不影响现有功能的稳定性。

测试时请重点关注状态切换的流畅性、语音提示的及时性以及异常情况的处理能力。