node-red-contrib-symi-mesh 1.2.3 → 1.2.4

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
@@ -563,15 +563,12 @@ node-red-contrib-symi-mesh/
563
563
 
564
564
  ## 更新日志
565
565
 
566
- ### v1.2.3 (2025-10-28)
567
- - 修复三合一设备新风方向状态同步问题
568
- - 优化日志输出,提升系统性能
569
- - 完善Home Assistant MQTT Discovery兼容性
570
-
571
- ### v1.2.0 (2025-10-27)
572
- - 完整支持三合一设备(空调+新风+地暖)
573
- - 新增MQTT Discovery自动发现功能
574
- - 优化设备识别和状态同步机制
566
+ ### v1.2.4 (2025-11-04)
567
+ - **重大优化**:大幅减少日志输出,解决长期运行日志膨胀问题
568
+ - 将高频日志(Frame接收/发送、状态事件、MQTT消息等)改为debug级别
569
+ - 保留关键日志(连接/断开、设备发现、错误)用于问题排查
570
+ - 提升系统性能和稳定性,适合7x24小时长期运行
571
+ - 修复网关或MQTT服务器离线时的错误处理
575
572
 
576
573
 
577
574
  ## 许可证
@@ -585,8 +582,8 @@ Copyright (c) 2025 SYMI 亖米
585
582
  ## 关于
586
583
 
587
584
  **作者**: SYMI 亖米
588
- **版本**: 1.2.3
585
+ **版本**: 1.2.4
589
586
  **协议**: 蓝牙MESH网关(初级版)串口协议V1.0
590
- **最后更新**: 2025-10-28
587
+ **最后更新**: 2025-11-04
591
588
  **仓库**: https://github.com/symi-daguo/node-red-contrib-symi-mesh
592
589
  **npm包**: https://www.npmjs.com/package/node-red-contrib-symi-mesh
package/lib/tcp-client.js CHANGED
@@ -236,9 +236,9 @@ class TCPClient extends EventEmitter {
236
236
  return;
237
237
  }
238
238
 
239
- // 添加发送日志
239
+ // 使用debug记录发送帧,避免日志泛滥
240
240
  const frameHex = frame.toString('hex').toUpperCase();
241
- this.logger.log(`[TCP Frame] 发送: ${frameHex}`);
241
+ this.logger.debug(`[TCP Frame] 发送: ${frameHex}`);
242
242
 
