diff --git a/README.md b/README.md
index de4a67a..8815801 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,211 @@
-# xiaozhi-esp32
+# 超级小智-ESP32
+(中文 | English(编写中) | 日本語(编写中))
+
+基于 https://github.com/78/xiaozhi-esp32 改良的船新版本
+
+## 💡介绍
+这是一个由虾哥开源的 ESP32 项目,以 MIT 许可证发布,允许任何人免费使用,或用于商业用途。
+
+我们希望通过这个项目,能够帮助大家了解 AI 硬件开发,将当下飞速发展的大语言模型应用到实际的硬件设备中。
+
+如果你有任何想法或建议,请随时提出 Issues 或加入 QQ 群:暂无,Telegram群:暂无。
+
+项目主要贡献者:小霜霜Meow(抖音、B站UP)、空白泡泡糖果(B站UP),硅灵造物科技(B站UP)
+
+贡献者说明:引入部分其它贡献者在其它项目上的代码,并进行了部分修改。
+
+音乐服务器、相关源码提供者(为爱发电):小霜霜Meow
+
+音乐服务器源码请见 https://github.com/IntelligentlyEverything/MeowMusicServer
+
+### ❕注意事项
+1. 如果小智说找不到歌曲怎么办?
+进入[小智后台](https://xiaozhi.me/),找到对应设备,修改角色配置
+- 选择 DeepSeekV3 大语言模型
+- 在人物介绍中填入
+ - 收到音乐相关的需求时,只使用 MPC tool self.music.play_song 工具,同时禁止使用 search_music 功能。
+
+2. 内置API调用失败怎么办?
+请查看具体错误代码后,加入QQ群:865754861,或电报群 http://t.me/MeowMusicServer 给出错误代码和日志,等待我们修复。
+
+### ⚙️已支持硬件芯片系列
+
+- ESP32
+- ESP32-S2
+- ESP32-S3
+- ESP32-C2
+- ESP32-C3
+- ESP32-C5
+- ESP32-C6
+- ESP32-C61
+- ESP32-H2
+- ESP32-H4
+- ESP32-H21
+- ESP32-P4
+
+❕大部分硬件由于没有进行完整测试,可能会存在一些问题,属于正常现象,具体可提交issues进行反馈。
+
+### 项目改动范围
+新增:
+- main/boards/common/music.h
+- main/boards/common/esp32_music.h
+- main/boards/common/esp32_music.cc
+
+修改:
+- main/audio/audio_codec.h
+- main/audio/audio_codec.cc
+- main/audio/audio_service.h
+- main/audio/audio_service.cc
+- main/boards/common/board.h
+- main/boards/common/board.cc
+- main/display/display.h
+- main/display/display.cc
+- main/application.h
+- main/application.cc
+- main/idf_component.yml
+- main/mcp_server.cc
+
+### 基于 MCP 控制万物
+小智 AI 聊天机器人作为一个语音交互入口,利用 Qwen / DeepSeek 等大模型的 AI 能力,通过 MCP 协议实现多端控制。
+
+
+
+### 已实现功能
+
+- Wi-Fi / ML307 Cat.1 4G
+- 离线语音唤醒 [ESP-SR](https://github.com/espressif/esp-sr)
+- 支持两种通信协议([Websocket](docs/websocket.md) 或 MQTT+UDP)
+- 采用 OPUS 音频编解码
+- 基于流式 ASR + LLM + TTS 架构的语音交互
+- 声纹识别,识别当前说话人的身份 [3D Speaker](https://github.com/modelscope/3D-Speaker)
+- OLED / LCD 显示屏,支持表情显示
+- 电量显示与电源管理
+- 支持多语言(中文、英文、日文)
+- 支持 ESP32-C3、ESP32-S3、ESP32-P4 芯片平台
+- 通过设备端 MCP 实现设备控制(音量、灯光、电机、GPIO 等)
+- 通过云端 MCP 扩展大模型能力(智能家居控制、PC桌面操作、知识搜索、邮件收发等)
+本项目新增功能:
+- 新增音乐播放功能,支持播放本地音乐(开发中,敬请期待)、云端音乐(完善中)。
+
+## 硬件
+
+### 面包板手工制作实践
+
+详见飞书文档教程:
+
+👉 [《小智 AI 聊天机器人百科全书》](https://ccnphfhqs21z.feishu.cn/wiki/F5krwD16viZoF0kKkvDcrZNYnhb?from=from_copylink)
+
+面包板效果图如下:
+
+
+
+### 支持 70 多个开源硬件(仅展示部分)
+
+- 立创·实战派 ESP32-S3 开发板
+- 乐鑫 ESP32-S3-BOX3
+- M5Stack CoreS3
+- M5Stack AtomS3R + Echo Base
+- 神奇按钮 2.4
+- 微雪电子 ESP32-S3-Touch-AMOLED-1.8
+- LILYGO T-Circle-S3
+- 虾哥 Mini C3
+- 璀璨·AI 吊坠
+- 无名科技 Nologo-星智-1.54TFT
+- SenseCAP Watcher
+- ESP-HI 超低成本机器狗
+
+
+
+## 软件
+
+### 固件烧录
+
+新手第一次操作建议先不要搭建开发环境,直接使用免开发环境烧录的固件。
+
+固件默认接入 [xiaozhi.me](https://xiaozhi.me) 官方服务器,个人用户注册账号可以免费使用 Qwen 实时模型。
+
+👉 [新手烧录固件教程](https://ccnphfhqs21z.feishu.cn/wiki/Zpz4wXBtdimBrLk25WdcXzxcnNS)
+
+### 开发环境
+
+- Cursor 或 VSCode
+- 安装 ESP-IDF 插件,选择 SDK 版本 5.4 或以上
+- Linux 比 Windows 更好,编译速度快,也免去驱动问题的困扰
+- 本项目使用 Google C++ 代码风格,提交代码时请确保符合规范
+
+### 开发者文档
+
+- [自定义开发板指南](main/boards/README.md) - 学习如何为小智 AI 创建自定义开发板
+- [MCP 协议物联网控制用法说明](docs/mcp-usage.md) - 了解如何通过 MCP 协议控制物联网设备
+- [MCP 协议交互流程](docs/mcp-protocol.md) - 设备端 MCP 协议的实现方式
+- [MQTT + UDP 混合通信协议文档](docs/mqtt-udp.md)
+- [一份详细的 WebSocket 通信协议文档](docs/websocket.md)
+
+## 大模型配置
+
+如果你已经拥有一个小智 AI 聊天机器人设备,并且已接入官方服务器,可以登录 [xiaozhi.me](https://xiaozhi.me) 控制台进行配置。
+
+👉 [后台操作视频教程(旧版界面)](https://www.bilibili.com/video/BV1jUCUY2EKM/)
+
+## 相关开源项目
+
+在个人电脑上部署服务器,可以参考以下第三方开源的项目:
+
+- [xinnan-tech/xiaozhi-esp32-server](https://github.com/xinnan-tech/xiaozhi-esp32-server) Python 服务器
+- [joey-zhou/xiaozhi-esp32-server-java](https://github.com/joey-zhou/xiaozhi-esp32-server-java) Java 服务器
+- [AnimeAIChat/xiaozhi-server-go](https://github.com/AnimeAIChat/xiaozhi-server-go) Golang 服务器
+
+使用小智通信协议的第三方客户端项目:
+
+- [huangjunsen0406/py-xiaozhi](https://github.com/huangjunsen0406/py-xiaozhi) Python 客户端
+- [TOM88812/xiaozhi-android-client](https://github.com/TOM88812/xiaozhi-android-client) Android 客户端
+- [100askTeam/xiaozhi-linux](http://github.com/100askTeam/xiaozhi-linux) 百问科技提供的 Linux 客户端
+- [78/xiaozhi-sf32](https://github.com/78/xiaozhi-sf32) 思澈科技的蓝牙芯片固件
+- [QuecPython/solution-xiaozhiAI](https://github.com/QuecPython/solution-xiaozhiAI) 移远提供的 QuecPython 固件
+
+## Star History
+
+
+
+
+
+
+
+
diff --git a/docs/mcp-based-graph.jpg b/docs/mcp-based-graph.jpg
new file mode 100644
index 0000000..af81cd2
Binary files /dev/null and b/docs/mcp-based-graph.jpg differ
diff --git a/docs/mcp-protocol.md b/docs/mcp-protocol.md
new file mode 100644
index 0000000..0c8ec90
--- /dev/null
+++ b/docs/mcp-protocol.md
@@ -0,0 +1,269 @@
+# MCP (Model Context Protocol) 交互流程
+
+NOTICE: AI 辅助生成, 在实现后台服务时, 请参照代码确认细节!!
+
+本项目中的 MCP 协议用于后台 API(MCP 客户端)与 ESP32 设备(MCP 服务器)之间的通信,以便后台能够发现和调用设备提供的功能(工具)。
+
+## 协议格式
+
+根据代码 (`main/protocols/protocol.cc`, `main/mcp_server.cc`),MCP 消息是封装在基础通信协议(如 WebSocket 或 MQTT)的消息体中的。其内部结构遵循 [JSON-RPC 2.0](https://www.jsonrpc.org/specification) 规范。
+
+整体消息结构示例:
+
+```json
+{
+ "session_id": "...", // 会话 ID
+ "type": "mcp", // 消息类型,固定为 "mcp"
+ "payload": { // JSON-RPC 2.0 负载
+ "jsonrpc": "2.0",
+ "method": "...", // 方法名 (如 "initialize", "tools/list", "tools/call")
+ "params": { ... }, // 方法参数 (对于 request)
+ "id": ..., // 请求 ID (对于 request 和 response)
+ "result": { ... }, // 方法执行结果 (对于 success response)
+ "error": { ... } // 错误信息 (对于 error response)
+ }
+}
+```
+
+其中,`payload` 部分是标准的 JSON-RPC 2.0 消息:
+
+- `jsonrpc`: 固定的字符串 "2.0"。
+- `method`: 要调用的方法名称 (对于 Request)。
+- `params`: 方法的参数,一个结构化值,通常为对象 (对于 Request)。
+- `id`: 请求的标识符,客户端发送请求时提供,服务器响应时原样返回。用于匹配请求和响应。
+- `result`: 方法成功执行时的结果 (对于 Success Response)。
+- `error`: 方法执行失败时的错误信息 (对于 Error Response)。
+
+## 交互流程及发送时机
+
+MCP 的交互主要围绕客户端(后台 API)发现和调用设备上的“工具”(Tool)进行。
+
+1. **连接建立与能力通告**
+
+ - **时机:** 设备启动并成功连接到后台 API 后。
+ - **发送方:** 设备。
+ - **消息:** 设备发送基础协议的 "hello" 消息给后台 API,消息中包含设备支持的能力列表,例如通过支持 MCP 协议 (`"mcp": true`)。
+ - **示例 (非 MCP 负载,而是基础协议消息):**
+ ```json
+ {
+ "type": "hello",
+ "version": ...,
+ "features": {
+ "mcp": true,
+ ...
+ },
+ "transport": "websocket", // 或 "mqtt"
+ "audio_params": { ... },
+ "session_id": "..." // 设备收到服务器hello后可能设置
+ }
+ ```
+
+2. **初始化 MCP 会话**
+
+ - **时机:** 后台 API 收到设备 "hello" 消息,确认设备支持 MCP 后,通常作为 MCP 会话的第一个请求发送。
+ - **发送方:** 后台 API (客户端)。
+ - **方法:** `initialize`
+ - **消息 (MCP payload):**
+
+ ```json
+ {
+ "jsonrpc": "2.0",
+ "method": "initialize",
+ "params": {
+ "capabilities": {
+ // 客户端能力,可选
+
+ // 摄像头视觉相关
+ "vision": {
+ "url": "...", //摄像头: 图片处理地址(必须是http地址, 不是websocket地址)
+ "token": "..." // url token
+ }
+
+ // ... 其他客户端能力
+ }
+ },
+ "id": 1 // 请求 ID
+ }
+ ```
+
+ - **设备响应时机:** 设备收到 `initialize` 请求并处理后。
+ - **设备响应消息 (MCP payload):**
+ ```json
+ {
+ "jsonrpc": "2.0",
+ "id": 1, // 匹配请求 ID
+ "result": {
+ "protocolVersion": "2024-11-05",
+ "capabilities": {
+ "tools": {} // 这里的 tools 似乎不列出详细信息,需要 tools/list
+ },
+ "serverInfo": {
+ "name": "...", // 设备名称 (BOARD_NAME)
+ "version": "..." // 设备固件版本
+ }
+ }
+ }
+ ```
+
+3. **发现设备工具列表**
+
+ - **时机:** 后台 API 需要获取设备当前支持的具体功能(工具)列表及其调用方式时。
+ - **发送方:** 后台 API (客户端)。
+ - **方法:** `tools/list`
+ - **消息 (MCP payload):**
+ ```json
+ {
+ "jsonrpc": "2.0",
+ "method": "tools/list",
+ "params": {
+ "cursor": "" // 用于分页,首次请求为空字符串
+ },
+ "id": 2 // 请求 ID
+ }
+ ```
+ - **设备响应时机:** 设备收到 `tools/list` 请求并生成工具列表后。
+ - **设备响应消息 (MCP payload):**
+ ```json
+ {
+ "jsonrpc": "2.0",
+ "id": 2, // 匹配请求 ID
+ "result": {
+ "tools": [ // 工具对象列表
+ {
+ "name": "self.get_device_status",
+ "description": "...",
+ "inputSchema": { ... } // 参数 schema
+ },
+ {
+ "name": "self.audio_speaker.set_volume",
+ "description": "...",
+ "inputSchema": { ... } // 参数 schema
+ }
+ // ... 更多工具
+ ],
+ "nextCursor": "..." // 如果列表很大需要分页,这里会包含下一个请求的 cursor 值
+ }
+ }
+ ```
+ - **分页处理:** 如果 `nextCursor` 字段非空,客户端需要再次发送 `tools/list` 请求,并在 `params` 中带上这个 `cursor` 值以获取下一页工具。
+
+4. **调用设备工具**
+
+ - **时机:** 后台 API 需要执行设备上的某个具体功能时。
+ - **发送方:** 后台 API (客户端)。
+ - **方法:** `tools/call`
+ - **消息 (MCP payload):**
+ ```json
+ {
+ "jsonrpc": "2.0",
+ "method": "tools/call",
+ "params": {
+ "name": "self.audio_speaker.set_volume", // 要调用的工具名称
+ "arguments": {
+ // 工具参数,对象格式
+ "volume": 50 // 参数名及其值
+ }
+ },
+ "id": 3 // 请求 ID
+ }
+ ```
+ - **设备响应时机:** 设备收到 `tools/call` 请求,执行相应的工具函数后。
+ - **设备成功响应消息 (MCP payload):**
+ ```json
+ {
+ "jsonrpc": "2.0",
+ "id": 3, // 匹配请求 ID
+ "result": {
+ "content": [
+ // 工具执行结果内容
+ { "type": "text", "text": "true" } // 示例:set_volume 返回 bool
+ ],
+ "isError": false // 表示成功
+ }
+ }
+ ```
+ - **设备失败响应消息 (MCP payload):**
+ ```json
+ {
+ "jsonrpc": "2.0",
+ "id": 3, // 匹配请求 ID
+ "error": {
+ "code": -32601, // JSON-RPC 错误码,例如 Method not found (-32601)
+ "message": "Unknown tool: self.non_existent_tool" // 错误描述
+ }
+ }
+ ```
+
+5. **设备主动发送消息 (Notifications)**
+ - **时机:** 设备内部发生需要通知后台 API 的事件时(例如,状态变化,虽然代码示例中没有明确的工具发送此类消息,但 `Application::SendMcpMessage` 的存在暗示了设备可能主动发送 MCP 消息)。
+ - **发送方:** 设备 (服务器)。
+ - **方法:** 可能是以 `notifications/` 开头的方法名,或者其他自定义方法。
+ - **消息 (MCP payload):** 遵循 JSON-RPC Notification 格式,没有 `id` 字段。
+ ```json
+ {
+ "jsonrpc": "2.0",
+ "method": "notifications/state_changed", // 示例方法名
+ "params": {
+ "newState": "idle",
+ "oldState": "connecting"
+ }
+ // 没有 id 字段
+ }
+ ```
+ - **后台 API 处理:** 接收到 Notification 后,后台 API 进行相应的处理,但不回复。
+
+## 交互图
+
+下面是一个简化的交互序列图,展示了主要的 MCP 消息流程:
+
+```mermaid
+sequenceDiagram
+ participant Device as ESP32 Device
+ participant BackendAPI as 后台 API (Client)
+
+ Note over Device, BackendAPI: 建立 WebSocket / MQTT 连接
+
+ Device->>BackendAPI: Hello Message (包含 "mcp": true)
+
+ BackendAPI->>Device: MCP Initialize Request
+ Note over BackendAPI: method: initialize
+ Note over BackendAPI: params: { capabilities: ... }
+
+ Device->>BackendAPI: MCP Initialize Response
+ Note over Device: result: { protocolVersion: ..., serverInfo: ... }
+
+ BackendAPI->>Device: MCP Get Tools List Request
+ Note over BackendAPI: method: tools/list
+ Note over BackendAPI: params: { cursor: "" }
+
+ Device->>BackendAPI: MCP Get Tools List Response
+ Note over Device: result: { tools: [...], nextCursor: ... }
+
+ loop Optional Pagination
+ BackendAPI->>Device: MCP Get Tools List Request
+ Note over BackendAPI: method: tools/list
+ Note over BackendAPI: params: { cursor: "..." }
+ Device->>BackendAPI: MCP Get Tools List Response
+ Note over Device: result: { tools: [...], nextCursor: "" }
+ end
+
+ BackendAPI->>Device: MCP Call Tool Request
+ Note over BackendAPI: method: tools/call
+ Note over BackendAPI: params: { name: "...", arguments: { ... } }
+
+ alt Tool Call Successful
+ Device->>BackendAPI: MCP Tool Call Success Response
+ Note over Device: result: { content: [...], isError: false }
+ else Tool Call Failed
+ Device->>BackendAPI: MCP Tool Call Error Response
+ Note over Device: error: { code: ..., message: ... }
+ end
+
+ opt Device Notification
+ Device->>BackendAPI: MCP Notification
+ Note over Device: method: notifications/...
+ Note over Device: params: { ... }
+ end
+```
+
+这份文档概述了该项目中 MCP 协议的主要交互流程。具体的参数细节和工具功能需要参考 `main/mcp_server.cc` 中 `McpServer::AddCommonTools` 以及各个工具的实现。
diff --git a/docs/mcp-usage.md b/docs/mcp-usage.md
new file mode 100644
index 0000000..fa50a39
--- /dev/null
+++ b/docs/mcp-usage.md
@@ -0,0 +1,115 @@
+# MCP 协议物联网控制用法说明
+
+> 本文档介绍如何基于 MCP 协议实现 ESP32 设备的物联网控制。详细协议流程请参考 [`mcp-protocol.md`](./mcp-protocol.md)。
+
+## 简介
+
+MCP(Model Context Protocol)是新一代推荐用于物联网控制的协议,通过标准 JSON-RPC 2.0 格式在后台与设备间发现和调用"工具"(Tool),实现灵活的设备控制。
+
+## 典型使用流程
+
+1. 设备启动后通过基础协议(如 WebSocket/MQTT)与后台建立连接。
+2. 后台通过 MCP 协议的 `initialize` 方法初始化会话。
+3. 后台通过 `tools/list` 获取设备支持的所有工具(功能)及参数说明。
+4. 后台通过 `tools/call` 调用具体工具,实现对设备的控制。
+
+详细协议格式与交互请见 [`mcp-protocol.md`](./mcp-protocol.md)。
+
+## 设备端工具注册方法说明
+
+设备通过 `McpServer::AddTool` 方法注册可被后台调用的"工具"。其常用函数签名如下:
+
+```cpp
+void AddTool(
+ const std::string& name, // 工具名称,建议唯一且有层次感,如 self.dog.forward
+ const std::string& description, // 工具描述,简明说明功能,便于大模型理解
+ const PropertyList& properties, // 输入参数列表(可为空),支持类型:布尔、整数、字符串
+ std::function callback // 工具被调用时的回调实现
+);
+```
+- name:工具唯一标识,建议用"模块.功能"命名风格。
+- description:自然语言描述,便于 AI/用户理解。
+- properties:参数列表,支持类型有布尔、整数、字符串,可指定范围和默认值。
+- callback:收到调用请求时的实际执行逻辑,返回值可为 bool/int/string。
+
+## 典型注册示例(以 ESP-Hi 为例)
+
+```cpp
+void InitializeTools() {
+ auto& mcp_server = McpServer::GetInstance();
+ // 例1:无参数,控制机器人前进
+ mcp_server.AddTool("self.dog.forward", "机器人向前移动", PropertyList(), [this](const PropertyList&) -> ReturnValue {
+ servo_dog_ctrl_send(DOG_STATE_FORWARD, NULL);
+ return true;
+ });
+ // 例2:带参数,设置灯光 RGB 颜色
+ mcp_server.AddTool("self.light.set_rgb", "设置RGB颜色", PropertyList({
+ Property("r", kPropertyTypeInteger, 0, 255),
+ Property("g", kPropertyTypeInteger, 0, 255),
+ Property("b", kPropertyTypeInteger, 0, 255)
+ }), [this](const PropertyList& properties) -> ReturnValue {
+ int r = properties["r"].value();
+ int g = properties["g"].value();
+ int b = properties["b"].value();
+ led_on_ = true;
+ SetLedColor(r, g, b);
+ return true;
+ });
+}
+```
+
+## 常见工具调用 JSON-RPC 示例
+
+### 1. 获取工具列表
+```json
+{
+ "jsonrpc": "2.0",
+ "method": "tools/list",
+ "params": { "cursor": "" },
+ "id": 1
+}
+```
+
+### 2. 控制底盘前进
+```json
+{
+ "jsonrpc": "2.0",
+ "method": "tools/call",
+ "params": {
+ "name": "self.chassis.go_forward",
+ "arguments": {}
+ },
+ "id": 2
+}
+```
+
+### 3. 切换灯光模式
+```json
+{
+ "jsonrpc": "2.0",
+ "method": "tools/call",
+ "params": {
+ "name": "self.chassis.switch_light_mode",
+ "arguments": { "light_mode": 3 }
+ },
+ "id": 3
+}
+```
+
+### 4. 摄像头翻转
+```json
+{
+ "jsonrpc": "2.0",
+ "method": "tools/call",
+ "params": {
+ "name": "self.camera.set_camera_flipped",
+ "arguments": {}
+ },
+ "id": 4
+}
+```
+
+## 备注
+- 工具名称、参数及返回值请以设备端 `AddTool` 注册为准。
+- 推荐所有新项目统一采用 MCP 协议进行物联网控制。
+- 详细协议与进阶用法请查阅 [`mcp-protocol.md`](./mcp-protocol.md)。
\ No newline at end of file
diff --git a/docs/mqtt-udp.md b/docs/mqtt-udp.md
new file mode 100644
index 0000000..478e466
--- /dev/null
+++ b/docs/mqtt-udp.md
@@ -0,0 +1,393 @@
+# MQTT + UDP 混合通信协议文档
+
+基于代码实现整理的 MQTT + UDP 混合通信协议文档,概述设备端与服务器之间如何通过 MQTT 进行控制消息传输,通过 UDP 进行音频数据传输的交互方式。
+
+---
+
+## 1. 协议概览
+
+本协议采用混合传输方式:
+- **MQTT**:用于控制消息、状态同步、JSON 数据交换
+- **UDP**:用于实时音频数据传输,支持加密
+
+### 1.1 协议特点
+
+- **双通道设计**:控制与数据分离,确保实时性
+- **加密传输**:UDP 音频数据使用 AES-CTR 加密
+- **序列号保护**:防止数据包重放和乱序
+- **自动重连**:MQTT 连接断开时自动重连
+
+---
+
+## 2. 总体流程概览
+
+```mermaid
+sequenceDiagram
+ participant Device as ESP32 设备
+ participant MQTT as MQTT 服务器
+ participant UDP as UDP 服务器
+
+ Note over Device, UDP: 1. 建立 MQTT 连接
+ Device->>MQTT: MQTT Connect
+ MQTT->>Device: Connected
+
+ Note over Device, UDP: 2. 请求音频通道
+ Device->>MQTT: Hello Message (type: "hello", transport: "udp")
+ MQTT->>Device: Hello Response (UDP 连接信息 + 加密密钥)
+
+ Note over Device, UDP: 3. 建立 UDP 连接
+ Device->>UDP: UDP Connect
+ UDP->>Device: Connected
+
+ Note over Device, UDP: 4. 音频数据传输
+ loop 音频流传输
+ Device->>UDP: 加密音频数据 (Opus)
+ UDP->>Device: 加密音频数据 (Opus)
+ end
+
+ Note over Device, UDP: 5. 控制消息交换
+ par 控制消息
+ Device->>MQTT: Listen/TTS/MCP 消息
+ MQTT->>Device: STT/TTS/MCP 响应
+ end
+
+ Note over Device, UDP: 6. 关闭连接
+ Device->>MQTT: Goodbye Message
+ Device->>UDP: Disconnect
+```
+
+---
+
+## 3. MQTT 控制通道
+
+### 3.1 连接建立
+
+设备通过 MQTT 连接到服务器,连接参数包括:
+- **Endpoint**:MQTT 服务器地址和端口
+- **Client ID**:设备唯一标识符
+- **Username/Password**:认证凭据
+- **Keep Alive**:心跳间隔(默认240秒)
+
+### 3.2 Hello 消息交换
+
+#### 3.2.1 设备端发送 Hello
+
+```json
+{
+ "type": "hello",
+ "version": 3,
+ "transport": "udp",
+ "features": {
+ "mcp": true
+ },
+ "audio_params": {
+ "format": "opus",
+ "sample_rate": 16000,
+ "channels": 1,
+ "frame_duration": 60
+ }
+}
+```
+
+#### 3.2.2 服务器响应 Hello
+
+```json
+{
+ "type": "hello",
+ "transport": "udp",
+ "session_id": "xxx",
+ "audio_params": {
+ "format": "opus",
+ "sample_rate": 24000,
+ "channels": 1,
+ "frame_duration": 60
+ },
+ "udp": {
+ "server": "192.168.1.100",
+ "port": 8888,
+ "key": "0123456789ABCDEF0123456789ABCDEF",
+ "nonce": "0123456789ABCDEF0123456789ABCDEF"
+ }
+}
+```
+
+**字段说明:**
+- `udp.server`:UDP 服务器地址
+- `udp.port`:UDP 服务器端口
+- `udp.key`:AES 加密密钥(十六进制字符串)
+- `udp.nonce`:AES 加密随机数(十六进制字符串)
+
+### 3.3 JSON 消息类型
+
+#### 3.3.1 设备端→服务器
+
+1. **Listen 消息**
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "listen",
+ "state": "start",
+ "mode": "manual"
+ }
+ ```
+
+2. **Abort 消息**
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "abort",
+ "reason": "wake_word_detected"
+ }
+ ```
+
+3. **MCP 消息**
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "mcp",
+ "payload": {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": {...}
+ }
+ }
+ ```
+
+4. **Goodbye 消息**
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "goodbye"
+ }
+ ```
+
+#### 3.3.2 服务器→设备端
+
+支持的消息类型与 WebSocket 协议一致,包括:
+- **STT**:语音识别结果
+- **TTS**:语音合成控制
+- **LLM**:情感表达控制
+- **MCP**:物联网控制
+- **System**:系统控制
+- **Custom**:自定义消息(可选)
+
+---
+
+## 4. UDP 音频通道
+
+### 4.1 连接建立
+
+设备收到 MQTT Hello 响应后,使用其中的 UDP 连接信息建立音频通道:
+1. 解析 UDP 服务器地址和端口
+2. 解析加密密钥和随机数
+3. 初始化 AES-CTR 加密上下文
+4. 建立 UDP 连接
+
+### 4.2 音频数据格式
+
+#### 4.2.1 加密音频包结构
+
+```
+|type 1byte|flags 1byte|payload_len 2bytes|ssrc 4bytes|timestamp 4bytes|sequence 4bytes|
+|payload payload_len bytes|
+```
+
+**字段说明:**
+- `type`:数据包类型,固定为 0x01
+- `flags`:标志位,当前未使用
+- `payload_len`:负载长度(网络字节序)
+- `ssrc`:同步源标识符
+- `timestamp`:时间戳(网络字节序)
+- `sequence`:序列号(网络字节序)
+- `payload`:加密的 Opus 音频数据
+
+#### 4.2.2 加密算法
+
+使用 **AES-CTR** 模式加密:
+- **密钥**:128位,由服务器提供
+- **随机数**:128位,由服务器提供
+- **计数器**:包含时间戳和序列号信息
+
+### 4.3 序列号管理
+
+- **发送端**:`local_sequence_` 单调递增
+- **接收端**:`remote_sequence_` 验证连续性
+- **防重放**:拒绝序列号小于期望值的数据包
+- **容错处理**:允许轻微的序列号跳跃,记录警告
+
+### 4.4 错误处理
+
+1. **解密失败**:记录错误,丢弃数据包
+2. **序列号异常**:记录警告,但仍处理数据包
+3. **数据包格式错误**:记录错误,丢弃数据包
+
+---
+
+## 5. 状态管理
+
+### 5.1 连接状态
+
+```mermaid
+stateDiagram
+ direction TB
+ [*] --> Disconnected
+ Disconnected --> MqttConnecting: StartMqttClient()
+ MqttConnecting --> MqttConnected: MQTT Connected
+ MqttConnecting --> Disconnected: Connect Failed
+ MqttConnected --> RequestingChannel: OpenAudioChannel()
+ RequestingChannel --> ChannelOpened: Hello Exchange Success
+ RequestingChannel --> MqttConnected: Hello Timeout/Failed
+ ChannelOpened --> UdpConnected: UDP Connect Success
+ UdpConnected --> AudioStreaming: Start Audio Transfer
+ AudioStreaming --> UdpConnected: Stop Audio Transfer
+ UdpConnected --> ChannelOpened: UDP Disconnect
+ ChannelOpened --> MqttConnected: CloseAudioChannel()
+ MqttConnected --> Disconnected: MQTT Disconnect
+```
+
+### 5.2 状态检查
+
+设备通过以下条件判断音频通道是否可用:
+```cpp
+bool IsAudioChannelOpened() const {
+ return udp_ != nullptr && !error_occurred_ && !IsTimeout();
+}
+```
+
+---
+
+## 6. 配置参数
+
+### 6.1 MQTT 配置
+
+从设置中读取的配置项:
+- `endpoint`:MQTT 服务器地址
+- `client_id`:客户端标识符
+- `username`:用户名
+- `password`:密码
+- `keepalive`:心跳间隔(默认240秒)
+- `publish_topic`:发布主题
+
+### 6.2 音频参数
+
+- **格式**:Opus
+- **采样率**:16000 Hz(设备端)/ 24000 Hz(服务器端)
+- **声道数**:1(单声道)
+- **帧时长**:60ms
+
+---
+
+## 7. 错误处理与重连
+
+### 7.1 MQTT 重连机制
+
+- 连接失败时自动重试
+- 支持错误上报控制
+- 断线时触发清理流程
+
+### 7.2 UDP 连接管理
+
+- 连接失败时不自动重试
+- 依赖 MQTT 通道重新协商
+- 支持连接状态查询
+
+### 7.3 超时处理
+
+基类 `Protocol` 提供超时检测:
+- 默认超时时间:120 秒
+- 基于最后接收时间计算
+- 超时时自动标记为不可用
+
+---
+
+## 8. 安全考虑
+
+### 8.1 传输加密
+
+- **MQTT**:支持 TLS/SSL 加密(端口8883)
+- **UDP**:使用 AES-CTR 加密音频数据
+
+### 8.2 认证机制
+
+- **MQTT**:用户名/密码认证
+- **UDP**:通过 MQTT 通道分发密钥
+
+### 8.3 防重放攻击
+
+- 序列号单调递增
+- 拒绝过期数据包
+- 时间戳验证
+
+---
+
+## 9. 性能优化
+
+### 9.1 并发控制
+
+使用互斥锁保护 UDP 连接:
+```cpp
+std::lock_guard lock(channel_mutex_);
+```
+
+### 9.2 内存管理
+
+- 动态创建/销毁网络对象
+- 智能指针管理音频数据包
+- 及时释放加密上下文
+
+### 9.3 网络优化
+
+- UDP 连接复用
+- 数据包大小优化
+- 序列号连续性检查
+
+---
+
+## 10. 与 WebSocket 协议的比较
+
+| 特性 | MQTT + UDP | WebSocket |
+|------|------------|-----------|
+| 控制通道 | MQTT | WebSocket |
+| 音频通道 | UDP (加密) | WebSocket (二进制) |
+| 实时性 | 高 (UDP) | 中等 |
+| 可靠性 | 中等 | 高 |
+| 复杂度 | 高 | 低 |
+| 加密 | AES-CTR | TLS |
+| 防火墙友好度 | 低 | 高 |
+
+---
+
+## 11. 部署建议
+
+### 11.1 网络环境
+
+- 确保 UDP 端口可达
+- 配置防火墙规则
+- 考虑 NAT 穿透
+
+### 11.2 服务器配置
+
+- MQTT Broker 配置
+- UDP 服务器部署
+- 密钥管理系统
+
+### 11.3 监控指标
+
+- 连接成功率
+- 音频传输延迟
+- 数据包丢失率
+- 解密失败率
+
+---
+
+## 12. 总结
+
+MQTT + UDP 混合协议通过以下设计实现高效的音视频通信:
+
+- **分离式架构**:控制与数据通道分离,各司其职
+- **加密保护**:AES-CTR 确保音频数据安全传输
+- **序列化管理**:防止重放攻击和数据乱序
+- **自动恢复**:支持连接断开后的自动重连
+- **性能优化**:UDP 传输保证音频数据的实时性
+
+该协议适用于对实时性要求较高的语音交互场景,但需要在网络复杂度和传输性能之间做出权衡。
\ No newline at end of file
diff --git a/docs/v0/AtomMatrix-echo-base.jpg b/docs/v0/AtomMatrix-echo-base.jpg
new file mode 100644
index 0000000..979cf81
Binary files /dev/null and b/docs/v0/AtomMatrix-echo-base.jpg differ
diff --git a/docs/v0/ESP32-BreadBoard.jpg b/docs/v0/ESP32-BreadBoard.jpg
new file mode 100644
index 0000000..f7a6fd4
Binary files /dev/null and b/docs/v0/ESP32-BreadBoard.jpg differ
diff --git a/docs/v0/atoms3r-echo-base.jpg b/docs/v0/atoms3r-echo-base.jpg
new file mode 100755
index 0000000..961e72b
Binary files /dev/null and b/docs/v0/atoms3r-echo-base.jpg differ
diff --git a/docs/v0/esp32s3-box3.jpg b/docs/v0/esp32s3-box3.jpg
new file mode 100644
index 0000000..53c4b55
Binary files /dev/null and b/docs/v0/esp32s3-box3.jpg differ
diff --git a/docs/v0/lichuang-s3.jpg b/docs/v0/lichuang-s3.jpg
new file mode 100644
index 0000000..721e0a0
Binary files /dev/null and b/docs/v0/lichuang-s3.jpg differ
diff --git a/docs/v0/m5stack-cores3.jpg b/docs/v0/m5stack-cores3.jpg
new file mode 100644
index 0000000..b123f73
Binary files /dev/null and b/docs/v0/m5stack-cores3.jpg differ
diff --git a/docs/v0/magiclick-2p4.jpg b/docs/v0/magiclick-2p4.jpg
new file mode 100644
index 0000000..beffb3d
Binary files /dev/null and b/docs/v0/magiclick-2p4.jpg differ
diff --git a/docs/v0/waveshare-esp32-s3-touch-amoled-1.8.jpg b/docs/v0/waveshare-esp32-s3-touch-amoled-1.8.jpg
new file mode 100644
index 0000000..90f2744
Binary files /dev/null and b/docs/v0/waveshare-esp32-s3-touch-amoled-1.8.jpg differ
diff --git a/docs/v0/wiring.jpg b/docs/v0/wiring.jpg
new file mode 100644
index 0000000..764c170
Binary files /dev/null and b/docs/v0/wiring.jpg differ
diff --git a/docs/v1/atoms3r.jpg b/docs/v1/atoms3r.jpg
new file mode 100644
index 0000000..45cbb45
Binary files /dev/null and b/docs/v1/atoms3r.jpg differ
diff --git a/docs/v1/electron-bot.png b/docs/v1/electron-bot.png
new file mode 100644
index 0000000..4d00d6d
Binary files /dev/null and b/docs/v1/electron-bot.png differ
diff --git a/docs/v1/esp-hi.jpg b/docs/v1/esp-hi.jpg
new file mode 100644
index 0000000..d6fc714
Binary files /dev/null and b/docs/v1/esp-hi.jpg differ
diff --git a/docs/v1/esp-sparkbot.jpg b/docs/v1/esp-sparkbot.jpg
new file mode 100644
index 0000000..b738840
Binary files /dev/null and b/docs/v1/esp-sparkbot.jpg differ
diff --git a/docs/v1/espbox3.jpg b/docs/v1/espbox3.jpg
new file mode 100644
index 0000000..641d74b
Binary files /dev/null and b/docs/v1/espbox3.jpg differ
diff --git a/docs/v1/lichuang-s3.jpg b/docs/v1/lichuang-s3.jpg
new file mode 100644
index 0000000..a559070
Binary files /dev/null and b/docs/v1/lichuang-s3.jpg differ
diff --git a/docs/v1/lilygo-t-circle-s3.jpg b/docs/v1/lilygo-t-circle-s3.jpg
new file mode 100644
index 0000000..45985d8
Binary files /dev/null and b/docs/v1/lilygo-t-circle-s3.jpg differ
diff --git a/docs/v1/m5cores3.jpg b/docs/v1/m5cores3.jpg
new file mode 100644
index 0000000..6a30cef
Binary files /dev/null and b/docs/v1/m5cores3.jpg differ
diff --git a/docs/v1/magiclick.jpg b/docs/v1/magiclick.jpg
new file mode 100644
index 0000000..3c01463
Binary files /dev/null and b/docs/v1/magiclick.jpg differ
diff --git a/docs/v1/movecall-cuican-esp32s3.jpg b/docs/v1/movecall-cuican-esp32s3.jpg
new file mode 100755
index 0000000..ae70cfd
Binary files /dev/null and b/docs/v1/movecall-cuican-esp32s3.jpg differ
diff --git a/docs/v1/movecall-moji-esp32s3.jpg b/docs/v1/movecall-moji-esp32s3.jpg
new file mode 100644
index 0000000..dec4526
Binary files /dev/null and b/docs/v1/movecall-moji-esp32s3.jpg differ
diff --git a/docs/v1/otto-robot.png b/docs/v1/otto-robot.png
new file mode 100644
index 0000000..d61cbdc
Binary files /dev/null and b/docs/v1/otto-robot.png differ
diff --git a/docs/v1/sensecap_watcher.jpg b/docs/v1/sensecap_watcher.jpg
new file mode 100644
index 0000000..b1d7e4c
Binary files /dev/null and b/docs/v1/sensecap_watcher.jpg differ
diff --git a/docs/v1/waveshare.jpg b/docs/v1/waveshare.jpg
new file mode 100644
index 0000000..7dacf2f
Binary files /dev/null and b/docs/v1/waveshare.jpg differ
diff --git a/docs/v1/wiring2.jpg b/docs/v1/wiring2.jpg
new file mode 100644
index 0000000..f3a67ae
Binary files /dev/null and b/docs/v1/wiring2.jpg differ
diff --git a/docs/v1/wmnologo_xingzhi_0.96.jpg b/docs/v1/wmnologo_xingzhi_0.96.jpg
new file mode 100644
index 0000000..24369cc
Binary files /dev/null and b/docs/v1/wmnologo_xingzhi_0.96.jpg differ
diff --git a/docs/v1/wmnologo_xingzhi_1.54.jpg b/docs/v1/wmnologo_xingzhi_1.54.jpg
new file mode 100644
index 0000000..7456477
Binary files /dev/null and b/docs/v1/wmnologo_xingzhi_1.54.jpg differ
diff --git a/docs/v1/xmini-c3.jpg b/docs/v1/xmini-c3.jpg
new file mode 100644
index 0000000..f1ed8c2
Binary files /dev/null and b/docs/v1/xmini-c3.jpg differ
diff --git a/docs/websocket.md b/docs/websocket.md
new file mode 100644
index 0000000..f767114
--- /dev/null
+++ b/docs/websocket.md
@@ -0,0 +1,495 @@
+以下是一份基于代码实现整理的 WebSocket 通信协议文档,概述设备端与服务器之间如何通过 WebSocket 进行交互。
+
+该文档仅基于所提供的代码推断,实际部署时可能需要结合服务器端实现进行进一步确认或补充。
+
+---
+
+## 1. 总体流程概览
+
+1. **设备端初始化**
+ - 设备上电、初始化 `Application`:
+ - 初始化音频编解码器、显示屏、LED 等
+ - 连接网络
+ - 创建并初始化实现 `Protocol` 接口的 WebSocket 协议实例(`WebsocketProtocol`)
+ - 进入主循环等待事件(音频输入、音频输出、调度任务等)。
+
+2. **建立 WebSocket 连接**
+ - 当设备需要开始语音会话时(例如用户唤醒、手动按键触发等),调用 `OpenAudioChannel()`:
+ - 根据配置获取 WebSocket URL
+ - 设置若干请求头(`Authorization`, `Protocol-Version`, `Device-Id`, `Client-Id`)
+ - 调用 `Connect()` 与服务器建立 WebSocket 连接
+
+3. **设备端发送 "hello" 消息**
+ - 连接成功后,设备会发送一条 JSON 消息,示例结构如下:
+ ```json
+ {
+ "type": "hello",
+ "version": 1,
+ "features": {
+ "mcp": true
+ },
+ "transport": "websocket",
+ "audio_params": {
+ "format": "opus",
+ "sample_rate": 16000,
+ "channels": 1,
+ "frame_duration": 60
+ }
+ }
+ ```
+ - 其中 `features` 字段为可选,内容根据设备编译配置自动生成。例如:`"mcp": true` 表示支持 MCP 协议。
+ - `frame_duration` 的值对应 `OPUS_FRAME_DURATION_MS`(例如 60ms)。
+
+4. **服务器回复 "hello"**
+ - 设备等待服务器返回一条包含 `"type": "hello"` 的 JSON 消息,并检查 `"transport": "websocket"` 是否匹配。
+ - 服务器可选下发 `session_id` 字段,设备端收到后会自动记录。
+ - 示例:
+ ```json
+ {
+ "type": "hello",
+ "transport": "websocket",
+ "session_id": "xxx",
+ "audio_params": {
+ "format": "opus",
+ "sample_rate": 24000,
+ "channels": 1,
+ "frame_duration": 60
+ }
+ }
+ ```
+ - 如果匹配,则认为服务器已就绪,标记音频通道打开成功。
+ - 如果在超时时间(默认 10 秒)内未收到正确回复,认为连接失败并触发网络错误回调。
+
+5. **后续消息交互**
+ - 设备端和服务器端之间可发送两种主要类型的数据:
+ 1. **二进制音频数据**(Opus 编码)
+ 2. **文本 JSON 消息**(用于传输聊天状态、TTS/STT 事件、MCP 协议消息等)
+
+ - 在代码里,接收回调主要分为:
+ - `OnData(...)`:
+ - 当 `binary` 为 `true` 时,认为是音频帧;设备会将其当作 Opus 数据进行解码。
+ - 当 `binary` 为 `false` 时,认为是 JSON 文本,需要在设备端用 cJSON 进行解析并做相应业务逻辑处理(如聊天、TTS、MCP 协议消息等)。
+
+ - 当服务器或网络出现断连,回调 `OnDisconnected()` 被触发:
+ - 设备会调用 `on_audio_channel_closed_()`,并最终回到空闲状态。
+
+6. **关闭 WebSocket 连接**
+ - 设备在需要结束语音会话时,会调用 `CloseAudioChannel()` 主动断开连接,并回到空闲状态。
+ - 或者如果服务器端主动断开,也会引发同样的回调流程。
+
+---
+
+## 2. 通用请求头
+
+在建立 WebSocket 连接时,代码示例中设置了以下请求头:
+
+- `Authorization`: 用于存放访问令牌,形如 `"Bearer "`
+- `Protocol-Version`: 协议版本号,与 hello 消息体内的 `version` 字段保持一致
+- `Device-Id`: 设备物理网卡 MAC 地址
+- `Client-Id`: 软件生成的 UUID(擦除 NVS 或重新烧录完整固件会重置)
+
+这些头会随着 WebSocket 握手一起发送到服务器,服务器可根据需求进行校验、认证等。
+
+---
+
+## 3. 二进制协议版本
+
+设备支持多种二进制协议版本,通过配置中的 `version` 字段指定:
+
+### 3.1 版本1(默认)
+直接发送 Opus 音频数据,无额外元数据。Websocket 协议会区分 text 与 binary。
+
+### 3.2 版本2
+使用 `BinaryProtocol2` 结构:
+```c
+struct BinaryProtocol2 {
+ uint16_t version; // 协议版本
+ uint16_t type; // 消息类型 (0: OPUS, 1: JSON)
+ uint32_t reserved; // 保留字段
+ uint32_t timestamp; // 时间戳(毫秒,用于服务器端AEC)
+ uint32_t payload_size; // 负载大小(字节)
+ uint8_t payload[]; // 负载数据
+} __attribute__((packed));
+```
+
+### 3.3 版本3
+使用 `BinaryProtocol3` 结构:
+```c
+struct BinaryProtocol3 {
+ uint8_t type; // 消息类型
+ uint8_t reserved; // 保留字段
+ uint16_t payload_size; // 负载大小
+ uint8_t payload[]; // 负载数据
+} __attribute__((packed));
+```
+
+---
+
+## 4. JSON 消息结构
+
+WebSocket 文本帧以 JSON 方式传输,以下为常见的 `"type"` 字段及其对应业务逻辑。若消息里包含未列出的字段,可能为可选或特定实现细节。
+
+### 4.1 设备端→服务器
+
+1. **Hello**
+ - 连接成功后,由设备端发送,告知服务器基本参数。
+ - 例:
+ ```json
+ {
+ "type": "hello",
+ "version": 1,
+ "features": {
+ "mcp": true
+ },
+ "transport": "websocket",
+ "audio_params": {
+ "format": "opus",
+ "sample_rate": 16000,
+ "channels": 1,
+ "frame_duration": 60
+ }
+ }
+ ```
+
+2. **Listen**
+ - 表示设备端开始或停止录音监听。
+ - 常见字段:
+ - `"session_id"`:会话标识
+ - `"type": "listen"`
+ - `"state"`:`"start"`, `"stop"`, `"detect"`(唤醒检测已触发)
+ - `"mode"`:`"auto"`, `"manual"` 或 `"realtime"`,表示识别模式。
+ - 例:开始监听
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "listen",
+ "state": "start",
+ "mode": "manual"
+ }
+ ```
+
+3. **Abort**
+ - 终止当前说话(TTS 播放)或语音通道。
+ - 例:
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "abort",
+ "reason": "wake_word_detected"
+ }
+ ```
+ - `reason` 值可为 `"wake_word_detected"` 或其他。
+
+4. **Wake Word Detected**
+ - 用于设备端向服务器告知检测到唤醒词。
+ - 在发送该消息之前,可提前发送唤醒词的 Opus 音频数据,用于服务器进行声纹检测。
+ - 例:
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "listen",
+ "state": "detect",
+ "text": "你好小明"
+ }
+ ```
+
+5. **MCP**
+ - 推荐用于物联网控制的新一代协议。所有设备能力发现、工具调用等均通过 type: "mcp" 的消息进行,payload 内部为标准 JSON-RPC 2.0(详见 [MCP 协议文档](./mcp-protocol.md))。
+
+ - **设备端到服务器发送 result 的例子:**
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "mcp",
+ "payload": {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": {
+ "content": [
+ { "type": "text", "text": "true" }
+ ],
+ "isError": false
+ }
+ }
+ }
+ ```
+
+---
+
+### 4.2 服务器→设备端
+
+1. **Hello**
+ - 服务器端返回的握手确认消息。
+ - 必须包含 `"type": "hello"` 和 `"transport": "websocket"`。
+ - 可能会带有 `audio_params`,表示服务器期望的音频参数,或与设备端对齐的配置。
+ - 服务器可选下发 `session_id` 字段,设备端收到后会自动记录。
+ - 成功接收后设备端会设置事件标志,表示 WebSocket 通道就绪。
+
+2. **STT**
+ - `{"session_id": "xxx", "type": "stt", "text": "..."}`
+ - 表示服务器端识别到了用户语音。(例如语音转文本结果)
+ - 设备可能将此文本显示到屏幕上,后续再进入回答等流程。
+
+3. **LLM**
+ - `{"session_id": "xxx", "type": "llm", "emotion": "happy", "text": "😀"}`
+ - 服务器指示设备调整表情动画 / UI 表达。
+
+4. **TTS**
+ - `{"session_id": "xxx", "type": "tts", "state": "start"}`:服务器准备下发 TTS 音频,设备端进入 "speaking" 播放状态。
+ - `{"session_id": "xxx", "type": "tts", "state": "stop"}`:表示本次 TTS 结束。
+ - `{"session_id": "xxx", "type": "tts", "state": "sentence_start", "text": "..."}`
+ - 让设备在界面上显示当前要播放或朗读的文本片段(例如用于显示给用户)。
+
+5. **MCP**
+ - 服务器通过 type: "mcp" 的消息下发物联网相关的控制指令或返回调用结果,payload 结构同上。
+
+ - **服务器到设备端发送 tools/call 的例子:**
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "mcp",
+ "payload": {
+ "jsonrpc": "2.0",
+ "method": "tools/call",
+ "params": {
+ "name": "self.light.set_rgb",
+ "arguments": { "r": 255, "g": 0, "b": 0 }
+ },
+ "id": 1
+ }
+ }
+ ```
+
+6. **System**
+ - 系统控制命令,常用于远程升级更新。
+ - 例:
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "system",
+ "command": "reboot"
+ }
+ ```
+ - 支持的命令:
+ - `"reboot"`:重启设备
+
+7. **Custom**(可选)
+ - 自定义消息,当 `CONFIG_RECEIVE_CUSTOM_MESSAGE` 启用时支持。
+ - 例:
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "custom",
+ "payload": {
+ "message": "自定义内容"
+ }
+ }
+ ```
+
+8. **音频数据:二进制帧**
+ - 当服务器发送音频二进制帧(Opus 编码)时,设备端解码并播放。
+ - 若设备端正在处于 "listening" (录音)状态,收到的音频帧会被忽略或清空以防冲突。
+
+---
+
+## 5. 音频编解码
+
+1. **设备端发送录音数据**
+ - 音频输入经过可能的回声消除、降噪或音量增益后,通过 Opus 编码打包为二进制帧发送给服务器。
+ - 根据协议版本,可能直接发送 Opus 数据(版本1)或使用带元数据的二进制协议(版本2/3)。
+
+2. **设备端播放收到的音频**
+ - 收到服务器的二进制帧时,同样认定是 Opus 数据。
+ - 设备端会进行解码,然后交由音频输出接口播放。
+ - 如果服务器的音频采样率与设备不一致,会在解码后再进行重采样。
+
+---
+
+## 6. 常见状态流转
+
+以下为常见设备端关键状态流转,与 WebSocket 消息对应:
+
+1. **Idle** → **Connecting**
+ - 用户触发或唤醒后,设备调用 `OpenAudioChannel()` → 建立 WebSocket 连接 → 发送 `"type":"hello"`。
+
+2. **Connecting** → **Listening**
+ - 成功建立连接后,若继续执行 `SendStartListening(...)`,则进入录音状态。此时设备会持续编码麦克风数据并发送到服务器。
+
+3. **Listening** → **Speaking**
+ - 收到服务器 TTS Start 消息 (`{"type":"tts","state":"start"}`) → 停止录音并播放接收到的音频。
+
+4. **Speaking** → **Idle**
+ - 服务器 TTS Stop (`{"type":"tts","state":"stop"}`) → 音频播放结束。若未继续进入自动监听,则返回 Idle;如果配置了自动循环,则再度进入 Listening。
+
+5. **Listening** / **Speaking** → **Idle**(遇到异常或主动中断)
+ - 调用 `SendAbortSpeaking(...)` 或 `CloseAudioChannel()` → 中断会话 → 关闭 WebSocket → 状态回到 Idle。
+
+### 自动模式状态流转图
+
+```mermaid
+stateDiagram
+ direction TB
+ [*] --> kDeviceStateUnknown
+ kDeviceStateUnknown --> kDeviceStateStarting:初始化
+ kDeviceStateStarting --> kDeviceStateWifiConfiguring:配置WiFi
+ kDeviceStateStarting --> kDeviceStateActivating:激活设备
+ kDeviceStateActivating --> kDeviceStateUpgrading:检测到新版本
+ kDeviceStateActivating --> kDeviceStateIdle:激活完成
+ kDeviceStateIdle --> kDeviceStateConnecting:开始连接
+ kDeviceStateConnecting --> kDeviceStateIdle:连接失败
+ kDeviceStateConnecting --> kDeviceStateListening:连接成功
+ kDeviceStateListening --> kDeviceStateSpeaking:开始说话
+ kDeviceStateSpeaking --> kDeviceStateListening:结束说话
+ kDeviceStateListening --> kDeviceStateIdle:手动终止
+ kDeviceStateSpeaking --> kDeviceStateIdle:自动终止
+```
+
+### 手动模式状态流转图
+
+```mermaid
+stateDiagram
+ direction TB
+ [*] --> kDeviceStateUnknown
+ kDeviceStateUnknown --> kDeviceStateStarting:初始化
+ kDeviceStateStarting --> kDeviceStateWifiConfiguring:配置WiFi
+ kDeviceStateStarting --> kDeviceStateActivating:激活设备
+ kDeviceStateActivating --> kDeviceStateUpgrading:检测到新版本
+ kDeviceStateActivating --> kDeviceStateIdle:激活完成
+ kDeviceStateIdle --> kDeviceStateConnecting:开始连接
+ kDeviceStateConnecting --> kDeviceStateIdle:连接失败
+ kDeviceStateConnecting --> kDeviceStateListening:连接成功
+ kDeviceStateIdle --> kDeviceStateListening:开始监听
+ kDeviceStateListening --> kDeviceStateIdle:停止监听
+ kDeviceStateIdle --> kDeviceStateSpeaking:开始说话
+ kDeviceStateSpeaking --> kDeviceStateIdle:结束说话
+```
+
+---
+
+## 7. 错误处理
+
+1. **连接失败**
+ - 如果 `Connect(url)` 返回失败或在等待服务器 "hello" 消息时超时,触发 `on_network_error_()` 回调。设备会提示"无法连接到服务"或类似错误信息。
+
+2. **服务器断开**
+ - 如果 WebSocket 异常断开,回调 `OnDisconnected()`:
+ - 设备回调 `on_audio_channel_closed_()`
+ - 切换到 Idle 或其他重试逻辑。
+
+---
+
+## 8. 其它注意事项
+
+1. **鉴权**
+ - 设备通过设置 `Authorization: Bearer ` 提供鉴权,服务器端需验证是否有效。
+ - 如果令牌过期或无效,服务器可拒绝握手或在后续断开。
+
+2. **会话控制**
+ - 代码中部分消息包含 `session_id`,用于区分独立的对话或操作。服务端可根据需要对不同会话做分离处理。
+
+3. **音频负载**
+ - 代码里默认使用 Opus 格式,并设置 `sample_rate = 16000`,单声道。帧时长由 `OPUS_FRAME_DURATION_MS` 控制,一般为 60ms。可根据带宽或性能做适当调整。为了获得更好的音乐播放效果,服务器下行音频可能使用 24000 采样率。
+
+4. **协议版本配置**
+ - 通过设置中的 `version` 字段配置二进制协议版本(1、2 或 3)
+ - 版本1:直接发送 Opus 数据
+ - 版本2:使用带时间戳的二进制协议,适用于服务器端 AEC
+ - 版本3:使用简化的二进制协议
+
+5. **物联网控制推荐 MCP 协议**
+ - 设备与服务器之间的物联网能力发现、状态同步、控制指令等,建议全部通过 MCP 协议(type: "mcp")实现。原有的 type: "iot" 方案已废弃。
+ - MCP 协议可在 WebSocket、MQTT 等多种底层协议上传输,具备更好的扩展性和标准化能力。
+ - 详细用法请参考 [MCP 协议文档](./mcp-protocol.md) 及 [MCP 物联网控制用法](./mcp-usage.md)。
+
+6. **错误或异常 JSON**
+ - 当 JSON 中缺少必要字段,例如 `{"type": ...}`,设备端会记录错误日志(`ESP_LOGE(TAG, "Missing message type, data: %s", data);`),不会执行任何业务。
+
+---
+
+## 9. 消息示例
+
+下面给出一个典型的双向消息示例(流程简化示意):
+
+1. **设备端 → 服务器**(握手)
+ ```json
+ {
+ "type": "hello",
+ "version": 1,
+ "features": {
+ "mcp": true
+ },
+ "transport": "websocket",
+ "audio_params": {
+ "format": "opus",
+ "sample_rate": 16000,
+ "channels": 1,
+ "frame_duration": 60
+ }
+ }
+ ```
+
+2. **服务器 → 设备端**(握手应答)
+ ```json
+ {
+ "type": "hello",
+ "transport": "websocket",
+ "session_id": "xxx",
+ "audio_params": {
+ "format": "opus",
+ "sample_rate": 16000
+ }
+ }
+ ```
+
+3. **设备端 → 服务器**(开始监听)
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "listen",
+ "state": "start",
+ "mode": "auto"
+ }
+ ```
+ 同时设备端开始发送二进制帧(Opus 数据)。
+
+4. **服务器 → 设备端**(ASR 结果)
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "stt",
+ "text": "用户说的话"
+ }
+ ```
+
+5. **服务器 → 设备端**(TTS开始)
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "tts",
+ "state": "start"
+ }
+ ```
+ 接着服务器发送二进制音频帧给设备端播放。
+
+6. **服务器 → 设备端**(TTS结束)
+ ```json
+ {
+ "session_id": "xxx",
+ "type": "tts",
+ "state": "stop"
+ }
+ ```
+ 设备端停止播放音频,若无更多指令,则回到空闲状态。
+
+---
+
+## 10. 总结
+
+本协议通过在 WebSocket 上层传输 JSON 文本与二进制音频帧,完成功能包括音频流上传、TTS 音频播放、语音识别与状态管理、MCP 指令下发等。其核心特征:
+
+- **握手阶段**:发送 `"type":"hello"`,等待服务器返回。
+- **音频通道**:采用 Opus 编码的二进制帧双向传输语音流,支持多种协议版本。
+- **JSON 消息**:使用 `"type"` 为核心字段标识不同业务逻辑,包括 TTS、STT、MCP、WakeWord、System、Custom 等。
+- **扩展性**:可根据实际需求在 JSON 消息中添加字段,或在 headers 里进行额外鉴权。
+
+服务器与设备端需提前约定各类消息的字段含义、时序逻辑以及错误处理规则,方能保证通信顺畅。上述信息可作为基础文档,便于后续对接、开发或扩展。