chore: archive diagnostics and project documentation
This commit is contained in:
@@ -0,0 +1,708 @@
|
||||
# TQ Cat 固件整体架构与运行工作流
|
||||
|
||||
本文档基于 `feature/st7789p3-new-board` 分支的代码,面向项目接手、问题定位和后续重构。内容以实际函数调用关系为准。
|
||||
|
||||
## 1. 系统定位
|
||||
|
||||
项目运行在 ESP32-S3 上,主要负责:
|
||||
|
||||
- ST7789P3 LCD 表情播放;
|
||||
- ES8311 音频采集与播放;
|
||||
- Opus 编解码与 WebSocket 多模态对话;
|
||||
- TTP223 PTT、SW1、SW2 按键处理;
|
||||
- ULN2003 步进电机和转盘校准;
|
||||
- Wi-Fi 连接、重连和配置热点;
|
||||
- 设备身份、JWT 和会话令牌;
|
||||
- 用户出生资料、每日运势和财富方向;
|
||||
- NVS、LittleFS、远程日志和工厂 CLI。
|
||||
|
||||
## 2. 分层架构
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Main["main / app_main"]
|
||||
App["app_composition<br/>启动顺序与应用装配"]
|
||||
CP["control_plane<br/>策略、状态机、任务、重试"]
|
||||
Domain["domain<br/>方向、校准、运势、表情语义"]
|
||||
Platform["platform<br/>GPIO、LCD、音频、网络、存储"]
|
||||
HW["ESP32-S3 新板硬件"]
|
||||
|
||||
Main --> App --> CP --> Domain --> Platform --> HW
|
||||
```
|
||||
|
||||
各层职责:
|
||||
|
||||
| 层 | 主要职责 | 典型内容 |
|
||||
| --- | --- | --- |
|
||||
| `main` | 固件入口 | 只调用 composition 入口 |
|
||||
| `app_composition` | 决定启动顺序 | 存储、音频、LCD、校准、联网、workers |
|
||||
| `control_plane` | 产品策略和生命周期 | Wi-Fi、PTT、多模态、任务、重试、异常恢复 |
|
||||
| `domain` | 业务语义和状态 | 方向、角度、校准、运势、LCD 表情映射 |
|
||||
| `platform` | 硬件与传输原语 | GPIO、I2S、I2C、SPI、WebSocket、NVS、HTTP |
|
||||
|
||||
## 3. 启动总流程
|
||||
|
||||
入口:
|
||||
|
||||
```text
|
||||
app_main()
|
||||
└── app_composition_start_default_runtime()
|
||||
└── app_composition_run_plan_a_boot_sequence()
|
||||
```
|
||||
|
||||
主要文件:
|
||||
|
||||
- `main/main.c`
|
||||
- `components/app_composition/src/runtime/app_composition_default_runtime.c`
|
||||
|
||||
启动阶段:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Entry["app_main"]
|
||||
Storage["准备 NVS / 文件系统"]
|
||||
Audio["初始化音频并播放开机音"]
|
||||
LCD["初始化 LCD 和渲染任务"]
|
||||
Core["初始化 platform / domain"]
|
||||
Expression["请求默认 LCD 表情"]
|
||||
Calibration["执行转盘原点校准"]
|
||||
WiFi["连接 Wi-Fi 或启动配置 AP"]
|
||||
Workers["启动运行时 workers"]
|
||||
|
||||
Entry --> Storage --> Audio --> LCD --> Core --> Expression --> Calibration --> WiFi --> Workers
|
||||
```
|
||||
|
||||
### 3.1 存储初始化
|
||||
|
||||
```text
|
||||
control_plane_prepare_runtime_storage()
|
||||
└── domain_runtime_prepare_storage()
|
||||
└── platform_prepare_storage()
|
||||
├── nvs_flash_init()
|
||||
├── 必要时 nvs_flash_erase()
|
||||
├── 再次 nvs_flash_init()
|
||||
└── platform_log_nvs_stats()
|
||||
```
|
||||
|
||||
默认 NVS namespace 包括 `wifi`、`ota`、`auth`、`auth_key` 和 `fortune`。
|
||||
|
||||
### 3.2 音频与开机音
|
||||
|
||||
```text
|
||||
control_plane_play_boot_sound(timeout)
|
||||
├── domain_runtime_multimodal_audio_init()
|
||||
│ └── platform_multimodal_audio_init()
|
||||
│ └── multimodal_audio_init()
|
||||
└── domain_runtime_behavior_play_prompt_file(path)
|
||||
```
|
||||
|
||||
`multimodal_audio_init()` 的主要步骤:
|
||||
|
||||
```text
|
||||
fill_codec_sample_info()
|
||||
→ audio_init_heap_guard_passed()
|
||||
→ init_opus_codec()
|
||||
→ init_i2c_bus()
|
||||
→ init_i2s_bus()
|
||||
→ create_codec_path()
|
||||
→ open_codec_device()
|
||||
→ apply_codec_default_controls()
|
||||
→ ensure_uplink_worker_tasks()
|
||||
→ ensure_downstream_playback_task()
|
||||
```
|
||||
|
||||
开机音失败只记录 warning,不会终止启动。
|
||||
|
||||
### 3.3 LCD 初始化
|
||||
|
||||
```text
|
||||
control_plane_init_lcd_device()
|
||||
└── domain_runtime_init_lcd_device()
|
||||
└── platform_init_lcd_device()
|
||||
└── lcd_direct_init_device()
|
||||
├── lcd_direct_gpio_init()
|
||||
└── lcd_direct_panel_init()
|
||||
```
|
||||
|
||||
渲染任务:
|
||||
|
||||
```text
|
||||
control_plane_start_lcd_render_worker()
|
||||
└── control_plane_lcd_render_loop_task()
|
||||
└── control_plane_start_lcd_render_loop()
|
||||
└── domain_runtime_start_lcd_render_loop()
|
||||
└── platform_start_lcd_render_loop()
|
||||
└── lcd_direct_start_render_loop()
|
||||
```
|
||||
|
||||
### 3.4 platform/domain 初始化
|
||||
|
||||
```text
|
||||
control_plane_init()
|
||||
├── domain_direction_default_axis_config()
|
||||
├── domain_direction_default_calibration()
|
||||
└── domain_init(axis_config, calibration)
|
||||
├── domain_runtime_platform_init()
|
||||
│ └── platform_init()
|
||||
│ ├── platform_power_hold_init()
|
||||
│ ├── platform_io_effects_init()
|
||||
│ ├── platform_stepper_driver_init()
|
||||
│ └── platform_stepper_driver_power_off()
|
||||
├── 初始化方向状态
|
||||
└── domain_calibration_store_set()
|
||||
```
|
||||
|
||||
注意:启动日志将 power hold 描述为已提前拉起,但实际 `platform_power_hold_init()` 位于 `platform_init()` 中。新板应真机验证 GPIO9 拉高时机是否足够早。
|
||||
|
||||
## 4. 新板关键 GPIO
|
||||
|
||||
| 功能 | GPIO | 电气语义 |
|
||||
| --- | ---: | --- |
|
||||
| Power Hold | 9 | 高有效 |
|
||||
| LCD CLK | 8 | SPI clock |
|
||||
| LCD MOSI | 18 | SPI data |
|
||||
| LCD CS | 15 | 低有效 |
|
||||
| LCD DC | 16 | 数据/命令 |
|
||||
| LCD RESET | 17 | 低有效 reset |
|
||||
| LCD Backlight | 7 | 高有效 |
|
||||
| TTP223 / PTT | 3 | 高有效,无内部上下拉 |
|
||||
| SW1 校准开关 | 12 | 低有效,上拉 |
|
||||
| SW2 功能开关 | 13 | 低有效,上拉 |
|
||||
| Stepper IN1/2/3/4 | 45/48/47/21 | ULN2003 相线 |
|
||||
| Audio PA | 11 | 功放使能 |
|
||||
| ES8311 I2C SDA/SCL | 1/2 | codec 控制 |
|
||||
| I2S MCLK/BCLK/DOUT/WS/DIN | 38/39/40/41/42 | 音频数据 |
|
||||
|
||||
## 5. 转盘校准与旋转
|
||||
|
||||
启动校准调用链:
|
||||
|
||||
```text
|
||||
control_plane_calibrate()
|
||||
└── control_plane_calibrate_with_timeout()
|
||||
└── control_plane_direction_calibrate_internal()
|
||||
└── domain_calibrate_with_timeout()
|
||||
```
|
||||
|
||||
`domain_calibrate_with_timeout()`:
|
||||
|
||||
```text
|
||||
锁定方向状态
|
||||
→ prepare_calibration_switch()
|
||||
→ 检查 SW1 是否已有效
|
||||
→ 循环执行 calibration_rotate_and_track()
|
||||
→ calibration_settle()
|
||||
→ 再次读取 SW1
|
||||
→ 触发后 calibration_return_from_limit()
|
||||
→ domain_set_current_angle(home_angle)
|
||||
→ domain_runtime_stepper_power_off()
|
||||
```
|
||||
|
||||
底层旋转:
|
||||
|
||||
```text
|
||||
domain_runtime_stepper_rotate_angle_with_accel_timeout()
|
||||
└── platform_stepper_rotate_angle_with_accel_timeout()
|
||||
└── platform_stepper_driver_rotate_angle_with_accel()
|
||||
└── rotate_with_accel()
|
||||
├── calculate_motion_segments()
|
||||
├── stepper_advance_phase()
|
||||
└── precise_delay_us()
|
||||
```
|
||||
|
||||
绝对角度旋转:
|
||||
|
||||
```text
|
||||
control_plane_rotate_to_angle()
|
||||
└── domain_rotate_to_angle_with_timeout()
|
||||
├── domain_angle_normalize()
|
||||
├── domain_angle_shortest_rotation()
|
||||
├── 执行电机旋转
|
||||
└── 更新 s_current_angle
|
||||
```
|
||||
|
||||
## 6. Wi-Fi 启动与恢复
|
||||
|
||||
启动入口:
|
||||
|
||||
```text
|
||||
control_plane_bootstrap_connectivity(seed_ssid, seed_password, timeout, "TQ-CAT")
|
||||
```
|
||||
|
||||
调用链:
|
||||
|
||||
```text
|
||||
control_plane_register_wifi_behavior_hooks()
|
||||
→ domain_runtime_wifi_portal_init_defaults()
|
||||
→ wifi_portal_init_defaults()
|
||||
→ 检查已保存凭据
|
||||
→ control_plane_connect_sta_with_feedback()
|
||||
→ 最多三次 STA 连接
|
||||
→ 成功则播放提示音
|
||||
→ 失败则按错误类型保留或清除凭据
|
||||
→ 必要时启动 TQ-CAT 配置 AP
|
||||
```
|
||||
|
||||
运行时由 `control_plane_wifi_state_task()` 负责:
|
||||
|
||||
- 检测 Wi-Fi 断开;
|
||||
- 等待短暂 disconnect grace;
|
||||
- 停止多模态 client 和用户配置 server;
|
||||
- 请求断网表情;
|
||||
- 按指数退避重连;
|
||||
- 重连后恢复 idle 表情、WebSocket 和配置 server;
|
||||
- 同时驱动 PTT 状态机。
|
||||
|
||||
## 7. 运行时任务拓扑
|
||||
|
||||
入口:
|
||||
|
||||
```text
|
||||
control_plane_start_runtime_workers()
|
||||
```
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Start["control_plane_start_runtime_workers"]
|
||||
Model["cp_model_cmd<br/>模型设备命令"]
|
||||
WiFi["cp_wifi_state<br/>Wi-Fi、WS、PTT"]
|
||||
LCD["cp_lcd_render<br/>LCD 启动"]
|
||||
Events["cp_system_event<br/>事件分发"]
|
||||
Keys["cp_key_input<br/>GPIO 与消抖"]
|
||||
Logs["remote log worker"]
|
||||
Fortune["cp_fortune<br/>每日运势"]
|
||||
Monitor["cp_task_monitor<br/>可选诊断"]
|
||||
|
||||
Start --> Model
|
||||
Start --> WiFi
|
||||
Start --> LCD
|
||||
Start --> Events
|
||||
Start --> Keys
|
||||
Start --> Logs
|
||||
Start --> Fortune
|
||||
Start --> Monitor
|
||||
```
|
||||
|
||||
`control_plane_schedule_websocket_wait_task()` 当前只设置 `s_ws_start_requested = true`,实际 WebSocket 启动由 `cp_wifi_state` 执行。
|
||||
|
||||
## 8. 按键和系统事件
|
||||
|
||||
按键中断链路:
|
||||
|
||||
```text
|
||||
GPIO edge
|
||||
→ control_plane_key_gpio_isr_handler()
|
||||
→ xQueueSendFromISR(s_gpio_irq_queue)
|
||||
→ control_plane_key_input_task()
|
||||
→ control_plane_process_key_timers()
|
||||
→ control_plane_handle_debounced_transition()
|
||||
→ control_plane_emit_key_event()
|
||||
→ control_plane_post_system_event()
|
||||
→ control_plane_system_event_task()
|
||||
→ control_plane_dispatch_system_event()
|
||||
→ control_plane_dispatch_key_event()
|
||||
```
|
||||
|
||||
事件包括:
|
||||
|
||||
- `PRESSED`;
|
||||
- `RELEASED`;
|
||||
- `SHORT_PRESS`;
|
||||
- `LONG_PRESS_START`;
|
||||
- `LONG_PRESS_RELEASE`;
|
||||
- `DOUBLE_CLICK`。
|
||||
|
||||
行为映射:
|
||||
|
||||
| 输入 | 行为 |
|
||||
| --- | --- |
|
||||
| PTT 短按 | `control_plane_set_ptt_active(true)` |
|
||||
| PTT 在服务端回复时按下 | `control_plane_multimodal_send_request_to_speak()` |
|
||||
| PTT 双击 | 请求 `DOMAIN_EXPRESSION_MUYU` |
|
||||
| SW2 单击 | 请求 `DOMAIN_EXPRESSION_CHOUQIAN` |
|
||||
| SW2 双击 | 请求 `DOMAIN_EXPRESSION_WUXING` |
|
||||
|
||||
## 9. PTT 状态机
|
||||
|
||||
状态:
|
||||
|
||||
```text
|
||||
IDLE
|
||||
WAIT_WIFI
|
||||
WAIT_WS
|
||||
WAIT_START_SENT
|
||||
WAIT_LISTENING
|
||||
WAIT_SPEECH_STARTED
|
||||
STREAMING
|
||||
TEARDOWN_LOCAL
|
||||
TEARDOWN_REMOTE
|
||||
DENIED
|
||||
```
|
||||
|
||||
状态机由 `control_plane_drive_ptt_state_machine()` 在 `cp_wifi_state` 中周期驱动:
|
||||
|
||||
```text
|
||||
无 Wi-Fi → WAIT_WIFI
|
||||
无 WebSocket → WAIT_WS
|
||||
无 active task → WAIT_START_SENT
|
||||
服务端未 Listening → WAIT_LISTENING
|
||||
未发送 SendSpeech → WAIT_SPEECH_STARTED
|
||||
uplink 已运行 → STREAMING
|
||||
释放/超时 → TEARDOWN_LOCAL → TEARDOWN_REMOTE → IDLE
|
||||
```
|
||||
|
||||
每次推进调用 `control_plane_multimodal_handle_ptt_press_step()`,根据当前会话状态选择:
|
||||
|
||||
- `control_plane_multimodal_send_start()`;
|
||||
- `control_plane_multimodal_send_request_to_speak()`;
|
||||
- `control_plane_multimodal_send_speech_start()`;
|
||||
- `control_plane_multimodal_start_uplink()`。
|
||||
|
||||
## 10. 设备认证和 WebSocket
|
||||
|
||||
启动链:
|
||||
|
||||
```text
|
||||
cp_wifi_state
|
||||
→ control_plane_try_start_multimodal_from_state_machine()
|
||||
→ control_plane_start_multimodal_client()
|
||||
→ control_plane_multimodal_start()
|
||||
```
|
||||
|
||||
`control_plane_start_multimodal_client()`:
|
||||
|
||||
```text
|
||||
control_plane_prepare_for_multimodal_start()
|
||||
→ 注册 event callback
|
||||
→ 注册 downstream audio callback
|
||||
→ 创建 mm_watchdog
|
||||
→ control_plane_multimodal_start()
|
||||
```
|
||||
|
||||
认证链:
|
||||
|
||||
```text
|
||||
control_plane_multimodal_auth_fetch()
|
||||
├── resolve_device_identity()
|
||||
├── control_plane_multimodal_device_auth_ensure()
|
||||
│ ├── control_plane_multimodal_device_auth_init()
|
||||
│ ├── 检查已有 JWT 和 scope
|
||||
│ └── refresh_jwt_internal()
|
||||
├── control_plane_multimodal_device_auth_copy_jwt()
|
||||
├── HTTP POST token endpoint
|
||||
├── 401/403 时 invalidate JWT 并重试
|
||||
└── parse_token_response()
|
||||
```
|
||||
|
||||
WebSocket 链:
|
||||
|
||||
```text
|
||||
domain_runtime_multimodal_transport_start()
|
||||
└── platform_multimodal_transport_start()
|
||||
└── multimodal_ws_start()
|
||||
├── 停止旧 client
|
||||
├── 构造 Authorization 和 Workspace headers
|
||||
├── 创建 send mutex
|
||||
├── create_worker_pipeline()
|
||||
└── start_websocket_client_with_fallback()
|
||||
```
|
||||
|
||||
## 11. 一次完整语音会话
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as 用户/PTT
|
||||
participant CP as Control Plane
|
||||
participant Session as Session Service
|
||||
participant Audio as Audio Pipeline
|
||||
participant WS as WebSocket
|
||||
participant Server as 服务端
|
||||
|
||||
User->>CP: 短按
|
||||
CP->>Session: send_start()
|
||||
Session->>WS: run-task / Start
|
||||
Server-->>Session: DialogStateChanged(Listening)
|
||||
CP->>Session: send_speech_start()
|
||||
CP->>Audio: start_uplink()
|
||||
Audio->>WS: Opus binary frames
|
||||
Server-->>Session: SpeechEnded / RespondingStarted
|
||||
Session->>Audio: stop uplink / begin response
|
||||
Server-->>Audio: Opus binary frames
|
||||
Audio-->>User: 扬声器播放
|
||||
Server-->>Session: RespondingEnded
|
||||
Audio-->>Session: playback completed
|
||||
Session->>WS: LocalRespondingEnded
|
||||
```
|
||||
|
||||
### 11.1 Start
|
||||
|
||||
```text
|
||||
control_plane_multimodal_send_start()
|
||||
→ 生成 task UUID
|
||||
→ 构造 run-task / Start JSON
|
||||
→ 设置 upstream/downstream Opus 参数
|
||||
→ domain_runtime_multimodal_transport_send_text()
|
||||
→ 保存 s_task_id
|
||||
```
|
||||
|
||||
### 11.2 开始采集和上行
|
||||
|
||||
```text
|
||||
control_plane_multimodal_send_speech_start()
|
||||
→ send_directive("continue-task", "SendSpeech")
|
||||
→ control_plane_multimodal_start_uplink()
|
||||
→ domain_runtime_multimodal_audio_start_uplink()
|
||||
→ multimodal_audio_start_uplink()
|
||||
```
|
||||
|
||||
实时音频:
|
||||
|
||||
```text
|
||||
I2S capture task
|
||||
→ PCM 整理
|
||||
→ Opus encode
|
||||
→ uplink send queue
|
||||
→ uplink_send_task
|
||||
→ control_plane_audio_uplink_send_cb()
|
||||
→ control_plane_multimodal_send_audio_realtime()
|
||||
→ multimodal_ws_send_binary_realtime()
|
||||
```
|
||||
|
||||
### 11.3 下行播放
|
||||
|
||||
```text
|
||||
WebSocket binary frame
|
||||
→ transport_event_bridge()
|
||||
→ control_plane_downstream_audio_bridge()
|
||||
→ control_plane_multimodal_play_downstream_audio()
|
||||
→ multimodal_audio_handle_downstream_opus()
|
||||
→ downstream playback queue
|
||||
→ Opus decode
|
||||
→ I2S / ES8311 播放
|
||||
```
|
||||
|
||||
服务端 `RespondingEnded` 和本地播放完成都满足后,才发送 `LocalRespondingEnded`。
|
||||
|
||||
## 12. 服务端事件解析
|
||||
|
||||
所有文本帧进入 `process_text_json()`,主要处理:
|
||||
|
||||
- `task-failed`;
|
||||
- `task-started`;
|
||||
- `DialogStateChanged`;
|
||||
- `RequestAccepted`;
|
||||
- `RespondingStarted`;
|
||||
- `RespondingContent`;
|
||||
- `RespondingEnded`;
|
||||
- `SpeechStarted`;
|
||||
- `SpeechContent`;
|
||||
- `SpeechEnded`;
|
||||
- `Stopped`;
|
||||
- `Error`。
|
||||
|
||||
回复文本还会进入:
|
||||
|
||||
```text
|
||||
notify_responding_text()
|
||||
→ control_plane_responding_text_bridge()
|
||||
→ control_plane_extract_model_command()
|
||||
→ control_plane_on_model_command()
|
||||
→ model command queue
|
||||
→ control_plane_model_command_task()
|
||||
```
|
||||
|
||||
设备命令包括方向、校准动作和抽签。
|
||||
|
||||
## 13. LCD 表情工作流
|
||||
|
||||
```text
|
||||
domain_runtime_request_expression()
|
||||
├── domain_resolve_expression_platform_request()
|
||||
└── platform_lcd_request_presentation()
|
||||
└── lcd_direct_request_presentation()
|
||||
```
|
||||
|
||||
domain 负责把业务语义映射成 platform 播放请求:
|
||||
|
||||
```text
|
||||
IDLE
|
||||
SERVER_ERROR
|
||||
WIFI_DISCONNECTED
|
||||
WEALTH_SPIN
|
||||
WEALTH_DIRECTION
|
||||
MUYU
|
||||
CHOUQIAN
|
||||
WUXING
|
||||
```
|
||||
|
||||
platform 只处理:
|
||||
|
||||
- asset directory;
|
||||
- frame index;
|
||||
- frame interval;
|
||||
- priority;
|
||||
- interrupt policy;
|
||||
- repeat count;
|
||||
- return-to-idle。
|
||||
|
||||
渲染循环:
|
||||
|
||||
```text
|
||||
lcd_direct_take_pending()
|
||||
→ lcd_direct_play_asset_sequence() 或 lcd_direct_play_step_sequence()
|
||||
→ lcd_direct_signal_completion()
|
||||
→ 无 pending 时播放 basic idle face
|
||||
```
|
||||
|
||||
## 14. 财富方向与运势
|
||||
|
||||
财富方向动作:
|
||||
|
||||
```text
|
||||
control_plane_apply_wealth_direction()
|
||||
├── domain_runtime_preheat_expression(reveal)
|
||||
├── 阻塞播放 WEALTH_SPIN
|
||||
├── 请求 WEALTH_DIRECTION reveal
|
||||
├── 记录 start_angle
|
||||
├── 旋转固定角度
|
||||
├── 延时
|
||||
└── 返回 start_angle
|
||||
```
|
||||
|
||||
当前 `direction_index` 主要选择 LCD 方向资源,电机仍执行固定角度转出再返回,并非直接旋转到方向目录的绝对角度。
|
||||
|
||||
每日运势 worker:
|
||||
|
||||
```text
|
||||
control_plane_daily_fortune_task()
|
||||
├── 等待 birth profile
|
||||
├── 等待 Wi-Fi
|
||||
├── control_plane_wait_for_synced_time()
|
||||
├── 等待 WebSocket TLS 握手稳定
|
||||
├── 计算本地日期
|
||||
├── control_plane_fortune_fetch()
|
||||
├── domain_fortune_result_store_set()
|
||||
└── control_plane_apply_wealth_direction()
|
||||
```
|
||||
|
||||
运势 HTTPS 与 WebSocket TLS 握手被有意串行化,以避免内部 DMA RAM 不足。
|
||||
|
||||
## 15. 局域网用户配置
|
||||
|
||||
联网后 `control_plane_wifi_state_task()` 启动用户配置 server:
|
||||
|
||||
```text
|
||||
control_plane_ensure_user_config_server()
|
||||
└── domain_user_config_server_start()
|
||||
└── platform_lan_http_server_start()
|
||||
```
|
||||
|
||||
路由:
|
||||
|
||||
| 方法 | 路径 | 处理函数 |
|
||||
| --- | --- | --- |
|
||||
| GET | `/` | `handle_index()` |
|
||||
| GET | `/api/profile` | `handle_get_profile()` |
|
||||
| POST | `/api/profile` | `handle_post_profile()` |
|
||||
| GET | `/api/fortune` | `handle_get_fortune()` |
|
||||
|
||||
资料更新后:
|
||||
|
||||
```text
|
||||
domain_birth_profile_store_set()
|
||||
→ birth profile observer
|
||||
→ control_plane_request_fortune_refresh()
|
||||
→ 唤醒 cp_fortune
|
||||
```
|
||||
|
||||
## 16. Watchdog 和异常恢复
|
||||
|
||||
`multimodal_watchdog_task()` 每秒检查:
|
||||
|
||||
- WebSocket 是否连接;
|
||||
- 是否存在 active task;
|
||||
- heartbeat 是否到期;
|
||||
- 是否长时间没有下行;
|
||||
- transport 是否空闲超过 30 秒。
|
||||
|
||||
处理:
|
||||
|
||||
```text
|
||||
heartbeat 到期
|
||||
→ control_plane_multimodal_send_heartbeat()
|
||||
|
||||
无下行超时
|
||||
→ control_plane_multimodal_send_stop("NoResponseTimeout")
|
||||
→ stop uplink
|
||||
|
||||
transport 空闲 30 秒
|
||||
→ control_plane_multimodal_stop()
|
||||
```
|
||||
|
||||
WebSocket 断开或错误时,会停止 uplink,并由 `cp_wifi_state` 安排后续重连。
|
||||
|
||||
## 17. 停止流程
|
||||
|
||||
```text
|
||||
control_plane_stop_runtime_workers()
|
||||
├── 设置 runtime stop flag
|
||||
├── 停止用户配置 server
|
||||
├── 注销模型命令和 profile observer
|
||||
├── 停止 key task 和 system event task
|
||||
├── 停止 LCD render loop
|
||||
├── bounded wait 各 worker
|
||||
├── 必要时强制删除 task
|
||||
├── 删除 model command queue
|
||||
└── control_plane_stop_multimodal_client()
|
||||
├── stop_watchdog_task()
|
||||
└── control_plane_multimodal_stop()
|
||||
├── stop uplink
|
||||
├── 停止本地 responding worker
|
||||
├── 注销 callbacks
|
||||
├── transport_stop(2000)
|
||||
└── reset_session_state_locked()
|
||||
```
|
||||
|
||||
## 18. 调试索引
|
||||
|
||||
遇到问题时先判断属于哪个状态机:
|
||||
|
||||
1. `control_plane_wifi_state_task()`:Wi-Fi、WebSocket 启动、PTT;
|
||||
2. multimodal session:task、Listening、Speech、Responding;
|
||||
3. audio pipeline:capture、send queue、decode、playback。
|
||||
|
||||
推荐排查路径:
|
||||
|
||||
| 现象 | 优先检查 |
|
||||
| --- | --- |
|
||||
| 上电后掉电 | GPIO9、`platform_power_hold_init()` 调用时机 |
|
||||
| LCD 无显示 | GPIO、`lcd_direct_init_device()`、背光和 SPI |
|
||||
| 电机不动 | `platform_stepper_driver_init()`、相序、限位状态 |
|
||||
| 开机校准超时 | GPIO12、有效电平、最大 sweep、旋转方向 |
|
||||
| PTT 无反应 | ISR queue、消抖、system event、PTT state |
|
||||
| 有按键但没录音 | Listening、SendSpeech、audio init、uplink task |
|
||||
| 有录音但服务端收不到 | Opus queue、uplink callback、WS binary send |
|
||||
| 服务端回复但没声音 | binary callback、decode queue、I2S、PA GPIO11 |
|
||||
| 第二轮对话失败 | `s_task_id`、Listening、speech flags、playback completion |
|
||||
| 断网不恢复 | `cp_wifi_state`、saved credentials、backoff、WS start request |
|
||||
|
||||
## 19. 关键源码入口
|
||||
|
||||
- `main/main.c`
|
||||
- `components/app_composition/src/runtime/app_composition_default_runtime.c`
|
||||
- `components/control_plane/src/runtime/control_plane_runtime_workers.c`
|
||||
- `components/control_plane/src/runtime/control_plane_connectivity_runtime.c`
|
||||
- `components/control_plane/src/runtime/control_plane_key_input.c`
|
||||
- `components/control_plane/src/runtime/control_plane_system_events.c`
|
||||
- `components/control_plane/src/multimodal/control_plane_multimodal_runtime.c`
|
||||
- `components/control_plane/src/multimodal/control_plane_multimodal_session_service.c`
|
||||
- `components/control_plane/src/multimodal/control_plane_multimodal_auth_service.c`
|
||||
- `components/control_plane/src/multimodal/control_plane_multimodal_device_auth.c`
|
||||
- `components/domain/src/direction/domain_direction_service.c`
|
||||
- `components/domain/src/calibration/domain_calibration_service.c`
|
||||
- `components/domain/src/runtime/domain_runtime_adapters.c`
|
||||
- `components/platform/src/multimodal/audio_pipeline/audio_pipeline_runtime_impl.c`
|
||||
- `components/platform/src/multimodal/transport_ws/transport_ws_runtime_impl.c`
|
||||
- `components/platform/src/lcd_direct.c`
|
||||
- `components/platform/src/platform_stepper_driver.c`
|
||||
|
||||
Reference in New Issue
Block a user