243
243
  this.client.write(frame, (error) => {
244
244
  if (error) {
@@ -124,16 +124,16 @@ module.exports = function(RED) {
124
124
  };
125
125
 
126
126
  SymiGatewayNode.prototype.handleFrame = function(frame) {
127
- // 记录所有接收到的frame的详细信息
127
+ // 使用debug记录详细frame信息,避免日志泛滥
128
128
  const frameHex = Buffer.from([frame.header, frame.opcode, ...(frame.status !== null ? [frame.status] : []), frame.length, ...frame.payload, frame.checksum]).toString('hex').toUpperCase();
129
- this.log(`[TCP Frame] 接收: ${frameHex} (opcode=0x${frame.opcode.toString(16).toUpperCase()})`);
129
+ this.debug(`[TCP Frame] 接收: ${frameHex} (opcode=0x${frame.opcode.toString(16).toUpperCase()})`);
130
130
 
131
131
  if (frame.opcode === OP_RESP_DEVICE_LIST && frame.status === 0x00) {
132
132
  this.parseDeviceListFrame(frame);
133
133
  } else if (frame.isDeviceStatusEvent()) {
134
134
  try {
135
135
  const event = parseStatusEvent(frame);
136
- this.log(`[状态事件] 地址=0x${event.networkAddress.toString(16).toUpperCase()}, 消息类型=0x${event.attrType.toString(16).toUpperCase()}, 参数=[${Array.from(event.parameters).map(p => '0x' + p.toString(16).toUpperCase()).join(', ')}]`);
136
+ this.debug(`[状态事件] 地址=0x${event.networkAddress.toString(16).toUpperCase()}, 消息类型=0x${event.attrType.toString(16).toUpperCase()}, 参数=[${Array.from(event.parameters).map(p => '0x' + p.toString(16).toUpperCase()).join(', ')}]`);
137
137
 
138
138
  const device = this.deviceManager.updateDeviceState(
139
139
  event.networkAddress,
@@ -156,10 +156,10 @@ module.exports = function(RED) {
156
156
  }
157
157
  } else if (frame.opcode === 0xB0) {
158
158
  // 控制命令响应
159
- this.log(`[控制响应] 0xB0: ${frameHex} ${frame.status === 0 ? '(成功)' : '(失败)'}`)
159
+ this.debug(`[控制响应] 0xB0: ${frameHex} ${frame.status === 0 ? '(成功)' : '(失败)'}`)
160
160
  } else {
161
161
  // 其他frame类型
162
- this.log(`[其他Frame] ${frameHex}`);
162
+ this.debug(`[其他Frame] ${frameHex}`);
163
163
  }
164
164
  };
165
165
 
@@ -344,13 +344,13 @@ module.exports = function(RED) {
344
344
 
345
345
  if (device && typeof device.getCurrentSwitchState === 'function') {
346
346
  currentState = device.getCurrentSwitchState();
347
- this.log(`使用缓存状态: 0x${currentState.toString(16).toUpperCase()}`);
347
+ this.debug(`使用缓存状态: 0x${currentState.toString(16).toUpperCase()}`);
348
348
  } else if (device && device.state.switchState !== undefined) {
349
349
  currentState = device.state.switchState;
350
- this.log(`使用保存状态: 0x${currentState.toString(16).toUpperCase()}`);
350
+ this.debug(`使用保存状态: 0x${currentState.toString(16).toUpperCase()}`);
351
351
  } else {
352
352
  // 如果没有当前状态,查询一次
353
- this.log(`查询开关状态: 地址0x${networkAddr.toString(16).toUpperCase()}`);
353
+ this.debug(`查询开关状态: 地址0x${networkAddr.toString(16).toUpperCase()}`);
354
354
  const queryFrame = this.protocolHandler.buildDeviceStatusQueryFrame(networkAddr, 0x02);
355
355
  await this.client.sendFrame(queryFrame, 2);
356
356
  await this.sleep(200);
@@ -361,7 +361,7 @@ module.exports = function(RED) {
361
361
  // 使用默认全关状态
362
362
  const defaultStates = { 2: 0x05, 3: 0x15, 4: 0x55, 6: 0x5555 };
363
363
  currentState = defaultStates[channels] || 0x55;
364
- this.log(`使用默认状态: 0x${currentState.toString(16).toUpperCase()}`);
364
+ this.debug(`使用默认状态: 0x${currentState.toString(16).toUpperCase()}`);
365
365
  }
366
366
  }
367
367
 
@@ -377,7 +377,7 @@ module.exports = function(RED) {
377
377
  controlParam = Buffer.from([stateValue]);
378
378
  }
379
379
 
380
- this.log(`发送开关控制: 地址0x${networkAddr.toString(16).toUpperCase()}, 第${targetChannel}路${targetState ? '开' : '关'}, 状态值0x${stateValue.toString(16).toUpperCase()}`);
380
+ this.debug(`发送开关控制: 地址0x${networkAddr.toString(16).toUpperCase()}, 第${targetChannel}路${targetState ? '开' : '关'}, 状态值0x${stateValue.toString(16).toUpperCase()}`);
381
381
  const frame = this.protocolHandler.buildDeviceControlFrame(networkAddr, attrType, controlParam);
382
382
  return await this.client.sendFrame(frame, 1);
383
383
 
@@ -92,7 +92,7 @@ module.exports = function(RED) {
92
92
  node.mqttClient = mqtt.connect(node.mqttBroker, options);
93
93
 
94
94
  node.mqttClient.on('message', (topic, message) => {
95
- node.log(`[MQTT消息] topic=${topic}, message=${message.toString()}`);
95
+ node.debug(`[MQTT消息] topic=${topic}, message=${message.toString()}`);
96
96
  node.handleMQTTMessage(topic, message);
97
97
  });
98
98
 
@@ -114,7 +114,7 @@ module.exports = function(RED) {
114
114
  });
115
115
 
116
116
  node.mqttClient.on('reconnect', () => {
117
- node.log('MQTT正在重连...');
117
+ node.debug('MQTT正在重连...');
118
118
  node.status({ fill: 'yellow', shape: 'ring', text: '重连中' });
119
119
  });
120
120
 
@@ -192,7 +192,7 @@ module.exports = function(RED) {
192
192
  node.mqttClient.subscribe(topic, (err) => {
193
193
  if (!err) {
194
194
  node.subscriptions.set(topic, device.macAddress);
195
- node.log(`订阅topic: ${topic} → ${device.macAddress}`);
195
+ node.debug(`订阅topic: ${topic} → ${device.macAddress}`);
196
196
  } else {
197
197
  node.error(`订阅失败: ${topic}, ${err.message}`);
198
198
  }
@@ -329,9 +329,9 @@ module.exports = function(RED) {
329
329
  topic: `symi_mesh/${macClean}/climate/mode`,
330
330
  payload: mode
331
331
  });
332
- node.log(`发布温控器模式: ${mode} (开关=ON, climateMode=${state.climateMode})`);
332
+ node.debug(`发布温控器模式: ${mode} (开关=ON, climateMode=${state.climateMode})`);
333
333
  } else {
334
- node.log(`温控器开启但模式未设置,等待0x1D消息`);
334
+ node.debug(`温控器开启但模式未设置,等待0x1D消息`);
335
335
  }
336
336
  } else {
337
337
  // 关闭状态:明确发布off
@@ -339,7 +339,7 @@ module.exports = function(RED) {
339
339
  topic: `symi_mesh/${macClean}/climate/mode`,
340
340
  payload: 'off'
341
341
  });
342
- node.log(`发布温控器模式: off`);
342
+ node.debug(`发布温控器模式: off`);
343
343
  }
344
344
  } else if (device.deviceType === 4 || device.deviceType === 0x18) {
345
345
  // 灯光开关:发布JSON格式
@@ -368,7 +368,7 @@ module.exports = function(RED) {
368
368
  topic: `symi_mesh/${macClean}/light/state`,
369
369
  payload: JSON.stringify(lightState)
370
370
  });
371
- node.log(`发布灯光开关: ${lightState.state} (JSON)`);
371
+ node.debug(`发布灯光开关: ${lightState.state} (JSON)`);
372
372
  } else if (device.deviceType === 9) {
373
373
  // 插卡取电器
374
374
  const switchState = convertStateValue('switch', 0x02, state.switch);
@@ -376,14 +376,14 @@ module.exports = function(RED) {
376
376
  topic: `symi_mesh/${macClean}/switch/state`,
377
377
  payload: switchState
378
378
  });
379
- node.log(`发布插卡取电器开关状态: ${switchState}`);
379
+ node.debug(`发布插卡取电器开关状态: ${switchState}`);
380
380
  } else if (device.channels === 1) {
381
381
  const switchState = convertStateValue('switch', 0x02, state.switch);
382
382
  publishes.push({
383
383
  topic: `symi_mesh/${macClean}/switch/state`,
384
384
  payload: switchState
385
385
  });
386
- node.log(`发布开关状态: ${switchState}`);
386
+ node.debug(`发布开关状态: ${switchState}`);
387
387
  } else {
388
388
  // 发布每个继电器的状态
389
389
  for (let i = 1; i <= device.channels; i++) {
@@ -394,7 +394,7 @@ module.exports = function(RED) {
394
394
  topic: `symi_mesh/${macClean}/switch_${i}/state`,
395
395
  payload: switchState
396
396
  });
397
- node.log(`发布开关路${i}: ${switchState}`);
397
+ node.debug(`发布开关路${i}: ${switchState}`);
398
398
  }
399
399
  }
400
400
  }
