node-red-contrib-symi-mesh 1.6.6 → 1.6.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.
@@ -4,8 +4,25 @@
4
4
  */
5
5
 
6
6
  const mqtt = require('mqtt');
7
+ const net = require('net');
7
8
  const { generateDiscoveryConfig, generateStateTopics, convertStateValue } = require('../lib/mqtt-helper');
8
9
 
10
+ // 检查TCP端口是否可用
11
+ function checkPort(host, port, timeout = 2000) {
12
+ return new Promise((resolve) => {
13
+ const socket = new net.Socket();
14
+ socket.setTimeout(timeout);
15
+ socket.on('connect', () => { socket.destroy(); resolve(true); });
16
+ socket.on('timeout', () => { socket.destroy(); resolve(false); });
17
+ socket.on('error', () => { socket.destroy(); resolve(false); });
18
+ try {
19
+ socket.connect({ port, host, family: 4 });
20
+ } catch (e) {
21
+ resolve(false);
22
+ }
23
+ });
24
+ }
25
+
9
26
  module.exports = function(RED) {
10
27
  function SymiMQTTNode(config) {
11
28
  RED.nodes.createNode(this, config);
@@ -193,10 +210,34 @@ module.exports = function(RED) {
193
210
  });
194
211
  }
195
212
 
196
- SymiMQTTNode.prototype.connectMQTT = function() {
213
+ SymiMQTTNode.prototype.connectMQTT = async function() {
197
214
  const node = this;
198
215
 
199
216
  try {
217
+ // 解析broker地址
218
+ let host = 'localhost', port = 1883;
219
+ try {
220
+ const url = new URL(node.mqttBroker);
221
+ host = url.hostname || 'localhost';
222
+ port = parseInt(url.port) || 1883;
223
+ } catch (e) {
224
+ // 使用默认值
225
+ }
226
+
227
+ // 先检查端口是否可用,避免连接失败导致崩溃
228
+ const isAvailable = await checkPort(host, port, 3000);
229
+ if (!isAvailable) {
230
+ // 只在首次或每分钟记录一次警告,避免日志刷屏
231
+ if (!node._lastMqttWarn || Date.now() - node._lastMqttWarn > 60000) {
232
+ node.warn(`MQTT broker ${host}:${port} 不可用,每30秒重试`);
233
+ node._lastMqttWarn = Date.now();
234
+ }
235
+ node.status({ fill: 'yellow', shape: 'ring', text: `Broker不可用 ${host}:${port}` });
236
+ // 30秒后重试
237
+ setTimeout(() => node.connectMQTT(), 30000);
238
+ return;
239
+ }
240
+
200
241
  const options = {
201
242
  clientId: `symi-mesh-${Math.random().toString(16).substring(2, 10)}`,
202
243
  clean: true,
@@ -210,6 +251,14 @@ module.exports = function(RED) {
210
251
 
211
252
  node.mqttClient = mqtt.connect(node.mqttBroker, options);
212
253
 
254
+ // 立即绑定错误处理
255
+ node.mqttClient.on('error', (error) => {
256
+ if (error.code !== 'ECONNREFUSED' && error.code !== 'ENOTFOUND') {
257
+ node.error(`MQTT错误: ${error.message}`);
258
+ }
259
+ node.status({ fill: 'red', shape: 'ring', text: '连接失败' });
260
+ });
261
+
213
262
  node.mqttClient.on('message', (topic, message) => {
214
263
  node.log(`[MQTT消息] topic=${topic}, message=${message.toString()}`);
215
264
  node.handleMQTTMessage(topic, message);
@@ -236,14 +285,6 @@ module.exports = function(RED) {
236
285
  node.debug('MQTT正在重连...');
237
286
  node.status({ fill: 'yellow', shape: 'ring', text: '重连中' });
238
287
  });
239
-
240
- node.mqttClient.on('error', (error) => {
241
- // 只记录非连接错误,避免重连时大量日志
242
- if (error.code !== 'ECONNREFUSED' && error.code !== 'ENOTFOUND') {
243
- node.error(`MQTT错误: ${error.message}`);
244
- }
245
- node.status({ fill: 'red', shape: 'ring', text: '错误' });
246
- });
247
288
 
248
289
  node.mqttClient.on('offline', () => {
249
290
  node.status({ fill: 'yellow', shape: 'ring', text: '离线' });
@@ -552,7 +593,8 @@ module.exports = function(RED) {
552
593
  });
553
594
  node.debug(`[状态发布] ${device.name} 第${i}路: ${switchState} (value=${value})`);
554
595
  } else {
555
- node.warn(`[状态发布] ${device.name} 第${i}路状态未定义`);
596
+ // 部分路未使用是正常情况,不需要警告
597
+ node.debug(`[状态发布] ${device.name} 第${i}路状态未定义`);
556
598
  }
557
599
  }
558
600
  }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "node-red-contrib-symi-mesh",
3
- "version": "1.6.6",
3
+ "version": "1.6.7",
4
4
  "description": "Node-RED节点集合,用于通过TCP/串口连接Symi蓝牙Mesh网关,支持Home Assistant MQTT Discovery自动发现和云端数据同步",
5
- "main": "index.js",
5
+ "main": "nodes/symi-gateway.js",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"
8
8
  },
@@ -34,7 +34,8 @@
34
34
  "symi-cloud-sync": "nodes/symi-cloud-sync.js",
35
35
  "symi-485-config": "nodes/symi-485-config.js",
36
36
  "symi-rs485-bridge": "nodes/symi-485-bridge.js",
37
- "rs485-debug": "nodes/rs485-debug.js"
37
+ "rs485-debug": "nodes/rs485-debug.js",
38
+ "symi-knx-bridge": "nodes/symi-knx-bridge.js"
38
39
  }
39
40
  },
40
41
  "dependencies": {