node-red-contrib-symi-mesh 1.7.4 → 1.7.5
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 +15 -18
- package/examples/knx-sync-example.json +2 -2
- package/nodes/rs485-debug.html +1 -1
- package/nodes/symi-485-bridge.html +2 -2
- package/nodes/symi-485-config.html +1 -1
- package/nodes/symi-device.html +13 -5
- package/nodes/symi-gateway.html +1 -1
- package/nodes/symi-knx-bridge.js +6 -3
- package/nodes/symi-mqtt-sync.html +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1462,6 +1462,20 @@ node-red-contrib-symi-mesh/
|
|
|
1462
1462
|
|
|
1463
1463
|
## 更新日志
|
|
1464
1464
|
|
|
1465
|
+
### v1.7.5 (2025-12-24)
|
|
1466
|
+
- **API路径兼容性修复**:修复HassOS环境下节点配置界面无法加载设备列表的问题
|
|
1467
|
+
- **根本原因**:HassOS Node-RED使用nginx反向代理,绝对路径`/api`会被拦截,需使用相对路径`api`
|
|
1468
|
+
- **修复范围**:所有节点HTML中的`$.getJSON()`调用统一使用相对路径
|
|
1469
|
+
- **开发规范**:后续开发节点时,所有前端API调用必须使用相对路径,不带前导斜杠
|
|
1470
|
+
- **KNX Bridge双向同步修复**:修复Mesh控制KNX开关不工作的问题
|
|
1471
|
+
- **根本原因**:knxUltimate节点当`setTopicType: "str"`时使用`msg.topic`作为目标地址,而非`msg.destination`
|
|
1472
|
+
- **修复方案**:发送消息同时包含`topic`和`destination`字段,确保兼容所有knxUltimate配置
|
|
1473
|
+
- **消息格式**:`{ topic, destination, payload, dpt, event }`
|
|
1474
|
+
- **防死循环**:不包含`knx`对象,避免触发knxUltimate的循环引用保护机制
|
|
1475
|
+
- **用户体验优化**:
|
|
1476
|
+
- 设备列表加载时显示"加载中..."提示
|
|
1477
|
+
- API调用失败时显示"加载失败,请重试"提示
|
|
1478
|
+
|
|
1465
1479
|
### v1.7.4 (2025-12-24)
|
|
1466
1480
|
- **串口配置完善**:完整的串口参数配置,解决HassOS环境串口锁定问题
|
|
1467
1481
|
- **完整参数**:波特率、数据位(7/8)、停止位(1/2)、校验位(None/Even/Odd)
|
|
@@ -1585,23 +1599,6 @@ node-red-contrib-symi-mesh/
|
|
|
1585
1599
|
- 防死循环机制优化
|
|
1586
1600
|
- 内存优化,防止日志溢出
|
|
1587
1601
|
|
|
1588
|
-
### v1.6.9 (2025-12-20)
|
|
1589
|
-
- **KNX-HA双向同步**:新增`symi-knx-ha-bridge`节点
|
|
1590
|
-
- 直接连接KNX与HA实体,实现双向同步
|
|
1591
|
-
- 支持Tab分隔格式导入KNX组地址配置(与KNX桥接节点100%一致)
|
|
1592
|
-
- 使用共享HA服务器节点,通过REST API自动加载HA实体列表
|
|
1593
|
-
- 支持开关、灯光、窗帘、空调、风扇等设备类型
|
|
1594
|
-
- 完整双向同步:KNX↔HA实时状态同步
|
|
1595
|
-
- 事件驱动架构,通过HA events-state节点实时接收事件
|
|
1596
|
-
- 智能防抖:调光300ms、窗帘500ms,只同步最终值
|
|
1597
|
-
- 内置防死循环机制(800ms防抖)
|
|
1598
|
-
- 快速输入框:支持输入实体ID或名称搜索,自动提示806+实体
|
|
1599
|
-
- 手动刷新按钮,随时重新加载HA实体
|
|
1600
|
-
- 宽屏界面:对话框最小1000px宽度
|
|
1601
|
-
- 持久化配置保存,内存优化
|
|
1602
|
-
- 连接knxUltimate节点,无缝集成
|
|
1603
|
-
- 适用于已有KNX系统与HA整合的场景
|
|
1604
|
-
|
|
1605
1602
|
## 许可证
|
|
1606
1603
|
|
|
1607
1604
|
MIT License
|
|
@@ -1613,7 +1610,7 @@ Copyright (c) 2025 SYMI 亖米
|
|
|
1613
1610
|
## 关于
|
|
1614
1611
|
|
|
1615
1612
|
**作者**: SYMI 亖米
|
|
1616
|
-
**版本**: 1.7.
|
|
1613
|
+
**版本**: 1.7.5
|
|
1617
1614
|
**协议**: 蓝牙MESH网关(初级版)串口协议V1.0
|
|
1618
1615
|
**最后更新**: 2025-12-24
|
|
1619
1616
|
**仓库**: https://github.com/symi-daguo/node-red-contrib-symi-mesh
|
|
@@ -80,12 +80,12 @@
|
|
|
80
80
|
"notifyreadrequest": false,
|
|
81
81
|
"notifyresponse": false,
|
|
82
82
|
"notifywrite": true,
|
|
83
|
-
"name": "Universal KNX",
|
|
83
|
+
"name": "Universal KNX Output",
|
|
84
84
|
"outputtype": "write",
|
|
85
85
|
"outputRBE": "false",
|
|
86
86
|
"inputRBE": "false",
|
|
87
87
|
"passthrough": "no",
|
|
88
|
-
"listenallga":
|
|
88
|
+
"listenallga": false,
|
|
89
89
|
"buttonEnabled": false,
|
|
90
90
|
"x": 620,
|
|
91
91
|
"y": 120,
|
package/nodes/rs485-debug.html
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
|
|
35
35
|
function loadHistory() {
|
|
36
36
|
if (!node.id) return;
|
|
37
|
-
$.getJSON('
|
|
37
|
+
$.getJSON('rs485-debug/history/' + node.id, function(messages) {
|
|
38
38
|
var container = $('#debug-history');
|
|
39
39
|
|
|
40
40
|
if (messages.length === 0) {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
if (callback) callback();
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
|
-
$.getJSON('
|
|
46
|
+
$.getJSON('symi-rs485-bridge/mesh-devices/' + gatewayId)
|
|
47
47
|
.done(function(devices) {
|
|
48
48
|
meshDevices = devices || [];
|
|
49
49
|
console.log('[RS485 Bridge] 加载Mesh设备:', meshDevices.length);
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// 加载协议模板
|
|
59
|
-
$.getJSON('
|
|
59
|
+
$.getJSON('symi-rs485-bridge/protocols', function(data) {
|
|
60
60
|
protocolData = data || { brands: {} };
|
|
61
61
|
// 延迟加载设备,确保gateway选择框已初始化
|
|
62
62
|
setTimeout(function() {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
$btn.prop('disabled', true);
|
|
39
39
|
$select.empty().append('<option value="">搜索中...</option>').show();
|
|
40
40
|
|
|
41
|
-
$.getJSON('
|
|
41
|
+
$.getJSON('symi-gateway/serial-ports', function(ports) {
|
|
42
42
|
$select.empty();
|
|
43
43
|
if (ports && ports.length > 0) {
|
|
44
44
|
$select.append('<option value="">-- 选择串口 --</option>');
|
package/nodes/symi-device.html
CHANGED
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
|
|
61
61
|
var loadDevices = function(gatewayId) {
|
|
62
62
|
if (!gatewayId) {
|
|
63
|
+
console.log('[symi-device] 网关ID为空,跳过加载');
|
|
63
64
|
return;
|
|
64
65
|
}
|
|
65
66
|
|
|
@@ -67,11 +68,16 @@
|
|
|
67
68
|
var currentValue = deviceSelect.val();
|
|
68
69
|
|
|
69
70
|
deviceSelect.empty();
|
|
70
|
-
deviceSelect.append('<option value=""
|
|
71
|
+
deviceSelect.append('<option value="">加载中...</option>');
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
var apiUrl = 'symi-gateway/devices/' + gatewayId;
|
|
74
|
+
console.log('[symi-device] 加载设备列表, API:', apiUrl);
|
|
75
|
+
|
|
76
|
+
$.getJSON(apiUrl)
|
|
73
77
|
.done(function(devices) {
|
|
74
|
-
console.log('
|
|
78
|
+
console.log('[symi-device] 加载成功:', devices ? devices.length : 0, '个设备');
|
|
79
|
+
deviceSelect.empty();
|
|
80
|
+
deviceSelect.append('<option value="">-- 选择设备 --</option>');
|
|
75
81
|
if (devices && devices.length > 0) {
|
|
76
82
|
devices.forEach(function(device) {
|
|
77
83
|
var label = device.name + ' (' + device.mac + ')';
|
|
@@ -99,8 +105,10 @@
|
|
|
99
105
|
|
|
100
106
|
deviceSelect.trigger('change');
|
|
101
107
|
})
|
|
102
|
-
.fail(function(err) {
|
|
103
|
-
console.log('加载设备失败:', err);
|
|
108
|
+
.fail(function(xhr, status, err) {
|
|
109
|
+
console.log('[symi-device] 加载设备失败:', status, err, xhr.responseText);
|
|
110
|
+
deviceSelect.empty();
|
|
111
|
+
deviceSelect.append('<option value="">加载失败,请重试</option>');
|
|
104
112
|
});
|
|
105
113
|
};
|
|
106
114
|
|
package/nodes/symi-gateway.html
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
$btn.prop('disabled', true).text('搜索中...');
|
|
38
38
|
$select.empty().append('<option value="">搜索中...</option>');
|
|
39
39
|
|
|
40
|
-
$.getJSON('
|
|
40
|
+
$.getJSON('symi-gateway/serial-ports', function(ports) {
|
|
41
41
|
$select.empty();
|
|
42
42
|
if (ports && ports.length > 0) {
|
|
43
43
|
$select.append('<option value="">-- 选择串口 --</option>');
|
package/nodes/symi-knx-bridge.js
CHANGED
|
@@ -760,9 +760,12 @@ module.exports = function(RED) {
|
|
|
760
760
|
const destAddr = knxMsg.knx.destination;
|
|
761
761
|
node.lastKnxAddrSent[destAddr] = Date.now();
|
|
762
762
|
|
|
763
|
-
// knxUltimate
|
|
764
|
-
//
|
|
763
|
+
// knxUltimate输入格式:topic + destination + payload + dpt + event
|
|
764
|
+
// topic: 当setTopicType=str时,knxUltimate使用msg.topic作为目标地址
|
|
765
|
+
// destination: 官方备用字段
|
|
766
|
+
// 注意:不能包含knx对象,否则会触发knxUltimate的循环引用保护
|
|
765
767
|
const sendMsg = {
|
|
768
|
+
topic: destAddr,
|
|
766
769
|
destination: destAddr,
|
|
767
770
|
payload: knxMsg.payload,
|
|
768
771
|
dpt: knxMsg.dpt || knxMsg.knx.dpt,
|
|
@@ -784,7 +787,7 @@ module.exports = function(RED) {
|
|
|
784
787
|
timestamp: new Date().toISOString()
|
|
785
788
|
};
|
|
786
789
|
|
|
787
|
-
node.log(`[Mesh->KNX] 发送:
|
|
790
|
+
node.log(`[Mesh->KNX] 发送: topic=${sendMsg.topic}, payload=${sendMsg.payload}, dpt=${sendMsg.dpt}`);
|
|
788
791
|
|
|
789
792
|
// 同时发送到两个输出端口(一次send调用)
|
|
790
793
|
node.send([sendMsg, debugMsg]);
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
if (callback) callback();
|
|
60
60
|
return;
|
|
61
61
|
}
|
|
62
|
-
$.getJSON('
|
|
62
|
+
$.getJSON('symi-gateway/devices/' + gatewayId, function(devices) {
|
|
63
63
|
meshDevices = devices || [];
|
|
64
64
|
if (callback) callback();
|
|
65
65
|
}).fail(function() {
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
if (callback) callback();
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
|
-
$.getJSON('
|
|
79
|
+
$.getJSON('symi-mqtt-brand/devices/' + brandConfigId, function(devices) {
|
|
80
80
|
brandDevices = devices || [];
|
|
81
81
|
if (callback) callback();
|
|
82
82
|
}).fail(function() {
|