@@ -416,9 +416,9 @@ module.exports = function(RED) {
416
416
  topic: switchTopic,
417
417
  payload: switchState
418
418
  });
419
- node.log(`发布插卡状态: ${cardState} → ${cardTopic}`);
420
- node.log(`发布开关状态: ${switchState} → ${switchTopic}`);
421
- node.log(`插卡原始值: cardInserted=${state.cardInserted}, switch=${state.switch}`);
419
+ node.debug(`发布插卡状态: ${cardState} → ${cardTopic}`);
420
+ node.debug(`发布开关状态: ${switchState} → ${switchTopic}`);
421
+ node.debug(`插卡原始值: cardInserted=${state.cardInserted}, switch=${state.switch}`);
422
422
  }
423
423
  break;
424
424
 
@@ -456,7 +456,7 @@ module.exports = function(RED) {
456
456
  topic: `symi_mesh/${macClean}/light/state`,
457
457
  payload: JSON.stringify(lightState)
458
458
  });
459
- node.log(`发布灯光亮度: ${state.brightness}% -> ${lightState.brightness}/255`);
459
+ node.debug(`发布灯光亮度: ${state.brightness}% -> ${lightState.brightness}/255`);
460
460
  }
461
461
  break;
462
462
 
@@ -477,7 +477,7 @@ module.exports = function(RED) {
477
477
  topic: `symi_mesh/${macClean}/light/state`,
478
478
  payload: JSON.stringify(lightState)
479
479
  });
