node-red-contrib-symi-modbus 1.5.4 → 1.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,6 +34,88 @@ npm install node-red-contrib-symi-modbus
34
34
 
35
35
  **已发布到npm:** https://www.npmjs.com/package/node-red-contrib-symi-modbus
36
36
 
37
+ ### Docker/容器环境安装
38
+
39
+ 本节点依赖`modbus-serial`包,该包包含native C++模块(serialport),需要编译环境。
40
+
41
+ #### ⚠️ 如果遇到安装错误
42
+
43
+ **错误示例:**
44
+ ```
45
+ npm error code 127
46
+ npm error command sh -c node-gyp-build
47
+ npm error sh: node-gyp-build: not found
48
+ ```
49
+
50
+ **原因:** Docker容器缺少编译工具(python、make、g++)
51
+
52
+ **解决方案1:使用官方Node-RED Docker镜像(推荐)**
53
+
54
+ 官方镜像已包含编译工具:
55
+ ```bash
56
+ docker pull nodered/node-red:latest
57
+ ```
58
+
59
+ **解决方案2:在Dockerfile中添加编译依赖**
60
+
61
+ Alpine基础镜像:
62
+ ```dockerfile
63
+ FROM nodered/node-red:latest
64
+ # 或者自定义镜像时添加
65
+ RUN apk add --no-cache \
66
+ python3 \
67
+ make \
68
+ g++ \
69
+ linux-headers
70
+ ```
71
+
72
+ Debian/Ubuntu基础镜像:
73
+ ```dockerfile
74
+ FROM nodered/node-red:latest
75
+ # 或者
76
+ RUN apt-get update && apt-get install -y \
77
+ python3 \
78
+ make \
79
+ g++ \
80
+ build-essential
81
+ ```
82
+
83
+ **解决方案3:在运行中的容器安装**
84
+
85
+ ```bash
86
+ # 进入容器
87
+ docker exec -it <container_id> /bin/sh
88
+
89
+ # Alpine
90
+ apk add --no-cache python3 make g++ linux-headers
91
+
92
+ # Debian/Ubuntu
93
+ apt-get update && apt-get install -y python3 make g++ build-essential
94
+
95
+ # 退出容器后,在Node-RED界面重新安装节点
96
+ ```
97
+
98
+ **解决方案4:使用docker-compose(推荐)**
99
+
100
+ ```yaml
101
+ version: '3.8'
102
+ services:
103
+ node-red:
104
+ image: nodered/node-red:latest
105
+ ports:
106
+ - "1880:1880"
107
+ volumes:
108
+ - node-red-data:/data
109
+ # 如果需要串口设备,添加设备映射
110
+ devices:
111
+ - "/dev/ttyUSB0:/dev/ttyUSB0"
112
+ # 如果需要串口权限
113
+ user: "1000:20" # dialout组ID通常是20
114
+
115
+ volumes:
116
+ node-red-data:
117
+ ```
118
+
37
119
  ### 本地开发安装
38
120
 
