- Mark Ren
-
2025年11月19日 -
下午5:10 -
0 评论
为什么选择 Node-RED + Modbus Server + MQTT?
在工业物联网(IIoT)场景中,Modbus TCP 依然是最常见、最可靠的设备通信协议之一。大量 PLC、电表、传感器都依赖 Modbus 进行参数读取或状态上报。然而,传统工控软件通常封闭、难以扩展,不便与现代 MQTT、云平台或自研平台(例如 ZedIoT)对接。
Node-RED 则具备如下天然优势:

- 支持 Modbus、MQTT、HTTP 等常见协议
- 可视化流程,搭建网关无需编写大量代码
- 插件生态丰富,可扩展规则引擎、数据清洗、联动逻辑
- 跨平台运行,适合 Linux 服务器、树莓派、Docker 环境
因此,“Node-RED + Modbus Server + MQTT” 是一种非常轻量、灵活、可移植的网关方案,适合工业设备数据接入平台端。
整体架构设计
设备多数作为 Modbus Client(主站) 主动连接网关,而网关(Node-RED)作为 Modbus Server(从站) 监听端口并提供寄存器空间。
随后,Node-RED 再通过 Modbus Client 节点轮询自身的这个 Server,获得写入后的寄存器数据,并按规则转发到 MQTT Broker(如 EMQX、Mosquitto、ZedIoT MQTT 等)。
架构流程如下:
系统架构图
符合你要求的 Mermaid 语法:
--- title: "Node-RED Modbus Server → MQTT 多层数据流架构" --- graph TD %% ===== 样式定义 ===== classDef field fill:#FFEED6,stroke:#E67E22,stroke-width:2,rx:10,ry:10,color:#6E2C00,font-weight:bold; classDef nodered fill:#E3F2FD,stroke:#1976D2,stroke-width:2,rx:10,ry:10,color:#0D47A1,font-weight:bold; classDef logic fill:#F3E5F5,stroke:#8E24AA,stroke-width:2,rx:10,ry:10,color:#4A148C,font-weight:bold; classDef mqtt fill:#E2F7E2,stroke:#2E7D32,stroke-width:2,rx:10,ry:10,color:#1B5E20,font-weight:bold; classDef cloud fill:#FFF4C2,stroke:#F4A300,stroke-width:2,rx:10,ry:10,color:#5D4037,font-weight:bold; classDef note fill:#FFF9E6,stroke:#E6A700,stroke-width:1.5,rx:8,ry:8,color:#5D3B00; linkStyle default stroke:#555,stroke-width:1.5; %% ===== Layer 1:现场 Modbus 设备层(多个设备) ===== subgraph L1["① 现场设备层(Modbus TCP Clients)"] direction LR A1["🏭 PLC / 控制柜<br/>Modbus TCP Client #1"]:::field A2["⚙️ 变频器 / 电机驱动<br/>Modbus TCP Client #2"]:::field A3["🌡️ 温度/压力传感器网关<br/>Modbus TCP Client #3"]:::field end %% ===== Layer 2:Node-RED Modbus 接入层(多个节点) ===== subgraph L2["② Node-RED Modbus 接入层"] direction TB B1["🖧 Modbus Server (TCP 1502)<br/>统一寄存器入口"]:::nodered B2["📘 Modbus Read Client<br/>周期轮询寄存器"]:::nodered B3["✏️ Modbus Write Client<br/>下发控制命令 (可选)"]:::nodered end %% ===== Layer 3:Node-RED 规则与处理层(多个 Flow) ===== subgraph L3["③ Node-RED 规则引擎与数据处理"] direction LR D1["⚙️ Function:解析寄存器<br/>单位换算 / 字段映射"]:::logic D2["🚨 Function:告警规则<br/>阈值判断 / 状态机"]:::logic D3["📊 Node-RED Dashboard<br/>本地监控大屏"]:::logic end %% ===== Layer 4:MQTT 与云平台层(多个消费者) ===== subgraph L4["④ MQTT / 云平台层"] direction LR E1["☁️ MQTT Broker<br/>ZedIoT / Mosquitto"]:::mqtt E2["📈 ZedAIoT 云平台<br/>时序存储 / AI 分析"]:::cloud E3["🔧 其他订阅者<br/>如 InfluxDB / Node-RED 其他 Flow"]:::mqtt end %% ===== 现场 → Node-RED Modbus 流 ===== A1 -->|"读/写寄存器"| B1 A2 -->|"读/写寄存器"| B1 A3 -->|"读/写寄存器"| B1 B1 -->|"寄存器缓存 / Holding Registers"| B2 B1 -->|"控制命令写入 (可选)"| B3 %% ===== Node-RED 内部处理流 ===== B2 -->|"原始寄存器值"| D1 D1 -->|"结构化数据 (JSON)"| D2 D1 -->|"实时数据"| D3 D2 -->|"Telemetry / Alert 消息"| E1 %% ===== MQTT / 云端分发 ===== E1 -->|"Topic: factory/+/telemetry"| E2 E1 -->|"Topic: factory/+/alert"| E3
关键原理解析
1. 工业设备如何写入 Node-RED?
在 Modbus 协议里,设备无法“主动上传”,而是通过对 Server 的写寄存器操作实现数据上报,例如:
- FC06:写单个保持寄存器
- FC16:写多个保持寄存器
Node-RED 的 modbus-server 节点会将这些写入操作记录到内部寄存器缓冲区。
2. 为什么需要 Node-RED 自己再做 Modbus Read?
modbus-server 节点 不会主动输出消息。
因此,如果想获取最新寄存器内容,需要使用:
- modbus-read
- 或 modbus-flex-getter
去轮询这个 Server。
这是 Node-RED 搭建 Modbus 网关的关键设计点。
3. 如何把寄存器数据转为 MQTT?
在 function 节点中解析 Modbus 数据,映射为业务字段,例如:
msg.topic = "iot/device001/telemetry";
msg.payload = {
temperature: msg.payload[0] / 10,
humidity: msg.payload[1] / 10,
ts: Date.now()
};
return msg;然后传给 mqtt out 发往平台。
在服务器上通过 Docker 部署 Node-RED
为了让网关稳定运行并具备可持续扩展能力,推荐使用 Docker 方式部署 Node-RED。Docker 提供独立运行环境,避免依赖冲突,并支持快速迁移和升级。
以下是最小可用的 Node-RED Docker 启动命令:
docker run -d \
--name nodered-modbus \
-p 1880:1880 \
-p 1502:1502 \
-v /opt/nodered_data:/data \
-e TZ=Asia/Shanghai \
nodered/node-red:latest参数说明
| 参数 | 含义 |
|---|---|
| 1880:1880 | Node-RED Web 编辑器端口 |
| 1502:1502 | 对外开放 Modbus Server 端口 |
| /opt/nodered_data:/data | 持久化 Flow、配置、安装的插件 |
| TZ | 指定服务器时区,方便日志统一管理 |
部署完成后访问:
http://服务器IP:1880即可看到 Node-RED 的可视化管理界面。
安装 Modbus 与 MQTT 节点
进入 Node-RED 编辑器:
- 右上角菜单 → Manage palette
- 选择 Install
- 搜索并安装:
- node-red-contrib-modbus
- MQTT 节点(若未自带):node-red-node-mqtt
安装完成后,你即可在左侧节点栏看到:
- Modbus 类节点:modbus-server, modbus-read, modbus-write, modbus-flex-getter
- MQTT 类节点:mqtt in, mqtt out
搭建 Modbus TCP Server(作为从站)
拖入 modbus-server 节点,双击配置:
- Name: Modbus TCP Server (1502)
- Type: TCP
- Hostname: 0.0.0.0
- Port: 1502
- Unit-Id: 1
- Holding Registers: 1024(可根据设备数据量调整)
- Input Registers: 1024
- Coils/Discrete Inputs: 通常可不使用
部署之后,这台服务器即可作为 Modbus 从站,被 PLC、智能仪表或测试客户端访问。
通过 Modbus Read 轮询数据(关键环节)
如前文所述,modbus-server 不会主动输出消息,因此我们需要使用 modbus-read 节点主动轮询寄存器内容。
示例配置
- Unit ID: 1
- Function: FC3: Read Holding Registers
- Address: 0
- Quantity: 4
- Rate: 1 秒
- Server: 指向本机 Modbus Server (127.0.0.1:1502)
流程示意:
[modbus-read] → [function 解码数据] → [mqtt out]
↘ [debug]当 Modbus 客户端(设备)向地址 0 写入寄存器时,modbus-read 每秒即可看到变化。
数据解析与业务字段映射(Function 节点)
根据设备协议,将寄存器解析为温湿度、电压、电流、状态等业务字段,并构造 MQTT Payload。
示例 Function 代码:
// 假设读取了 [温度*10, 湿度*10, 状态寄存器, 保留]
let reg = msg.payload;
let data = {
temperature: reg[0] / 10,
humidity: reg[1] / 10,
status: reg[2],
ts: Date.now()
};
// 设置 MQTT topic
msg.topic = "iot/device001/telemetry";
msg.payload = data;
return msg;你也可以扩展逻辑,例如告警判断、数据清洗、单位转换等:
if (data.temperature > 50) {
data.alert = "HIGH_TEMPERATURE";
}MQTT Server 配置(推送到平台端)
拖入 mqtt out 节点 → 编辑:
- Broker 地址:mqtt.example.com(或 ZedIoT MQTT 服务器)
- 端口:1883 / 8883
- 账号密码:按平台配置
- Client ID:如 modbus-gateway-01
在 Topic 留空时,消息将采用 Function 内设置的 msg.topic。
最终实现链路:
Modbus Client → Node-RED Server
Node-RED 轮询 → 数据解析 → MQTT 推送## 完整测试流程(含工具与方法)
在正式接入设备前,必须验证 Node-RED 的 Modbus Server 与 MQTT 上报流程是否完整可用。以下是推荐的测试方式。
方法一:使用 Mac/Windows 的 Modbus TCP Client 工具
最简单的验证方式是使用图形化工具直接向 Node-RED 的 Modbus Server 写入寄存器:
推荐客户端:
| 工具 | 系统 | 特点 |
|---|---|---|
| QModMaster | macOS / Windows / Linux | 完全免费,界面简洁 |
| Modbus Doctor | macOS | App Store 可直接安装 |
| Modbus Poll | Windows | 工控行业标准工具 |
测试用核心参数:
- Host:Node-RED 所在服务器 IP
- Port:1502
- Unit ID:1
- 功能码:FC06(写单个寄存器)
- 地址:0
- 值:1234(模拟温度 123.4℃)
写入成功后,每次 modbus-read 轮询都将在 Debug 面板看到:
[1234, 0, 0, 0]说明数据链路已经打通。
方法二:使用 Node-RED 自带的 Modbus Client 节点测试(自嗨模式)
Node-RED 自己可以同时做 Server 和 Client,这对于开发与排查非常实用。
示例测试 Flow:
[inject] → [modbus-write] → 写入保持寄存器
[modbus-read] → [debug] → 读取自身 Server 数据可以模拟真实设备写入,观察数值变化是否被读取、解析并 MQTT 上传。
整体可导入的 Node-RED Flow(完整示例)
以下是一个 可直接导入 的 Modbus Server + Read + MQTT 网关模板,包含最小架构与解析逻辑,可直接投入使用或二次开发:
你可以复制以下 JSON,进入 Node-RED:菜单 → Import → Clipboard → 粘贴 → Deploy
[
{
"id": "modbus-flow",
"type": "tab",
"label": "Modbus Gateway",
"disabled": false
},
{
"id": "modbus-server-1502",
"type": "modbus-server",
"z": "modbus-flow",
"name": "Modbus Server 1502",
"logEnabled": true,
"serverPort": 1502,
"hostname": "0.0.0.0",
"responseDelay": 100,
"delayUnit": "ms",
"coilsBufferSize": 1024,
"holdingBufferSize": 1024,
"inputBufferSize": 1024,
"discreteBufferSize": 1024,
"unitid": 1,
"x": 200,
"y": 80,
"wires": [[],[],[]]
},
{
"id": "modbus-client-127",
"type": "modbus-client",
"name": "Local Client 1502",
"tcpHost": "127.0.0.1",
"tcpPort": "1502",
"unit_id": 1,
"clienttype": "tcp",
"bufferCommands": true,
"parallelUnitIdsAllowed": true
},
{
"id": "modbus-read-hr",
"type": "modbus-read",
"z": "modbus-flow",
"name": "Read HR(0..3)",
"dataType": "HoldingRegister",
"adr": "0",
"quantity": "4",
"rate": "1",
"rateUnit": "s",
"server": "modbus-client-127",
"x": 210,
"y": 160,
"wires": [["fn-decode"],[]]
},
{
"id": "fn-decode",
"type": "function",
"z": "modbus-flow",
"name": "解析寄存器并转 MQTT",
"func": "let reg = msg.payload;\n\nlet data = {\n temperature: reg[0] / 10,\n humidity: reg[1] / 10,\n status: reg[2],\n ts: Date.now()\n};\n\nmsg.topic = \"iot/modbus/device001/telemetry\";\nmsg.payload = data;\nreturn msg;",
"outputs": 1,
"x": 430,
"y": 160,
"wires": [["mqtt-out","debug-decoded"]]
},
{
"id": "mqtt-out",
"type": "mqtt out",
"z": "modbus-flow",
"name": "MQTT Server",
"broker": "mqtt-broker",
"topic": "",
"qos": "",
"retain": "",
"x": 680,
"y": 160,
"wires": []
},
{
"id": "debug-decoded",
"type": "debug",
"z": "modbus-flow",
"name": "Decoded Data",
"complete": "payload",
"x": 690,
"y": 220,
"wires": []
},
{
"id": "mqtt-broker",
"type": "mqtt-broker",
"name": "MQTT Example",
"broker": "YOUR_MQTT_HOST",
"port": "1883",
"clientid": "modbus-gateway-01",
"usetls": false
}
]你只需修改:
- YOUR_MQTT_HOST → MQTT 服务器地址
- iot/modbus/device001/telemetry → 自定义 topic
- 解析逻辑 → 按设备协议调整
即可立即投入使用。
常见问题与排查方法
1. Modbus Client 连不上 Server?
- 确认 Docker 映射端口:
docker ps
# 应看到 0.0.0.0:1502->1502/tcp- 确保不存在端口占用:
sudo lsof -i:15022. Node-RED Debug 无数据?
最常见原因:
你把 debug 接在 modbus-server 后面,而该节点本身不会输出 msg。
解决方案(关键):
✔ 使用 modbus-read / modbus-flex-getter
✔ 对自身的 Server 进行轮询
✔ 再在输出节点连接 debug
3. MQTT 无法上报?
检查:
- broker 地址是否正确
- 是否开启 TLS(1883 vs 8883)
- topic 是否正确
- 防火墙是否开启 1883 端口
进阶扩展:支持多设备、多寄存器、多 Topic
实际生产场景中,一个网关通常要接多个 Modbus 设备、多个从站 ID 或多个寄存器区段。你可以按以下方式扩展:
- 多个 modbus-read 节点 分别轮询不同 unitId
- 使用 function 动态构造 topic,例如:
msg.topic = `iot/modbus/${unitId}/telemetry`;- 使用 switch 节点 按寄存器地址分流到不同解析逻辑
- 增加本地缓存、累加器、过滤器,实现更高级的规则引擎
另外,你也可以加入:
- InfluxDB 时序数据库
- Grafana 可视化
- ZedIoT Rule Engine
- 告警 Webhook / 邮件 / 钉钉 / Slack
构成更完整的工业 IoT 边缘计算网关。
通过 Node-RED 快速搭建 Modbus Server → 轮询数据 → MQTT 推送的流程,可将传统工业设备无缝接入现代物联网平台。该方案轻量、灵活、跨平台,既能满足小规模部署,也适合扩展为企业级工业 IoT 网关。
如果你正在构建类似 ZedIoT 的平台,也可以直接将此方案作为 边缘设备数据采集模板,加入更多协议如 OPC UA、BACnet、DL/T645、485-WIFI 网关等,实现更广泛的设备接入能力。
典型应用介绍


