关于 ESP32 MCP Server
ESP32 MCP Server 运行在 ESP32 上(nRF52840 为仅传感器模式),通过 WebSocket 和 JSON-RPC 2.0 向 AI 助手暴露传感器数据与总线协议解析结果。适合希望让 AI Agent 直接读取硬件的嵌入式与船用、车载数据场景。
主要功能
- 01基于 WebSocket 的 JSON-RPC 2.0 MCP 接口
- 02I2C 传感器自动扫描与多种驱动
- 03解析 NMEA 0183 数据并校验 XOR 校验和
- 04解码 NMEA 2000 与 OBD-II CAN 报文
- 05总线历史环形缓冲区,可通过 MCP 查询
适用场景
- 01让 AI Agent 读取 I2C 温湿度与气压传感器
- 02解析 GPS 或海图仪输出的 NMEA 0183 数据
- 03查询车辆 OBD-II 参数与 CAN 总线历史记录
MCP 相关
该项目是 MCP 服务,在 ESP32 上通过 WebSocket 提供 resources 与传感器、总线相关方法,供 MCP 客户端调用和订阅。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
ESP32 MCP 服务
一个运行于 ESP32(以及传感器专用模式下的 Nordic nRF52840)的模型上下文协议(MCP)服务,通过 WebSocket / JSON-RPC 2.0 向 AI 助手和自动化工具提供真实世界的传感器数据与总线协议。
将 AI Agent 直接连接到你的硬件:查询 I2C 传感器、解析 NMEA 0183 GPS/船用数据、解码 NMEA 2000 和 OBD-II CAN 帧、重放总线历史记录——这一切都通过标准 MCP 接口完成。

