Node-RED Modbus节点,支持TCP/串口通信、多主站独立运行、串口自动搜索、多设备轮询、可选MQTT集成(支持纯本地模式和MQTT模式)、Home Assistant自动发现、HomeKit网桥、可视化控制看板、自定义协议转换和物理开关面板双向同步(支持Symi/Clowire品牌),工控机长期稳定运行
npm install node-red-contrib-symi-modbusNode-RED的Modbus继电器控制节点,支持TCP/串口通信和MQTT集成。



- 多协议支持:
- Modbus TCP(标准Modbus TCP)
- Modbus RTU over TCP(TCP转RS485网关)
- Telnet ASCII(推荐用于TCP转RS485网关)
- Modbus RTU(串口直连)
- Symi开关支持:自动识别并处理Symi私有协议按键事件,无需额外配置
- 多设备轮询:最多支持10台Modbus从站设备同时轮询
- 32路继电器:每台设备支持32个线圈(继电器通道)
- 智能轮询:从站上报时自动暂停轮询,优先处理数据,完成后继续轮询
- 灵活配置:可自定义轮询间隔(100-10000ms,默认200ms)、线圈范围、从站地址
- MQTT集成:自动生成Home Assistant兼容的MQTT发现消息
- 实时状态:实时监控和控制继电器状态
- 主从模式:提供主站节点和从站控制节点
- 稳定可靠:完整的内存管理和错误处理,适合工控机长期稳定运行
本插件包含以下核心节点:
| 节点名称 | 功能描述 |
| :--- | :--- |
| Modbus主站 | 核心调度中心,负责协议解析、多设备轮询和状态管理。 |
| 从站开关 | 监听物理面板(Symi/Clowire)按键事件并联动继电器,支持LED同步。 |
| HomeKit网桥 | 一键将所有 Modbus 继电器接入 Apple HomeKit,支持自定义名称。 |
| 控制看板 | 在 Node-RED 编辑器内直接控制和查看所有继电器的实时状态。 |
| Mesh透传 | 适配 Symi 蓝牙 Mesh 网关,支持窗帘、杜亚电机及各种子设备。 |
| 继电器输出 | 灵活的联动节点,支持按键触发、延时控制和多种动作逻辑。 |
| Modbus调试 | 实时监控原始 485 总线报文,方便现场调试和协议分析。 |
| 自定义协议 | 支持通过 JavaScript 编写自定义协议转换逻辑。 |
| 配置节点 | 包含串口配置、MQTT配置和Modbus服务器配置。 |
通过npm安装(推荐)
``bash`
cd ~/.node-red
npm install node-red-contrib-symi-modbus
node-red-restart
通过Node-RED界面安装
1. 点击右上角菜单 - 设置 - 节点管理
2. 搜索 node-red-contrib-symi-modbus
3. 点击安装
1. 拖拽任意节点到流程画布
2. 双击节点,找到"MQTT服务器"字段
3. 点击编辑按钮,填写MQTT服务器信息:
- MQTT Broker: mqtt://localhost:1883 (或你的MQTT服务器地址)modbus/relay
- 用户名/密码: 按需填写
- 基础主题: (默认)
1. 拖拽 Modbus主站 节点到流程画布
2. 配置连接参数:
- 串口模式(直连RS485设备):
- 连接类型: 串口/dev/ttyUSB0
- 串口路径: (Linux/Mac) 或 COM1 (Windows)9600
- 波特率: (默认)8
- 数据位: 1
- 停止位: 无
- 校验位: TCP/IP
- TCP模式(通过TCP转RS485网关):
- 连接类型: Telnet ASCII
- TCP模式: (推荐,适用于大多数TCP转RS485网关)192.168.2.110
- TCP主机: 1031
- TCP端口: RTU over TCP
- 其他模式:
- :适用于支持Modbus RTU over TCP的网关Modbus TCP
- :适用于标准Modbus TCP设备10
3. 配置从站设备:
- 从站地址: (默认,可添加多个,如10、11、12、13)0-31
- 线圈范围: 200ms
- 轮询间隔: (默认,支持100-10000ms)
4. 启用MQTT并选择MQTT服务器配置
5. 部署流程
如果需要物理开关面板控制,首先创建RS-485连接配置:
1. 点击右上角菜单 - 配置节点
2. 添加新的 serial-port-config 配置节点
3. 选择连接类型:
- 串口模式(本地RS-485总线):
- 连接类型: 串口/dev/ttyUSB0
- 串口路径: (可点击"搜索"按钮自动发现)9600
- 波特率: 8
- 数据位: 1
- 停止位: 无 (N)
- 校验位: TCP网关
- TCP模式(通过TCP转RS485网关):
- 连接类型: 192.168.2.110
- TCP主机: 1031
- TCP端口:
4. 保存配置
使用物理开关面板控制继电器:
1. 拖拽 从站开关 节点到流程画布
2. 选择刚创建的RS-485连接配置
3. 配置开关面板信息:
- 面板品牌: Symi / Clowire(克伦威尔)开关按钮
- 开关ID: 物理面板地址 (0-255)
- 按钮编号: 按键编号 (1-8)
- 按钮类型:
- :Symi 面板下,按下=开,释放=关(有独立开/关码),适合直接映射单个继电器场景按钮
- :Clowire 推荐使用,以及 Symi 场景键;每次按下都触发一次 Toggle,由指示灯和继电器状态共同决定“当前是开还是关”10
4. 配置映射到的继电器:
- 目标从站地址: 0
- 目标线圈编号:
5. 部署流程
#### HomeKit 接入
1. 拖拽 HomeKit网桥 节点。
2. 选择关联的 Modbus主站。
3. 在节点属性中,你可以为每一路继电器命名(如“客厅灯”),这些名称将同步显示在 iPhone 的家庭 App 中。
4. 部署后,使用 iPhone 扫描节点显示的二维码或输入 Pin码(默认 031-45-154)即可完成接入。
#### 网页控制看板
1. 拖拽 控制看板 节点。
2. 选择关联的 Modbus主站。
3. 部署后,在 Node-RED 编辑器中双击该节点,即可看到一个直观的控制界面,支持实时查看状态和点击控制。
#### Mesh 窗帘/电机控制
1. 拖拽 Mesh透传 节点。
2. 选择对应的 RS-485配置节点(连接到蓝牙 Mesh 网关)。
3. 节点会自动发现网关下的子设备,选择目标窗帘或杜亚电机。
4. 配置 控制逻辑(仅窗帘类型显示):
- 循环 (开-停-关-停):单键依次 打开→暂停→关闭→暂停。
- 打开/关闭:单键在 开/关 之间切换,到顶/到底后再次按键必为 关/开。
5. 可选绑定 按键触发:
- 使用 从站开关 或 继电器输出 节点,面板品牌选择 Symi / Clowire,按钮类型选择 场景按钮,并与 Mesh 窗帘节点的 switchId / buttonNumber 保持一致value=false
- Clowire 按键在内部统一按“场景模式”处理:每次物理按键都会触发一次事件,不会因为 被忽略
6. 状态与按键记忆:窗帘上报的位置(0%/100%)会更新节点内部状态;下次同一按键按下时,会根据“到顶/到底”正确执行 关/开 或 暂停,无需额外配置。
- 运动过程中(收到中间百分比,未到 0%/100%),再次按键一律发送 暂停,不会发生错误翻转
- 只有在电机真正上报到端点(Mesh 0x06 / 杜亚 0x04 的 0% / 100%)时,才会记为“开着/关着”,下一次按键才直接翻转为 关/开
7. 支持杜亚 485 电机:勾选“启用解析”、填写电机地址(高位-低位),可同时控制 Mesh 窗帘与杜亚电机并双向同步位置。
主站节点自动支持两种控制方式,无需额外配置:
#### 方式1:Modbus RTU轮询(标准)
- 主站定期轮询从站线圈状态
- 通过MQTT或Node-RED流程控制继电器
- 适用于所有Modbus RTU设备
#### 方式2:Symi私有协议(自动)
- 自动识别Symi开关按键事件(协议格式:7E [地址] 03 0F ...)7E [地址] 04 0F ...
- 自动应答并控制对应继电器(协议格式:)
- 映射规则:
- 设备地址1 → 从站10
- 设备地址2 → 从站11
- 设备地址3 → 从站12
- 设备地址4 → 从站13
- 通道号1-8 → 线圈0-7
按钮类型说明:
1. 开关按钮(推荐)
- 控制方式:按键有独立的开/关状态
- LED反馈:面板LED指示灯精确同步开关状态
- 适用场景:
- 灯光开关(客厅灯、卧室灯等)
- 插座开关(电器控制)
- 窗帘开关(电动窗帘)
- 任何需要明确开/关状态的场景
- 技术特点:
- 使用SET协议(0x03)发送LED反馈
- 使用原始设备地址确保LED精确反馈
- 支持物理按键和Home Assistant远程控制
- 面板LED完美同步,响应速度快
2. 场景按钮
- 控制方式:每次按下toggle切换状态(开→关→开)
- LED反馈:根据当前状态显示LED(开=亮,关=灭)
- 适用场景:
- 场景触发(回家模式、离家模式等)
- 一键全开/全关
- 需要状态指示的场景按钮
- 技术特点:
- 使用REPORT协议(0x04)发送LED反馈
- 使用原始设备地址确保LED精确反馈
- 支持物理按键和Home Assistant远程控制
- 200ms防抖,避免重复触发
两种模式对比:
| 特性 | 开关按钮 | 场景按钮 |
|------|---------|---------|
| 控制方式 | 开/关独立 | Toggle切换 |
| LED反馈协议 | SET (0x03) | REPORT (0x04) |
| 按键事件 | 独立开/关码 | 统一触发码 |
| LED同步 | ✓ 完美同步 | ✓ 完美同步 |
| HA远程控制 | ✓ 支持 | ✓ 支持 |
| 推荐场景 | 灯光/插座 | 场景触发 |
配置说明:
1. RS-485连接:选择串口配置节点(波特率9600,8N1)
2. MQTT服务器:选择MQTT配置节点(连接Home Assistant等)
3. 面板配置:
- 面板品牌:选择Symi
- 按钮类型:开关按钮或场景按钮
- 开关ID:物理面板的RS-485地址(0-255)
- 按钮编号:面板上的按键序号(1-8)
4. 继电器映射:
- 从站地址:Modbus继电器地址(10-247)
- 继电器路数:继电器通道(1-32路)
使用示例:
示例1:客厅灯光开关
- 面板:开关ID=2,按键1(开关按钮)
- 继电器:从站10,1路
- 效果:按下面板按键,客厅灯开/关,面板LED同步状态
示例2:全开场景
- 面板:开关ID=2,按键8(场景按钮)
- 继电器:从站10,32路
- 效果:按下面板按键,触发全开场景
主站轮询时,从站开关可以同时使用。当从站开关上报数据到服务器后:
1. 自动暂停轮询:主站检测到写入操作,立即暂停轮询
2. 优先处理数据:处理从站上报的数据(写入Modbus继电器)
3. 继续轮询:数据处理完成后(100ms延迟),自动恢复轮询
4. 日志记录:记录轮询暂停时长和跳过的轮询次数
这种机制确保:
- 主站轮询不会与从站写入冲突
- 从站上报的数据得到优先处理
- 系统响应迅速,状态同步及时
启用MQTT后,自动生成Home Assistant兼容的Discovery配置:
- 唯一性保证:每个实体使用稳定的unique_id,避免重复生成retain=true
- 设备分组:同一从站的所有继电器自动分组到一个设备下
- 状态持久化:使用确保状态持久化
- 在线状态:自动发布设备可用性状态
所有节点配置自动保存到Node-RED的flows文件中:
- 从站地址、线圈范围、轮询间隔
- MQTT服务器配置
- 开关面板映射关系
部署后配置永久生效,重启Node-RED后自动恢复。
针对工控机24/7长期运行优化:
- 内存管理:自动清理缓存,释放无用对象
- 事件监听器清理:关闭时移除所有监听器,防止内存泄漏
- 智能日志限流:错误日志10分钟输出一次,避免日志刷屏
- 智能重连机制:
- Modbus连接断开自动重连(指数退避:5秒→10秒→20秒...最大60秒)
- MQTT连接断开自动重连(支持多地址fallback)
- 串口拔插自动检测并重连
- TCP网络故障自动恢复
- 连接前彻底清理旧实例,避免资源泄漏
- 互斥锁机制:防止读写冲突导致的数据异常
- Keep-Alive心跳:TCP连接启用30秒心跳检测
- 协议类型:Modbus TCP / Modbus RTU
- 底层库:modbus-serial ^8.0.23(内部封装serialport,支持TCP和串口)
- 功能码支持:0x01(读线圈)、0x05(写单个线圈)、0x0F(写多个线圈)
- 从站地址范围:1-247(建议从10开始)
- 线圈数量:每台设备32个(0-31)
- 最大设备数:10台同时轮询
- 轮询间隔:默认200ms(建议300-500ms,支持100-10000ms)
- 串口配置:9600 8-N-1(波特率9600,8数据位,无校验,1停止位)
- 超时设置:5000ms(TCP和串口通用)
- Node.js: >= 14.0.0
- Node-RED: >= 2.0.0
- MQTT Broker: Mosquitto / EMQX / Any MQTT 3.1.1/5.0
- Home Assistant: 2024.x+(MQTT Discovery标准)
- 操作系统: Windows / Linux / macOS / HassOS
启用MQTT后,设备自动出现在Home Assistant中:
- 实体ID: switch.relay_{从站地址}_{线圈编号}Modbus继电器-{从站地址}
- 设备名称:
- 自动分组: 同一从站的所有继电器分组到一个设备
``
状态主题: modbus/relay/{从站}/{线圈}/state
命令主题: modbus/relay/{从站}/{线圈}/set
可用性主题: modbus/relay/{从站}/availability
发现主题: homeassistant/switch/modbus_relay_{从站}_{线圈}/config
Linux:
`bash查看串口设备
ls -l /dev/ttyUSB /dev/ttyS
macOS:
`bash
查看串口设备(注意macOS使用cu.而不是tty.)
ls -l /dev/cu.*
`Docker/HassOS:
`yaml
在docker-compose.yml或HassOS插件配置中添加设备映射
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
`$3
1. 确认MQTT broker正在运行:
`bash
# Linux
sudo systemctl status mosquitto
# macOS
brew services list | grep mosquitto
`2. 测试MQTT连接:
`bash
mosquitto_sub -h localhost -t test
`3. 检查Node-RED日志中的MQTT连接信息
$3
1. 确认已添加所有从站设备(如10、11、12、13)
2. 确认轮询间隔(默认200ms)
3. 查看Node-RED调试日志
4. 检查串口波特率(9600)
5. 检查从站地址(1-247)
6. 确认从站设备在线
7. 检查MQTT连接(轮询不依赖MQTT,但状态发布需要MQTT)
$3
1. 检查RS-485连接
2. 确认开关面板地址和按钮编号
3. 检查MQTT连接
4. 查看Node-RED日志中的协议解析信息
输入消息格式
$3
`javascript
// 启动轮询
msg.payload = {cmd: "start"};// 停止轮询
msg.payload = {cmd: "stop"};
// 写单个线圈
msg.payload = {
cmd: "writeCoil",
slave: 10, // 从站地址
coil: 0, // 线圈编号
value: true // true=开, false=关
};
// 批量写多个线圈
msg.payload = {
cmd: "writeCoils",
slave: 10, // 从站地址
startCoil: 0, // 起始线圈
values: [true, false, true, false] // 线圈值数组
};
`$3
`javascript
// 发送开关命令
msg.payload = true; // 或 false
msg.payload = "ON"; // 或 "OFF"
msg.payload = 1; // 或 0
`输出消息格式
$3
`javascript
{
payload: {
slave: 10, // 从站地址
coils: [true, false, ...], // 线圈状态数组
timestamp: 1234567890 // 时间戳
}
}
`$3
`javascript
{
payload: true, // 开关状态
topic: "switch_0_btn1", // 主题
switchId: 0, // 开关面板ID
button: 1, // 按钮编号
targetSlave: 10, // 目标从站地址
targetCoil: 0 // 目标线圈编号
}
`性能指标
- 内存占用:< 50MB(单个主站节点,轮询10个设备)
- CPU占用:< 5%(正常轮询状态)
- 连接延迟:Modbus响应 < 100ms,MQTT发布 < 50ms
- 稳定运行:经过工控机7x24小时长期运行验证
- 容错能力:Modbus从站离线不影响其他从站,MQTT断线自动重连
示例Flow
`json
[
{
"id": "modbus-master-1",
"type": "modbus-master",
"name": "主站",
"connectionType": "serial",
"serialPort": "/dev/ttyUSB0",
"serialBaudRate": 9600,
"slaves": [
{"address": 10, "coilStart": 0, "coilEnd": 31, "pollInterval": 200},
{"address": 11, "coilStart": 0, "coilEnd": 31, "pollInterval": 200},
{"address": 12, "coilStart": 0, "coilEnd": 31, "pollInterval": 200},
{"address": 13, "coilStart": 0, "coilEnd": 31, "pollInterval": 200}
],
"enableMqtt": true,
"mqttServer": "mqtt-config-1"
}
]
`项目信息
$3
#### v2.10.17 (2026-02-07)
- Mesh 窗帘协议兼容性:按照《蓝牙MESH网关(初级版)串口协议V1.0》修正 0x53 0x80 0x06 节点状态帧解析逻辑,明确区分事件类型 RESULT_EVENT_NODE_STATUS(0x06) 与
VD_MSG_TYPE_CURT_RUN_STATUS(0x05) / VD_MSG_TYPE_CURT_RUN_PER_POS(0x06),不再误把 subOp 当成窗帘 msg_type 使用,严格从数据区解析 [msg_type][param]。
- 窗帘状态与端点记忆:窗帘动作(0x05) 与位置(0x06) 在内部状态中分离存储,位置只由真正的 0x06 位置帧(含杜亚485位置反馈)更新;仅当位置为 0%/100% 且确认为当前运动方向的目标端点时才标记到达端点并更新 lastAction/lastDirection,避免 0x05 帧或“打开中收到0% / 关闭中收到100%”被误判为端点。
- 开停关停 / 打开-关闭 行为:
- 引入 isMoving 统一表示“运动过程”,只要执行过开/关且未到端点(0%/100%),物理按键再次点击必发送暂停(3),不会直接翻转方向。
- 停在 0%/100% 后会进行“端点收敛”:端点上报后不会再多走一次暂停,下一次按键一定是「关着→打开 / 开着→关闭」,到顶/到底后再次点击必然反向(关/开)。
- 修正 cycle 模式下起点 0%/100% 刚起步时第二下按键误判为翻转的问题;到端点仅在 isMoving=false && reachedEndpoint=true && endpointPosition=0/100 时生效,并移除“>50% / <=50% 位置兜底”,中途暂停后的方向完全由 lastDirection/lastAction` 决定,保证绝对的「开-停-关-停」节奏。#### v2.10.16 (2026-02-06)
- 按键记忆:同一帧内若同时上报位置与动作(如 position=100 + action=打开中),以位置为准到端点即按「已停止」记忆,避免被动作覆盖导致下次按键误判。
- 开停关停 / 打开关闭:状态记忆更稳,到顶/到底后再次按键必为关/开;开停关停模式下运动中点击会正确发送暂停(3)。
- 场景按键:场景模式下不再因 value=false 忽略一次按下,每次物理按键都会触发控制,解决「多按一次」才生效的问题。
#### v2.10.15 (2026-02-05)
- Mesh 窗帘控制:修复重启后实体消失、到头不记忆位置、再次点击误发暂停等问题;新增「打开/关闭」单键循环逻辑;「开-停-关-停」循环逻辑完整可用。
- 配置界面:控制逻辑选项正确保存与显示,选择「打开/关闭」后不再被覆盖为「循环」。
- Mesh 透传与杜亚:与杜亚电机状态双向同步优化;窗帘到端点(0%/100%)状态正确同步到按键,点击时能正确执行开/关。
- 稳定性:实体持久化与存储校验增强,兼容更多固件版本的窗帘协议。
#### v2.10.14 (2026-02-03)
- 多种 Modbus 协议支持(Telnet ASCII、RTU over TCP、TCP、串口);智能轮询暂停,面板事件响应更及时。
- Home Assistant MQTT Discovery 与实体唯一 ID;串口热插拔与 TCP 故障自动恢复。
- 开关/场景按钮双模式,LED 反馈同步。