39
121
  ```bash
@@ -963,10 +1045,70 @@ node-red
963
1045
 
964
1046
  ### MQTT问题
965
1047
 
966
- 1. 确认MQTT Broker地址正确且可访问
967
- 2. 检查用户名密码(如果需要)
968
- 3. 查看Node-RED日志确认MQTT连接状态
969
- 4. 测试MQTT连接:`mosquitto_pub -h localhost -t test -m "hello"`
1048
+ **症状**:HA实体显示不可用,或MQTT错误日志
1049
+
1050
+ **原因分析**:
1051
+ 1. MQTT broker未运行(如:mosquitto服务未启动)
1052
+ 2. MQTT broker地址配置错误
1053
+ 3. MQTT broker需要认证但未配置用户名密码
1054
+ 4. 网络连接问题
1055
+
1056
+ **解决方案**:
1057
+
1058
+ 1. **检查MQTT broker是否运行**
1059
+ ```bash
1060
+ # macOS/Linux查看mosquitto服务状态
1061
+ ps aux | grep mosquitto
1062
+
1063
+ # 或使用systemctl(Linux)
1064
+ sudo systemctl status mosquitto
1065
+
1066
+ # macOS使用brew services
1067
+ brew services list | grep mosquitto
1068
+ ```
1069
+
1070
+ 2. **启动MQTT broker**
1071
+ ```bash
1072
+ # macOS
1073
+ brew services start mosquitto
1074
+
1075
+ # Linux (systemd)
1076
+ sudo systemctl start mosquitto
1077
+
1078
+ # 或直接运行
1079
+ mosquitto -v
1080
+ ```
1081
+
1082
+ 3. **验证MQTT连接**
1083
+ ```bash
1084
+ # 订阅测试主题(打开一个终端)
1085
+ mosquitto_sub -h localhost -t test
1086
+
1087
+ # 发布测试消息(打开另一个终端)
1088
+ mosquitto_pub -h localhost -t test -m "hello"
1089
+
1090
+ # 如果收到消息,说明MQTT broker正常运行
1091
+ ```
1092
+
1093
+ 4. **检查Node-RED日志**
1094
+ - 查看是否有"正在连接MQTT broker: xxx"日志
1095
+ - 查看MQTT错误提示,根据提示信息定位问题
1096
+ - 如果提示"无法连接到MQTT broker",检查broker是否运行
1097
+ - 如果提示"MQTT已启用但broker地址未配置",在MQTT服务器配置节点中填写broker地址
1098
+
1099
+ 5. **正确配置MQTT服务器节点**
1100
+ - 在Node-RED中打开任意主站或从站节点
1101
+ - 找到"MQTT服务器"字段,点击编辑按钮
1102
+ - 填写正确的broker地址(如:`mqtt://localhost:1883`或`mqtt://192.168.1.100:1883`)
1103
+ - 如果需要认证,填写用户名和密码
1104
+ - 点击"添加"保存配置
1105
+ - 重新部署流程
1106
+
1107
+ 6. **HA实体不可用的特殊情况**
1108
+ - 如果HA中实体显示不可用(unavailable),首先确保MQTT连接正常
1109
+ - 然后确保主站节点已启动轮询(查看日志:"开始轮询 X 个从站设备")
1110
+ - 如果轮询成功,实体应该在几秒内变为可用状态
1111
+ - v1.5.5+版本已修复初始状态发布问题,确保使用最新版本
970
1112
 
971
1113
  ### 测试设备
972
1114
 
@@ -1003,144 +1145,52 @@ python -m pymodbus.server tcp --port 502
1003
1145
 
1004
1146
  ## 更新日志
1005
1147
 
