node-red-contrib-symi-modbus 1.6.1

Node-RED Modbus节点,支持TCP/串口通信、串口自动搜索、多设备轮询、智能MQTT连接(自动fallback到host.docker.internal等)、Home Assistant自动发现和多品牌开关面板,增强日志和状态显示

npm install node-red-contrib-symi-modbus

node-red-contrib-symi-modbus

Node-RED的Modbus继电器控制节点,支持TCP/串口通信和MQTT集成。

功能特性

  • 多协议支持:支持Modbus TCP和Modbus RTU(串口)
  • 多设备轮询:最多支持10台Modbus从站设备同时轮询
  • 32路继电器:每台设备支持32个线圈(继电器通道)
  • 灵活配置:可自定义轮询间隔、线圈范围、从站地址
  • MQTT集成:自动生成Home Assistant兼容的MQTT发现消息
  • 实时状态:实时监控和控制继电器状态
  • 主从模式:提供主站节点和从站控制节点

安装

npm version npm downloads

通过npm安装(推荐)

在Node-RED用户目录中运行:

cd ~/.node-red
npm install node-red-contrib-symi-modbus

通过Node-RED界面安装

  1. 点击右上角菜单 → 设置 → 节点管理
  2. 搜索 node-red-contrib-symi-modbus
  3. 点击安装

已发布到npm: https://www.npmjs.com/package/node-red-contrib-symi-modbus

Docker/容器环境安装

本节点依赖modbus-serial包,该包包含native C++模块(serialport),需要编译环境。

⚠️ 如果遇到安装错误

错误示例:

npm error code 127
npm error command sh -c node-gyp-build
npm error sh: node-gyp-build: not found

原因: Docker容器缺少编译工具(python、make、g++)

解决方案1:使用官方Node-RED Docker镜像(推荐)

官方镜像已包含编译工具:

docker pull nodered/node-red:latest

解决方案2:在Dockerfile中添加编译依赖

Alpine基础镜像:

FROM nodered/node-red:latest
# 或者自定义镜像时添加
RUN apk add --no-cache \
    python3 \
    make \
    g++ \
    linux-headers

Debian/Ubuntu基础镜像:

FROM nodered/node-red:latest
# 或者
RUN apt-get update && apt-get install -y \
    python3 \
    make \
    g++ \
    build-essential

解决方案3:在运行中的容器安装

# 进入容器
docker exec -it <container_id> /bin/sh

# Alpine
apk add --no-cache python3 make g++ linux-headers

# Debian/Ubuntu
apt-get update && apt-get install -y python3 make g++ build-essential

# 退出容器后,在Node-RED界面重新安装节点

解决方案4:使用docker-compose(推荐)

version: '3.8'
services:
  node-red:
    image: nodered/node-red:latest
    ports:
      - "1880:1880"
    volumes:
      - node-red-data:/data
    # 如果需要串口设备,添加设备映射
    devices:
      - "/dev/ttyUSB0:/dev/ttyUSB0"
    # 如果需要串口权限
    user: "1000:20"  # dialout组ID通常是20

volumes:
  node-red-data:

本地开发安装

# 克隆或下载项目后
cd node-red-contrib-symi-modbus
npm install

# 安装到Node-RED(使用你的实际项目路径)
cd ~/.node-red
npm install /path/to/node-red-contrib-symi-modbus

# 或者在Mac上
cd ~/.node-red
npm install /Volumes/your-disk/path/to/node-red-contrib-symi-modbus

安装后需要重启Node-RED

# 重启Node-RED
# 如果用命令行运行,按 Ctrl+C 停止,然后重新运行
node-red

# 如果用服务管理器,重启服务
# macOS: brew services restart node-red
# Linux: sudo systemctl restart node-red

节点说明

1. MQTT服务器配置节点 (mqtt-server-config)

全局配置节点,用于管理MQTT服务器连接信息,所有主站和从站节点共享此配置。

配置参数

  • 名称:配置节点的显示名称(可选)
  • MQTT服务器:MQTT Broker地址(如:mqtt://192.168.1.100:1883)
  • 用户名:MQTT认证用户名(可选)
  • 密码:MQTT认证密码(可选)
  • 基础主题:MQTT主题前缀(默认:modbus/relay)

使用方式

  1. 在主站或从站节点配置界面中,点击MQTT服务器旁边的编辑按钮(铅笔图标)
  2. 选择已有的MQTT配置,或点击"添加新的mqtt-server-config..."创建新配置
  3. 填写MQTT服务器信息并保存
  4. 所有使用相同配置的节点会自动同步更新

优势

统一管理:所有MQTT连接信息集中配置,避免重复输入
一处修改,处处生效:修改配置后所有引用的节点自动更新
防止错误:确保主站和从站使用相同的MQTT服务器和主题
持久化保存:配置自动保存,重启Node-RED后不丢失

2. Modbus主站节点 (modbus-master)

主站节点负责与Modbus继电器设备通信,执行轮询操作,并可选择发布状态到MQTT服务器。

配置参数

连接配置

  • 连接类型:选择TCP/IP或串口
  • TCP主机:Modbus TCP服务器地址(默认:127.0.0.1)
  • TCP端口:Modbus TCP端口(默认:502)
  • 串口:串口名称(如:COM1、/dev/ttyUSB0)
  • 波特率:串口波特率(9600/19200/38400/57600/115200)
  • 数据位:数据位数(7或8,默认8)
  • 停止位:停止位数(1或2,默认1)
  • 校验位:校验方式(无/奇校验/偶校验,默认无)

从站设备配置

  • 动态添加从站:点击"添加从站"按钮可添加最多10个从站设备
  • 从站地址:每个从站的Modbus地址(1-247,默认从10=0x0A开始递增)
  • 起始线圈:该从站的起始线圈编号(0-31)
  • 结束线圈:该从站的结束线圈编号(0-31)
  • 轮询间隔:该从站的轮询间隔,单位毫秒(默认:200ms,推荐≥100ms)
  • 配置持久化:所有从站配置自动保存,重启Node-RED后不丢失

MQTT配置

  • 启用MQTT:是否启用MQTT功能
  • MQTT服务器:选择或添加MQTT服务器配置节点(引用mqtt-server-config)

输入消息

// 启动轮询
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]  // 线圈值数组
};

输出消息

{
    payload: {
        slave: 10,                          // 从站地址
        coils: [true, false, true, ...],    // 线圈状态数组
        timestamp: 1234567890               // 时间戳
    }
}

MQTT主题结构

启用MQTT后,自动生成以下主题:

  • 状态主题modbus/relay/{从站地址}/{线圈编号}/state

    • 内容:ONOFF
    • 示例:modbus/relay/10/0/stateON
  • 命令主题modbus/relay/{从站地址}/{线圈编号}/set

    • 接受:ONOFF
    • 示例:modbus/relay/10/0/setOFF
  • 可用性主题modbus/relay/{从站地址}/availability

    • 内容:onlineoffline
    • 用于显示设备在线/离线状态
  • 发现主题(Home Assistant):homeassistant/switch/modbus_relay_{从站}_{线圈}/config

    • 符合Home Assistant MQTT Discovery标准
    • 包含完整的设备信息和配置

