17191073931

17191073931

使用 Node-RED + Modbus Server 快速搭建协议网关:实现工业设备数据到 MQTT 的完整链路

本文介绍如何使用 Node-RED + Modbus TCP Server在服务器上快速搭建Modbus协议处理服务器,将工业设备数据解析、转换并转发到 MQTT Server,实现设备上报、规则处理与 IoT 平台集成的完整方案。内容包含架构原理、部署方法、配置步骤以及测试验证流程。


为什么选择 Node-RED + Modbus Server + MQTT?

在工业物联网(IIoT)场景中,Modbus TCP 依然是最常见、最可靠的设备通信协议之一。大量 PLC、电表、传感器都依赖 Modbus 进行参数读取或状态上报。然而,传统工控软件通常封闭、难以扩展,不便与现代 MQTT、云平台或自研平台(例如 ZedIoT)对接。

Node-RED 则具备如下天然优势:

modbus devices
  • 支持 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:1880Node-RED Web 编辑器端口
1502:1502对外开放 Modbus Server 端口
/opt/nodered_data:/data持久化 Flow、配置、安装的插件
TZ指定服务器时区,方便日志统一管理

部署完成后访问:

http://服务器IP:1880

即可看到 Node-RED 的可视化管理界面。


安装 Modbus 与 MQTT 节点

进入 Node-RED 编辑器:

  1. 右上角菜单 → Manage palette
  2. 选择 Install
  3. 搜索并安装:
  • 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 写入寄存器:

推荐客户端:

工具系统特点
QModMastermacOS / Windows / Linux完全免费,界面简洁
Modbus DoctormacOSApp Store 可直接安装
Modbus PollWindows工控行业标准工具

测试用核心参数:

  • 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:1502

2. 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 网关等,实现更广泛的设备接入能力。



典型应用介绍

相关技术方案

{{brizy_dc_image_alt imageSrc=

是否需要我们帮忙?

若是您有同样的需求或困扰,打电话给我们,我们会帮您梳理需求,定制合适的方案。

010-62386352


{{brizy_dc_image_alt imageSrc=
{{brizy_dc_image_alt imageSrc=

© 2025 ZedIoT Ltd. 北京星野云联科技有限公司 All Rights Reserved.

京ICP备2021029338号-2