node-red-contrib-symi-modbus 2.0.0 → 2.0.2

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
@@ -45,45 +45,39 @@ Node-RED的Modbus继电器控制节点,支持TCP/串口通信和MQTT集成。
45
45
 
46
46
  本节点支持**智能地址fallback机制**,自动适配不同部署环境:
47
47
 
48
- ** HassOS/Home Assistant环境**
48
+ **🏠 HassOS环境(推荐)**
49
49
  ```yaml
50
- 推荐配置: mqtt://core-mosquitto:1883
51
- 备选地址: mqtt://supervisor:1883 或 mqtt://homeassistant.local:1883
50
+ 配置: mqtt://127.0.0.1:1883
52
51
 
53
- 说明:
54
- - core-mosquitto: HassOS官方MQTT插件的容器名
55
- - supervisor: HassOS Supervisor服务
56
- - 系统会自动尝试多个地址,无需担心配置错误
52
+ 说明:无需任何额外设置,直接填写即可
53
+ - 系统会自动尝试 core-mosquitto、supervisor 等地址
54
+ - 适用于HassOS内置的Mosquitto broker插件
57
55
  ```
58
56
 
59
- ** Docker环境**
57
+ **🌐 局域网环境(工控机/独立服务器)**
60
58
  ```yaml
61
- 推荐配置: mqtt://host.docker.internal:1883
62
- 备选地址: mqtt://172.17.0.1:1883 或 宿主机IP
63
-
64
- 说明:
65
- - host.docker.internal: Docker Desktop的宿主机地址(Mac/Windows)
66
- - 172.17.0.1: Docker默认网桥网关(Linux
67
- - 172.30.32.1: HassOS的网桥网关
68
- - 如果知道宿主机IP,直接使用IP地址更可靠
59
+ 配置: mqtt://192.168.1.100:1883
60
+
61
+ 说明:直接填写具体IP地址
62
+ - 填写MQTT broker所在设备的局域网IP
63
+ - 系统会直接连接,不启用fallback
64
+ - 适合Linux工控机和独立部署的MQTT服务器
69
65
  ```
70
66
 
71
- **💻 本机环境(非容器)**
67
+ **💻 本机环境**
72
68
  ```yaml
73
- 推荐配置: mqtt://localhost:1883 或 mqtt://127.0.0.1:1883
69
+ 配置: mqtt://localhost:1883 或 mqtt://127.0.0.1:1883
74
70
 
75
- 说明:
76
- - 本机直接运行Node-RED时使用
77
- - Linux工控机部署推荐使用此配置
71
+ 说明:本机直接运行Node-RED时使用
72
+ - 适合开发测试环境
73
+ - 系统会自动尝试Docker环境的fallback地址
78
74
  ```
79
75
 
80
- ** 配置错误也不用担心**
76
+ **⚙️ 智能fallback机制**
81
77
 
82
- 本节点实现了**智能fallback机制**:
83
- - 配置 `127.0.0.1` 后,系统会自动尝试 `core-mosquitto`、`supervisor`、`host.docker.internal` 等地址
84
- - 配置 `core-mosquitto` 后,系统会自动尝试 `localhost`、`127.0.0.1` 等地址
85
- - 所有候选地址会按顺序尝试连接,直到成功为止
86
- - **建议**:HassOS环境直接填 `127.0.0.1:1883`,系统会自动找到正确的地址
78
+ - **局域网IP**(192.168.x.x, 10.x.x.x):直接连接,不启用fallback
79
+ - **localhost/127.0.0.1**:自动尝试 core-mosquittosupervisorhost.docker.internal 等地址
80
+ - **容器名**:自动尝试 localhost127.0.0.1 等备用地址
87
81
 
88
82
  ## 安装
89
83
 
@@ -321,10 +321,11 @@
321
321
  </div>
322
322
  <div style="font-size: 11px; color: #555; padding: 8px 10px; background: linear-gradient(135deg, #e8f5e9 0%, #f1f8e9 100%); border-left: 4px solid #4caf50; border-radius: 4px; margin-top: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); line-height: 1.5;">
323
323
  <strong style="color: #2e7d32;">💡 串口说明:</strong><br>
324
- <span style="color: #555;">
324
+ <span style="color: #555; font-size: 11px;">
325
325
  • <strong>Windows</strong>: COM1, COM2, COM3...<br>
326
326
  • <strong>Linux</strong>: /dev/ttyUSB0, /dev/ttyS0, /dev/ttyAMA0<br>