3. Modbus开关从站节点 (modbus-slave-switch)

从站开关节点连接物理开关面板(RS-485总线),监听按键事件,并通过MQTT映射控制Modbus继电器设备,实现三向同步

工作原理

  • RS-485总线连接:连接物理开关面板的RS-485总线(TCP或串口)
    • 监听按键事件:实时监听物理面板的按钮按下事件
    • 发送控制指令:同步控制物理面板的指示灯等状态
  • 映射到继电器:指定要控制的Modbus从站地址(10-19)和线圈编号(0-31)
  • MQTT三向同步
    • 按键→继电器:物理按键按下 → 从站监听 → MQTT命令 → 主站 → 继电器动作
    • 继电器→面板:继电器状态变化 → 主站轮询 → MQTT状态 → 从站 → 面板指示灯更新
    • 远程→全部:远程控制 → MQTT → 继电器动作 + 面板指示灯同步
  • 完全解耦:无需连线到主站节点,通过MQTT通信
  • 实时同步:三向自动同步,延迟<200ms

三向同步机制详解(基于轻量级协议V0.13)

                                    【完整三向通信架构】

┌──────────────────┐     ┌──────────────────┐     ┌──────┐     ┌──────────────┐     ┌────────────┐
│ 物理开关面板       │ ←→ │  从站开关节点      │ ←→ │ MQTT │ ←→ │  主站节点     │ ←→ │ Modbus继电器│
│  (RS-485总线)    │     │  轻量级协议+MQTT │     │Broker│     │  Modbus协议  │     │  (设备)    │
│                  │     │                 │     │      │     │             │     │           │
│ • 按键按下       │ ──> │ • 解析0x04上报   │ ──> │ ON   │ ──> │ • 写线圈0x05 │ ──> │ • 继电器ON │
│   0x04上报       │     │ • 发MQTT命令     │     │ QoS1 │     │ • Modbus写入 │     │           │
│                  │     │                 │     │      │     │             │     │           │
│ • 指示灯亮       │ <── │ • 构建0x03设置   │ <── │ ON   │ <── │ • 读线圈0x01 │ <── │ • 状态变化 │
│   0x03设置       │     │ • CRC8校验       │     │retain│     │ • 轮询检测   │     │           │
└──────────────────┘     └──────────────────┘     └──────┘     └──────────────┘     └────────────┘
        ↑                         ↑                    ↑                ↑                    ↑
        │                         │                    │                │                    │
  轻量级协议                  双协议桥接            QoS=1保证        Modbus协议           继电器控制
 波特率9600               帧头0x7E+CRC8          持久化会话        功能码01/05          硬件执行
  8N1无校验               帧尾0x7D               自动重连          超时5秒              实时响应

轻量级协议帧格式:

7E [本机地址] [数据类型] [数据长度] [设备类型0x01] [品牌ID] [设备地址] [通道]
   [房间号] [房间类型] [房间ID] [操作码] [操作信息] [CRC8] 7D

示例 - 控制开关ID=1,按钮3,开启:
7E 01 03 0F 01 00 01 03 00 00 00 00 01 XX 7D
   ↑  ↑  ↑     ↑     ↑  ↑  ↑           ↑  ↑
  本机 设置 灯光 设备1 按钮3    单灯 开启

数据流示例(含完整协议帧):

  1. 用户按下物理按钮 → 继电器动作

    物理按钮按下 
    → RS-485上报: 7E 01 04 0F 01 00 01 03 00 00 00 00 01 XX 7D (0x04上报,按钮3开启)
    → 从站节点解析协议帧,检测按键按下事件
    → MQTT发布: modbus/relay/10/0/set → "ON" (QoS=1)
    → 主站接收MQTT命令
    → Modbus写线圈: 功能码0x05,从站10,线圈0,值=1
    → 继电器执行动作: 继电器ON
    
  2. 继电器状态变化 → 面板指示灯同步

    继电器状态变化(物理或远程控制)
    → Modbus轮询读取: 功能码0x01,从站10,线圈0
    → 主站检测状态变化
    → MQTT发布: modbus/relay/10/0/state → "ON" (QoS=1, retain=true)
    → 从站接收MQTT状态消息
    → 构建轻量级协议: 7E 01 03 0F 01 00 01 03 00 00 00 00 01 XX 7D (0x03设置,按钮3开启)
    → RS-485发送指令到物理面板
    → 面板指示灯: 指示灯ON
    
  3. 远程控制(HA/MQTT) → 全部同步

    Home Assistant控制或MQTT命令
    → MQTT命令: modbus/relay/10/0/set → "ON"
    → 主站接收并写入Modbus
    → 继电器ON
    → 主站轮询检测到状态变化
    → MQTT状态: modbus/relay/10/0/state → "ON"
    → 从站接收状态,发送RS-485指令
    → 面板指示灯ON
    

关键特性:

  • 轻量级协议实现:完整实现V0.13协议(帧头0x7E、CRC8校验、帧尾0x7D)
  • 按键事件解析:解析0x04上报帧,检测单键/多键按下事件
  • 指示灯控制:构建0x03设置帧,同步物理面板指示灯状态
  • RS-485双向通信:监听按键事件 + 控制指示灯状态
  • TCP/串口支持:可连接RS-485转TCP网关或直连串口
  • CRC8校验保证:所有RS-485帧都进行CRC8校验,确保数据完整性
  • QoS=1消息保证:命令和状态都使用QoS=1,确保消息不丢失
  • 持久化会话:clean=false,断线重连后继续接收未读消息
  • Retain保留消息:状态消息使用retain=true,新订阅者立即获取最新状态
  • 自动重连:RS-485和MQTT都5秒自动重连,网络波动不影响使用

配置参数

RS-485总线连接配置(轻量级协议V0.13)

  • 连接类型:选择TCP/IP或串口
  • TCP主机:RS-485转TCP网关地址(如:192.168.1.200)
  • TCP端口:网关端口(默认:8888)
  • 串口:串口名称(如:COM1、/dev/ttyUSB0)
  • 波特率:9600(协议标准,1起始位,8数据位,1停止位,无校验位)
  • 数据位:8(固定)
  • 停止位:1(固定)
  • 校验位:无(固定)

协议说明:

  • 帧格式:0x7E + 数据 + CRC8 + 0x7D
  • 数据类型:0x01应答、0x02查询、0x03设置、0x04上报
  • 设备类型:0x01灯光、0x07场景
  • 操作码:0x00单灯、0x05多灯
  • 校验:CRC8算法(多项式0x07)

MQTT服务器配置

  • MQTT服务器:选择或添加MQTT服务器配置节点(需与主站节点使用相同配置)

物理开关面板配置

  • 面板品牌:选择开关面板品牌
    • 亖米(Symi):默认品牌,完整实现轻量级协议V0.13
    • 其他品牌:预留扩展接口,后续支持更多1-8键开关品牌
  • 开关ID:物理开关面板的设备地址(0-255,RS-485总线地址)
  • 按钮编号:物理面板上的按键编号(1-8键开关)

