node-red-contrib-symi-modbus 1.5.4 → 1.5.6
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 +92 -139
- package/nodes/modbus-master.js +17 -4
- package/nodes/modbus-slave-switch.js +8 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -963,10 +963,70 @@ node-red
|
|
|
963
963
|
|
|
964
964
|
### MQTT问题
|
|
965
965
|
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
966
|
+
**症状**:HA实体显示不可用,或MQTT错误日志
|
|
967
|
+
|
|
968
|
+
**原因分析**:
|
|
969
|
+
1. MQTT broker未运行(如:mosquitto服务未启动)
|
|
970
|
+
2. MQTT broker地址配置错误
|
|
971
|
+
3. MQTT broker需要认证但未配置用户名密码
|
|
972
|
+
4. 网络连接问题
|
|
973
|
+
|
|
974
|
+
**解决方案**:
|
|
975
|
+
|
|
976
|
+
1. **检查MQTT broker是否运行**
|
|
977
|
+
```bash
|
|
978
|
+
# macOS/Linux查看mosquitto服务状态
|
|
979
|
+
ps aux | grep mosquitto
|
|
980
|
+
|
|
981
|
+
# 或使用systemctl(Linux)
|
|
982
|
+
sudo systemctl status mosquitto
|
|
983
|
+
|
|
984
|
+
# macOS使用brew services
|
|
985
|
+
brew services list | grep mosquitto
|
|
986
|
+
```
|
|
987
|
+
|
|
988
|
+
2. **启动MQTT broker**
|
|
989
|
+
```bash
|
|
990
|
+
# macOS
|
|
991
|
+
brew services start mosquitto
|
|
992
|
+
|
|
993
|
+
# Linux (systemd)
|
|
994
|
+
sudo systemctl start mosquitto
|
|
995
|
+
|
|
996
|
+
# 或直接运行
|
|
997
|
+
mosquitto -v
|
|
998
|
+
```
|
|
999
|
+
|
|
1000
|
+
3. **验证MQTT连接**
|
|
1001
|
+
```bash
|
|
1002
|
+
# 订阅测试主题(打开一个终端)
|
|
1003
|
+
mosquitto_sub -h localhost -t test
|
|
1004
|
+
|
|
1005
|
+
# 发布测试消息(打开另一个终端)
|
|
1006
|
+
mosquitto_pub -h localhost -t test -m "hello"
|
|
1007
|
+
|
|
1008
|
+
# 如果收到消息,说明MQTT broker正常运行
|
|
1009
|
+
```
|
|
1010
|
+
|
|
1011
|
+
4. **检查Node-RED日志**
|
|
1012
|
+
- 查看是否有"正在连接MQTT broker: xxx"日志
|
|
1013
|
+
- 查看MQTT错误提示,根据提示信息定位问题
|
|
1014
|
+
- 如果提示"无法连接到MQTT broker",检查broker是否运行
|
|
1015
|
+
- 如果提示"MQTT已启用但broker地址未配置",在MQTT服务器配置节点中填写broker地址
|
|
1016
|
+
|
|
1017
|
+
5. **正确配置MQTT服务器节点**
|
|
1018
|
+
- 在Node-RED中打开任意主站或从站节点
|
|
1019
|
+
- 找到"MQTT服务器"字段,点击编辑按钮
|
|
1020
|
+
- 填写正确的broker地址(如:`mqtt://localhost:1883`或`mqtt://192.168.1.100:1883`)
|
|
1021
|
+
- 如果需要认证,填写用户名和密码
|
|
1022
|
+
- 点击"添加"保存配置
|
|
1023
|
+
- 重新部署流程
|
|
1024
|
+
|
|
1025
|
+
6. **HA实体不可用的特殊情况**
|
|
1026
|
+
- 如果HA中实体显示不可用(unavailable),首先确保MQTT连接正常
|
|
1027
|
+
- 然后确保主站节点已启动轮询(查看日志:"开始轮询 X 个从站设备")
|
|
1028
|
+
- 如果轮询成功,实体应该在几秒内变为可用状态
|
|
1029
|
+
- v1.5.5+版本已修复初始状态发布问题,确保使用最新版本
|
|
970
1030
|
|
|
971
1031
|
### 测试设备
|
|
972
1032
|
|
|
@@ -1003,144 +1063,37 @@ python -m pymodbus.server tcp --port 502
|
|
|
1003
1063
|
|
|
1004
1064
|
## 更新日志
|
|
1005
1065
|
|
|
1006
|
-
### v1.5.
|
|
1007
|
-
- ✅ **MQTT
|
|
1008
|
-
- MQTT
|
|
1009
|
-
-
|
|
1010
|
-
-
|
|
1011
|
-
-
|
|
1012
|
-
- ✅
|
|
1013
|
-
-
|
|
1014
|
-
-
|
|
1015
|
-
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
-
|
|
1066
|
+
### v1.5.6 (2025-10-18) - MQTT错误提示优化 ✅最新版本
|
|
1067
|
+
- ✅ **MQTT错误提示改进**:
|
|
1068
|
+
- 当MQTT连接失败且错误消息为空时,提供友好的默认提示
|
|
1069
|
+
- 明确提示broker地址和可能的原因:"无法连接到MQTT broker: xxx,请检查broker是否运行"
|
|
1070
|
+
- 添加MQTT连接日志:"正在连接MQTT broker: xxx",便于调试
|
|
1071
|
+
- 帮助用户快速定位MQTT配置问题
|
|
1072
|
+
- ✅ **调试信息完善**:
|
|
1073
|
+
- MQTT连接过程增加详细日志输出
|
|
1074
|
+
- 错误提示更加明确和友好
|
|
1075
|
+
- 便于用户排查MQTT连接问题
|
|
1076
|
+
|
|
1077
|
+
### v1.5.5 (2025-10-18) - HA自动发现修复和初始状态发布
|
|
1078
|
+
- ✅ **修复HA实体不可用问题**:
|
|
1079
|
+
- 添加MQTT broker配置验证,空地址时不尝试连接并给出警告
|
|
1080
|
+
- 第一次轮询成功后立即发布所有线圈的初始状态到MQTT
|
|
1081
|
+
- 确保HA能立即获取到设备的真实状态,实体显示为可用
|
|
1082
|
+
- 解决初始状态为false时不发布导致实体不可用的问题
|
|
1083
|
+
- ✅ **初始状态发布机制**:
|
|
1084
|
+
- 新增initialPublished标志,记录每个从站是否已发布初始状态
|
|
1085
|
+
- 第一次轮询成功后,无论状态值是什么,都发布到MQTT
|
|
1086
|
+
- 后续轮询只在状态改变时发布,减少MQTT消息量
|
|
1087
|
+
- 确保HA自动发现后立即显示正确的设备状态
|
|
1088
|
+
- ✅ **MQTT配置优化**:
|
|
1089
|
+
- 主站和从站都添加broker地址验证
|
|
1090
|
+
- 配置无效时不尝试连接,避免无意义的错误日志
|
|
1091
|
+
- 提供清晰的警告信息,帮助用户配置
|
|
1020
1092
|
- ✅ **完整测试验证**:
|
|
1021
|
-
-
|
|
1022
|
-
-
|
|
1093
|
+
- 从站轮询正常,HA实体自动创建并显示可用
|
|
1094
|
+
- 初始状态正确同步到HA
|
|
1023
1095
|
- 配置持久化保存正常
|
|
1024
1096
|
|
|
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
1097
|
## 许可证
|
|
1145
1098
|
|
|
1146
1099
|
MIT License - 详见 [LICENSE](LICENSE) 文件
|
package/nodes/modbus-master.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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