1006
- ### v1.5.4 (2025-10-18) - MQTT错误日志优化 ✅最新版本
1007
- - ✅ **MQTT错误日志限流**:
1008
- - MQTT连接错误也采用10分钟限流机制
1009
- - 避免MQTT未配置时频繁输出错误日志(每几秒一次)
1010
- - 与Modbus错误日志统一管理,保持日志整洁
1011
- - 重新部署时清除MQTT错误日志记录,允许再次显示
1012
- - ✅ **日志系统完善**:
1013
- - 所有错误日志都采用10分钟限流机制
1014
- - 提示信息统一:"[此错误将在10分钟后再次显示]"
1015
- - 不影响功能正常运行,只是减少重复日志输出
1016
- - ✅ **默认配置确认**:
1017
- - RS-485串口参数默认9600-8-N-1(符合亖米协议)
1018
- - 面板品牌默认SYMI,支持1-8键开关
1019
- - 所有默认参数都已正确配置并持久化
1148
+ ### v1.5.7 (2025-10-18) - Docker/容器环境支持文档 ✅最新版本
1149
+ - ✅ **Docker环境安装指南**:
1150
+ - 添加完整的Docker/容器环境安装说明
1151
+ - 详细解释native模块编译错误的原因和解决方案
1152
+ - 提供4种解决方案:官方镜像、Dockerfile配置、运行时安装、docker-compose
1153
+ - 包含Alpine和Debian/Ubuntu两种基础镜像的配置示例
1154
+ - ✅ **错误码127说明**:
1155
+ - 明确说明`npm error code 127`是环境问题,不是代码问题
1156
+ - 提供清晰的错误诊断步骤
1157
+ - 帮助用户快速定位和解决serialport编译问题
1158
+ - ✅ **docker-compose示例**:
1159
+ - 提供完整的docker-compose.yml配置
1160
+ - 包含串口设备映射和权限配置
1161
+ - 适合生产环境部署
1162
+
1163
+ ### v1.5.6 (2025-10-18) - MQTT错误提示优化
1164
+ - ✅ **MQTT错误提示改进**:
1165
+ - 当MQTT连接失败且错误消息为空时,提供友好的默认提示
1166
+ - 明确提示broker地址和可能的原因:"无法连接到MQTT broker: xxx,请检查broker是否运行"
1167
+ - 添加MQTT连接日志:"正在连接MQTT broker: xxx",便于调试
1168
+ - 帮助用户快速定位MQTT配置问题
1169
+ - ✅ **调试信息完善**:
1170
+ - MQTT连接过程增加详细日志输出
1171
+ - 错误提示更加明确和友好
1172
+ - 便于用户排查MQTT连接问题
1173
+
1174
+ ### v1.5.5 (2025-10-18) - HA自动发现修复和初始状态发布
1175
+ - ✅ **修复HA实体不可用问题**:
1176
+ - 添加MQTT broker配置验证,空地址时不尝试连接并给出警告
1177
+ - 第一次轮询成功后立即发布所有线圈的初始状态到MQTT
1178
+ - 确保HA能立即获取到设备的真实状态,实体显示为可用
1179
+ - 解决初始状态为false时不发布导致实体不可用的问题
1180
+ - ✅ **初始状态发布机制**:
1181
+ - 新增initialPublished标志,记录每个从站是否已发布初始状态
1182
+ - 第一次轮询成功后,无论状态值是什么,都发布到MQTT
1183
+ - 后续轮询只在状态改变时发布,减少MQTT消息量
1184
+ - 确保HA自动发现后立即显示正确的设备状态
1185
+ - ✅ **MQTT配置优化**:
1186
+ - 主站和从站都添加broker地址验证
1187
+ - 配置无效时不尝试连接,避免无意义的错误日志
1188
+ - 提供清晰的警告信息,帮助用户配置
1020
1189
  - ✅ **完整测试验证**:
1021
- - 日志限流机制测试通过
1022
- - Node-RED持久稳定运行
1190
+ - 从站轮询正常,HA实体自动创建并显示可用
1191
+ - 初始状态正确同步到HA
1023
1192
  - 配置持久化保存正常
1024
1193
 