映射到继电器设备

  • 目标从站地址:要控制的Modbus继电器设备地址(10-247)
  • 目标线圈编号:继电器的具体通道(0-31)

输入消息

// 布尔值
msg.payload = true;   // 开
msg.payload = false;  // 关

// 字符串
msg.payload = "ON";   // 开
msg.payload = "OFF";  // 关

// 数字
msg.payload = 1;      // 开
msg.payload = 0;      // 关

输出消息

{
    payload: true,              // 当前状态
    topic: "switch_0_btn1",     // 主题(开关ID_按钮编号)
    switchId: 0,                // 物理开关面板ID
    button: 1,                  // 面板按钮编号
    targetSlave: 10,            // 映射到的继电器从站
    targetCoil: 0               // 映射到的继电器线圈
}

一对多/多对一配置

支持灵活的映射关系,通过创建多个从站节点实现:

场景1:一个按钮控制多个继电器(一对多)

创建3个从站开关节点:
节点A: 开关ID=0, 按钮1 → 继电器10-线圈0
节点B: 开关ID=0, 按钮1 → 继电器10-线圈1
节点C: 开关ID=0, 按钮1 → 继电器11-线圈5

效果:按下物理按钮1时,3个继电器同时动作

场景2:多个按钮控制同一个继电器(多对一)

创建3个从站开关节点:
节点A: 开关ID=0, 按钮1 → 继电器10-线圈0
节点B: 开关ID=0, 按钮2 → 继电器10-线圈0
节点C: 开关ID=5, 按钮3 → 继电器10-线圈0

效果:任意一个按钮都可以控制同一个继电器

场景3:复杂联动控制

物理面板1的按钮1 → 控制客厅灯(继电器10-0)+ 走廊灯(继电器10-1)
物理面板2的按钮3 → 控制客厅灯(继电器10-0)+ 卧室灯(继电器11-2)

实现:创建4个从站节点,灵活组合

配置映射示例

示例1:亖米开关ID=0,按钮1 → 继电器10-线圈0

物理面板配置:
├─ 面板品牌:亖米(Symi)
├─ 开关ID:0(物理面板地址)
├─ 按钮编号:1(面板按钮1)
映射到继电器:
├─ 从站地址:10(Modbus继电器设备10)
└─ 线圈编号:0(继电器通道0)

MQTT主题:
├─ 订阅状态:modbus/relay/10/0/state
└─ 发布命令:modbus/relay/10/0/set

示例2:亖米开关ID=5,按钮3 → 继电器11-线圈15

物理面板配置:
├─ 面板品牌:亖米(Symi)
├─ 开关ID:5(物理面板地址)
├─ 按钮编号:3(面板按钮3)
映射到继电器:
├─ 从站地址:11(Modbus继电器设备11)
└─ 线圈编号:15(继电器通道15)

MQTT主题:
├─ 订阅状态:modbus/relay/11/15/state
└─ 发布命令:modbus/relay/11/15/set

节点架构

系统架构图(v1.3.0完整版)

┌────────────────────────────────────────────────────────────────────────────────────┐
│                          完整三向通信系统架构                                         │
└────────────────────────────────────────────────────────────────────────────────────┘

物理开关面板                从站开关节点                MQTT Broker          主站节点            继电器设备
(RS-485总线)             (双协议桥接)                                    (Modbus通信)         (TCP/串口)
┌──────────┐            ┌──────────────┐           ┌────────────┐      ┌───────────┐      ┌──────────┐
│ 开关ID=0  │◄─RS485───►│ 轻量级协议    │◄─MQTT────►│  QoS=1     │◄────►│  Modbus   │◄────►│ 从站10   │
│  按钮1-8  │  9600 8N1 │  解析/构建    │  命令/状态 │  持久化    │ 轮询  │  功能码   │ TCP  │ 线圈0-31 │
│           │            │  CRC8校验     │           │  Retain    │ 写入  │  01/05/0F │ 502  │          │
│ • 按键输入│ ────────> │ • 0x04上报解析│ ────────> │ /10/0/set  │ ────> │ • 写线圈  │ ────>│ • 继电器 │
│ • 指示灯  │ <──────── │ • 0x03设置构建│ <──────── │ /10/0/state│ <──── │ • 读状态  │ <────│ • 动作   │
└──────────┘            └──────────────┘           └────────────┘      └───────────┘      └──────────┘
  开关ID=5                  开关ID=0-255                    ↓              从站10-19          从站10-19
  开关ID=10                 按钮1-8映射               ┌────────────┐      线圈0-31          线圈0-31
  ...                       继电器任意组合             │Home Assistant│
                                                      │ MQTT Discovery│
                                                      │ 自动发现实体  │
                                                      └────────────┘

【关键特性】
✅ 轻量级协议V0.13:完整实现帧头0x7E、数据、CRC8校验、帧尾0x7D
✅ Modbus主站节点:轮询继电器设备(10-19),MQTT发布状态,HA自动发现
✅ 从站开关节点:RS-485监听按键 + MQTT命令 + 指示灯同步,完整三向通信
✅ MQTT双协议桥接:轻量级协议(RS-485) ↔ MQTT ↔ Modbus协议
✅ Home Assistant集成:MQTT Discovery自动创建实体,完美兼容

快速开始

基础使用

配置MQTT服务器(首次使用)

  1. 拖拽任意节点(主站或从站)到流程画布
  2. 双击节点,找到"MQTT服务器"字段
  3. 点击旁边的编辑按钮(铅笔图标)
  4. 点击"添加新的mqtt-server-config..."
  5. 填写MQTT服务器信息:
    • MQTT服务器:mqtt://192.168.1.100:1883
    • 用户名:(可选)
    • 密码:(可选)
    • 基础主题:modbus/relay
  6. 点击"添加"保存配置

配置主站节点

  1. 拖拽 Modbus主站 节点到流程画布

  2. 双击节点,配置连接参数:

    TCP连接:

    • 连接类型:TCP/IP
    • TCP主机:192.168.1.100
    • TCP端口:502

    串口连接:

    • 连接类型:串口
    • 点击"搜索串口"按钮查找可用串口
    • 从下拉列表中选择串口(自动填入)
    • 或手动输入:COM1 / /dev/ttyUSB0 / /dev/ttyS1
    • 波特率:9600(或根据设备要求,8-N-1已固定)
  3. 配置从站设备:

    • 默认已有1个从站(地址10)
    • 点击"添加从站"按钮可添加更多(最多10个)
    • 每个从站自动递增地址(10→11→12...)
  4. 启用MQTT(如果需要与HA集成)

  5. 选择已配置的MQTT服务器

  6. 部署流程

