九章 MCP 验证板使用 UART-MCP 协议 在 STM32 MCU 与 Ai-WV01-32S AI 模组之间进行通信。本文档描述协议的帧格式、工具注册/调用流程以及错误码。
TIP
完整的 UART-MCP 协议文档请参考 UART-MCP 协议介绍 和 使用指南。
1. 串口配置
| 参数 | 值 |
|---|---|
| 波特率 | 115200(默认,可配置 300~2000000) |
| 数据位 | 8 |
| 停止位 | 1 |
| 校验位 | 无 |
| 帧结束符 | \r\n(回车换行) |
WARNING
每个 JSON 指令必须以 \r\n 结尾,否则 AI 模组无法识别。
2. JSON 帧格式
2.1 通用帧结构
所有交互消息均为 JSON 格式,包含以下顶层字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
role | string | 是 | 发送者标识:"AI board" 或 "MCU" |
msgType | string | 是 | 消息类型(见下文) |
data | string/object | 视类型而定 | 消息内容 |
2.2 消息类型(msgType)
| msgType | 方向 | 说明 |
|---|---|---|
status | AI → MCU | 状态通知(启动、WiFi 连接、唤醒等) |
mcp_set | AI → MCU | MCP 控制指令(AI 调用工具) |
mcp_check | AI → MCU | MCP 查询指令 |
MCP Text | AI → MCU | AI 回复的字幕文本 |
tool_list | MCU → AI | 注册 MCP 工具列表 |
ctrl_result | MCU → AI | 工具执行结果返回 |
volume | 双向 | 音量设置/查询 |
wake-up | MCU → AI | 主动唤醒 |
uart_baudrate | MCU → AI | 波特率设置 |
3. AI 模组 → MCU 消息
3.1 状态下发
AI 模组将自身状态变化通知 MCU:
json
{"role":"AI board","msgType":"status","data":"<状态信息>"}常见状态值:
| data 值 | 说明 |
|---|---|
AI Start | AI 设备启动完成 |
1.WiFi connect OK | WiFi 连接成功 |
2.WakeUP | 模组唤醒(语音唤醒后触发) |
3.Sleep | 模组进入睡眠 |
4.NetCFG | 配网模式 |
5.NetERR | 网络错误 |
6.OTAUPDATE | OTA 开始 |
7.OTA OK | OTA 成功 |
8.OTA ERR | OTA 失败 |
OK | 命令执行成功 |
ERROR:<信息> | 命令执行失败 |
3.2 MCP 控制指令(工具调用)
AI 模组下发工具调用请求:
json
{"role":"AI board","msgType":"mcp_set","tools":"<工具名称>","data":{"<参数名>":<参数值>}}示例 — AI 调用 LED 控制工具:
json
{"role":"AI board","msgType":"mcp_set","tools":"led","data":{"enable":true}}3.3 MCP 查询指令
AI 模组查询工具状态:
json
{"role":"AI board","msgType":"mcp_check","tools":"<工具名称>"}示例 — 查询 LED 状态:
json
{"role":"AI board","msgType":"mcp_check","tools":"led"}3.4 字幕文本
AI 回复内容以字幕形式下发,可用于 OLED 显示:
json
{"role":"AI board","msgType":"MCP Text","data":"当前温度是25.3摄氏度"}4. MCU → AI 模组消息
4.1 注册 MCP 工具
MCU 将工具定义列表发送给 AI 模组。每个工具包含名称、描述、属性和方法。
整个流程由 emMCP 库的 emMCP_RegistrationTools() 自动完成。底层发送的 JSON 格式如下:
json
<指令前缀>{"role":"MCU","msgType":"tool_list","data":[
{
"tool_name":"<工具名称>",
"description":"<工具描述>",
"properties":{
"<属性名>":{"description":"<属性描述>","type":"<类型>"}
},
"methods":{
"<方法名>":{"description":"<方法描述>","parameters":{
"<参数名>":{"description":"<参数描述>","type":"<类型>","required":true}
}}
}
}
]}限制条件
- 工具名称不得使用
Speaker或Light(系统保留) - 工具名称应仅含
[a-z0-9_] - 工具数量默认可配上限 4 个(通过
MCP_SERVER_TOOL_NUMBLE_MAX调整)
4.2 工具控制结果返回
MCU 执行完工具回调后,将结果返回 AI:
json
{"role":"MCU","msgType":"ctrl_result","data":"<结果JSON字符串>"}成功示例:
json
{"role":"MCU","msgType":"ctrl_result","data":"{\"result\":\"ok\"}"}4.3 工具查询结果返回
json
{"role":"MCU","msgType":"ctrl_result","data":"<查询结果JSON>"}示例 — 雷达状态查询:
json
{"role":"MCU","msgType":"ctrl_result","data":"{\"detected\":true}"}5. MCP 工具注册与调用流程
5.1 工具注册流程
5.2 工具控制调用流程
5.3 工具查询流程
6. 错误码
当 AI 模组检测到协议错误时,返回 ERROR:<错误信息> 格式:
| 错误信息 | 说明 | 严重程度 | 解决方法 |
|---|---|---|---|
ERROR:Tools NULL | MCP 工具列表为空 | 🟢 | 创建工具后调用 RegistrationTools |
ERROR:Invalid JSON format | 数据非合法 JSON | 🔴 | 检查 JSON 格式 |
ERROR:Invalid role | 缺失 role 字段 | 🔴 | 检查 JSON 是否包含 "role" |
ERROR:Invalid msgType | 缺失 msgType 字段 | 🔴 | 检查 JSON 是否包含 "msgType" |
ERROR:Invalid MCP | 缺失 MCP 关键字 | 🔴 | 检查 JSON 是否包含 "MCP" |
ERROR:Invalid tools | 缺失 tools 关键字 | 🔴 | 检查 JSON 是否包含 "tools" |
ERROR:Invalid tool_name | 缺失 tool_name | 🔴 | 检查 JSON 是否包含 "tool_name" |
ERROR:tool_name already exists | 工具名冲突或包含保留名 | 🔴 | 更换工具名,禁止使用 Speaker/Light |
ERROR:Failed to save tools | 工具保存失败 | 🔴 | 重启模组后重新注册 |
ERROR:Failed to allocate memory | 内存分配失败 | 🔴 | 重启模组 |
ERROR:Failed to parse tools | 工具数据非合法 JSON | 🔴 | 检查工具定义的 JSON 格式 |
ERROR:params is null | MCP 指令缺 params | 🟡 | 重新让 AI 下发指令 |
ERROR:tools call failed | 内部工具获取失败 | 🟡 | 重新让 AI 下发指令 |
ERROR:Timeout | MCU 超时未响应 | 🟡 | 确保在收到指令后 5 秒内返回结果 |
完整错误码列表请参考 UART-MCP 错误信息列表。
7. 数据流示例:完整对话
以下是一次完整的语音控制 LED 灯的数据流:
[用户] → 语音 → "小安,打开LED灯"
[AI] → UART → {"role":"AI board","msgType":"mcp_set","tools":"led","data":{"enable":true}}
[MCU] → 内部 → emMCP解析 → 调用 led.setRequestHandler
[MCU] → GPIO → HAL_GPIO_WritePin(PC13, SET)
[MCU] → UART → {"role":"MCU","msgType":"ctrl_result","data":"{\"result\":\"ok\"}"}
[AI] → 语音 → "已为您打开LED灯"