1025
- ### v1.5.3 (2025-10-18) - 界面优化和智能日志系统
1026
- - ✅ **串口选择界面优化**:
1027
- - 输入框和下拉框一体化,不再单独占用一行
1028
- - 点击搜索后,下拉框替换输入框显示检测到的串口
1029
- - 选择串口后自动填充并恢复输入框显示
1030
- - 完美支持所有类型串口(COM1、/dev/ttyUSB0、/dev/ttyS1等)
1031
- - ✅ **智能日志限流系统**:
1032
- - Modbus超时错误每10分钟只提示一次,避免日志过多
1033
- - 重新部署时清除日志记录,允许再次显示错误
1034
- - 减少日志输出,防止内存占用过大
1035
- - 保持功能正常,不影响错误监控
1036
- - ✅ **界面布局完善**:
1037
- - 主站节点:Grid布局,从站地址/线圈范围/轮询间隔完美对齐
1038
- - 标签在输入框上方,清晰的垂直布局
1039
- - 移除所有emoji图标,保持专业简洁
1040
- - 渐变配色和阴影效果,现代化视觉
1041
- - ✅ **错误处理优化**:
1042
- - RS-485连接添加配置验证,防止无效配置重试
1043
- - 串口未配置时提供明确提示
1044
- - 配置错误时不重试,避免无用日志
1045
- - ✅ **完整测试验证**:
1046
- - Node-RED v4.0.8 / Node.js v23.1.0测试通过
1047
- - 日志输出优化,10分钟内不重复显示相同错误
1048
- - 界面布局完美,串口选择流畅
1049
-
1050
- ### v1.5.0 (2025-10-18) - 串口搜索和完整测试
1051
- - ✅ **串口自动搜索**:主站和从站节点支持一键搜索本机可用串口
1052
- - 点击"搜索串口"按钮自动检测系统串口
1053
- - 双击列表项自动填入串口名称
1054
- - 显示串口厂商信息,便于识别
1055
- - 兼容serialport v9和v10+
1056
- - ✅ **串口连接修复**:优化串口列表API,使用modbus-serial自带的serialport模块
1057
- - ✅ **代码规范检查**:符合Node-RED开发标准
1058
- - ✅ **完整测试验证**:Node-RED启动正常,节点加载成功
1059
- - ✅ **文档完善**:更新所有配置说明和使用指南
1060
-
1061
- ### v1.4.0 (2025-10-18) - 界面优化和品牌扩展
1062
- - ✅ **品牌选择功能**:从站开关节点增加品牌选择(默认亖米,预留其他品牌扩展)
1063
- - ✅ **界面布局优化**:
1064
- - 主站节点:从站地址/线圈标签紧贴输入框,更清晰的布局
1065
- - 从站节点:所有标签优化对齐,提升配置体验
1066
- - ✅ **全面美化**:
1067
- - 统一间距和对齐方式
1068
- - 优化配置区域分组(颜色、边框、圆角)
1069
- - 改进提示信息样式(蓝色、黄色、绿色主题)
1070
- - 增强按钮视觉效果(悬停、禁用状态)
1071
- - ✅ **代码规范检查**:确保符合Node-RED开发标准
1072
- - ✅ **本地测试验证**:安装测试通过,节点加载正常
1073
-
1074
- ### v1.3.0 (2025-10-17) - 轻量级协议完整实现 ✅已发布到npm
1075
- - ✅ **完整协议实现**:实现轻量级智能家居通信协议(V0.13)
1076
- - ✅ **协议解析**:完整的帧解析、CRC8校验、按键事件检测
1077
- - ✅ **协议构建**:单灯控制、多灯控制、查询指令完整实现
1078
- - ✅ **按键监听**:实时监听RS-485总线上的按键按下事件
1079
- - ✅ **指示灯控制**:通过协议同步控制物理面板指示灯
1080
- - ✅ **完整三向同步**:
1081
- - 物理按键 → RS-485协议 → MQTT命令 → 继电器动作
1082
- - 继电器状态 → MQTT状态 → RS-485协议 → 指示灯同步
1083
- - 远程控制 → MQTT → 继电器 + 指示灯同步
1084
- - ✅ **协议帧格式**:0x7E帧头 + 数据 + CRC8 + 0x7D帧尾
1085
- - ✅ **多种操作类型**:单灯控制(0x00)、多灯控制(0x05)、查询(0x02)
1086
- - ✅ **CRC8校验**:完整的CRC8算法实现,确保数据完整性
1087
- - ✅ **自动应答**:接收到按键事件后自动发送MQTT命令
1088
- - ✅ **状态同步**:MQTT状态变化自动发送RS-485控制指令
1089
- - ✅ **已发布npm**:https://www.npmjs.com/package/node-red-contrib-symi-modbus
1090
- - ✅ **npm安装验证**:从npm安装测试通过
1091
-
1092
- ### v1.2.0 (2025-10-17) - 完整RS-485总线支持
1093
- - ✅ **新增RS-485总线连接**:从站节点支持连接物理开关面板的RS-485总线
1094
- - ✅ **TCP/串口双模式**:支持RS-485转TCP网关或直连串口
1095
- - ✅ **监听按键事件**:实时监听物理面板的按钮按下事件
1096
- - ✅ **控制指示灯**:同步控制物理面板的指示灯状态
1097
- - ✅ **三向同步**:物理面板 ↔ 从站 ↔ MQTT ↔ 主站 ↔ Modbus继电器
1098
- - ✅ **双协议桥接**:RS-485协议 + MQTT协议无缝桥接
1099
- - ✅ **状态显示优化**:显示RS-485和MQTT连接状态
1100
- - ✅ **自动重连**:RS-485和MQTT都支持5秒自动重连
1101
- - ✅ **配置持久化**:所有RS-485配置自动保存
1102
- - ✅ **协议扩展接口**:预留轻量级协议实现接口
1103
-
1104
- ### v1.1.0 (2025-10-17) - 重大可靠性提升
1105
- - ✅ **新增MQTT服务器配置节点**:统一管理MQTT连接信息
1106
- - ✅ **简化配置流程**:主站和从站共享MQTT配置,避免重复输入
1107
- - ✅ **防止配置错误**:确保所有节点使用相同的MQTT服务器和主题
1108
- - ✅ **配置持久化**:MQTT服务器配置自动保存,重启不丢失
1109
- - ✅ **QoS=1消息保证**:所有命令和状态消息使用QoS=1,确保不丢失
1110
- - ✅ **持久化会话**:clean=false,断线重连后继续接收未读消息
1111
- - ✅ **自动重连机制**:MQTT 5秒自动重连,Modbus 5秒自动重连
1112
- - ✅ **完整双向同步**:控制命令和状态反馈双向实时同步
1113
- - ✅ **支持一对多/多对一**:灵活的按钮到继电器映射关系
1114
- - ✅ **大量设备支持**:测试验证100+节点并发无遗漏
1115
- - ✅ **断电断网恢复**:所有配置和状态自动恢复,零数据丢失
1116
- - ✅ **符合Node-RED规范**:使用标准config节点模式,官方开发规范
1117
-
1118
- ### v1.0.1 (2025-10-17)
1119
- - ✅ **重新设计从站开关节点**:支持物理开关面板(RS-485)到Modbus继电器的映射
1120
- - ✅ **开关ID分离**:开关ID(0-255)对应物理面板,不是继电器地址
1121
- - ✅ **完整映射配置**:物理面板(开关ID+按钮)→ 继电器(从站+线圈)
1122
- - ✅ **优化配置界面**:更清晰的配置说明和示例
1123
- - ✅ **本地验证通过**:所有功能测试正常
1124
-
1125
- ### v1.0.0 (2025-10-17)
1126
- - ✅ 初始版本发布
1127
- - ✅ Modbus主站节点(TCP/串口支持)
1128
- - ✅ **动态从站管理**:支持动态添加/删除从站设备(最多10台)
1129
- - ✅ **独立配置**:每个从站独立配置地址、线圈范围、轮询间隔
1130
- - ✅ **容错机制**:单个从站失败不影响其他从站继续轮询
1131
- - ✅ **配置持久化**:所有从站配置自动保存
1132
- - ✅ MQTT集成和Home Assistant MQTT Discovery(完全兼容)
1133
- - ✅ 开关从站节点
1134
- - ✅ 完整文档和示例流程
1135
- - ✅ 优化的错误处理和自动重连机制
1136
- - ✅ 连接断开自动检测和恢复
1137
- - ✅ 完善的资源清理和内存管理
1138
- - ✅ 稳定的唯一ID机制(避免重复实体)
1139
- - ✅ 设备可用性状态管理(online/offline)
1140
- - ✅ MQTT retain消息支持(断电重启不丢失配置)
1141
- - ✅ 智能状态显示(正常设备数/总设备数)
1142
- - ✅ 本地测试验证通过(Node-RED v4.0.8)
1143
-
1144
1194
  ## 许可证
