Replies: 1 comment
|
Nice! |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
MCP 网关:让 AI 语音助手控制局域网里的任何设备
问题
Ai-WV01-32S-Kit 是安信可的 AI 语音模块,出厂固件已烧录好,开箱即用——它有自己的 WiFi、麦克风、扬声器,跑 PalChat AI 固件,支持 UART-MCP 协议与外部 MCU 交互。用户不需要对 AI 模块做任何二次开发。
想让它关电脑上的 QQ、调客厅的灯、查询树莓派状态?做不到——除非有人帮它把"手"伸到局域网里其他设备上。
WT32-SC01 做 MCP 网关中转
我用 WT32-SC01 做中转网关,连接在 AI 模块和局域网设备之间:
WT32-SC01 的三重角色:
对着 AI 说"关电脑上的 QQ",AI 模块通过 UART 调用网关注册的
remote.call工具,网关转发到 PC 上的 MCP 服务执行。AI 固件零改动,局域网设备各写各的,网关负责翻译和路由。网关核心:三层协议转换
WT32-SC01 网关的核心挑战是协议转换——Ai-WV01-32S-Kit 说 UART-MCP,局域网设备说 HTTP,两者之间需要一个翻译+路由引擎。AI 模块出厂固件已支持 UART-MCP 协议,网关只需要正确注册工具,AI 就能调用。
第一层:UART-MCP 南向接口
Ai-WV01-32S-Kit 出厂固件原生支持 UART-MCP 协议,通过串口发送 JSON 行消息。emMCP 库解析后触发回调,网关向 AI 注册 3 个 MCP 工具:
screen.brightnessled.switchremote.call本地工具直接操作硬件,代理工具走异步转发引擎。
第二层:HTTP Hub 北向接口
局域网设备通过 REST API 注册到网关:
设备注册时声明自己的工具列表:
网关收到注册后,立刻触发 MCP 工具重注册——重建
remote.call的描述字符串,让 AI 模块看到最新的可用设备+工具清单。第三层:异步代理转发引擎
这是网关最关键的部分。AI 调用
remote.call时,数据流:关键技术实现
1. remote.call 代理模式——突破 5 工具上限
emMCP 库最多注册 5 个 MCP 工具。本地占了 2 个,只剩 3 个坑位,局域网里 10 台设备怎么接?
解法:一个
remote.call代理工具搞定所有远程设备。AI 调用时传入{device, tool, params},网关路由到目标设备。工具描述动态生成:设备上下线时,描述字符串自动重建并重新注册。5 个坑位,无限扩展。
动态描述字符串的构建——每次设备增删时重建,AI 模块据此生成正确的调用参数:
2. 异步代理队列——不让 HTTP 请求冻住主循环
MCP 工具回调跑在
mcp.loop()内部。如果回调里直接发 HTTP 请求(1-3 秒),UART 解析、LVGL 渲染、动画帧全部卡死。解法:回调只入队,主循环每轮处理一个请求。队列深度 4,满了返回
proxy busy。整个系统保持响应,代理转发不阻塞。回调——验证参数、查找设备、入队:
主循环中处理队列——每次只取 1 个请求,HTTP 转发后立即返回:
3. cJSON 参数格式兼容——AI 模块传参不一致
AI 模块传参格式不固定,网关需要兼容所有情况:
4. 设备变更 → 工具重注册
设备增删时,网关必须通知 AI 模块更新工具列表。但重注册不能在 HTTP 处理回调中执行(emMCP 的 UART 发送不可重入),所以用标志位延迟到主循环:
HTTP Hub 实现
REST API
mDNS 自动发现
网关通过 mDNS 广播
_mcp-hub._tcp,局域网设备零配置发现:WiFi 指数退避重连
emMCP:网关的 UART-MCP 协议层
emMCP(Easy MCU MCP)是安信可开源的纯 C 协议库,最小资源占用 62 字节 RAM、1.7KB Flash。Ai-WV01-32S-Kit 的出厂固件原生支持 UART-MCP 协议,emMCP 是 MCU 端的协议适配库——用它就能和 AI 模块通信,无需了解底层协议细节。
C 核心结构
emMCP-arduino:Arduino 移植版
emMCP-arduino 是 emMCP 的 Arduino 移植库,将 C 核心封装为 Arduino 风格的 C++ API,提供链式 Builder 模式定义工具:
C/C++ 桥接:模板跳板(Template Trampoline)
C 核心只认
void(*)(void*)函数指针,Arduino 用户希望传 C++ 回调。emMCP-arduino 用模板跳板解决——为每个工具槽位生成编译期确定的静态分发函数:C 核心调用函数指针 → 跳板函数 → 用户 C++ 回调,完成 C 到 C++ 的桥接。
UART 串口适配
工具重注册
设备增删时需要重注册工具列表,
resetTools()清空内部状态:网关的本地工具
网关自身也暴露硬件控制工具,直接操作 ESP32 的 GPIO 和 PWM:
Ai-WV01-32S-Kit 事件处理
Ai-WV01-32S-Kit 出厂固件通过 UART 主动上报状态/文字/表情事件,网关解析后更新共享状态,驱动 UI 和表情模块:
关键设计:所有状态更新通过
volatile共享变量传递给 UI/表情模块,不在回调中直接操作 LVGL(LVGL 非线程安全)。表情脸:网关的可视化反馈
网关自带 480x320 IPS 触摸屏,显示 AI 状态和表情脸动画。表情脸是纯程序化渲染——不用 GIF、不用贴图,120x120 RGB565 离屏帧缓冲放 PSRAM,每帧重绘完整表情后一次
pushImage推屏。10 种表情各有独立动画逻辑,AI 说话时解析 emotion 字段立刻切换,空闲时每 10 秒自动轮换:
主循环编排
网关主循环的执行顺序经过精心设计,确保 UART 解析、代理转发、UI 渲染、表情动画互不冲突:
顺序不可随意调换——表情脸和设备列表使用直接 GFX(
pushImage),必须在 LVGL 渲染之后执行,否则 LVGL 的 flush 会覆盖。Python 测试工具
网关附带两个 Python 工具,用于测试和开发:
mcp_device_sim.py — 模拟远程 MCP 设备
自动发现 Hub、注册设备、接收转发调用:
模拟 4 个工具:
qq.switch、screen.brightness、status.query、echo。mcp_hub_client.py — Hub 管理客户端
PSRAM 策略
WT32-SC01 搭载 ESP32-WROVER-B,有 8MB PSRAM。网关把大缓冲区全部放 PSRAM,内部 RAM 留给实时逻辑:
硬件
项目结构
wt32-ai-assistantMCP/wt32-ai-assistant/emMCPMCP/emMCP/emMCP-arduinoMCP/emMCP-arduino/esp_emote_gfxMCP/esp_emote_gfx/网关 API 总结
UART-MCP 工具(Ai-WV01-32S-Kit 调用)
HTTP REST API(局域网设备调用)
mDNS 服务
Ai-WV01-32S-Kit 事件
代理错误处理
{"error":"device '...' not found"}{"error":"missing device or tool parameter"}{"error":"proxy busy"}{"error":"HTTP failed: "}项目仓库:https://github.com/LTLyaoni/MCP-_Gateway.git
10f6ee4eb2335f6d3120de3e8a71da9a.mp4
13430545508838781.mp4
All reactions