功能
| 能力 | 详情 |
|---|---|
| MCP 协议 | 通过 WebSocket 使用 JSON-RPC 2.0,支持资源发现与订阅 |
| I2C 传感器 | 自动扫描 + BME280、MPU6050、ADS1115、SHT31、BH1750、INA219 驱动 |
| NMEA 0183 | GGA、RMC、VTG、GSV、MWV、DBT、DPT、HDG、HDT,支持 XOR 校验和验证 |
| NMEA 2000 / CAN | 29 位 PGN:位置、航向、速度、深度、风、姿态、水温 |
| OBD-II / CAN | 标准 11 位 OBD-II 服务 01/09 PID 解码(60+ 个 PID) |
| 总线历史记录 | CAN、NMEA、NMEA 2000、OBD-II 的持久化环形缓冲区,可通过 MCP 查询 |
| 总线读取器 | 按时间限制读取串行数据和 CAN 数据,支持原始或解析模式,并输出 JSON |
| WiFi | AP 设置界面 + STA 模式;凭据存储于 NVS |
| 发现 | mDNS(_mcp._tcp)+ UDP 能力广播 |
| 指标 | 堆内存、运行时间、RSSI、直方图统计,并在重启后持久保存 |
| 多开发板支持 | ESP32-S3、ESP32-C3、ESP32、Adafruit HUZZAH32、M5Stack、Nordic nRF52840-DK、Adafruit Feather nRF52840 |
| 测试 | 原生单元测试(Unity),模拟 I2C / CAN / Serial / LittleFS |
支持的开发板
ESP32 开发板 — 完整 MCP 服务(WiFi + WebSocket + CAN)
| 开发板 | PlatformIO env | MCU | 闪存 | RAM | WiFi | BLE | CAN | RGB LED |
|---|---|---|---|---|---|---|---|---|
| ESP32-S3-DevKitC-1 | esp32-s3-devkitc-1 | Xtensa LX7 × 2 @ 240 MHz | 8 MB | 512 KB + 8 MB PSRAM | ✓ | 5.0 | ✓ | GPIO48 |
| ESP32-DevKitC V4 | esp32-devkitc | Xtensa LX6 × 2 @ 240 MHz | 4 MB | 520 KB | ✓ | 4.2 | ✓ | — |
| ESP32-C3-DevKitM-1 | esp32-c3-devkitm-1 | RISC-V @ 160 MHz | 4 MB | 400 KB | ✓ | 5.0 | ✓ | GPIO8 |
| Adafruit HUZZAH32 | adafruit-huzzah32 | Xtensa LX6 × 2 @ 240 MHz | 4 MB | 520 KB | ✓ | 4.2 | ✓ | — |
| M5Stack Core ESP32 | m5stack-core | Xtensa LX6 × 2 @ 240 MHz | 16 MB | 520 KB | ✓ | 4.2 | ✗ | — |
nRF52840 开发板 — 仅传感器(I2C + 串行,无 WiFi)
| 开发板 | PlatformIO env | MCU | 闪存 | RAM | BLE |
|---|---|---|---|---|---|
| Nordic nRF52840-DK | nrf52840-dk | Cortex-M4F @ 64 MHz | 1 MB | 256 KB | 5.0 + 802.15.4 |
| Adafruit Feather nRF52840 | nrf52840-feather | Cortex-M4F @ 64 MHz | 1 MB | 256 KB | 5.0 |
nRF52840 目标使用独立的
main_nrf.cpp入口点:仅支持传感器、I2C 和串行输出。不支持 WiFi、MCP WebSocket、LittleFS 或总线历史记录。要通过 WiFi 使用完整 MCP,可将处于 AT 命令模式的 ESP32-C3 连接到 UART1 作为桥接设备。
开发板功能矩阵
| 功能 | ESP32-S3 | ESP32 V4 | ESP32-C3 | HUZZAH32 | M5Stack | nRF52840-DK | nRF52840-Feather |
|---|---|---|---|---|---|---|---|
| WiFi | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ |
| BLE | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| CAN / TWAI | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ |
| I2C | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| UART (ext) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| LittleFS | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ |
| MCP 服务 | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ |
| 总线历史记录 | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ |
| mDNS / UDP 发现 | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ |
架构
flowchart TD
Client[AI Agent / MCP Client] -->|WebSocket :9000 JSON-RPC 2.0| MCPServer
subgraph ESP32
MCPServer -->|resources/list| Resources
MCPServer -->|sensors/i2c/scan| SensorMgr
MCPServer -->|sensors/read| SensorMgr
MCPServer -->|buses/serial/read| BusReader
MCPServer -->|buses/can/read| BusReader
MCPServer -->|bus/history/read| BusHistory
MCPServer -->|bus/history/config/*| BusHistory
SensorMgr -->|Wire I2C| I2CSensors[BME280 · MPU6050 · ADS1115\nSHT31 · BH1750 · INA219]
BusReader -->|UART| NMEAParser[NMEA 0183 Parser]
BusReader -->|CAN TWAI| CANParser[NMEA 2000 / OBD-II Parser]
BusReader -->|feed| BusHistory[Bus History\nRing Buffers]
BusHistory --> LittleFS
NetworkMgr[Network Manager] --> WiFi
NetworkMgr --> WebSetup[Setup UI :80]
DiscoveryMgr[Discovery Manager] -->|mDNS + UDP| Network
Metrics[Metrics System] --> LittleFS
uLogger --> LittleFS
end
MCPServer --> Metrics
MCPServer --> uLogger
硬件
引脚分配(ESP32-S3-DevKitC-1)
| GPIO | 功能 | 连接到 |
|---|---|---|
| IO8 | I2C SDA | 所有 I2C 传感器 |
| IO9 | I2C SCL | 所有 I2C 传感器 |
| IO16 | UART1 RX | GPS / 海图仪 TX |
| IO17 | UART1 TX | GPS / 海图仪 RX(可选) |
| IO4 | CAN RX | TJA1050 / SN65HVD230 CRXD |
| IO5 | CAN TX | TJA1050 / SN65HVD230 CTXD |
nRF52840-DK 引脚分配
| 引脚 | 功能 |
|---|---|
| P0.26 / D6 | I2C SDA |
| P0.27 / D7 | I2C SCL |
| P0.06 / TX | UART1 TX |
| P0.08 / RX | UART1 RX |
物料清单
| # | 部件 | 用途 |
|---|---|---|
| 1 | ESP32-S3-DevKitC-1 | 主 MCU |
| 1 | BME280 breakout | 温度 / 湿度 / 气压 |
| 1 | MPU6050 breakout | 6 轴 IMU(可选) |
| 1 | TJA1050 或 SN65HVD230 | CAN 总线收发器(可选) |
| 1 | GPS 模块(3.3 V UART) | NMEA 0183 位置 / 时间(可选) |
| 2 | 4.7 kΩ 电阻 | I2C 上拉电阻 |
| — | 面包板 + 跳线 |
ESP32-S3-DevKitC-1 接线
┌──────────────────────────────────────┐
│ ESP32-S3-DevKitC-1 │
│ │
3V3 ───┤ 3V3 GND ├─── GND
GND ───┤ GND IO0 ├
│ │
I2C SDA ── IO8 ───┤ IO8 ┌──────────┐ IO17 ├─── UART1 TX → GPS
I2C SCL ── IO9 ───┤ IO9 │ ESP32 │ IO16 ├─── UART1 RX ← GPS
│ IO10 │ S3 │ IO15 ├
│ IO11 └──────────┘ IO14 ├
│ IO12 IO13 ├
│ IO3 IO4 ├─── CAN RX ← TJA1050
│ IO46 IO5 ├─── CAN TX → TJA1050
│ │
│ USB (flash / serial log) │
└───────────────────────────────┘
I2C 传感器接线
所有传感器共用一条总线。添加 4.7 kΩ 上拉电阻,将 SDA 和 SCL 接至 3V3。
ESP32-S3 BME280 MPU6050 ADS1115 INA219
───────── ─────── ─────── ─────── ───────
IO8 (SDA)─────SDA──────────SDA──────────SDA──────────SDA
IO9 (SCL)─────SCL──────────SCL──────────SCL──────────SCL
3V3 ──────────VCC──────────VCC──────────VCC──────────VCC
GND ──────────GND──────────GND──────────GND──────────GND
SDO→GND AD0→GND ADDR→GND
(0x76) (0x68) (0x48) (0x40)
其他支持的传感器(接线方式相同):SHT31(0x44)、BH1750(0x23)。
NMEA 0183 接线(GPS / 海图仪)
GPS / chart plotter ESP32-S3
─────────────────── ────────
TX (3.3 V TTL NMEA out) ─────── IO16 (UART1 RX)
RX (optional NMEA in) ─────── IO17 (UART1 TX)
GND ─────── GND
VCC (3.3 V) ─────── 3V3
如果设备输出 RS-232 电平,请使用 MAX3232 电平转换器。切勿将 RS-232 直接连接到 ESP32 GPIO。
CAN 总线接线(NMEA 2000 / OBD-II)
TJA1050 / SN65HVD230 ESP32-S3
──────────────────── ────────
CTXD ─────────── IO5 (CAN TX)
CRXD ─────────── IO4 (CAN RX)
VCC (5 V for TJA1050) ─────────── VIN / external 5 V
GND ─────────── GND
CANH ──────────────── NMEA 2000 backbone / OBD-II CANH
CANL ──────────────── NMEA 2000 backbone / OBD-II CANL
NMEA 2000 的速率为 250 kbps。OBD-II 的速率为 500 kbps。请在
CANBusReader配置中相应设置波特率。
软件先决条件
- PlatformIO Core CLI 或适用于 VS Code 的 PlatformIO IDE 插件
- Python 3.8+
- Git
pip install platformio
构建与烧录
# 1. Clone
git clone https://github.com/navado/ESP32MCPServer.git
cd ESP32MCPServer
# 2. Install library dependencies
pio pkg install
# 3. Upload web assets to LittleFS (optional but recommended)
pio run -t uploadfs -e esp32-s3-devkitc-1
# 4. Build firmware
pio run -e esp32-s3-devkitc-1
# 5. Flash
pio run -t upload -e esp32-s3-devkitc-1
# 6. Monitor
pio device monitor --baud 115200
nRF52840
pio run -e nrf52840-dk
pio run -t upload -e nrf52840-dk
首次运行
- 为开发板上电。它会广播一个 WiFi AP:
ESP32_XXXXXX(MAC 地址最后 6 位十六进制数字)。 - 连接到该 AP 并打开
http://192.168.4.1。 - 输入 WiFi 凭据,然后点击 Save。
- 开发板会加入网络,并在串口控制台输出其 IP 地址。
- 将 MCP 客户端连接到
ws://<IP>:9000。
Web 仪表板
基于浏览器的仪表板从闪存提供,地址为 http://<IP>/app。
| 标签页 | 功能 |
|---|---|
| 传感器 | 扫描 I²C 总线,显示检测到的设备,读取数值并自动刷新 |
| 指标 | 列出所有指标、实时数值和迷你趋势历史图表 |
| 日志 | 查询并清除指标日志条目 |
| MCP 控制台 | 交互式 JSON-RPC 控制台,提供预设请求和实时消息日志 |
HTTP 端点(端口 80)
| 方法 | 路径 | 描述 |
|---|---|---|
| GET | / | WiFi 设置页面 |
| POST | /save | 保存 WiFi 凭据(ssid、password 表单参数) |
| GET | /status | 网络状态 JSON |
| WS | /ws | 实时网络状态 WebSocket |
| GET | /app | 浏览器仪表板 |
| GET | /bus-history | 读取总线历史配置 JSON |
| POST | /bus-history | 更新总线历史配置 JSON |
MCP API 参考(WebSocket 端口 9000)
所有方法均通过 WebSocket 使用 JSON-RPC 2.0。
协议
| 方法 | 参数 | 描述 |
|---|---|---|
initialize | — | 服务信息、协议版本、功能 |
resources/list | — | 列出已注册的 MCP 资源 |
resources/read | uri | 按 URI 读取资源 |
resources/subscribe | uri | 订阅资源的推送更新 |
resources/unsubscribe | uri | 取消订阅 |
传感器
| 方法 | 参数 | 描述 |
|---|---|---|
sensors/i2c/scan | — | 扫描 I²C 总线;自动检测并初始化驱动程序 |
sensors/read | sensorId? | 读取一个传感器的所有通道(省略 ID 则读取全部) |
sensors/i2c/scan
{"jsonrpc":"2.0","method":"sensors/i2c/scan","id":1}
{
"jsonrpc":"2.0","id":1,
"result":{"devices":[
{"address":118,"name":"BME280","supported":true,"parameters":["temperature","pressure","humidity"]},
{"address":104,"name":"MPU6050","supported":true,"parameters":["accel_x","accel_y","accel_z","gyro_x","gyro_y","gyro_z","temperature"]}
]}
}
sensors/read
{"jsonrpc":"2.0","method":"sensors/read","id":2,"params":{"sensorId":"bme280_0x76"}}
{
"jsonrpc":"2.0","id":2,
"result":{"readings":[
{"sensorId":"bme280_0x76","parameter":"temperature","value":22.4,"unit":"°C","timestamp":1234567890,"valid":true},
{"sensorId":"bme280_0x76","parameter":"humidity","value":58.1,"unit":"%RH","timestamp":1234567890,"valid":true},
{"sensorId":"bme280_0x76","parameter":"pressure","value":101320.0,"unit":"Pa","timestamp":1234567890,"valid":true}
]}
}
总线历史记录
总线历史记录会将 CAN 帧、NMEA 行、已解码的 NMEA 2000 消息和 OBD-II 记录累积到循环 RAM 缓冲区中。缓冲区大小根据可配置的 RAM 预算确定,其配置会持久化到 LittleFS。
| 方法 | 参数 | 描述 |
|---|---|---|
bus/history/read | type、limit? | 从历史缓冲区读取累积的消息 |
bus/history/config/get | — | 读取当前的缓冲区大小配置 |
bus/history/config/set | 配置字段 | 调整缓冲区大小并持久化配置 |
bus/history/read
type 必须为以下值之一:can、nmea、nmea2000、obdii。limit 默认为读取所有已存储条目。
{"jsonrpc":"2.0","method":"bus/history/read","id":3,"params":{"type":"can","limit":10}}
{
"jsonrpc":"2.0","id":3,
"result":{
"type":"can",
"frames":["7E8#0441050300000000","7E8#04410D0000000000"],
"count":2,
"capacity":500
}
}
{"jsonrpc":"2.0","method":"bus/history/read","id":4,"params":{"type":"nmea2000"}}
{
"jsonrpc":"2.0","id":4,
"result":{
"type":"nmea2000",
"messages":[
{"pgn":129025,"priority":2,"source":0,"name":"Position Rapid Update",
"valid":true,"hasPosition":true,"latitude":47.6097,"longitude":-122.3331}
],
"count":1,"capacity":200
}
}
{"jsonrpc":"2.0","method":"bus/history/read","id":5,"params":{"type":"obdii"}}
{
"jsonrpc":"2.0","id":5,
"result":{
"type":"obdii",
"records":[
{"service":1,"pid":12,"name":"Engine RPM","value":1500,"unit":"rpm","valid":true},
{"service":1,"pid":13,"name":"Vehicle Speed","value":65,"unit":"km/h","valid":true}
],
"count":2,"capacity":300
}
}
bus/history/config/get
{"jsonrpc":"2.0","method":"bus/history/config/get","id":6}
{
"jsonrpc":"2.0","id":6,
"result":{
"canFrameCount":500,
"nmeaLineCount":1000,
"nmea2000Count":200,
"obdiiCount":300,
"ramBudgetBytes":1048576,
"safetyMarginBytes":65536,
"freeHeapBytes":2097152
}
}
bus/history/config/set
所有字段均为可选;未提供的字段将保留当前值。
{
"jsonrpc":"2.0","method":"bus/history/config/set","id":7,
"params":{"canFrameCount":1000,"ramBudgetBytes":2097152}
}
{"jsonrpc":"2.0","id":7,"result":{"ok":true,"canFrameCount":1000,"nmeaLineCount":1000,"nmea2000Count":200,"obdiiCount":300,"ramBudgetBytes":2097152,"safetyMarginBytes":65536}}
将
canFrameCount、nmeaLineCount、nmea2000Count、obdiiCount全部设为0,即可启用自动调整大小:服务会根据每种记录类型的大小,将ramBudgetBytes平均分配给四种缓冲区类型。
指标
| 方法 | 参数 | 描述 |
|---|---|---|
metrics/list | category? | 列出所有已注册的指标(名称、类型、单位、类别) |
metrics/get | name | 获取单个指标的当前值 |
metrics/history | name、seconds? | 获取单个指标的历史样本(默认:最近 300 s) |
metrics/list
{"jsonrpc":"2.0","method":"metrics/list","id":8,"params":{"category":"system"}}
{
"jsonrpc":"2.0","id":8,
"result":{"metrics":[
{"name":"system.heap.free","type":"gauge","description":"Free heap","unit":"bytes","category":"system"},
{"name":"system.uptime","type":"counter","description":"Uptime","unit":"s","category":"system"},
{"name":"system.wifi.rssi","type":"gauge","description":"WiFi signal strength","unit":"dBm","category":"system"}
]}
}
指标类型:counter(累积整数)、gauge(当前值)、histogram(包含最小值、最大值、平均值和计数的对象)。
metrics/get
{"jsonrpc":"2.0","method":"metrics/get","id":9,"params":{"name":"system.heap.free"}}
{
"jsonrpc":"2.0","id":9,
"result":{"name":"system.heap.free","type":"gauge","value":214032,"unit":"bytes","category":"system","timestamp":1234567890}
}
对于直方图指标,value 是一个对象:{"mean":…,"min":…,"max":…,"count":…}。
metrics/history
{"jsonrpc":"2.0","method":"metrics/history","id":10,"params":{"name":"system.heap.free","seconds":60}}
{
"jsonrpc":"2.0","id":10,
"result":{"name":"system.heap.free","entries":[
{"ts":1234567800,"val":214100},
{"ts":1234567830,"val":214032}
]}
}
日志
| 方法 | 参数 | 描述 |
|---|---|---|
logs/query | name?、seconds? | 查询二进制指标日志(默认:最近 3600 s) |
logs/clear | — | 从 LittleFS 删除所有日志条目 |
{"jsonrpc":"2.0","method":"logs/query","id":11,"params":{"name":"system.heap.free","seconds":120}}
{
"jsonrpc":"2.0","id":11,
"result":{"name":"system.heap.free","count":4,"entries":[
{"ts":1234567810,"val":214100},
{"ts":1234567840,"val":214032}
]}
}
{"jsonrpc":"2.0","method":"logs/clear","id":12}
{"jsonrpc":"2.0","id":12,"result":{"ok":true}}
订阅
{"jsonrpc":"2.0","method":"resources/subscribe","id":13,"params":{"uri":"sensor://i2c/bme280_0x76"}}
订阅后,每当值发生变化,服务都会主动推送 notifications/resources/updated 通知:
{"jsonrpc":"2.0","method":"notifications/resources/updated","params":{"uri":"sensor://i2c/bme280_0x76"}}
TypeScript 客户端示例
完整的类型化客户端请参见 examples/client/client.ts。
I2C 传感器参考
| 传感器 | 地址 | 参数 | 单位 |
|---|---|---|---|
| BME280 / BMP280 | 0x76、0x77 | temperature、pressure、humidity¹ | °C、Pa、%RH |
| MPU6050 | 0x68、0x69 | accel_x/y/z、gyro_x/y/z、temperature | g、°/s、°C |
| ADS1115 | 0x48–0x4B | ch0_V、ch1_V、ch2_V、ch3_V | V(±4.096 范围) |
| SHT31 | 0x44、0x45 | temperature、humidity | °C、%RH |
| BH1750 | 0x23、0x5C | light_lux | lux |
| INA219 | 0x40–0x4F | bus_voltage_V、shunt_mV、current_mA、power_mW | V、mV、mA、mW |
¹ BMP280 不提供 humidity。
支持的 NMEA 0183 语句
| 语句 | 描述 | 解码字段 |
|---|---|---|
| GGA | GPS 定位数据 | 时间、纬度、经度、定位质量、卫星数、HDOP、海拔、地球椭球面与大地水准面的高差 |
| RMC | 推荐最小导航信息 | 时间、活动状态、纬度、经度、速度(kn 和 km/h)、航向、磁偏角 |
| VTG | 对地航迹 / 地速 | 航向(真北和磁北)、速度(kn 和 km/h) |
| GSV | 可见卫星 | 卫星总数、各卫星的 PRN、仰角、方位角、SNR |
| MWV | 风速和风向角 | 角度、相对/真风、速度、单位(K/M/N) |
| DBT | 换能器下方水深 | 深度(英尺 / 米 / 英寻) |
| DPT | 水深 | 深度(米) |
| HDG | 航向——偏差与磁偏角 | 航向、偏差、磁偏角(E/W) |
| HDT | 航向——真北 | 航向(真北) |
解析功能:XOR 校验和验证、DDMM.MMMM → 有符号十进制度数、HHMMSS.SS 时间、提取 talker ID、妥善处理空字段。
支持的 NMEA 2000 PGN
| PGN | 名称 | 关键字段 |
|---|---|---|
| 127250 | 船艏向 | heading, variation |
| 127257 | 姿态 | pitch, roll, yaw |
| 128259 | 对水速度 | speedKnots |
| 128267 | 水深 | depthMetres, offset |
| 129025 | 位置快速更新 | latitude, longitude |
| 129026 | 对地航向和对地速度 | courseOverGround, speedOverGround |
| 130306 | 风数据 | speedKnots, angle, 表观风/真风标志 |
| 130310 | 水温 | tempCelsius |
支持的 OBD-II PID(服务 01)
已解码所选 PID;完整列表见 src/CANParser.cpp:
| 类别 | PID |
|---|---|
| 发动机 | 转速、负荷、冷却液温度、进气温度、MAP、MAF、点火提前角 |
| 燃油 | 燃油压力、燃油修正(短期/长期)、油轨压力、喷油正时、燃油流量 |
| 排放 | O2 传感器电压、EGR、蒸发排放系统、DPF 压力 |
| 运动 | 车速、节气门位置、加速踏板位置 |
| 温度 | 机油温度、进气温度、EGR 温度、发动机排气温度(EGT) |
| 电气 | 控制模块电压、电池电压 |
| 混合动力 | 混合动力电池剩余寿命 |
| 扭矩 | 驾驶员需求扭矩、实际扭矩、参考扭矩 |
| 车辆信息 | VIN、校准 ID(服务 09) |
发现
连接网络后,服务会注册两个 mDNS 服务,并定期发送 UDP 能力信标:
| 发现方式 | 详情 |
|---|---|
| mDNS | _mcp._tcp 和 _http._tcp,包含 TXT 记录:版本、能力、检测到的传感器 |
| UDP 广播 | 每 30 秒向 255.255.255.255:5354 发送 JSON 信标(可配置);包含传感器清单 |
加入网络、I2C 扫描完成、MCP 服务就绪以及总线历史记录配置变更时,都会自动触发 mDNS 和 UDP。
测试
测试可在 Linux 上原生编译和运行,无需硬件。
# All tests
pio test -e native
# Specific suites
pio test -e native -f test_nmea_parser
pio test -e native -f test_can_parser
pio test -e native -f test_i2c_sensors
pio test -e native -f test_bus_reader
pio test -e native -f test_mcp_server
pio test -e native -f test_metrics_system
# With coverage (requires lcov)
pio test -e native --coverage
| 测试套件 | 覆盖内容 |
|---|---|
test_nmea_parser | GGA、RMC、VTG、GSV、MWV、DBT、DPT、HDG、HDT、校验和验证 |
test_can_parser | OBD-II PID、NMEA 2000 PGN 127250/127257/128259/128267/129025/129026/130306/130310 |
test_i2c_sensors | 通过模拟 I2C 测试 BME280、MPU6050、ADS1115、SHT31、BH1750、INA219 |
test_bus_reader | 定时读取、原始/解析模式、超时处理 |
test_mcp_server | JSON-RPC 分发、资源管理、方法注册 |
test_metrics_system | 计数器、仪表、直方图、LittleFS 持久化 |
使用自定义 MCP 方法扩展
在运行时注册其他 JSON-RPC 处理程序:
mcpServer.registerMethodHandler("myns/doSomething",
[](uint8_t clientId, uint32_t reqId, const JsonObject& params) {
StaticJsonDocument<256> doc;
doc["result"]["ok"] = true;
std::string out;
serializeJson(doc, out);
return out;
});
// Remove when no longer needed
mcpServer.unregisterMethodHandler("myns/doSomething");
贡献
- Fork 此仓库
- 创建功能分支:
git checkout -b feature/my-feature - 为新功能添加测试(
pio test -e native必须通过) - 提交拉取请求
编码风格和指南请参阅 CONTRIBUTING.md。
许可证
MIT — 详见 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。