480
- node.log(`发布灯光色温: ${state.colorTemp}% -> ${lightState.color_temp}mireds, 亮度: ${lightState.brightness}/255`);
480
+ node.debug(`发布灯光色温: ${state.colorTemp}% -> ${lightState.color_temp}mireds, 亮度: ${lightState.brightness}/255`);
481
481
  }
482
482
  break;
483
483
 
@@ -491,7 +491,7 @@ module.exports = function(RED) {
491
491
  topic: `symi_mesh/${macClean}/cover/state`,
492
492
  payload: curtainState
493
493
  });
494
- node.log(`发布窗帘运行状态: ${curtainState} (原始值=${state.curtainStatus})`);
494
+ node.debug(`发布窗帘运行状态: ${curtainState} (原始值=${state.curtainStatus})`);
495
495
 
496
496
  // 到头(status=0)时也发布position,确保HA显示正确位置
497
497
  if (state.curtainStatus === 0 && state.curtainPosition !== undefined) {
@@ -499,7 +499,7 @@ module.exports = function(RED) {
499
499
  topic: `symi_mesh/${macClean}/cover/position`,
500
500
  payload: state.curtainPosition.toString()
501
501
  });
502
- node.log(`窗帘到头,同时发布位置: ${state.curtainPosition}%`);
502
+ node.debug(`窗帘到头,同时发布位置: ${state.curtainPosition}%`);
503
503
  }
504
504
  }
505
505
  break;
@@ -511,7 +511,7 @@ module.exports = function(RED) {
511
511
  topic: `symi_mesh/${macClean}/cover/position`,
512
512
  payload: state.curtainPosition.toString()
513
513
  });
514
- node.log(`发布窗帘位置: ${state.curtainPosition}%`);
514
+ node.debug(`发布窗帘位置: ${state.curtainPosition}%`);
515
515
 
516
516
  // 同时发布运行状态(确保HA正确显示)
517
517
  if (state.curtainStatus !== undefined) {
@@ -521,7 +521,7 @@ module.exports = function(RED) {
521
521
  topic: `symi_mesh/${macClean}/cover/state`,
522
522
  payload: curtainState
523
523
  });
524
- node.log(`同时发布窗帘状态: ${curtainState}`);
524
+ node.debug(`同时发布窗帘状态: ${curtainState}`);
525
525
  }
526
526
  }
527
527
  break;
@@ -535,8 +535,8 @@ module.exports = function(RED) {
535
535
  topic: motionTopic,
536
536
  payload: motionState
537
537
  });
538
- node.log(`发布人体感应状态: ${motionState} → ${motionTopic}`);
539
- node.log(`人体感应原始值: motion=${state.motion}, MAC=${device.macAddress}`);
538
+ node.debug(`发布人体感应状态: ${motionState} → ${motionTopic}`);
539
+ node.debug(`人体感应原始值: motion=${state.motion}, MAC=${device.macAddress}`);
540
540
  }
541
541
  break;
542
542
 
@@ -557,7 +557,7 @@ module.exports = function(RED) {
557
557
  topic: `symi_mesh/${macClean}/light/state`,
558
558
  payload: JSON.stringify(lightState)
559
559
  });