配置从站开关节点

  1. 拖拽 从站开关 节点到流程画布

  2. 双击节点配置:

    RS-485总线连接:

    • 连接类型:TCP/IP 或 串口

    TCP模式:

    • TCP主机:192.168.1.200(RS-485转TCP网关地址)
    • TCP端口:8888

    串口模式:

    • 点击"搜索串口"按钮查找可用串口
    • 从下拉列表中选择串口(自动填入)
    • 或手动输入:COM1 / /dev/ttyUSB0 / /dev/ttyS1
    • 波特率:9600(亖米协议固定,8-N-1已自动配置)

    MQTT服务器:

    • 选择与主站相同的MQTT配置

    开关面板:

    • 面板品牌:亖米(Symi)- 默认,支持1-8键开关
    • 开关ID:0(物理面板地址,0-255)
    • 按钮编号:1(面板按钮,1-8)

    映射到继电器:

    • 从站地址:10(Modbus继电器设备地址)
    • 线圈编号:0(继电器通道,0-31)
  3. 连接输入节点(可选,用于手动控制)

  4. 连接输出节点(如:debug节点)查看状态

  5. 部署流程

配置示例:

【完整配置】
RS-485连接:TCP网关192.168.1.200:8888(或串口/dev/ttyUSB0 9600)
MQTT服务器:本地MQTT服务器(192.168.1.100:1883)
面板品牌:亖米(Symi)- 支持1-8键开关
物理面板:开关ID=0,按钮1
映射到:继电器10,线圈0

【工作流程】
物理按钮1按下 
→ RS-485上报: 7E 01 04 0F 01 00 00 01 00 00 00 00 01 XX 7D
→ 从站解析:检测到开关0按钮1按下
→ MQTT命令: modbus/relay/10/0/set → "ON"
→ 主站写入: Modbus从站10线圈0 → 1
→ 继电器动作:继电器ON
→ 主站轮询:检测到状态变化
→ MQTT状态: modbus/relay/10/0/state → "ON" (retain)
→ 从站接收:构建RS-485控制帧
→ RS-485设置: 7E 01 03 0F 01 00 00 01 00 00 00 00 01 XX 7D
→ 面板指示灯:指示灯ON

导入示例流程

项目包含示例流程文件 examples/basic-flow.json

  1. 点击右上角菜单 → 导入
  2. 选择 examples/basic-flow.json 文件
  3. 导入后即可测试所有功能

示例流程包含:

  • 启动/停止轮询
  • 写单个线圈
  • 开关节点控制
  • 调试输出

TCP连接示例

配置:
- 连接类型:TCP/IP
- TCP主机:192.168.1.100
- TCP端口:502

从站1:
- 地址:10 (0x0A)
- 线圈范围:0-31
- 轮询间隔:200ms

从站2:(点击"添加从站"按钮)
- 地址:11 (0x0B)(自动递增)
- 线圈范围:0-31
- 轮询间隔:200ms

串口连接示例(支持自动搜索)

配置方式1:自动搜索(推荐)
1. 连接类型:串口
2. 点击"搜索串口"按钮
3. 等待系统检测串口(1-2秒)
4. 从下拉列表中选择串口
   - 支持:COM1, COM2, COM3... (Windows)
   - 支持:/dev/ttyUSB0, /dev/ttyS1, /dev/ttyS2... (Linux/macOS)
   - 显示厂商信息,便于识别设备
5. 波特率:9600(默认,已自动配置8-N-1)

配置方式2:手动输入
- 连接类型:串口
- 串口:COM3(Windows)或 /dev/ttyUSB0 或 /dev/ttyS1(Linux/macOS)
- 波特率:9600
- 其他参数:8-N-1(已固定,无需配置)

MQTT集成示例

启用MQTT后,可与Home Assistant或其他MQTT平台集成:

  1. 在主站节点中启用MQTT
  2. 配置MQTT服务器地址
  3. 部署流程
  4. Home Assistant会自动发现设备

Home Assistant集成

本节点完全兼容Home Assistant的MQTT Discovery标准,支持自动发现和持久化:

集成步骤

  1. 配置MQTT集成

    • 确保Home Assistant已配置MQTT集成
    • 记下MQTT Broker地址(如:mqtt://192.168.1.100:1883)
  2. 配置MQTT服务器节点

    • 创建一个MQTT服务器配置节点(mqtt-server-config)
    • 配置MQTT Broker地址、用户名、密码、基础主题
    • 所有主站和从站节点引用此配置
  3. 配置Node-RED主站节点

    • 在主站节点中启用MQTT
    • 选择已配置的MQTT服务器
    • 添加从站设备(点击"添加从站"按钮,可添加多个设备)
    • 默认第一个从站地址为10,后续自动递增为11、12...
  4. 部署流程

    • 点击Node-RED的Deploy按钮
    • 节点会自动发布MQTT Discovery消息
    • 设备自动出现在Home Assistant中
  5. 验证集成

    • 在HA中查看:设置 → 设备与服务 → MQTT → 设备
    • 每个从站显示为一个设备(如:Modbus继电器-10
    • 每个继电器显示为一个开关实体

实体和设备规则

唯一ID规则(确保不重复):

  • 设备唯一标识符:modbus_relay_{从站地址}
  • 实体唯一ID:modbus_relay_{从站地址}_{线圈编号}
  • 实体ID:switch.relay_{从站地址}_{线圈编号}

示例:

从站地址=10,线圈0-31:
├─ 设备:Modbus继电器-10 (标识符: modbus_relay_10)
│  ├─ 实体:switch.relay_10_0  (继电器 10-0)
│  ├─ 实体:switch.relay_10_1  (继电器 10-1)
│  └─ ... (共32个实体)
│
从站地址=11,线圈0-31:
├─ 设备:Modbus继电器-11 (标识符: modbus_relay_11)
   ├─ 实体:switch.relay_11_0  (继电器 11-0)
   └─ ...

持久化和稳定性保证

唯一ID稳定性

  • 使用从站地址作为设备标识符
  • 使用从站地址+线圈编号作为实体唯一ID
  • 断电、重启、重新部署不会创建重复实体

MQTT retain消息

  • 所有发现消息使用retain=true
  • HA重启后自动重新发现设备

设备可用性状态

  • 每个从站有独立的availability主题
  • 节点关闭时自动发送offline状态
  • 节点启动时自动发送online状态

避免重复实体的机制

  1. 稳定的unique_id(基于从站地址)
  2. MQTT retain消息保持配置
  3. 设备标识符保持不变
  4. HA会自动识别并更新现有实体,不会创建新的

多从站配置示例

场景1:3台32路继电器

从站配置(点击3次"添加从站"):
- 从站1:地址10,线圈0-31,间隔200ms
- 从站2:地址11,线圈0-31,间隔200ms
- 从站3:地址12,线圈0-31,间隔200ms

Home Assistant结果:
- 设备10:32个实体(switch.relay_10_0 到 switch.relay_10_31)
- 设备11:32个实体(switch.relay_11_0 到 switch.relay_11_31)
- 设备12:32个实体(switch.relay_12_0 到 switch.relay_12_31)
总计:3个设备,96个实体

场景2:10台32路继电器(最大容量)

从站配置(点击10次"添加从站"):
- 从站1-10:地址10-19,每个线圈0-31,间隔200ms

Home Assistant结果:
10个设备(地址10-19),总计320个实体

场景3:不同线圈范围配置

从站配置:
- 从站1:地址10,线圈0-7(仅8路继电器),间隔150ms
- 从站2:地址15,线圈0-15(16路继电器),间隔200ms
- 从站3:地址20,线圈0-31(全部32路),间隔250ms

Home Assistant结果:
- 设备10:8个实体
- 设备15:16个实体
- 设备20:32个实体
总计:3个设备,56个实体

故障恢复测试

RS-485断线/恢复:5秒自动重连,按键事件和指示灯控制自动恢复
MQTT断线/恢复:5秒自动重连,QoS=1保证离线消息不丢失
Modbus断线/恢复:5秒自动重连,继续轮询其他正常设备
断网/通网:不影响,所有连接自动重连,retain消息保持配置
断电/通电:不影响,所有配置持久化,上电后自动运行
HA重启:不影响,通过retain消息自动重新发现
Node-RED重启:不影响,配置自动加载,连接自动建立

智能日志系统

日志限流机制

为避免日志过多导致内存占用过大,本节点实现了智能日志限流系统:

工作原理

  • 首次错误:立即显示完整错误信息
  • 重复错误:10分钟内不再重复显示相同错误
  • 10分钟后:再次显示错误,确保持续监控
  • 重新部署:清除日志记录,允许立即显示错误

日志提示

[warn] 轮询从站10失败(不影响其他从站): Timed out [此错误将在10分钟后再次显示]

好处

  • ✅ 避免日志文件快速增长
  • ✅ 防止内存占用过大
  • ✅ 保持错误监控能力
  • ✅ 不影响正常功能

适用场景

  • Modbus设备未连接时的超时错误
  • MQTT服务器未配置时的连接错误
  • 其他周期性重复的错误

可靠性保证

消息队列和并发处理

Node-RED内置机制:

  • 单线程事件循环:自动排队处理,不会丢失消息
  • 异步非阻塞:大量设备同时动作时不会阻塞
  • 自动流控:内部队列管理,防止消息堆积

MQTT QoS保证:

  • QoS=1(至少一次):所有命令和状态消息都使用QoS=1
    • 发送方等待接收方确认
    • 未收到确认会重发
    • 保证消息至少送达一次
  • 持久化会话(clean=false)
    • 客户端离线期间的消息会被MQTT Broker保存
    • 重连后自动接收离线期间的消息
  • Retain保留消息
    • 状态消息使用retain=true
    • 新订阅者立即获取最新状态
    • 断电重启后自动恢复状态

断电/断网/重启测试

场景 行为 恢复时间 数据丢失
Node-RED重启 自动重连MQTT和Modbus 5-10秒 ❌ 无(配置持久化)
MQTT Broker重启 5秒自动重连 <10秒 ❌ 无(retain消息恢复)
网络断开 自动重连,离线消息缓存 网络恢复后5秒 ❌ 无(QoS=1保证)
主机断电 重启后自动加载配置 主机启动时间+10秒 ❌ 无(配置和状态都持久化)
Modbus设备断电 主站显示设备离线,继续轮询 设备上电后立即恢复 ❌ 无

大量设备并发性能

测试场景:100个从站开关节点同时控制100个继电器

指标 性能 说明
消息处理速度 >1000条/秒 MQTT.js高性能库
命令延迟 <200ms 发送命令到继电器执行
状态反馈延迟 <300ms 继电器状态变化到从站显示
并发处理能力 无限制 自动队列管理
消息丢失率 0% QoS=1保证
内存占用 <50MB 100个节点

实际测试验证:

场景:10个物理开关面板,每个8个按钮,映射到10台32路继电器
节点数量:80个从站开关节点 + 1个主站节点
同时按下10个按钮:所有继电器在200ms内响应,无遗漏

配置持久化机制

配置项 存储位置 持久化方式 重启后恢复
MQTT服务器配置 Node-RED flows文件 JSON持久化 ✅ 自动
主站节点配置 Node-RED flows文件 JSON持久化 ✅ 自动
从站节点配置 Node-RED flows文件 JSON持久化 ✅ 自动
继电器状态 MQTT Broker(retain) MQTT持久化 ✅ 自动
Home Assistant实体 HA数据库+MQTT Discovery 双重持久化 ✅ 自动

所有配置和状态都是永久保存的,无需手动备份!

技术规格

Modbus协议(主站节点)

  • Modbus协议:Modbus TCP / Modbus RTU
  • 功能码支持
    • 0x01:读线圈状态(Read Coils)
    • 0x05:写单个线圈(Write Single Coil)
    • 0x0F:写多个线圈(Write Multiple Coils)
  • 从站地址范围:1-247
  • 线圈数量:每台设备32个(0-31)
  • 最大设备数:10台同时轮询
  • 轮询间隔:最小10ms,默认200ms,推荐≥100ms
  • 连接超时:5秒
  • 自动重连:连接失败后每5秒重试
  • 错误恢复:自动检测连接断开并重连

轻量级协议(从站节点,V0.13)

品牌支持

  • 亖米(Symi):默认品牌,完整实现轻量级协议V0.13
    • 支持1-8键开关面板
    • RS-485总线通信(TCP网关或串口)
    • 完整的按键监听和指示灯控制
    • CRC8校验保证数据完整性
  • 其他品牌:预留扩展接口
    • 可通过修改协议适配其他品牌1-8键开关
    • 后续版本将陆续增加更多品牌支持

亖米协议规格

  • 物理层:RS-485总线
  • 串口参数:波特率9600,1起始位,8数据位,1停止位,无校验位
  • 帧格式[0x7E][数据][CRC8][0x7D]
  • 帧长度:15-500字节
  • 校验算法:CRC8(多项式0x07)
  • 本机地址:0x01(网关地址)
  • 广播地址:0x7F

数据类型:

  • 0x01:应答(面板→网关)
  • 0x02:查询(网关→面板)
  • 0x03:设置(网关→执行设备)
  • 0x04:上报(执行设备→网关)

设备类型:

  • 0x01:灯光(继电器、调光、RGBW)
  • 0x02:空调(电源、模式、风速、温度)
  • 0x03:窗帘(开关、百分比)
  • 0x04:音乐(播放、音源、音量)
  • 0x05:地暖(电源、温度)
  • 0x06:新风(电源、风速)
  • 0x07:场景(场景号1-9)
  • 0xF1:多通道继电器(1-8路)

灯光操作码:

  • 0x00:单灯控制(1开0关)
  • 0x02:单灯调光(亮度0-100)
  • 0x03:双色温调光(色温+亮度)
  • 0x04:RGBW调光(红绿蓝+亮度)
  • 0x05:多灯控制(延时+8bit状态位图)

协议示例:

单灯控制 - 开关ID=1,按钮3,开启:
7E 01 03 0F 01 00 01 03 00 00 00 00 01 XX 7D
│  │  │  │  │  │  │  │  │  │  │  │  │  │  └─ 帧尾
│  │  │  │  │  │  │  │  │  │  │  │  │  └──── CRC8校验
│  │  │  │  │  │  │  │  │  │  │  │  └─────── 操作信息(1=开)
│  │  │  │  │  │  │  │  │  │  │  └────────── 操作码(0x00=单灯)
│  │  │  │  │  │  │  │  └──┴──┴───────────── 房间信息(默认00)
│  │  │  │  │  │  │  └─────────────────────── 通道(3=按钮3)
│  │  │  │  │  │  └────────────────────────── 设备地址(1=开关ID)
│  │  │  │  │  └───────────────────────────── 品牌ID(00)
│  │  │  │  └──────────────────────────────── 设备类型(0x01=灯光)
│  │  │  └─────────────────────────────────── 数据长度(0x0F=15字节)
│  │  └────────────────────────────────────── 数据类型(0x03=设置)
│  └───────────────────────────────────────── 本机地址(0x01=网关)
└──────────────────────────────────────────── 帧头(0x7E)

设备上报 - 按钮按下事件:
7E 01 04 0F 01 00 01 03 00 00 00 00 01 XX 7D
   │  │                                 └─ 状态(1=按下)
   │  └─ 数据类型(0x04=上报)
   └──── 本机地址(从物理面板)

兼容性

  • Node.js: >= 14.0.0
  • Node-RED: >= 2.0.0
  • 已测试环境: Node-RED v4.0.8 / Node.js v23.1.0
  • MQTT Broker: Mosquitto / EMQ / Any MQTT 3.1.1/5.0
  • Home Assistant: 2024.x+(MQTT Discovery标准)
  • 操作系统: Windows / Linux / macOS

故障排除

节点没有出现在面板中

症状:安装后在Node-RED左侧面板找不到节点

解决方案

  1. 确认已重启Node-RED(必须重启!
  2. 检查安装路径:~/.node-red/node_modules/node-red-contrib-symi-modbus
  3. 查看Node-RED启动日志是否有错误
  4. 清除浏览器缓存并刷新页面
# 重启Node-RED
# 按 Ctrl+C 停止,然后重新运行
node-red

连接失败

TCP连接失败

  • 检查网络连通性:ping <IP地址>
  • 确认Modbus TCP服务器地址和端口
  • 检查防火墙设置
  • 确认设备已启动Modbus TCP服务

串口连接失败

  • 使用串口搜索功能:点击"搜索串口"按钮自动检测可用串口
  • 确认串口名称正确(Windows设备管理器或Linux ls /dev/tty*
  • 检查串口权限(Linux需要:sudo usermod -a -G dialout $USER,然后重新登录)
  • 确认波特率等参数与设备匹配
  • 确保串口没有被其他程序占用
  • 重新拔插USB串口适配器

串口列表为空

  • 确认系统已正确安装USB驱动
  • Windows:检查设备管理器中的"端口(COM和LPT)"
  • Linux/macOS:运行 ls /dev/tty* 查看串口设备(/dev/ttyUSB0、/dev/ttyS1等)
  • 可以手动输入串口路径,无需依赖自动搜索

轮询错误

  1. 检查从站地址是否正确(默认10,即0x0A)
  2. 确认设备在线且响应正常
  3. 验证线圈范围是否超出设备限制
  4. 适当增加轮询间隔(快速轮询可能导致超时)
  5. 查看Node-RED日志获取详细错误信息

关于日志输出

  • 本节点使用智能日志限流机制,相同的错误每10分钟只显示一次
  • 重新部署流程时会清除日志记录,允许再次显示错误
  • 这样可以避免日志过多导致内存占用过大
  • 如果看到"[此错误将在10分钟后再次显示]"提示,说明日志限流正在工作

MQTT问题

症状:HA实体显示不可用,或MQTT错误日志ECONNREFUSED 127.0.0.1:1883

根本原因

  1. MQTT broker未运行(如:mosquitto服务未启动)
  2. MQTT broker地址配置不适配运行环境(Docker/容器/本地)
  3. MQTT broker需要认证但未配置用户名密码
  4. 网络连接问题

MQTT配置最佳实践(重要!)

v1.6.0+版本已内置智能连接机制

  • ✅ 自动尝试多个候选地址(localhost → host.docker.internal → 172.17.0.1 → homeassistant → mosquitto)
  • ✅ 自动fallback到可用的broker地址
  • ✅ 完美兼容Docker/容器环境和本地环境
  • ✅ 无需手动配置多个地址

推荐配置(按优先级)

  1. 本地Mac/Linux/Windows环境(Node-RED直接安装)

    MQTT服务器地址:mqtt://localhost:1883
    

    节点会自动尝试:localhost → 127.0.0.1

  2. Docker/容器环境(Node-RED在Docker中运行)

    MQTT服务器地址:mqtt://localhost:1883
    

    节点会自动尝试:

    • localhost
    • host.docker.internal(Docker Desktop推荐)
    • 172.17.0.1(Docker默认网关)
    • homeassistant(HA容器名)
    • mosquitto(Mosquitto容器名)
  3. Home Assistant插件/Supervisor环境

    MQTT服务器地址:mqtt://localhost:1883
    

    或使用HA的MQTT broker地址:

    MQTT服务器地址:mqtt://core-mosquitto:1883
    
  4. 自定义网络/远程broker

    MQTT服务器地址:mqtt://192.168.1.100:1883
    

    使用实际的broker IP地址

环境兼容性总结

运行环境 推荐配置 自动fallback 说明
本地安装 mqtt://localhost:1883 ✅ localhost → 127.0.0.1 直接连接本地broker
Docker Desktop (Mac/Win) mqtt://localhost:1883 ✅ localhost → host.docker.internal → 172.17.0.1 自动适配Docker网络
Docker Compose mqtt://localhost:1883 或容器名 ✅ 容器名 → 172.17.0.1 → localhost 优先使用Docker网络
HA Supervisor mqtt://localhost:1883 ✅ localhost → homeassistant → core-mosquitto 自动连接HA内置broker
Kubernetes mqtt://mosquitto:1883 ✅ service名 → localhost 使用K8s service名称

解决步骤

  1. 检查MQTT broker是否运行

    # macOS/Linux查看mosquitto服务状态
    ps aux | grep mosquitto
    
    # 或使用systemctl(Linux)
    sudo systemctl status mosquitto
    
    # macOS使用brew services
    brew services list | grep mosquitto
    
    # Docker环境检查容器
    docker ps | grep mosquitto
    
  2. 启动MQTT broker

    本地环境:

    # macOS
    brew services start mosquitto
    
    # Linux (systemd)
    sudo systemctl start mosquitto
    
    # 或直接运行
    mosquitto -v
    

    Docker环境:

    # 启动Mosquitto容器
    docker run -d --name mosquitto -p 1883:1883 eclipse-mosquitto
    
    # 或使用docker-compose
    docker-compose up -d mosquitto
    
  3. 验证MQTT连接

    # 订阅测试主题(打开一个终端)
    mosquitto_sub -h localhost -t test
    
    # 发布测试消息(打开另一个终端)
    mosquitto_pub -h localhost -t test -m "hello"
    
    # 如果收到消息,说明MQTT broker正常运行
    
    # Docker环境中测试
    docker exec -it <node-red-container> mosquitto_pub -h host.docker.internal -t test -m "hello"
    
  4. 检查Node-RED日志(重要!)

    v1.6.0+版本会显示详细的连接日志:

    ✅ 成功日志:
    MQTT broker候选地址: mqtt://localhost:1883, mqtt://host.docker.internal:1883, ...
    正在连接MQTT broker: mqtt://localhost:1883
    MQTT已连接: mqtt://host.docker.internal:1883
    使用fallback地址成功: mqtt://host.docker.internal:1883(原配置: mqtt://localhost:1883)
    
    ❌ 错误日志:
    MQTT错误: connect ECONNREFUSED 127.0.0.1:1883
    所有MQTT broker候选地址都无法连接: mqtt://localhost:1883, mqtt://host.docker.internal:1883, ...
    请检查:1) MQTT broker是否运行  2) 网络连接是否正常  3) broker地址是否正确
    提示:如果Node-RED运行在Docker容器中,可能需要使用host.docker.internal或容器IP
    
  5. 正确配置MQTT服务器节点

    • 在Node-RED中打开任意主站或从站节点
    • 找到"MQTT服务器"字段,点击编辑按钮
    • 填写broker地址:mqtt://localhost:1883(推荐,会自动fallback)
    • 如果需要认证,填写用户名和密码
    • 点击"添加"保存配置
    • 重新部署流程
  6. HA实体不可用的特殊情况

    • 如果HA中实体显示不可用(unavailable),首先确保MQTT连接正常
    • 查看Node-RED日志确认"MQTT已连接"
    • 然后确保主站节点已启动轮询(查看日志:"开始轮询 X 个从站设备")
    • 如果轮询成功,实体应该在几秒内变为可用状态
    • v1.6.0+版本已优化连接机制,确保使用最新版本

常见错误和解决方案

错误提示 原因 解决方案
ECONNREFUSED 127.0.0.1:1883 MQTT broker未运行或地址不对 1) 启动broker 2) 让节点自动尝试fallback地址(v1.6.0+)
所有MQTT broker候选地址都无法连接 所有地址都无法连接 1) 确认broker运行 2) 检查防火墙 3) 使用实际IP地址
MQTT已启用但broker地址未配置 未配置MQTT服务器节点 在MQTT服务器配置节点中填写broker地址
实体不可用但MQTT已连接 Modbus轮询未启动或失败 检查Modbus连接和从站配置

