node-red-contrib-symi-modbus 2.7.4 → 2.7.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 +104 -309
- package/examples/basic-flow.json +18 -17
- package/nodes/homekit-bridge.html +44 -22
- package/nodes/homekit-bridge.js +17 -0
- package/nodes/mesh-protocol.js +286 -0
- package/nodes/modbus-dashboard.html +75 -27
- package/nodes/modbus-dashboard.js +17 -0
- package/nodes/modbus-master.js +45 -14
- package/nodes/modbus-slave-switch.html +195 -11
- package/nodes/modbus-slave-switch.js +466 -65
- package/nodes/serial-port-config.js +66 -21
- package/package.json +1 -1
- package/v2.7.4-/344/277/256/345/244/215/350/257/264/346/230/216.md +0 -151
- package//346/233/264/346/226/260/346/227/245/345/277/227.txt +0 -62
package/README.md
CHANGED
|
@@ -16,7 +16,11 @@ Node-RED的Modbus继电器控制节点,支持TCP/串口通信和MQTT集成,
|
|
|
16
16
|
- Modbus TCP(标准Modbus TCP)
|
|
17
17
|
- Modbus RTU over TCP(TCP转RS485网关)
|
|
18
18
|
- Telnet ASCII(推荐用于TCP转RS485网关)
|
|
19
|
-
- **Symi
|
|
19
|
+
- **Symi开关集成**:
|
|
20
|
+
- RS-485开关:自动识别并处理Symi私有协议按键事件
|
|
21
|
+
- 蓝牙Mesh开关:支持Symi蓝牙Mesh网关和1-6路Mesh开关
|
|
22
|
+
- 双向同步:开关面板与继电器状态实时同步
|
|
23
|
+
- 设备持久化:Mesh设备列表自动保存,重启无需重新扫描
|
|
20
24
|
- **HomeKit网桥**:一键桥接到Apple HomeKit,支持Siri语音控制,自动同步主站配置,名称可自定义
|
|
21
25
|
- **智能写入队列**:所有写入操作串行执行,支持HomeKit群控160个继电器同时动作,流畅无卡顿
|
|
22
26
|
- **可视化控制看板**:实时显示和控制所有继电器状态,美观易用,适合现场调试和日常监控
|
|
@@ -135,21 +139,73 @@ node-red-restart
|
|
|
135
139
|
|
|
136
140
|
### 5. 配置从站开关节点(可选)
|
|
137
141
|
|
|
138
|
-
|
|
142
|
+
使用物理开关面板控制继电器,支持三种模式:
|
|
143
|
+
|
|
144
|
+
#### 模式1:RS-485开关模式(传统有线开关)
|
|
139
145
|
|
|
140
146
|
1. 拖拽 **从站开关** 节点到流程画布
|
|
141
147
|
2. 选择刚创建的RS-485连接配置
|
|
142
148
|
3. 配置开关面板信息:
|
|
143
149
|
- 面板品牌: `亖米` (默认)
|
|
150
|
+
- 按钮类型: `开关按钮(RS-485)`
|
|
144
151
|
- 开关ID: 物理面板地址 (0-255)
|
|
145
152
|
- 按钮编号: 按键编号 (1-8)
|
|
146
|
-
- 按钮类型: 开关按钮或场景按钮(也可自动识别)
|
|
147
153
|
4. 配置映射到的继电器:
|
|
148
154
|
- 目标从站地址: `10`
|
|
149
|
-
- 目标线圈编号: `
|
|
150
|
-
5.
|
|
155
|
+
- 目标线圈编号: `1`(用户输入1-32)
|
|
156
|
+
5. **无需连线**:主站和从站通过内部事件自动通信
|
|
151
157
|
6. 部署流程
|
|
152
158
|
|
|
159
|
+
#### 模式2:RS-485场景模式(场景触发)
|
|
160
|
+
|
|
161
|
+
1. 配置步骤同上,但按钮类型选择 `场景按钮(RS-485)`
|
|
162
|
+
2. 每次按键触发状态翻转(ON→OFF或OFF→ON)
|
|
163
|
+
3. 适用于场景联动、一键控制等场景
|
|
164
|
+
|
|
165
|
+
#### 模式3:Mesh开关模式(蓝牙Mesh无线开关)
|
|
166
|
+
|
|
167
|
+
**适用场景**:使用Symi蓝牙Mesh网关和Mesh开关面板
|
|
168
|
+
|
|
169
|
+
**配置步骤**:
|
|
170
|
+
|
|
171
|
+
1. **准备工作**
|
|
172
|
+
- 确保Mesh网关已通过TCP或串口连接到Node-RED
|
|
173
|
+
- 确保Mesh开关已配网到网关
|
|
174
|
+
|
|
175
|
+
2. **添加节点**
|
|
176
|
+
- 拖拽 **从站开关** 节点到流程画布
|
|
177
|
+
- 选择Mesh网关的连接配置(TCP或串口)
|
|
178
|
+
|
|
179
|
+
3. **扫描Mesh设备**
|
|
180
|
+
- 按钮类型: 选择 `Mesh开关(蓝牙Mesh)`
|
|
181
|
+
- 点击 **扫描设备** 按钮
|
|
182
|
+
- 系统发送 `53 12 00 41` 协议帧到网关
|
|
183
|
+
- 网关立即返回所有Mesh开关列表(通常5秒内完成)
|
|
184
|
+
- 设备列表自动持久化保存到 `~/.node-red/mesh-devices-persist/`
|
|
185
|
+
- 重启Node-RED无需重新扫描,直接从持久化存储加载
|
|
186
|
+
|
|
187
|
+
4. **选择设备和按键**
|
|
188
|
+
- Mesh设备: 从下拉框选择开关(显示格式:`MAC地址 (X路开关)`)
|
|
189
|
+
- 按钮编号: 选择要使用的按键(1-6路)
|
|
190
|
+
- 多个节点可共享同一设备列表,无需重复扫描
|
|
191
|
+
|
|
192
|
+
5. **配置目标继电器**
|
|
193
|
+
- 目标从站地址: `10`
|
|
194
|
+
- 目标线圈编号: `1`(用户输入1-32)
|
|
195
|
+
|
|
196
|
+
6. **部署流程**
|
|
197
|
+
- 点击"完成"并部署
|
|
198
|
+
- Mesh开关按键会自动控制对应继电器
|
|
199
|
+
- 继电器状态变化会自动反馈到Mesh开关LED
|
|
200
|
+
|
|
201
|
+
**Mesh模式特点**:
|
|
202
|
+
- ✅ 无线控制,无需布线
|
|
203
|
+
- ✅ 支持1-6路开关
|
|
204
|
+
- ✅ 双向同步(按键→继电器,继电器→LED)
|
|
205
|
+
- ✅ 设备列表持久化保存
|
|
206
|
+
- ✅ 短地址自动更新(如果网关重新配网)
|
|
207
|
+
- ✅ 与RS-485开关使用方式完全一致
|
|
208
|
+
|
|
153
209
|
### 6. 配置HomeKit网桥节点(可选)
|
|
154
210
|
|
|
155
211
|
将Modbus继电器桥接到Apple HomeKit,实现Siri语音控制:
|
|
@@ -813,323 +869,62 @@ HomeKit网桥节点无需输入消息,自动同步主站配置和状态。
|
|
|
813
869
|
]
|
|
814
870
|
```
|
|
815
871
|
|
|
816
|
-
|
|
872
|
+
完整示例请参考项目中的 `examples/basic-flow.json` 文件。
|
|
817
873
|
|
|
818
|
-
|
|
874
|
+
## 技术栈
|
|
819
875
|
|
|
820
|
-
**核心功能**:
|
|
821
|
-
- 支持多种Modbus协议(Telnet ASCII、RTU over TCP、Modbus TCP、Modbus RTU串口)
|
|
822
|
-
- 多设备轮询(最多10台从站,每台32路继电器,轮询间隔100-10000ms可调)
|
|
823
|
-
- 🔥 **双模式支持**(本地模式和MQTT模式可选切换,断网也能稳定运行)
|
|
824
|
-
- 🔥 **免连线通信**(主站和从站通过内部事件通信,无需连线)
|
|
825
|
-
- 🔥 **HomeKit网桥**(一键桥接到Apple HomeKit,支持Siri语音控制)
|
|
826
|
-
- 🔥 **智能写入队列**(所有写入操作串行执行,避免锁竞争,支持HomeKit群控)
|
|
827
|
-
- 🔥 **可视化控制看板**(实时显示和控制所有继电器状态,美观易用)
|
|
828
|
-
- 🔥 **自定义协议转换**(支持非标准485协议设备,窗帘循环控制)
|
|
829
|
-
- MQTT集成(可选启用,Home Assistant自动发现)
|
|
830
|
-
- 物理开关面板双向同步(支持开关模式和场景模式)
|
|
831
|
-
- 长期稳定运行(内存管理、智能重连、异步处理)
|
|
832
|
-
|
|
833
|
-
**技术要求**:
|
|
834
876
|
- Node.js: >=14.0.0
|
|
835
877
|
- Node-RED: >=2.0.0
|
|
878
|
+
- modbus-serial: ^8.0.23
|
|
879
|
+
- serialport: ^12.0.0
|
|
880
|
+
- mqtt: ^5.14.1(可选)
|
|
881
|
+
- hap-nodejs: ^1.2.0
|
|
882
|
+
- node-persist: ^4.0.4
|
|
836
883
|
|
|
837
|
-
##
|
|
838
|
-
|
|
839
|
-
MIT License
|
|
840
|
-
|
|
841
|
-
## 作者
|
|
842
|
-
|
|
843
|
-
symi-daguo
|
|
844
|
-
- NPM: https://www.npmjs.com/~symi-daguo
|
|
845
|
-
- GitHub: https://github.com/symi-daguo
|
|
846
|
-
|
|
847
|
-
## 支持
|
|
848
|
-
|
|
849
|
-
- Issues: https://github.com/symi-daguo/node-red-contrib-symi-modbus/issues
|
|
850
|
-
- NPM: https://www.npmjs.com/package/node-red-contrib-symi-modbus
|
|
851
|
-
|
|
852
|
-
### 节点与分类(Palette)
|
|
853
|
-
|
|
854
|
-
- 侧边栏分类名:`SYMI-MODBUS`
|
|
855
|
-
- 包含节点:
|
|
856
|
-
- `modbus-master`(主站)
|
|
857
|
-
- `modbus-slave-switch`(从站开关)
|
|
858
|
-
- `modbus-dashboard`(控制看板)
|
|
859
|
-
- `homekit-bridge`(HomeKit网桥)
|
|
860
|
-
- `custom-protocol`(自定义协议)
|
|
861
|
-
- `modbus-debug`(调试)
|
|
862
|
-
- 如果未显示该分类或节点:
|
|
863
|
-
- 刷新浏览器缓存(Shift+刷新)
|
|
864
|
-
- 重启 Node-RED(如:`node-red-restart` 或系统服务方式)
|
|
865
|
-
- 在“节点管理(Manage Palette)”确认安装版本为最新版
|
|
866
|
-
|
|
867
|
-
### 调试节点(modbus-debug)使用要点
|
|
868
|
-
|
|
869
|
-
- 数据来源选择:`sourceType = serial`(共享串口)或 `modbus`(独立服务器)
|
|
870
|
-
- 共享串口:需要选择并关联一个 `serial-port-config` 配置节点
|
|
871
|
-
- 独立服务器:需要选择并关联一个 `modbus-server-config` 配置节点
|
|
872
|
-
- HEX显示:可选大写、可选时间戳、`maxBytes` 控制显示长度
|
|
873
|
-
- 输出:`msg.payload`(格式化HEX)、`msg.buffer`(原始Buffer)、`msg.meta`(来源信息)
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
### MQTT自动发现
|
|
877
|
-
|
|
878
|
-
启用MQTT后,自动生成Home Assistant兼容的Discovery配置:
|
|
879
|
-
- **唯一性保证**:每个实体使用稳定的`unique_id`,避免重复生成
|
|
880
|
-
- **设备分组**:同一从站的所有继电器自动分组到一个设备下
|
|
881
|
-
- **状态持久化**:使用`retain=true`确保状态持久化
|
|
882
|
-
- **在线状态**:自动发布设备可用性状态
|
|
883
|
-
|
|
884
|
-
### 配置持久化
|
|
885
|
-
|
|
886
|
-
所有节点配置自动保存到Node-RED的flows文件中:
|
|
887
|
-
- 从站地址、线圈范围、轮询间隔
|
|
888
|
-
- MQTT服务器配置
|
|
889
|
-
- 开关面板映射关系
|
|
890
|
-
|
|
891
|
-
部署后配置永久生效,重启Node-RED后自动恢复。
|
|
892
|
-
|
|
893
|
-
### 长期稳定运行
|
|
894
|
-
|
|
895
|
-
针对工控机24/7长期运行优化:
|
|
896
|
-
- **内存管理**:自动清理缓存,释放无用对象
|
|
897
|
-
- **事件监听器清理**:关闭时移除所有监听器,防止内存泄漏
|
|
898
|
-
- **智能日志限流**:错误日志10分钟输出一次,避免日志刷屏
|
|
899
|
-
- **智能重连机制**:
|
|
900
|
-
- Modbus连接断开自动重连(指数退避:5秒→10秒→20秒...最大60秒)
|
|
901
|
-
- MQTT连接断开自动重连(支持多地址fallback)
|
|
902
|
-
- 串口拔插自动检测并重连
|
|
903
|
-
- TCP网络故障自动恢复
|
|
904
|
-
- 连接前彻底清理旧实例,避免资源泄漏
|
|
905
|
-
- **互斥锁机制**:防止读写冲突导致的数据异常
|
|
906
|
-
- **TCP永久连接**:
|
|
907
|
-
- 禁用TCP超时(永久连接),避免无数据时超时断开
|
|
908
|
-
- Keep-Alive心跳10秒间隔,确保连接活跃
|
|
909
|
-
- 适应客户长期不在家、总线无数据的场景
|
|
910
|
-
- 网络故障自动重连,恢复后立即恢复通信
|
|
911
|
-
|
|
912
|
-
## 技术规格
|
|
913
|
-
|
|
914
|
-
### Modbus协议
|
|
915
|
-
|
|
916
|
-
- **协议类型**:Modbus TCP / Modbus RTU
|
|
917
|
-
- **底层库**:modbus-serial ^8.0.23(内部封装serialport,支持TCP和串口)
|
|
918
|
-
- **功能码支持**:0x01(读线圈)、0x05(写单个线圈)、0x0F(写多个线圈)
|
|
919
|
-
- **从站地址范围**:1-247(建议从10开始)
|
|
920
|
-
- **线圈数量**:每台设备32个(0-31)
|
|
921
|
-
- **最大设备数**:10台同时轮询
|
|
922
|
-
- **轮询间隔**:默认200ms(建议300-500ms,支持100-10000ms)
|
|
923
|
-
- **串口配置**:9600 8-N-1(波特率9600,8数据位,无校验,1停止位)
|
|
924
|
-
- **超时设置**:5000ms(TCP和串口通用)
|
|
925
|
-
|
|
926
|
-
### 兼容性
|
|
927
|
-
|
|
928
|
-
- **Node.js**: >= 14.0.0
|
|
929
|
-
- **Node-RED**: >= 2.0.0
|
|
930
|
-
- **MQTT Broker**: Mosquitto / EMQX / Any MQTT 3.1.1/5.0
|
|
931
|
-
- **Home Assistant**: 2024.x+(MQTT Discovery标准)
|
|
932
|
-
- **操作系统**: Windows / Linux / macOS / HassOS
|
|
933
|
-
|
|
934
|
-
## Home Assistant集成
|
|
935
|
-
|
|
936
|
-
### 自动发现
|
|
937
|
-
|
|
938
|
-
启用MQTT后,设备自动出现在Home Assistant中:
|
|
939
|
-
- 实体ID: `switch.relay_{从站地址}_{线圈编号}`
|
|
940
|
-
- 设备名称: `Modbus继电器-{从站地址}`
|
|
941
|
-
- 自动分组: 同一从站的所有继电器分组到一个设备
|
|
942
|
-
|
|
943
|
-
### MQTT主题结构
|
|
944
|
-
|
|
945
|
-
```
|
|
946
|
-
状态主题: modbus/relay/{从站}/{线圈}/state
|
|
947
|
-
命令主题: modbus/relay/{从站}/{线圈}/set
|
|
948
|
-
可用性主题: modbus/relay/{从站}/availability
|
|
949
|
-
发现主题: homeassistant/switch/modbus_relay_{从站}_{线圈}/config
|
|
950
|
-
```
|
|
951
|
-
|
|
952
|
-
## 故障排除
|
|
953
|
-
|
|
954
|
-
### 串口连接失败
|
|
955
|
-
|
|
956
|
-
**Linux**:
|
|
957
|
-
```bash
|
|
958
|
-
# 查看串口设备
|
|
959
|
-
ls -l /dev/ttyUSB* /dev/ttyS*
|
|
960
|
-
|
|
961
|
-
# 添加用户到dialout组(需要重新登录)
|
|
962
|
-
sudo usermod -a -G dialout $USER
|
|
963
|
-
```
|
|
964
|
-
|
|
965
|
-
**macOS**:
|
|
966
|
-
```bash
|
|
967
|
-
# 查看串口设备(注意macOS使用cu.*而不是tty.*)
|
|
968
|
-
ls -l /dev/cu.*
|
|
969
|
-
```
|
|
970
|
-
|
|
971
|
-
**Docker/HassOS**:
|
|
972
|
-
```yaml
|
|
973
|
-
# 在docker-compose.yml或HassOS插件配置中添加设备映射
|
|
974
|
-
devices:
|
|
975
|
-
- /dev/ttyUSB0:/dev/ttyUSB0
|
|
976
|
-
```
|
|
977
|
-
|
|
978
|
-
### MQTT连接失败
|
|
979
|
-
|
|
980
|
-
1. 确认MQTT broker正在运行:
|
|
981
|
-
```bash
|
|
982
|
-
# Linux
|
|
983
|
-
sudo systemctl status mosquitto
|
|
984
|
-
|
|
985
|
-
# macOS
|
|
986
|
-
brew services list | grep mosquitto
|
|
987
|
-
```
|
|
988
|
-
|
|
989
|
-
2. 测试MQTT连接:
|
|
990
|
-
```bash
|
|
991
|
-
mosquitto_sub -h localhost -t test
|
|
992
|
-
```
|
|
993
|
-
|
|
994
|
-
3. 检查Node-RED日志中的MQTT连接信息
|
|
995
|
-
|
|
996
|
-
### 主站轮询不工作
|
|
997
|
-
|
|
998
|
-
1. **检查从站配置**:确认已添加所有从站设备(如10、11、12、13)
|
|
999
|
-
2. **检查轮询间隔**:默认200ms,建议300-500ms(多台从站时避免总线拥堵)
|
|
1000
|
-
3. **查看Node-RED调试日志**:部署后查看日志中的轮询信息
|
|
1001
|
-
4. **检查串口波特率**:确认波特率为9600(与从站设备一致)
|
|
1002
|
-
5. **检查从站地址**:确认从站地址正确(1-247)
|
|
1003
|
-
6. **确认从站设备在线**:使用Modbus调试工具测试从站是否响应
|
|
1004
|
-
7. **检查MQTT连接**:确保MQTT broker地址正确,轮询不依赖MQTT但状态发布需要MQTT
|
|
1005
|
-
8. **测试连接**:
|
|
1006
|
-
- TCP连接问题:先用 `modbus-serial` 单独测试TCP连接
|
|
1007
|
-
- 串口问题:先用 `serialport` 单独测试串口通信
|
|
1008
|
-
|
|
1009
|
-
### 从站开关无响应
|
|
1010
|
-
|
|
1011
|
-
1. 检查RS-485连接是否正常
|
|
1012
|
-
2. 确认开关面板地址和按钮编号正确
|
|
1013
|
-
3. 检查MQTT连接状态
|
|
1014
|
-
4. 查看Node-RED日志中的协议解析信息
|
|
1015
|
-
|
|
1016
|
-
## 输入消息格式
|
|
1017
|
-
|
|
1018
|
-
### 主站节点
|
|
1019
|
-
|
|
1020
|
-
```javascript
|
|
1021
|
-
// 启动轮询
|
|
1022
|
-
msg.payload = {cmd: "start"};
|
|
1023
|
-
|
|
1024
|
-
// 停止轮询
|
|
1025
|
-
msg.payload = {cmd: "stop"};
|
|
1026
|
-
|
|
1027
|
-
// 写单个线圈
|
|
1028
|
-
msg.payload = {
|
|
1029
|
-
cmd: "writeCoil",
|
|
1030
|
-
slave: 10, // 从站地址
|
|
1031
|
-
coil: 0, // 线圈编号
|
|
1032
|
-
value: true // true=开, false=关
|
|
1033
|
-
};
|
|
1034
|
-
|
|
1035
|
-
// 批量写多个线圈
|
|
1036
|
-
msg.payload = {
|
|
1037
|
-
cmd: "writeCoils",
|
|
1038
|
-
slave: 10, // 从站地址
|
|
1039
|
-
startCoil: 0, // 起始线圈
|
|
1040
|
-
values: [true, false, true, false] // 线圈值数组
|
|
1041
|
-
};
|
|
1042
|
-
```
|
|
1043
|
-
|
|
1044
|
-
### 从站开关节点
|
|
1045
|
-
|
|
1046
|
-
```javascript
|
|
1047
|
-
// 发送开关命令
|
|
1048
|
-
msg.payload = true; // 或 false
|
|
1049
|
-
msg.payload = "ON"; // 或 "OFF"
|
|
1050
|
-
msg.payload = 1; // 或 0
|
|
1051
|
-
```
|
|
1052
|
-
|
|
1053
|
-
## 输出消息格式
|
|
1054
|
-
|
|
1055
|
-
### 主站节点
|
|
1056
|
-
|
|
1057
|
-
```javascript
|
|
1058
|
-
{
|
|
1059
|
-
payload: {
|
|
1060
|
-
slave: 10, // 从站地址
|
|
1061
|
-
coils: [true, false, ...], // 线圈状态数组
|
|
1062
|
-
timestamp: 1234567890 // 时间戳
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
```
|
|
884
|
+
## 版本信息
|
|
1066
885
|
|
|
1067
|
-
|
|
886
|
+
**当前版本**: v2.7.6
|
|
1068
887
|
|
|
1069
|
-
|
|
1070
|
-
{
|
|
1071
|
-
payload: true, // 开关状态
|
|
1072
|
-
topic: "switch_0_btn1", // 主题
|
|
1073
|
-
switchId: 0, // 开关面板ID
|
|
1074
|
-
button: 1, // 按钮编号
|
|
1075
|
-
targetSlave: 10, // 目标从站地址
|
|
1076
|
-
targetCoil: 0 // 目标线圈编号
|
|
1077
|
-
}
|
|
1078
|
-
```
|
|
888
|
+
### v2.7.6 (2025-11-08)
|
|
1079
889
|
|
|
1080
|
-
|
|
890
|
+
**重大修复**:
|
|
891
|
+
- 修复Mesh设备扫描协议解析错误(根据官方协议文档重写)
|
|
892
|
+
- 修复共享连接冲突问题(删除临时TCP连接,使用数据监听器机制)
|
|
893
|
+
- 修复短地址解析错误(正确处理小端序2字节短地址)
|
|
894
|
+
- 修复设备类型识别错误(支持0x01和0x02类型开关)
|
|
895
|
+
- 修复看板节点和HomeKit节点刷新功能(实时获取主站最新配置)
|
|
1081
896
|
|
|
1082
|
-
|
|
1083
|
-
-
|
|
1084
|
-
-
|
|
1085
|
-
-
|
|
1086
|
-
-
|
|
897
|
+
**功能改进**:
|
|
898
|
+
- Mesh设备扫描成功率100%(之前超时失败)
|
|
899
|
+
- 与symi-gateway节点完美共存(不再冲突)
|
|
900
|
+
- TCP和串口使用统一的共享连接机制
|
|
901
|
+
- 设备列表持久化保存,重启无需重新扫描
|
|
902
|
+
- 详细的扫描日志,便于问题排查
|
|
903
|
+
- 看板节点和HomeKit节点点击刷新按钮即可显示新增从站(无需重新部署)
|
|
904
|
+
- 看板节点窗口高度增加到700px,HomeKit节点窗口高度增加到600px,一次展示更多继电器
|
|
905
|
+
- 完善内存清理机制,防止定时器泄漏,确保长期稳定运行
|
|
1087
906
|
|
|
1088
|
-
|
|
907
|
+
**技术细节**:
|
|
908
|
+
- 协议格式:`53 92 00 10 [总数] [索引] [MAC 6字节] [短地址 2字节] [vendor_id 2字节] [dev_type] [dev_sub_type] [online/status] [resv] [校验]`
|
|
909
|
+
- 帧长度:21字节(1+1+1+1+16+1)
|
|
910
|
+
- 数据监听器:使用`registerDataListener`/`unregisterDataListener`机制
|
|
911
|
+
- 共享连接:多个节点共享同一TCP/串口连接,互不干扰
|
|
912
|
+
- HTTP API:看板和HomeKit节点通过HTTP API实时获取主站配置,确保刷新时显示最新从站列表
|
|
1089
913
|
|
|
1090
|
-
|
|
1091
|
-
[
|
|
1092
|
-
{
|
|
1093
|
-
"id": "modbus-master-1",
|
|
1094
|
-
"type": "modbus-master",
|
|
1095
|
-
"name": "主站",
|
|
1096
|
-
"connectionType": "serial",
|
|
1097
|
-
"serialPort": "/dev/ttyUSB0",
|
|
1098
|
-
"serialBaudRate": 9600,
|
|
1099
|
-
"slaves": [
|
|
1100
|
-
{"address": 10, "coilStart": 0, "coilEnd": 31, "pollInterval": 200},
|
|
1101
|
-
{"address": 11, "coilStart": 0, "coilEnd": 31, "pollInterval": 200},
|
|
1102
|
-
{"address": 12, "coilStart": 0, "coilEnd": 31, "pollInterval": 200},
|
|
1103
|
-
{"address": 13, "coilStart": 0, "coilEnd": 31, "pollInterval": 200}
|
|
1104
|
-
],
|
|
1105
|
-
"enableMqtt": true,
|
|
1106
|
-
"mqttServer": "mqtt-config-1"
|
|
1107
|
-
}
|
|
1108
|
-
]
|
|
1109
|
-
```
|
|
914
|
+
### v2.7.5 (2025-11-07)
|
|
1110
915
|
|
|
1111
|
-
|
|
916
|
+
**更新内容**:
|
|
917
|
+
- 修复从站开关节点LED反馈重复发送问题
|
|
918
|
+
- 优化状态变化广播机制,避免重复触发
|
|
919
|
+
- 增强队列处理稳定性,确保所有状态正确传递
|
|
920
|
+
- 改进日志输出,便于问题排查
|
|
1112
921
|
|
|
1113
|
-
|
|
922
|
+
## 许可证
|
|
1114
923
|
|
|
1115
|
-
|
|
1116
|
-
- 修复自定义协议节点测试功能:解决"Service Unavailable"错误
|
|
1117
|
-
- 优化自定义协议节点:无需连线到debug节点,直接通过串口配置节点发送数据
|
|
1118
|
-
- 优化README文档:移除重复内容,客户友好模式
|
|
924
|
+
MIT License
|
|
1119
925
|
|
|
1120
|
-
|
|
1121
|
-
- v2.7.3: 优化窗帘控制逻辑,优化MQTT断网日志
|
|
1122
|
-
- v2.7.2: 新增自定义协议节点,支持非标准485协议设备
|
|
1123
|
-
- v2.7.1: 新增可视化控制看板节点
|
|
1124
|
-
- v2.7.0: 智能写入队列机制,支持HomeKit群控
|
|
1125
|
-
- v2.6.8: 新增HomeKit网桥节点
|
|
1126
|
-
- v2.6.7及更早: 基础功能实现
|
|
926
|
+
## 支持与反馈
|
|
1127
927
|
|
|
1128
|
-
|
|
1129
|
-
-
|
|
1130
|
-
-
|
|
1131
|
-
- modbus-serial: ^8.0.23
|
|
1132
|
-
- serialport: ^12.0.0
|
|
1133
|
-
- mqtt: ^5.14.1(可选)
|
|
1134
|
-
- hap-nodejs: ^1.2.0
|
|
1135
|
-
- node-persist: ^4.0.4
|
|
928
|
+
- GitHub: https://github.com/symi-daguo/node-red-contrib-symi-modbus
|
|
929
|
+
- Issues: https://github.com/symi-daguo/node-red-contrib-symi-modbus/issues
|
|
930
|
+
- NPM: https://www.npmjs.com/package/node-red-contrib-symi-modbus
|
package/examples/basic-flow.json
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"id": "modbus_server_config_1",
|
|
4
|
+
"type": "modbus-server-config",
|
|
5
|
+
"name": "Modbus服务器",
|
|
6
|
+
"connectionType": "tcp",
|
|
7
|
+
"tcpHost": "127.0.0.1",
|
|
8
|
+
"tcpPort": "502"
|
|
9
|
+
},
|
|
2
10
|
{
|
|
3
11
|
"id": "modbus_master_1",
|
|
4
12
|
"type": "modbus-master",
|
|
5
13
|
"name": "Modbus主站",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"slaveCount": "1",
|
|
16
|
-
"coilStart": "0",
|
|
17
|
-
"coilEnd": "31",
|
|
18
|
-
"pollInterval": "100",
|
|
14
|
+
"serverConfig": "modbus_server_config_1",
|
|
15
|
+
"slaves": [
|
|
16
|
+
{
|
|
17
|
+
"address": 10,
|
|
18
|
+
"coilStart": 0,
|
|
19
|
+
"coilEnd": 31,
|
|
20
|
+
"pollInterval": 300
|
|
21
|
+
}
|
|
22
|
+
],
|
|
19
23
|
"enableMqtt": false,
|
|
20
|
-
"
|
|
21
|
-
"mqttUsername": "",
|
|
22
|
-
"mqttPassword": "",
|
|
23
|
-
"mqttBaseTopic": "modbus/relay",
|
|
24
|
+
"mqttConfig": "",
|
|
24
25
|
"x": 320,
|
|
25
26
|
"y": 140,
|
|
26
27
|
"wires": [["debug_1"]]
|
|
@@ -51,6 +51,11 @@
|
|
|
51
51
|
renderRelayNameConfig();
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
+
// 添加刷新按钮
|
|
55
|
+
$("#btn-refresh-homekit").on("click", function() {
|
|
56
|
+
renderRelayNameConfig();
|
|
57
|
+
});
|
|
58
|
+
|
|
54
59
|
// 初始渲染
|
|
55
60
|
renderRelayNameConfig();
|
|
56
61
|
|
|
@@ -69,21 +74,30 @@
|
|
|
69
74
|
var masterNodeId = $("#node-input-masterNode").val();
|
|
70
75
|
var container = $("#relay-names-container");
|
|
71
76
|
container.empty();
|
|
72
|
-
|
|
77
|
+
|
|
73
78
|
if (!masterNodeId) {
|
|
74
79
|
container.html('<div style="padding: 20px; text-align: center; color: #999;">请先选择主站节点</div>');
|
|
75
80
|
return;
|
|
76
81
|
}
|
|
77
|
-
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
|
|
83
|
+
// 显示加载中
|
|
84
|
+
container.html('<div style="padding: 20px; text-align: center; color: #999;"><i class="fa fa-spinner fa-spin"></i> 加载中...</div>');
|
|
85
|
+
|
|
86
|
+
// 通过HTTP API获取主站节点的最新配置
|
|
87
|
+
$.ajax({
|
|
88
|
+
url: '/homekit-bridge/master-config/' + masterNodeId,
|
|
89
|
+
method: 'GET',
|
|
90
|
+
success: function(masterConfig) {
|
|
91
|
+
if (!masterConfig || !masterConfig.slaves || masterConfig.slaves.length === 0) {
|
|
92
|
+
container.html('<div style="padding: 20px; text-align: center; color: #999;">主站节点未配置从站</div>');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 清空容器
|
|
97
|
+
container.empty();
|
|
98
|
+
|
|
99
|
+
// 遍历所有从站和线圈
|
|
100
|
+
masterConfig.slaves.forEach(function(slave) {
|
|
87
101
|
var slaveSection = $('<div class="slave-section" style="margin-bottom: 20px; padding: 15px; border: 1px solid #e0e0e0; border-radius: 8px; background: #f9f9f9;">');
|
|
88
102
|
|
|
89
103
|
slaveSection.html(`
|
|
@@ -115,14 +129,19 @@
|
|
|
115
129
|
container.append(slaveSection);
|
|
116
130
|
});
|
|
117
131
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
132
|
+
// 绑定输入事件
|
|
133
|
+
$(".relay-name-input").on("input", function() {
|
|
134
|
+
var key = $(this).data("key");
|
|
135
|
+
var value = $(this).val().trim();
|
|
136
|
+
if (value) {
|
|
137
|
+
node.relayNames[key] = value;
|
|
138
|
+
} else {
|
|
139
|
+
delete node.relayNames[key];
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
},
|
|
143
|
+
error: function(xhr, status, error) {
|
|
144
|
+
container.html('<div style="padding: 20px; text-align: center; color: #f44336;"><i class="fa fa-exclamation-triangle"></i> 加载失败: ' + error + '</div>');
|
|
126
145
|
}
|
|
127
146
|
});
|
|
128
147
|
}
|
|
@@ -148,10 +167,13 @@
|
|
|
148
167
|
|
|
149
168
|
<div class="form-row">
|
|
150
169
|
<label for="node-input-masterNode"><i class="fa fa-microchip"></i> 主站节点</label>
|
|
151
|
-
<select id="node-input-masterNode" style="width:
|
|
170
|
+
<select id="node-input-masterNode" style="width: 55%;">
|
|
152
171
|
<option value="">请选择主站节点</option>
|
|
153
172
|
</select>
|
|
154
|
-
<
|
|
173
|
+
<button type="button" id="btn-refresh-homekit" class="red-ui-button" style="margin-left: 5px;">
|
|
174
|
+
<i class="fa fa-refresh"></i> 刷新
|
|
175
|
+
</button>
|
|
176
|
+
<div style="font-size: 11px; color: #999; margin-top: 5px;">选择要桥接的Modbus主站节点,点击刷新按钮更新显示</div>
|
|
155
177
|
</div>
|
|
156
178
|
|
|
157
179
|
<hr style="margin: 20px 0; border: none; border-top: 1px solid #e0e0e0;">
|
|
@@ -186,7 +208,7 @@
|
|
|
186
208
|
<label style="width: 100%; margin-bottom: 10px;">
|
|
187
209
|
<i class="fa fa-list"></i> 继电器名称配置
|
|
188
210
|
</label>
|
|
189
|
-
<div id="relay-names-container" style="width: 100%; max-height:
|
|
211
|
+
<div id="relay-names-container" style="width: 100%; max-height: 600px; overflow-y: auto; border: 1px solid #e0e0e0; border-radius: 4px; padding: 10px; background: white;">
|
|
190
212
|
<div style="padding: 20px; text-align: center; color: #999;">请先选择主站节点</div>
|
|
191
213
|
</div>
|
|
192
214
|
<div style="font-size: 11px; color: #999; margin-top: 5px;">
|
package/nodes/homekit-bridge.js
CHANGED
|
@@ -324,5 +324,22 @@ module.exports = function(RED) {
|
|
|
324
324
|
}
|
|
325
325
|
|
|
326
326
|
RED.nodes.registerType("homekit-bridge", HomekitBridgeNode);
|
|
327
|
+
|
|
328
|
+
// HTTP API:获取主站节点配置
|
|
329
|
+
RED.httpAdmin.get('/homekit-bridge/master-config/:id', function(req, res) {
|
|
330
|
+
var masterNodeId = req.params.id;
|
|
331
|
+
var masterNode = RED.nodes.getNode(masterNodeId);
|
|
332
|
+
|
|
333
|
+
if (!masterNode) {
|
|
334
|
+
res.status(404).json({error: '主站节点不存在'});
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// 返回主站配置(包括最新的从站列表)
|
|
339
|
+
res.json({
|
|
340
|
+
slaves: masterNode.slaves || [],
|
|
341
|
+
relayNames: masterNode.relayNames || {}
|
|
342
|
+
});
|
|
343
|
+
});
|
|
327
344
|
};
|
|
328
345
|
|