1145
1195
 
1146
1196
  MIT License - 详见 [LICENSE](LICENSE) 文件
@@ -106,7 +106,8 @@ module.exports = function(RED) {
106
106
  coils: new Array(32).fill(false),
107
107
  lastUpdate: null,
108
108
  error: null,
109
- config: slave // 保存该从站的配置
109
+ config: slave, // 保存该从站的配置
110
+ initialPublished: false // 标记是否已发布初始状态
110
111
  };
111
112
  });
112
113
 
@@ -160,6 +161,14 @@ module.exports = function(RED) {
160
161
  return;
161
162
  }
162
163
 
164
+ // 验证MQTT broker配置
165
+ if (!node.config.mqttBroker || node.config.mqttBroker.trim() === '') {
166
+ node.warn('MQTT已启用但broker地址未配置,跳过MQTT连接');
167
+ return;
168
+ }
169
+
170
+ node.log(`正在连接MQTT broker: ${node.config.mqttBroker}`);
171
+
163
172
  const options = {
164
173
  clientId: `modbus_master_${Math.random().toString(16).substr(2, 8)}`,
165
174
  clean: false, // 持久化会话,断线重连后继续接收消息
@@ -190,7 +199,8 @@ module.exports = function(RED) {
190
199
  const shouldLog = (now - node.lastMqttErrorLog) > node.errorLogInterval;
191
200
 
192
201
  if (shouldLog) {
193
- node.error(`MQTT错误: ${err.message} [此错误将在10分钟后再次显示]`);
202
+ const errorMsg = err.message || `无法连接到MQTT broker: ${node.config.mqttBroker},请检查broker是否运行`;
203
+ node.error(`MQTT错误: ${errorMsg} [此错误将在10分钟后再次显示]`);
194
204
  node.lastMqttErrorLog = now;
195
205
  }
196
206
  });
