W600嵌入式OBD2 MCP服务器
W600 WiFi SoC的嵌入式模型上下文协议(MCP)服务器实现,通过HTTP上的ELM327 OBD-II接口提供车辆诊断功能。
MCP实现可以很容易地移植到运行FreeRTOS的其他MCU上。还有MCP服务器的lwIP Raw API实现(MCP_server_rawip.c),如果您需要,它可以在没有操作系统的裸机上运行。
黑客松
这是我们为Anthropic Gradio MCP的第一个生日黑客马拉松提交的一部分:https://huggingface.co/spaces/MCP-1st-Birthday/Vehicle-Diagnostic-Assistant
此存储库涵盖MCP服务器。我们也在这次黑客马拉松中开发了AI Agent,您可以在此处访问:
概述
该项目实现了一个直接在W600微控制器上运行的MCP服务器。它还提供ELM327驱动器,通过ELM327 OBD-II协议实现车辆诊断通信。该服务器通过HTTP公开MCP工具,允许AI助手和其他客户端查询车辆数据,读取故障诊断码(DTC),并无线执行OBD-II操作。
为了让人工智能代理诊断车辆,我们需要创建一个MCP服务器,它可以通过车辆的OBD-II端口发送命令。该项目实现了一个运行MCP服务器的自定义固件,安装在廉价的OBD-Ⅱ扫描仪(加密狗)上。
免责声明:我们这样做只是为了好玩,只是为了技术挑战和学习机会。我们不建议让人工智能代理在没有更多控制的情况下直接控制你的汽车。
特性
- MCP服务器实现:MCP HTTP流传输(版本2025-06-18),基于JSON-RPC 2.0的MCP服务器,运行在W600上
- ELM327支架:完整的ELM327 OBD-II命令接口,带UART通信
- OBD-II仿真:无需车辆连接即可进行测试的内置模拟器
- WiFi连接:通过WiFi接入点或车站模式连接
- HTTP接口:用于MCP通信的RESTful HTTP端点
- OTA更新:无线固件更新功能
- 日志记录:用于远程监控的非阻塞UDP syslog日志记录
硬件背景
OBD-II东乐建筑
在线提供的廉价OBD-II加密狗通常支持蓝牙或WiFi。这些是您连接到车辆OBD端口的加密狗。您通常使用连接到加密狗的移动应用程序(通过蓝牙或WiFi)来运行诊断。
这些设备通常有两个MCU:
- MCU与OBD-II端口通信 车辆(ELM327)
- MCU管理Wi-Fi或蓝牙连接 使用客户端应用程序
该项目取代了第二个MCU的固件,直接实现了MCP协议,允许AI代理直接与加密狗通信,而无需任何中介。
硬件标识
使用的具体设备是亚马逊的“OBD II汽车诊断工具自动扫描仪代码阅读器WiFi”。Wi-Fi MCU被识别为 WinnerMicro W600-B800 处理器(不是最初预期的ESP8266)。
关于 W600-B800,但有可用的SDK。SDK使用FreeRTOS/lwIP,并包含代码示例。WinnerMicro SDK刚刚开始工作——设置工具链的说明是成功的,虽然文档有限,但熟悉FreeRTOS/lwIP使开发变得简单明了。
固件上传
通过连接到PCB测试焊盘上传固件(从 此页):
- 编程器UART通过测试垫上的针连接到W600 UART0、115200 8N1
- 使用minicom,在SECBOOT期间切换到固件上传模式
- 在上传模式下,使用xmodem协议上传固件
- WinnerMicro说明
免责声明:需要明确的是,这只是一个有趣的项目。重新编程OBD-II加密狗不是生产使用的最佳方法。您可能会失去保修,并且很有可能损坏和/或弄脏您的设备,或者更糟糕的是,损坏您的汽车!
硬件要求
- W600 WiFi SoC开发板(或与W600兼容的OBD-II加密狗)
- ELM327 OBD-II接口模块(基于UART)
- 带OBD-II端口的车辆(用于实际诊断)
- USB转串行适配器(用于编程和调试)
软件需求
- W600 SDK(必需)
- GNU ARM工具链
- 串口软件(调试用)
固件开发方法
1.支持空中下载(OTA)更新的最小固件
将探针放置在测试板上以上传固件或访问日志并不理想。第一个目标是创建一个最小的固件,它将:
- 将设备连接到Wi-Fi网络(STA模式+DHCP)
- 自动检查特定URL上的固件是否可用,如果可用,则继续进行OTA(空中更新)
- 通过UDP syslog发送日志
第1项和第2项很简单——SDK中提供了演示。这些在开始时实施 App/main.c.
对于#3,SDK中不支持网络日志。因此,对现有的日志库进行了修改,以添加对非阻塞UDP syslog的支持。更改发生在: Src/App/easylogger/port/elog_port.c 和 Include/wm_log.h.
此时,固件更新变得容易(OTA),远程监控成为可能。
2.ELM327驱动器
下一步是为W600创建ELM327驱动程序,以便与ELM327芯片通信,发送指令(AT命令、OBD-II命令)并检索响应。当设备通电但未连接到车辆时,也实现了模拟模式。在这种情况下,AT命令被发送到硬件,但OBD-II命令由模拟器应答。
在擦除原始固件之前,探测W600和ELM327之间的串行线并记录通信。这符合 ELM327文件。您不希望处于不知道MCU或外围设备如何通信并且没有原始固件的情况。
UART连接: 来自W600的UART1连接到ELM327、38400 8N1上的EUSART1(第一个UART)。
ELM327驱动器位置: Src/App/elm327/elm327.c
创建了ELM327 API
| 函数 | 目的 | 关键返回值 |
|---|---|---|
elm327_init() | 初始化UART1@38400波特 | WM_SUCCESS / WM_FAILED |
elm327_send_command(cmd, resp, len, timeout) | 发送OBD-II命令 | >0 字节, -1 不是init, -2 无效参数, -3 UART故障, -4 超时 |
elm327_deinit() | 清理资源 | 无效 |
模拟API(可选)
与编译时可用 TLS_CONFIG_ELM327_SIMULATION.
| 函数 | 目的 | 返回 |
|---|---|---|
elm327_set_simulation_mode(enable) | 启用/禁用模拟模式 | void |
elm327_is_simulation_enabled() | 检查模拟是否处于活动状态 | true / false |
elm327_set_engine_state(running) | 设置模拟发动机状态 | void |
模拟说明:
- 启用后,OBD-II命令返回模拟响应
- AT命令总是指向真实的硬件
- 发动机状态会影响模拟的转速、温度和其他动态值
ELM327配置
- UART: UART1,38400波特,8N1,无流量控制
- 最大响应: 512字节(
ELM327_MAX_RESPONSE_LEN) - 默认超时时间: 2000毫秒(
ELM327_DEFAULT_TIMEOUT)
SDK在其API中定义了两种UART操作模式(中断和轮询),但实际实现仅支持中断模式。轮询模式枚举存在,但相应的代码路径已被注释掉(请参见 Platform/Drivers/uart/wm_uart.c:376).无论模式参数如何,中断始终处于启用状态。为了检索ELM327响应,使用了中断驱动的RX回调,并通过FreeRTOS信号量发出响应结束的信号。
3.MCP服务器架构
MCP服务器是该项目的主要部分。它主要符合MCP HTTP流传输(版本2025-06-18): https://modelcontextprotocol.io/specification/2025-06-18/basic/transports
┌──────────────────────────────────────────────────────────────────────────────────────┐
│ MCP Client │
│ (AI agent, Gradio, Claude Code, etc.) │
└────────────────────────────────────────┬─────────────────────────────────────────────┘
│
│ HTTP POST /mcp
│ (JSON-RPC over HTTP)
│
▼
┌──────────────────────────────────────────────────────────────────────────────────────┐
│ W600 WiFi SoC │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────────┐ │
│ │ MCP Server Orchestrator │ │
│ │ │ │
│ │ • TCP connection management (lwIP) │ │
│ │ • Request buffering & reassembly │ │
│ │ • Coordinate HTTP, JSON-RPC, and method layers │ │
│ │ • Response lifecycle management │ │
│ │ │ │
│ │ (mcp_server.c - Port 80) │ │
│ └─────────────┬────────────────────────────┬────────────────────────┬─────────────┘ │
│ │ │ │ │
│ │ │ │ │
│ ┌───────────▼──────────┐ ┌─────────────▼──────────┐ ┌─────────▼────────────┐ │
│ │ │ │ │ │ │ │
│ │ HTTP Protocol │ │ JSON-RPC Parser/ │ │ MCP Method Router │ │
│ │ Handler │ │ Builder │ │ │ │
│ │ │ │ │ │ │ │
│ │ • Parse HTTP │ │ • Parse JSON-RPC │ │ • initialize │ │
│ │ requests │ │ messages │ │ • tools/list │ │
│ │ • Build HTTP │ │ • Build success │ │ • tools/call │ │
│ │ responses │ │ responses │ │ │ │
│ │ • Validate │ │ • Build error │ │ Dispatches to │ │
│ │ headers │ │ responses │ │ tool handlers │ │
│ │ • Status codes │ │ • JSON-RPC 2.0 │ │ │ │
│ │ │ │ compliance │ │ (mcp_methods.c) │ │
│ │ (mcp_http.c) │ │ │ │ │ │
│ │ │ │ (mcp_jsonrpc.c) │ │ │ │
│ └──────────────────────┘ └────────────────────────┘ └─────────┬────────────┘ │
│ │ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────▼─────────────┐ │
│ │ Tool Handlers │ │
│ │ │ │
│ │ ┌───────────────────────────────┐ ┌────────────────────────────────┐ │ │
│ │ │ │ │ │ │ │
│ │ │ status │ │ send_elm327_command │ │ │
│ │ │ │ │ │ │ │
│ │ │ • IP address │ │ • Send AT commands │ │ │
│ │ │ • Network info │ │ • Send OBD-II PIDs │ │ │
│ │ │ • System uptime │ │ • Read responses │ │ │
│ │ │ • Memory usage │ │ • Format results │ │ │
│ │ │ │ │ │ │ │
│ │ └───────────────────────────────┘ └─────────────┬──────────────────┘ │ │
│ │ │ │ │
│ │ (mcp_tools.c) │ │ │
│ └────────────────────────────────────────────────────────┼──────────────────────┘ │
│ │ │
│ │ │
│ ┌────────────────────────────────────────────────────────▼──────────────────────┐ │
│ │ ELM327 Driver │ │
│ │ │ │
│ │ • UART1 communication @ 38400 baud │ │
│ │ • AT command protocol │ │
│ │ • OBD-II PID queries │ │
│ │ • 2-second default timeout │ │
│ │ • Response parsing │ │
│ │ │ │
│ │ (elm327.c) │ │
│ └─────────────────────────────────────────┬─────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ ELM327 Chip │ │
│ │ (UART1) │ │
│ └────────┬─────────┘ │
└────────────────────────────────────────────┼─────────────────────────────────────────┘
│
│
▼
┌──────────────────┐
│ Vehicle OBD-II │
│ Port │
└──────────────────┘固件直接在W600微控制器上实现了完整的MCP服务器堆栈,使AI代理能够与车辆诊断硬件通信,而无需任何中间服务或桥接软件。
MCP服务器编排器
实施: mcp_server.c
编排器是使用lwIP的socket API管理所有网络操作的基础层。(mcp_server_rawip.c中也支持基于回调的TCP API)。它监听端口80,处理传入的连接,缓冲并重新组装可能以多个TCP数据包形式到达的HTTP请求,并协调整个协议栈的请求-响应生命周期。使用RAW API,服务器通过TCP/IP线程调用的lwIP回调(接受、接收、错误)进行操作,使其能够有效管理多个并发客户端连接,而不需要专门的任务。
编排器直接调用三个并行层来处理协议的不同方面:
- HTTP协议处理程序 (
mcp_http.c)用于HTTP解析和响应构建 - JSON-RPC解析器/生成器 (
mcp_jsonrpc.c)用于JSON-RPC消息处理 - MCP方法路由器 (
mcp_methods.c)用于方法调度
这种设计提供了明确的关注点分离,同时将编排逻辑集中在 mcp_server.c.
HTTP协议处理程序
实施: mcp_http.c
此模块实现HTTP协议解析和响应生成。它从原始TCP数据中提取HTTP方法、路径、标头和正文内容,验证所需的标头(如content-Type和content-Length),并使用适当的状态代码和标头构建格式正确的HTTP响应。处理程序被设计为在嵌入式系统的内存约束下工作,并由编排器直接调用。
JSON-RPC解析器/生成器
实施: mcp_jsonrpc.c
MCP协议使用JSON-RPC 2.0作为其消息格式。此组件为JSON-RPC消息提供解析和构建功能。它解析传入的JSON-RPC请求,验证结构(检查“jsonrpc”、“method”和“id”等必填字段),并将响应打包回具有适当错误处理的有效JSON-RPC格式。请注意,此模块仅处理消息格式化,实际的方法路由由MCP方法路由器执行。
MCP方法路由器
实施: mcp_methods.c
该模块实现了规范中定义的核心MCP协议方法。它处理建立MCP会话的“初始化”握手,用可用的诊断工具响应“工具/列表”请求,并处理执行特定诊断操作的“工具/调用”调用。路由器由编排器直接调用,在使MCP规范适应嵌入式环境的同时保持协议合规性。
工具操作员
实施: mcp_tools.c
实际的诊断功能是作为MCP工具实现的。“状态”工具报告设备健康信息,包括IP地址、网络连接、正常运行时间和可用内存。“send_elm327_command”工具是主要的诊断接口,允许AI代理发送AT命令(用于elm327配置)和OBD-II PID(用于车辆数据)并接收响应。这些工具将高级MCP工具调用转换为低级硬件操作。
ELM327驱动层
实施: elm327.c
该驱动程序通过UART1以38400波特与ELM327芯片通信,通过适当的超时处理和响应解析实现ELM327命令响应协议。它包括一个可选的模拟模式(在编译时启用),当设备通电但未连接到车辆时,该模式会生成逼真的车辆响应,从而在不需要实际汽车的情况下促进开发和测试。
硬件接口
在堆栈的底部,固件与物理ELM327芯片连接,该芯片又使用标准汽车协议(CAN、J1850、ISO 9141等)与车辆的OBD-II端口通信。该硬件层在基于UART的ELM327协议和车辆的本地诊断总线之间进行转换。
安装
1.安装W600 SDK
从WinnerMicro官方网站或GitHub存储库下载并安装W600 SDK。按照操作系统的SDK安装说明进行操作。
2.复制项目文件
将此存储库中的文件复制到W600 SDK安装中的相应文件夹中:
App/文件夹内容→ 复制到{W600_SDK}/App/
- main.c -主要应用入口点 - wm_app_config.h -应用程序配置 - wifi_credentials.h.template -WiFi凭据模板
Src/App/文件夹内容→ 复制到{W600_SDK}/Src/App/
- easylogger/ -日志库 - elm327/ -ELM327驱动器和模拟器 - mcp/ -MCP服务器实现
3.配置WiFi凭据
- 复制模板文件:
cp App/wifi_credentials.h.template App/wifi_credentials.h- 编辑
App/wifi_credentials.h并添加您的WiFi凭据:
#define WIFI_SSID "your_ssid"
#define WIFI_PASSWORD "your_password"备注: wifi_credentials.h 保护您的凭据是合法的。
4.配置应用程序设置
编辑 App/wm_app_config.h 配置:
- 固件更新服务器:设置
FIRMWARE_SERVEROTA更新的URL - MCP服务器端口:默认端口为80
- ELM327设置:ELM327通信的UART配置
5.建设项目
导航到W600 SDK构建目录并编译:
cd {W600_SDK}/Tools/GNU
make clean
make这将在中生成固件映像 Bin/ 目录。
6.刷新固件
使用W600闪存工具将编译后的固件闪存到W600板上:
# Example using wm_tool (adjust COM port as needed)
wm_tool -c COM3 -ds 1M -dl {W600_SDK}/Bin/W600.fls配置
ELM327模拟模式
该项目包括一个OBD-II模拟器,用于在没有车辆的情况下进行测试。要配置:
编辑 Include/wm_config.h 在W600 SDK中:
/** ELM327 OBD-II **/
#define TLS_CONFIG_ELM327_SIMULATION CFG_ON // Enable simulator
// or
#define TLS_CONFIG_ELM327_SIMULATION CFG_OFF // Disable (use real ELM327)看 Src/App/elm327/README_SIMULATION.md 详细的模拟文档。
网络配置
该设备可以配置为:
- 工作站模式:连接到现有WiFi网络(默认)
- 无线基地台模式:创建自己的接入点
在中配置 App/main.c 通过修改WiFi初始化代码。
用法
启动服务器
- W600板上的电源
- 设备将使用配置的凭据连接到WiFi
- 监视分配的IP地址的串行输出
- MCP服务器在端口80上自动启动
访问MCP服务器
MCP服务器在以下位置接受JSON-RPC 2.0请求:
http://{device_ip}/mcpMCP请求示例
获取系统状态
curl -X POST http://192.168.1.100/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "status"
},
"id": 1
}'响应包括:IP地址、正常运行时间、可用内存、WiFi RSSI和ELM327状态。
发送ELM327命令
curl -X POST http://192.168.1.100/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "send_elm327_command",
"arguments": {
"command": "01 0C"
}
},
"id": 2
}'获取车辆速度
curl -X POST http://192.168.1.100/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "send_elm327_command",
"arguments": {
"command": "01 0D"
}
},
"id": 3
}'读取故障诊断码
curl -X POST http://192.168.1.100/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "send_elm327_command",
"arguments": {
"command": "03"
}
},
"id": 4
}'获取历史OBD-II数据
curl -X POST http://192.168.1.100/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "get_elm327_history",
"arguments": {
"count": 50
}
},
"id": 5
}'返回RPM、速度和冷却液温度的历史日志。省略 count 或者对所有记录设置为0。
项目结构
W600-embedded-OBD2/
├── App/
│ ├── main.c # Main application entry point
│ ├── wm_app_config.h # Application configuration
│ └── wifi_credentials.h.template # WiFi credentials template
│
├── Src/App/
│ ├── easylogger/ # Logging library
│ │ ├── inc/ # Header files
│ │ ├── port/ # W600 port implementation
│ │ └── src/ # Logger source code
│ │
│ ├── elm327/ # ELM327 OBD-II driver
│ │ ├── elm327.c # Main driver with simulation
│ │ ├── elm327_sim.c # OBD-II simulator
│ │ ├── elm327_sim.h # Simulator header
│ │ ├── elm327_history.c # Command history
│ │ └── README_SIMULATION.md # Simulation documentation
│ │
│ └── mcp/ # MCP server implementation
│ ├── mcp_server.c # Main server logic
│ ├── mcp_http.c # HTTP request handling
│ ├── mcp_jsonrpc.c # JSON-RPC protocol
│ ├── mcp_methods.c # MCP method handlers
│ ├── mcp_tools.c # MCP tool definitions
│ └── mcp_stream.c # Stream utilities
│
├── LICENSE
└── README.md # This file可用的MCP工具
服务器公开了以下MCP工具:
1. status
获取系统状态信息,包括网络、硬件和ELM327状态。
- 参数:无
- 退货:JSON对象,具有:
- ip_address -设备IP地址 - uptime_seconds -系统正常运行时间(秒) - free_memory_bytes -可用堆内存 - wifi_rssi_dbm -WiFi信号强度(dBm) - elm327_status -ELM327连接状态
2. send_elm327_command
向ELM327 OBD-II适配器发送命令并接收响应。
- 参数:
- command (字符串,必填)-要发送的ELM327命令(例如,“ATZ”、“01 0C”、“03”)
- 退货:来自ELM327适配器的文本响应
- 示例命令:
- "ATZ" -重置ELM327 - "01 0C" -获取发动机转速 - "01 0D" -获取车辆速度 - "03" -读取存储的DTC
3. get_elm327_history
使用流支持检索OBD-II数据(RPM、速度、冷却液温度)的历史日志。
- 参数:
- count (number,可选)-要检索的最新记录数 - 默认值:100 - 对所有可用记录设置为0
- 退货:历史数据条目数组,每个条目包含:
- seq -序列号 - time -时间戳(秒) - rpm -发动机转速 - speed -车速(km/h) - coolant_temp -冷却液温度(°C)
备注:此工具使用流式传输来高效处理大型数据集。
添加自定义工具
可以通过以下方式添加其他工具:
- 在中定义工具处理程序
Src/App/mcp/mcp_tools.c - 将工具定义添加到
tools[]数组 - 重建并刷新固件
发展
添加新的MCP工具
- 在中定义工具架构
Src/App/mcp/mcp_tools.c - 在中实现处理程序
Src/App/mcp/mcp_methods.c - 在方法调度表中注册方法
- 重建和闪存固件
调试
串行调试输出的波特率为115200。使用串行终端查看日志:
# Linux/Mac
screen /dev/ttyUSB0 115200
# Windows
putty -serial COM3 -sercfg 115200,8,n,1,NOTA更新
要执行OTA固件更新:
- 构建新固件
- 主机
.fls固件服务器上的文件 - 配置
FIRMWARE_SERVER和FIRMWARE_FILENAME在wm_app_config.h - 设备将在启动时检查更新
- 如果可用,固件将自动下载并应用
支持的OBD-II PID
使用模拟器或真实ELM327时,支持以下PID:
模式01(当前数据)
01 0C-发动机转速01 0D-车辆速度01 05-发动机冷却液温度01 04-计算发动机负载01 0F-进气温度- 还有更多(请参阅模拟文档)
模式03
03-读取存储的故障诊断码
模式04
04-清除故障诊断码
模式07
07-读取待处理的故障诊断码
模式09(车辆信息)
09 02-车辆识别码(VIN)09 04-校准ID09 0A-ECU名称
有关完整的PID列表,请参阅 Src/App/elm327/README_SIMULATION.md.
故障排除
WiFi连接问题
- 在中验证WiFi凭据
wifi_credentials.h - 检查串行输出的连接状态
- 确保WiFi网络为2.4GHz(W600不支持5GHz)
ELM327通信问题
- 检查UART接线(TX、RX、GND)
- 验证波特率配置(默认9600或38400)
- 启用无硬件测试的模拟模式
MCP服务器没有响应
- 从串行输出验证设备IP地址
- 检查防火墙设置
- 确保HTTP端口80可访问
许可证
此项目根据MIT许可证获得许可-有关详细信息,请参阅许可证文件。
贡献
欢迎投稿!请随时提交问题或拉取请求。
参考文献
- 模型上下文协议(MCP)规范
- ELM327命令参考
- OBD-II PID
- W600 SDK文档