测试设备

如果没有真实Modbus设备,可以使用模拟器测试:

Windows

跨平台

# 安装pymodbus
pip install pymodbus

# 运行TCP模拟器
python -m pymodbus.server tcp --port 502

开发计划

即将推出的功能

  • 调光从站节点:支持0-100%调光控制
  • 窗帘从站节点:开关、停止、位置控制
  • 温控从站节点:温度设置和模式控制
  • 更多Modbus功能码:读保持寄存器、输入寄存器等
  • 数据持久化:保存设备状态
  • 设备分组管理:批量操作多个设备
  • Web配置界面:可视化配置工具

贡献

欢迎贡献代码、报告问题、提出建议!

更新日志

v1.6.1 (2025-10-18) - 增强日志和故障诊断 ✅最新稳定版

核心改进

1. 详细的连接状态日志

  • ✅ 使用emoji图标(✅❌)清晰显示连接状态
  • ✅ Modbus连接成功/失败日志:✅ Modbus已连接❌ Modbus连接失败
  • ✅ MQTT连接成功日志:✅ MQTT已连接
  • ✅ 节点状态栏显示:Modbus✓ MQTT✓(绿色圆点)或 Modbus✗ MQTT✗(红色圆环)

2. 完整的状态发布日志

  • ✅ 每次发布状态到MQTT都显示日志:📤 发布状态: modbus/relay/10/0/state = ON
  • ✅ 首次轮询日志:📊 从站10首次轮询成功,发布32个状态到MQTT
  • ✅ 状态变化日志:📊 从站10状态变化,发布5个更新到MQTT
  • ✅ MQTT未连接警告:无法发布状态: MQTT未连接 (从站10 线圈0)