560
- node.log(`发布RGB颜色: R=${state.rgb.r}, G=${state.rgb.g}, B=${state.rgb.b}`);
560
+ node.debug(`发布RGB颜色: R=${state.rgb.r}, G=${state.rgb.g}, B=${state.rgb.b}`);
561
561
  }
562
562
  break;
563
563
 
@@ -596,7 +596,7 @@ module.exports = function(RED) {
596
596
  topic: `symi_mesh/${macClean}/climate/fan_mode`,
597
597
  payload: fanMode
598
598
  });
599
- node.log(`发布温控器风速: ${fanMode} (原始值=${state.fanMode})`);
599
+ node.debug(`发布温控器风速: ${fanMode} (原始值=${state.fanMode})`);
600
600
  }
601
601
  break;
602
602
 
@@ -621,7 +621,7 @@ module.exports = function(RED) {
621
621
  topic: `symi_mesh/${macClean}/binary_sensor/state`,
622
622
  payload: doorState
623
623
  });
624
- node.log(`发布门磁状态: ${doorState} (${state.doorOpen})`);
624
+ node.debug(`发布门磁状态: ${doorState} (${state.doorOpen})`);
625
625
  }
626
626
  break;
627
627
 
@@ -632,7 +632,7 @@ module.exports = function(RED) {
632
632
  topic: `symi_mesh/${macClean}/temperature/state`,
633
633
  payload: state.temperature.toFixed(1)
634
634
  });
635
- node.log(`发布温度: ${state.temperature.toFixed(1)}°C`);
635
+ node.debug(`发布温度: ${state.temperature.toFixed(1)}°C`);
636
636
  }
637
637
  // 温控器/三合一的当前温度也是0x16
638
638
  if (state.currentTemp !== undefined && (device.deviceType === 10 || device.isThreeInOne)) {
@@ -657,7 +657,7 @@ module.exports = function(RED) {
657
657
  topic: `symi_mesh/${macClean}/humidity/state`,
658
658
  payload: state.humidity.toString()
659
659
  });
660
- node.log(`发布湿度: ${state.humidity}%`);
660
+ node.debug(`发布湿度: ${state.humidity}%`);
661
661
  }
662
662
  break;
663
663
 
@@ -866,24 +866,24 @@ module.exports = function(RED) {
866
866
  }
867
867
 
868
868
  const payload = message.toString();
869
- node.log(`[MQTT收到] topic=${topic}, payload=${payload}, deviceType=${device.deviceType}, isThreeInOne=${device.isThreeInOne}`);
869
+ node.debug(`[MQTT收到] topic=${topic}, payload=${payload}, deviceType=${device.deviceType}, isThreeInOne=${device.isThreeInOne}`);
870
870
 
871
871
  const commands = node.parseMQTTCommand(topic, payload, device);
872
872
 