327
- • <strong>Docker</strong>: 需映射设备 <code style="background: #c8e6c9; padding: 2px 6px; border-radius: 3px;">--device=/dev/ttyUSB0</code> 或 <code style="background: #c8e6c9; padding: 2px 6px; border-radius: 3px;">--privileged</code>
327
+ • <strong>HassOS</strong>: 插件配置添加设备映射即可<br>
328
+ • <strong>Docker</strong>: 需映射设备 <code style="background: #c8e6c9; padding: 2px 6px; border-radius: 3px; font-size: 10px;">--device=/dev/ttyUSB0</code> 或 <code style="background: #c8e6c9; padding: 2px 6px; border-radius: 3px; font-size: 10px;">--privileged</code>
328
329
  </span>
329
330
  </div>
330
331
  </div>
@@ -404,12 +405,12 @@
404
405
  <label for="node-input-mqttServer" style="width: 110px;"><i class="fa fa-server"></i> MQTT服务器</label>
405
406
  <input type="text" id="node-input-mqttServer" placeholder="选择或添加MQTT服务器配置" style="width: calc(70% - 110px);">
406
407
  <div style="font-size: 11px; color: #555; padding: 10px 12px; background: linear-gradient(135deg, #fff3cd 0%, #fff8e1 100%); border-left: 4px solid #ff9800; border-radius: 4px; margin-left: 110px; margin-top: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); line-height: 1.6;">
407
- <strong style="color: #e65100;">🔧 环境配置说明:</strong><br>
408
- <span style="color: #666;">
409
- • <strong>HassOS环境</strong>:使用 <code style="background: #ffe0b2; padding: 2px 6px; border-radius: 3px;">core-mosquitto</code> 或 <code style="background: #ffe0b2; padding: 2px 6px; border-radius: 3px;">supervisor</code><br>
410
- • <strong>Docker环境</strong>:使用 <code style="background: #ffe0b2; padding: 2px 6px; border-radius: 3px;">host.docker.internal</code> 或宿主机IP<br>
411
- • <strong>本机环境</strong>:使用 <code style="background: #ffe0b2; padding: 2px 6px; border-radius: 3px;">localhost</code> 或 <code style="background: #ffe0b2; padding: 2px 6px; border-radius: 3px;">127.0.0.1</code><br>
412
- 系统会自动尝试多个地址fallback,无需担心配置错误
408
+ <strong style="color: #e65100; font-size: 11px;">🔧 MQTT配置说明:</strong><br>
409
+ <span style="color: #666; font-size: 11px;">
410
+ • <strong>HassOS</strong>:直接填 <code style="background: #ffe0b2; padding: 2px 6px; border-radius: 3px; font-size: 10px;">127.0.0.1:1883</code> 即可(无需任何额外设置)<br>
411
+ • <strong>局域网IP</strong>:直接填具体IP,如 <code style="background: #ffe0b2; padding: 2px 6px; border-radius: 3px; font-size: 10px;">192.168.1.100:1883</code><br>
412
+ • <strong>本机</strong>:填 <code style="background: #ffe0b2; padding: 2px 6px; border-radius: 3px; font-size: 10px;">localhost:1883</code> 或 <code style="background: #ffe0b2; padding: 2px 6px; border-radius: 3px; font-size: 10px;">127.0.0.1:1883</code><br>
413
+ 支持智能fallback,配置错误也能自动尝试其他地址
413
414
  </span>
414
415
  </div>
415
416
  </div>
@@ -231,9 +231,18 @@ module.exports = function(RED) {
231
231
  candidates.push(configuredBroker);
232
232
  }
233
233
 
234
- // Fallback候选地址(适配不同环境)
234
+ // Fallback候选地址(仅在配置localhost或容器名时启用)
235
235
  const fallbackHosts = [];
236
236
 
237
+ // 判断是否是局域网IP地址(192.168.x.x, 10.x.x.x, 172.16-31.x.x)
238
+ const isLanIp = /^(192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)/.test(host);
239
+
240
+ // 如果是局域网IP,不启用fallback(用户明确指定了IP)
241
+ if (isLanIp) {
242
+ node.log(`检测到局域网IP配置,将直接连接到 ${configuredBroker},不启用fallback`);
243
+ return candidates;
244
+ }
245
+
237
246
  // 如果配置的是localhost或127.0.0.1,添加Docker/HassOS环境的fallback