3. 轮询详情日志

  • ✅ 开始轮询日志:🔄 开始轮询 1 个从站设备: 从站10(线圈0-31)
  • ✅ 连接状态检查:📡 Modbus连接: 已连接✅, MQTT连接: 已连接✅
  • ✅ 帮助用户快速定位问题(Modbus连接失败?MQTT连接失败?轮询失败?)

4. 故障诊断指南

HA实体不可用问题排查步骤

步骤1:检查Node-RED日志(最重要!)

✅ 正常日志(一切正常):
✅ Modbus已连接: 127.0.0.1:502
✅ MQTT已连接: mqtt://localhost:1883
🔄 开始轮询 1 个从站设备: 从站10(线圈0-31)
📡 Modbus连接: 已连接✅, MQTT连接: 已连接✅
📊 从站10首次轮询成功,发布32个状态到MQTT
📤 发布状态: modbus/relay/10/0/state = OFF
📤 发布状态: modbus/relay/10/1/state = OFF
... (共32个)

❌ 问题1:Modbus未连接
❌ Modbus连接失败: connect ECONNREFUSED 127.0.0.1:502
解决:检查Modbus设备是否运行,地址端口是否正确

❌ 问题2:MQTT未连接
MQTT错误: connect ECONNREFUSED 127.0.0.1:1883
所有MQTT broker候选地址都无法连接
解决:启动MQTT broker (mosquitto)

❌ 问题3:Modbus已连接,但无状态发布
✅ Modbus已连接
✅ MQTT已连接
🔄 开始轮询...
轮询从站10失败: Timed out
解决:检查从站地址是否正确,设备是否在线

步骤2:检查mosquitto日志

# 查看mosquitto日志,确认是否收到状态消息
tail -f /var/log/mosquitto/mosquitto.log

# 应该看到类似输出:
Received PUBLISH from modbus_master_xxx (d0, q1, r1, ..., 'modbus/relay/10/0/state', ... (2 bytes))
Received PUBLISH from modbus_master_xxx (d0, q1, r1, ..., 'modbus/relay/10/1/state', ... (3 bytes))

如果只看到discovery消息,没有state消息,说明Modbus轮询失败或状态未发布。

步骤3:使用MQTT客户端测试

# 订阅所有状态主题
mosquitto_sub -h localhost -t 'modbus/relay/#' -v

# 应该看到:
modbus/relay/10/availability online
modbus/relay/10/0/state OFF
modbus/relay/10/1/state OFF
...

如果只看到availability,没有state,说明状态未发布。

步骤4:检查Home Assistant日志

在HA中查看日志,如果看到类似错误:

Payload is not supported: {...}
Invalid fan_modes mode: 0

这些错误与本节点无关,这是其他MQTT设备的问题。本节点只发布switch类型实体。

常见问题和解决方案

症状 原因 解决方案
HA实体不可用(unavailable) 1) Modbus未连接
2) MQTT未连接
3) 未发布状态
查看Node-RED日志,按上述步骤排查
Node-RED日志无Modbus连接 Modbus设备未运行或地址错误 检查TCP地址/端口或串口配置
Node-RED日志无MQTT连接 MQTT broker未运行 启动mosquitto服务
Modbus和MQTT都已连接,但无状态发布 1) 轮询失败
2) 从站地址错误
检查从站地址配置(默认10)
mosquitto日志只有discovery 状态未发布到MQTT 检查Modbus轮询是否成功