873
873
  if (commands && commands.length > 0) {
874
- node.log(`[MQTT解析] 解析出${commands.length}个命令:`);
874
+ node.debug(`[MQTT解析] 解析出${commands.length}个命令:`);
875
875
  commands.forEach((cmd, idx) => {
876
- node.log(` 命令${idx + 1}: attrType=0x${cmd.attrType.toString(16).toUpperCase()}, param=[${Array.from(cmd.param).map(p => '0x' + p.toString(16).toUpperCase()).join(', ')}]`);
876
+ node.debug(` 命令${idx + 1}: attrType=0x${cmd.attrType.toString(16).toUpperCase()}, param=[${Array.from(cmd.param).map(p => '0x' + p.toString(16).toUpperCase()).join(', ')}]`);
877
877
  });
878
878
 
879
879
  // 使用for循环而不是forEach以正确处理async
880
880
  (async () => {
881
881
  for (const command of commands) {
882
882
  const paramHex = Array.from(command.param).map(p => '0x' + p.toString(16).toUpperCase()).join(' ');
883
- node.log(`[MQTT发送] → 网关: addr=0x${device.networkAddress.toString(16).toUpperCase()}, attr=0x${command.attrType.toString(16).toUpperCase()}, param=[${paramHex}]`);
883
+ node.debug(`[MQTT发送] → 网关: addr=0x${device.networkAddress.toString(16).toUpperCase()}, attr=0x${command.attrType.toString(16).toUpperCase()}, param=[${paramHex}]`);
884
884
  try {
885
885
  await node.gateway.sendControl(device.networkAddress, command.attrType, command.param);
886
- node.log(`[MQTT发送] ✓ 成功: ${device.name}`);
886
+ node.debug(`[MQTT发送] ✓ 成功: ${device.name}`);
887
887
 
888
888
  // 立即发布状态更新(optimistic update)
889
889
  node.publishCommandFeedback(device, command, payload, topic);
@@ -902,7 +902,7 @@ module.exports = function(RED) {
902
902
  const node = this;
903
903
  const macClean = device.macAddress.replace(/:/g, '').toLowerCase();
904
904
 
905
- node.log(`反馈类型: attr=0x${command.attrType.toString(16)}, deviceType=${device.deviceType}, payload=${typeof payload === 'string' ? payload : JSON.stringify(payload)}`);
905
+ node.debug(`反馈类型: attr=0x${command.attrType.toString(16)}, deviceType=${device.deviceType}, payload=${typeof payload === 'string' ? payload : JSON.stringify(payload)}`);
906
906
 
907
907
  // 根据命令类型立即发布状态反馈(optimistic update)
908
908
  if (command.attrType === 0x02 && device.deviceType !== 4 && device.deviceType !== 0x18 && device.deviceType !== 10 && !device.isThreeInOne) {
@@ -912,7 +912,7 @@ module.exports = function(RED) {
912
912
  // 更新设备缓存状态
913
913
  device.state.switch = (payload === 'ON');
914
914
  node.mqttClient.publish(`symi_mesh/${macClean}/switch/state`, state, { retain: false });
915
- node.log(`立即反馈开关状态: ${state}`);
915
+ node.debug(`立即反馈开关状态: ${state}`);
916
916
  } else {
917
917
  // 多路开关
918
918
  const match = topic.match(/switch_(\d+)\/set/);
@@ -921,7 +921,7 @@ module.exports = function(RED) {
921
921
  // 更新设备缓存状态
922
922
  device.state[`switch_${channel}`] = (payload === 'ON');
923
923
  node.mqttClient.publish(`symi_mesh/${macClean}/switch_${channel}/state`, state, { retain: false });
924
- node.log(`立即反馈开关路${channel}状态: ${state}`);
924
+ node.debug(`立即反馈开关路${channel}状态: ${state}`);
925
925
  }
926
926
  } else if (command.attrType === 0x02 && (device.deviceType === 4 || device.deviceType === 0x18)) {
927
927
  // 灯光开关控制 - 不需要optimistic update,等待53 80反馈
@@ -943,15 +943,15 @@ module.exports = function(RED) {
943
943
  } else if (command.attrType === 0x1B || command.attrType === 0x1C || command.attrType === 0x1D || (command.attrType === 0x02 && (device.deviceType === 10 || device.isThreeInOne))) {
944
944
  // 温控器/三合一反馈 - 完全依赖53 80反馈,不做optimistic update
945
945
  // 因为这些设备的状态会通过53 80事件准确上报,optimistic update会被53 80覆盖导致状态不一致
946
- node.log(`温控器/三合一命令已发送(attr=0x${command.attrType.toString(16)}),等待53 80反馈`);
946
+ node.debug(`温控器/三合一命令已发送(attr=0x${command.attrType.toString(16)}),等待53 80反馈`);
947
947
  } else if (command.attrType === 0x68 || command.attrType === 0x6A || command.attrType === 0x6B || command.attrType === 0x6C) {
948
948
  // 三合一专用消息 - 完全依赖53 80反馈
949
- node.log(`三合一专用命令已发送(attr=0x${command.attrType.toString(16)}),等待53 80反馈`);
949
+ node.debug(`三合一专用命令已发送(attr=0x${command.attrType.toString(16)}),等待53 80反馈`);
950
950
  } else if (command.attrType === 0x03 && device.isThreeInOne && topic.includes('/fresh_air/')) {
951
951
  // 三合一新风亮度/风速控制反馈
952
952
  const speed = Math.round(parseFloat(payload));
953
953
  node.mqttClient.publish(`symi_mesh/${macClean}/fresh_air/speed`, speed.toString(), { retain: false });
954
- node.log(`立即反馈新风风速: ${speed}%`);
954
+ node.debug(`立即反馈新风风速: ${speed}%`);
955
955
  }
956
956
  };
957
957
 
@@ -996,7 +996,7 @@ module.exports = function(RED) {
996
996
 
997
997
  return commands;
998
998
  } catch(e) {
999
- this.log(`JSON解析失败: ${e.message}`);
999
+ this.debug(`JSON解析失败: ${e.message}`);
1000
1000
  return [];
1001
1001
  }
1002
1002
  }
@@ -1025,7 +1025,7 @@ module.exports = function(RED) {
1025
1025
  }
1026
1026
  } else if (topic.includes('/fresh_air/') && device.isThreeInOne) {
1027
1027
  // 三合一 - 新风控制(使用专用消息类型)
1028
- this.log(`[MQTT解析] 新风控制 - topic=${topic}, payload=${payload}, isThreeInOne=${device.isThreeInOne}`);
1028
+ this.debug(`[MQTT解析] 新风控制 - topic=${topic}, payload=${payload}, isThreeInOne=${device.isThreeInOne}`);
1029
1029
  if (topic.endsWith('/fresh_air/set')) {
1030
1030
  const value = payload === 'ON';
1031
1031
  commands.push({ attrType: 0x68, param: Buffer.from([value ? 0x02 : 0x01]) });
@@ -1075,12 +1075,12 @@ module.exports = function(RED) {
1075
1075
  if (mode !== undefined) {
1076
1076
  if (mode === 0) {
1077
1077
  commands.push({ attrType: 0x02, param: Buffer.from([0x01]) });
1078
- this.log(`[MQTT解析] 空调模式命令: 0x02=0x01 (关闭)`);
1078
+ this.debug(`[MQTT解析] 空调模式命令: 0x02=0x01 (关闭)`);
1079
1079
  } else {
1080
1080
  // 先开启空调
1081
1081
  commands.push({ attrType: 0x02, param: Buffer.from([0x02]) });
1082
1082
  commands.push({ attrType: 0x1D, param: Buffer.from([mode]) });
1083
- this.log(`[MQTT解析] 空调模式命令: 先开启(0x02) + 设置模式(0x1D=0x${mode.toString(16).toUpperCase()})`);
1083
+ this.debug(`[MQTT解析] 空调模式命令: 先开启(0x02) + 设置模式(0x1D=0x${mode.toString(16).toUpperCase()})`);
1084
1084
  }
1085
1085
  }
1086
1086
 
@@ -1090,7 +1090,7 @@ module.exports = function(RED) {
1090
1090
  const fan = fans[payload];
1091
1091
  if (fan !== undefined) {
1092
1092
  commands.push({ attrType: 0x1C, param: Buffer.from([fan]) });
1093
- this.log(`[MQTT解析] 空调风速命令: 0x1C=0x${fan.toString(16).toUpperCase()} (${payload})`);
1093
+ this.debug(`[MQTT解析] 空调风速命令: 0x1C=0x${fan.toString(16).toUpperCase()} (${payload})`);
1094
1094
  }
1095
1095
 
1096
1096
  } else if (topic.endsWith('/cover/set')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-symi-mesh",
3
- "version": "1.2.3",
3
+ "version": "1.2.4",
4
4
  "description": "Node-RED节点集合,用于通过TCP/串口连接Symi蓝牙Mesh网关,支持Home Assistant MQTT Discovery自动发现",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -49,7 +49,7 @@
49
49
  ],
50
50
  "repository": {
51
51
  "type": "git",
52
- "url": "https://github.com/symi-daguo/node-red-contrib-symi-mesh.git"
52
+ "url": "git+https://github.com/symi-daguo/node-red-contrib-symi-mesh.git"
53
53
  },
54
54
  "bugs": {
55
55
  "url": "https://github.com/symi-daguo/node-red-contrib-symi-mesh/issues"