238
247
  if (host === 'localhost' || host === '127.0.0.1') {
239
248
  // HassOS/Supervisor环境(最优先)
@@ -246,8 +255,6 @@ module.exports = function(RED) {
246
255
  fallbackHosts.push('172.17.0.1'); // Docker默认网关
247
256
  fallbackHosts.push('homeassistant'); // HA容器名
248
257
  fallbackHosts.push('mosquitto'); // Mosquitto容器名
249
- // 尝试获取宿主机真实IP(局域网)
250
- fallbackHosts.push('192.168.1.1'); // 常见路由器地址
251
258
  }
252
259
 
253
260
  // 如果配置的是容器名或Docker地址,添加本地地址fallback
@@ -352,16 +359,28 @@ module.exports = function(RED) {
352
359
 
353
360
  // 如果回到第一个地址,说明所有地址都试过了
354
361
  if (currentCandidateIndex === 0) {
355
- // 日志限流:MQTT错误最多每10分钟输出一次
356
- const shouldLog = (now - node.lastMqttErrorLog) > node.errorLogInterval;
362
+ const errorMsg = err.message || '连接失败';
363
+
364
+ // 判断是否是局域网IP配置(只有一个候选地址)
365
+ const isSingleIpConfig = brokerCandidates.length === 1;
357
366
 
358
- if (shouldLog) {
359
- const errorMsg = err.message || '连接失败';
360
- node.error(`MQTT错误: ${errorMsg}`);
361
- node.error(`所有MQTT broker候选地址都无法连接: ${brokerCandidates.join(', ')}`);
362
- node.error('请检查:1) MQTT broker是否运行 2) 网络连接是否正常 3) broker地址是否正确');
363
- node.error('提示:如果Node-RED运行在Docker容器中,可能需要使用host.docker.internal或容器IP [此错误将在10分钟后再次显示]');
364
- node.lastMqttErrorLog = now;
367
+ if (isSingleIpConfig) {
368
+ // 局域网IP配置失败,立即输出错误(不受日志限流限制)
369
+ node.error(`MQTT连接失败: ${errorMsg}`);
370
+ node.error(`无法连接到MQTT broker: ${brokerCandidates[0]}`);
371
+ node.error('请检查:1) MQTT broker是否在该地址运行 2) 网络是否连通 3) 端口是否正确');
372
+ node.error('提示:可以使用 telnet 192.168.x.x 1883 测试连接');
373
+ } else {
374
+ // 多个fallback地址都失败,使用日志限流
375
+ const shouldLog = (now - node.lastMqttErrorLog) > node.errorLogInterval;
376
+
377
+ if (shouldLog) {
378
+ node.error(`MQTT错误: ${errorMsg}`);
379
+ node.error(`所有MQTT broker候选地址都无法连接: ${brokerCandidates.join(', ')}`);
380
+ node.error('请检查:1) MQTT broker是否运行 2) 网络连接是否正常 3) broker地址是否正确');
381
+ node.error('提示:如果Node-RED运行在Docker容器中,可能需要使用host.docker.internal或容器IP [此错误将在10分钟后再次显示]');
382
+ node.lastMqttErrorLog = now;
383
+ }
365
384
  }
366
385
 
367
386
  // 5秒后重试第一个地址
@@ -129,12 +129,27 @@ module.exports = function(RED) {
129
129
  candidates.push(configuredBroker);
130
130
  }
131
131
 
132
- // Fallback候选地址(适配不同环境)
132
+ // Fallback候选地址(仅在配置localhost或容器名时启用)
133
133
  const fallbackHosts = [];
134
134
 
135
- // 如果配置的是localhost或127.0.0.1,添加Docker环境的fallback
135
+ // 判断是否是局域网IP地址(192.168.x.x, 10.x.x.x, 172.16-31.x.x)
136
+ const isLanIp = /^(192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)/.test(host);
137
+
138
+ // 如果是局域网IP,不启用fallback(用户明确指定了IP)
139
+ if (isLanIp) {
140
+ node.log(`检测到局域网IP配置,将直接连接到 ${configuredBroker},不启用fallback`);
141
+ return candidates;
142
+ }
143
+
144
+ // 如果配置的是localhost或127.0.0.1,添加Docker/HassOS环境的fallback
136
145
  if (host === 'localhost' || host === '127.0.0.1') {
137
- fallbackHosts.push('host.docker.internal'); // Docker Desktop (Mac/Windows)
146
+ // HassOS/Supervisor环境(最优先)
147
+ fallbackHosts.push('core-mosquitto'); // HassOS MQTT插件
148
+ fallbackHosts.push('supervisor'); // HassOS Supervisor
149
+ fallbackHosts.push('homeassistant.local'); // mDNS地址
150
+ // Docker环境
151
+ fallbackHosts.push('host.docker.internal'); // Docker Desktop (Mac/Windows)
152
+ fallbackHosts.push('172.30.32.1'); // HassOS网关
138
153
  fallbackHosts.push('172.17.0.1'); // Docker默认网关
139
154
  fallbackHosts.push('homeassistant'); // HA容器名
140
155
  fallbackHosts.push('mosquitto'); // Mosquitto容器名
@@ -142,7 +157,8 @@ module.exports = function(RED) {
142
157
 
143
158
  // 如果配置的是容器名或Docker地址,添加本地地址fallback
144
159
  if (host === 'host.docker.internal' || host.startsWith('172.') ||
145
- host === 'homeassistant' || host === 'mosquitto') {
160
+ host === 'homeassistant' || host === 'mosquitto' || host === 'supervisor' ||
161
+ host === 'core-mosquitto' || host.includes('.local')) {
146
162
  fallbackHosts.push('localhost');
147
163
  fallbackHosts.push('127.0.0.1');
148
164
  }
@@ -430,16 +446,28 @@ module.exports = function(RED) {
430
446
 
431
447
  // 如果回到第一个地址,说明所有地址都试过了
432
448
  if (currentCandidateIndex === 0) {
433
- // 日志限流:MQTT错误最多每10分钟输出一次
434
- const shouldLog = (now - node.lastMqttErrorLog) > node.errorLogInterval;
449
+ const errorMsg = err.message || '连接失败';
435
450
 
436
- if (shouldLog) {
437
- const errorMsg = err.message || '连接失败';
438
- node.error(`MQTT错误: ${errorMsg}`);
439
- node.error(`所有MQTT broker候选地址都无法连接: ${brokerCandidates.join(', ')}`);
440
- node.error('请检查:1) MQTT broker是否运行 2) 网络连接是否正常 3) broker地址是否正确');
441
- node.error('提示:如果Node-RED运行在Docker容器中,可能需要使用host.docker.internal或容器IP [此错误将在10分钟后再次显示]');
442
- node.lastMqttErrorLog = now;
451
+ // 判断是否是局域网IP配置(只有一个候选地址)
452
+ const isSingleIpConfig = brokerCandidates.length === 1;
453
+
454
+ if (isSingleIpConfig) {
455
+ // 局域网IP配置失败,立即输出错误(不受日志限流限制)
456
+ node.error(`MQTT连接失败: ${errorMsg}`);
457
+ node.error(`无法连接到MQTT broker: ${brokerCandidates[0]}`);
458
+ node.error('请检查:1) MQTT broker是否在该地址运行 2) 网络是否连通 3) 端口是否正确');
459
+ node.error('提示:可以使用 telnet 192.168.x.x 1883 测试连接');
460
+ } else {
461
+ // 多个fallback地址都失败,使用日志限流
462
+ const shouldLog = (now - node.lastMqttErrorLog) > node.errorLogInterval;
463
+
464
+ if (shouldLog) {
465
+ node.error(`MQTT错误: ${errorMsg}`);
466
+ node.error(`所有MQTT broker候选地址都无法连接: ${brokerCandidates.join(', ')}`);
467
+ node.error('请检查:1) MQTT broker是否运行 2) 网络连接是否正常 3) broker地址是否正确');
468
+ node.error('提示:如果Node-RED运行在Docker容器中,可能需要使用host.docker.internal或容器IP [此错误将在10分钟后再次显示]');
469
+ node.lastMqttErrorLog = now;
470
+ }
443
471
  }
444
472
 
445
473
  // 5秒后重试第一个地址
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-symi-modbus",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "Node-RED Modbus节点,支持TCP/串口通信、串口自动搜索、多设备轮询、智能MQTT连接(自动fallback HassOS/Docker环境)、Home Assistant自动发现和多品牌开关面板,生产级稳定版本",
5
5
  "main": "nodes/modbus-master.js",
6
6
  "scripts": {
@@ -50,4 +50,3 @@
50
50
  },
51
51
  "homepage": "https://github.com/symi-daguo/node-red-contrib-symi-modbus#readme"
52
52
  }
53
-