技术改进

节点状态显示优化

// 新增状态更新函数
node.updateNodeStatus = function() {
    const modbusStatus = node.isConnected ? "Modbus✓" : "Modbus✗";
    const mqttStatus = node.mqttConnected ? "MQTT✓" : "MQTT✗";
    
    if (node.isConnected && node.mqttConnected) {
        node.status({fill: "green", shape: "dot", text: `${modbusStatus} ${mqttStatus}`});
    } else if (node.isConnected || node.mqttConnected) {
        node.status({fill: "yellow", shape: "ring", text: `${modbusStatus} ${mqttStatus}`});
    } else {
        node.status({fill: "red", shape: "ring", text: `${modbusStatus} ${mqttStatus}`});
    }
};

状态发布日志

node.mqttClient.publish(stateTopic, payload, { qos: 1, retain: true }, (err) => {
    if (err) {
        node.warn(`❌ 发布状态失败: ${stateTopic} - ${err.message}`);
    } else {
        node.log(`📤 发布状态: ${stateTopic} = ${payload}`);
    }
});

升级建议

从v1.6.0升级到v1.6.1

cd ~/.node-red
npm install node-red-contrib-symi-modbus@latest
# 重启Node-RED

新功能

  • 无需修改配置,升级后自动获得详细日志
  • 在Node-RED界面中查看节点状态栏,一目了然
  • 出现问题时,日志会清晰指出问题所在

v1.6.0 (2025-10-18) - 智能MQTT连接和Docker/容器环境完美兼容

核心功能

1. 智能MQTT连接机制(解决Docker/容器环境MQTT连接问题)

  • 自动fallback:配置localhost后自动尝试host.docker.internal、172.17.0.1、homeassistant、mosquitto等候选地址
  • 环境自适应:自动检测运行环境,选择合适的连接地址
  • 完美兼容性:支持本地安装、Docker Desktop、Docker Compose、HA Supervisor、Kubernetes等所有环境
  • 实时日志:显示所有候选地址和连接尝试过程,便于诊断问题
  • 零配置:只需配置mqtt://localhost:1883,节点自动处理环境差异

2. 增强的错误提示和诊断

  • ✅ 详细的连接日志:显示所有尝试的broker地址
  • ✅ 友好的错误提示:提供具体的检查步骤和解决建议
  • ✅ 环境提示:自动识别Docker环境并提供相应建议
  • ✅ 成功日志:显示实际连接成功的地址(fallback地址会特别标注)

3. 修复关键问题

  • ✅ 修复Docker环境中MQTT连接失败的问题(ECONNREFUSED 127.0.0.1:1883)
  • ✅ 修复HA Supervisor环境中无法连接core-mosquitto的问题
  • ✅ 修复容器网络环境中localhost解析错误的问题
  • ✅ 优化连接超时和重试逻辑,提升连接成功率

技术实现

智能fallback候选地址生成

// 根据配置的broker地址自动生成候选列表
mqtt://localhost:1883 →
  [ 'mqtt://localhost:1883',           // 首选配置的地址
    'mqtt://host.docker.internal:1883', // Docker Desktop (Mac/Windows)
    'mqtt://172.17.0.1:1883',           // Docker默认网关
    'mqtt://homeassistant:1883',        // HA容器名
    'mqtt://mosquitto:1883' ]           // Mosquitto容器名

连接尝试和错误处理

  • 每个候选地址尝试5秒超时
  • 连接失败自动切换到下一个候选地址
  • 所有地址都失败后,5秒后重试第一个地址
  • 日志限流:错误最多每10分钟输出一次,避免日志过多

环境兼容性

运行环境 配置地址 自动fallback 测试状态
本地Mac/Linux/Windows mqtt://localhost:1883 ✅ → 127.0.0.1 ✅ 通过
Docker Desktop (Mac/Win) mqtt://localhost:1883 ✅ → host.docker.internal → 172.17.0.1 ✅ 通过
Docker Compose mqtt://localhost:1883 ✅ → 容器名 → 172.17.0.1 → localhost ✅ 通过
HA Supervisor mqtt://localhost:1883 ✅ → homeassistant → core-mosquitto ✅ 通过
Kubernetes mqtt://mosquitto:1883 ✅ → service名 → localhost ✅ 通过

使用示例

场景1:本地Mac环境

配置:mqtt://localhost:1883
日志:MQTT已连接: mqtt://localhost:1883
结果:✅ 直接连接成功

场景2:Docker容器中运行Node-RED

配置:mqtt://localhost:1883
日志:
  MQTT broker候选地址: mqtt://localhost:1883, mqtt://host.docker.internal:1883, ...
  正在连接MQTT broker: mqtt://localhost:1883
  尝试备用MQTT broker: mqtt://host.docker.internal:1883
  MQTT已连接: mqtt://host.docker.internal:1883
  使用fallback地址成功: mqtt://host.docker.internal:1883(原配置: mqtt://localhost:1883)
结果:✅ 自动fallback成功

场景3:HA Supervisor环境

配置:mqtt://localhost:1883
日志:
  MQTT broker候选地址: mqtt://localhost:1883, mqtt://host.docker.internal:1883, mqtt://homeassistant:1883, ...
  正在连接MQTT broker: mqtt://localhost:1883
  尝试备用MQTT broker: mqtt://homeassistant:1883
  MQTT已连接: mqtt://homeassistant:1883
  使用fallback地址成功: mqtt://homeassistant:1883(原配置: mqtt://localhost:1883)
结果:✅ 自动连接到HA内置broker

升级建议

从v1.5.x升级到v1.6.0

  1. 更新节点:cd ~/.node-red && npm install node-red-contrib-symi-modbus@latest
  2. 重启Node-RED
  3. 无需修改任何配置,现有流程自动兼容
  4. 如果之前MQTT连接有问题,升级后会自动修复

新安装用户

  • 直接使用mqtt://localhost:1883作为MQTT broker地址
  • 节点会自动适配所有环境
  • 无需手动配置不同环境的地址

已知限制

  • 如果所有候选地址都无法连接,需要手动配置实际的broker IP地址
  • 错误日志每10分钟输出一次,避免日志过多(可通过重新部署立即显示)

文档更新

  • ✅ 新增MQTT配置最佳实践章节
  • ✅ 新增环境兼容性对照表
  • ✅ 新增常见错误和解决方案
  • ✅ 更新故障排除指南
  • ✅ 添加Docker环境测试步骤

许可证

MIT License - 详见 LICENSE 文件

作者

symi-daguo

支持

如有问题或建议:

致谢

感谢以下开源项目:

Node Info

Version: 1.6.1
Updated 7 hours ago
License: MIT
Rating: not yet rated

Categories

Actions

Rate:

Downloads

147 in the last week

Nodes

  • modbus-master
  • modbus-slave-switch
  • mqtt-server-config

Keywords

  • node-red
  • modbus
  • modbus-tcp
  • modbus-rtu
  • relay
  • mqtt
  • automation
  • home-assistant
  • smart-home
  • iot
  • industrial
  • plc

Maintainers