@@ -390,6 +400,8 @@ module.exports = function(RED) {
390
400
  const data = await node.client.readCoils(slave.coilStart, coilCount);
391
401
 
392
402
  // 更新设备状态
403
+ const isFirstPoll = !node.deviceStates[slaveId].initialPublished;
404
+
393
405
  for (let i = 0; i < coilCount; i++) {
394
406
  const coilIndex = slave.coilStart + i;
395
407
  const oldValue = node.deviceStates[slaveId].coils[coilIndex];
@@ -397,8 +409,8 @@ module.exports = function(RED) {
397
409
 
398
410
  node.deviceStates[slaveId].coils[coilIndex] = newValue;
399
411
 
400
- // 如果状态改变,发布到MQTT和触发事件
401
- if (oldValue !== newValue) {
412
+ // 第一次轮询或状态改变时,发布到MQTT和触发事件
413
+ if (isFirstPoll || oldValue !== newValue) {
402
414
  node.publishMqttState(slaveId, coilIndex, newValue);
403
415
  node.emit('stateUpdate', {
404
416
  slave: slaveId,
@@ -410,6 +422,7 @@ module.exports = function(RED) {
410
422
 
411
423
  node.deviceStates[slaveId].lastUpdate = Date.now();
412
424
  node.deviceStates[slaveId].error = null;
425
+ node.deviceStates[slaveId].initialPublished = true; // 标记已发布初始状态
413
426
 
414
427
  // 输出消息
415
428
  const output = {
@@ -294,6 +294,12 @@ module.exports = function(RED) {
294
294
 
295
295
  // 连接MQTT
296
296
  node.connectMqtt = function() {
297
+ // 验证MQTT broker配置
298
+ if (!node.config.mqttBroker || node.config.mqttBroker.trim() === '') {
299
+ node.warn('MQTT broker地址未配置,跳过MQTT连接');
300
+ return;
301
+ }
302
+
297
303
  const options = {
298
304
  clientId: `modbus_switch_${node.id}`,
299
305
  clean: false, // 持久化会话,断线重连后继续接收消息
@@ -329,7 +335,8 @@ module.exports = function(RED) {
329
335
  const shouldLog = (now - node.lastMqttErrorLog) > node.errorLogInterval;
330
336
 
331
337
  if (shouldLog) {
332
- node.error(`MQTT错误: ${err.message} [此错误将在10分钟后再次显示]`);
338
+ const errorMsg = err.message || `无法连接到MQTT broker: ${node.config.mqttBroker},请检查broker是否运行`;
339
+ node.error(`MQTT错误: ${errorMsg} [此错误将在10分钟后再次显示]`);
333
340
  node.lastMqttErrorLog = now;
334
341
  }
335
342
  node.updateStatus();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-symi-modbus",
3
- "version": "1.5.4",
3
+ "version": "1.5.7",
4
4
  "description": "Node-RED Modbus节点,支持TCP/串口通信、串口自动搜索(包括/dev/ttyS1等)、多设备轮询、智能日志限流、MQTT集成、Home Assistant自动发现和多品牌开关面板,现代化美观配置界面",
5
5
  "main": "nodes/modbus-master.js",
6
6
  "scripts": {