iobroker.openknx 1.1.1 → 1.1.3
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 +1 -1
- package/admin/index_m.html +42 -18
- package/admin/roles.json +100 -95
- package/io-package.json +2 -2
- package/lib/tools.js +6 -6
- package/main.js +15 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ ioBroker adapter for KNX IP communication, powered by [KNXUltimate](https://gith
|
|
|
49
49
|
Placeholder for the next version (at the beginning of the line):
|
|
50
50
|
### **WORK IN PROGRESS**
|
|
51
51
|
-->
|
|
52
|
-
### 1.1.
|
|
52
|
+
### 1.1.3 (2026-03-23)
|
|
53
53
|
|
|
54
54
|
- (TA2k) **breaking:** KNX communication switched to KNXUltimate
|
|
55
55
|
- (TA2k) **breaking:** DPT21 property names changed (outofservice → outOfService, inalarm → inAlarm, alarmeunack → alarmUnAck), values must be boolean
|
package/admin/index_m.html
CHANGED
|
@@ -518,7 +518,6 @@
|
|
|
518
518
|
var gaNamespace = '';
|
|
519
519
|
var gaStateSubscribed = false;
|
|
520
520
|
var cachedDptList = null;
|
|
521
|
-
var cachedRoleList = null;
|
|
522
521
|
|
|
523
522
|
function loadGaTree() {
|
|
524
523
|
var targetNs = ($('#targetNamespace').val() || '').trim();
|
|
@@ -634,7 +633,7 @@
|
|
|
634
633
|
html += '<span style="font-size:1.3em;font-weight:500">' + (c.name || '') + '</span>';
|
|
635
634
|
html += '<span style="font-size:1.3em;font-weight:500;color:#666">' + (n.address || '') + '</span>';
|
|
636
635
|
html += '</div>';
|
|
637
|
-
html += '<div style="margin-bottom:4px;font-size:0.
|
|
636
|
+
html += '<div style="margin-bottom:4px;font-size:0.95em;color:#888;word-break:break-all">' + id + '</div>';
|
|
638
637
|
// Editable checkboxes (2x2 grid)
|
|
639
638
|
html += '<div style="display:grid;grid-template-columns:1fr 1fr;gap:2px 12px;margin-bottom:8px">';
|
|
640
639
|
html += '<label style="margin:0;font-size:12px"><input type="checkbox" id="gaWriteChk"' + (c.write ? ' checked' : '') + ' onchange="gaSaveCheckboxProp(\'common\',\'write\',\'gaWriteChk\')"/> <span style="font-size:12px">' + _('Write') + ' (write)</span></label>';
|
|
@@ -706,7 +705,8 @@
|
|
|
706
705
|
}
|
|
707
706
|
sel.html(optHtml);
|
|
708
707
|
});
|
|
709
|
-
// Populate Role dropdown async
|
|
708
|
+
// Populate Role dropdown async (filtered by read/write)
|
|
709
|
+
var rw = (c.read && c.write) ? 'both' : (c.read ? 'read' : (c.write ? 'write' : 'both'));
|
|
710
710
|
gaLoadRoleList(function (roles) {
|
|
711
711
|
var sel = $('#gaRoleSelect');
|
|
712
712
|
var currentRole = c.role || 'state';
|
|
@@ -721,7 +721,7 @@
|
|
|
721
721
|
optHtml = '<option value="' + currentRole + '" selected>' + currentRole + '</option>' + optHtml;
|
|
722
722
|
}
|
|
723
723
|
sel.html(optHtml);
|
|
724
|
-
});
|
|
724
|
+
}, rw);
|
|
725
725
|
}
|
|
726
726
|
|
|
727
727
|
function updateGaAccess(id) {
|
|
@@ -952,6 +952,7 @@
|
|
|
952
952
|
socket.emit('setObject', selectedGaId, gaObj, function () {
|
|
953
953
|
gaObjects[selectedGaId] = gaObj;
|
|
954
954
|
showToast(null, prop + ' saved', null, 2000);
|
|
955
|
+
if (prop === 'read' || prop === 'write') refreshRoleDropdown();
|
|
955
956
|
});
|
|
956
957
|
});
|
|
957
958
|
}
|
|
@@ -997,17 +998,43 @@
|
|
|
997
998
|
});
|
|
998
999
|
}
|
|
999
1000
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1001
|
+
var cachedRolesData = null;
|
|
1002
|
+
function gaLoadRoleList(callback, readWrite) {
|
|
1003
|
+
function filter(data) {
|
|
1004
|
+
if (Array.isArray(data)) return data; // legacy flat array
|
|
1005
|
+
if (readWrite === 'read') return data.read.concat(data.both);
|
|
1006
|
+
if (readWrite === 'write') return data.write.concat(data.both);
|
|
1007
|
+
return data.read.concat(data.write).concat(data.both);
|
|
1008
|
+
}
|
|
1009
|
+
if (cachedRolesData) { callback(filter(cachedRolesData)); return; }
|
|
1010
|
+
$.getJSON('roles.json', function (data) {
|
|
1011
|
+
cachedRolesData = data;
|
|
1012
|
+
callback(filter(data));
|
|
1005
1013
|
}).fail(function () {
|
|
1006
|
-
|
|
1007
|
-
callback(
|
|
1014
|
+
cachedRolesData = ['state', 'switch', 'value', 'level', 'indicator', 'sensor', 'text', 'button', 'date', 'json'];
|
|
1015
|
+
callback(cachedRolesData);
|
|
1008
1016
|
});
|
|
1009
1017
|
}
|
|
1010
1018
|
|
|
1019
|
+
function refreshRoleDropdown() {
|
|
1020
|
+
var r = $('#gaReadChk').is(':checked'), w = $('#gaWriteChk').is(':checked');
|
|
1021
|
+
var rw = (r && w) ? 'both' : (r ? 'read' : (w ? 'write' : 'both'));
|
|
1022
|
+
var currentRole = $('#gaRoleSelect').val() || '';
|
|
1023
|
+
gaLoadRoleList(function (roles) {
|
|
1024
|
+
var optHtml = '';
|
|
1025
|
+
var roleFound = false;
|
|
1026
|
+
for (var j = 0; j < roles.length; j++) {
|
|
1027
|
+
var selected = (roles[j] === currentRole) ? ' selected' : '';
|
|
1028
|
+
if (selected) roleFound = true;
|
|
1029
|
+
optHtml += '<option value="' + roles[j] + '"' + selected + '>' + roles[j] + '</option>';
|
|
1030
|
+
}
|
|
1031
|
+
if (!roleFound && currentRole) {
|
|
1032
|
+
optHtml = '<option value="' + currentRole + '" selected>' + currentRole + '</option>' + optHtml;
|
|
1033
|
+
}
|
|
1034
|
+
$('#gaRoleSelect').html(optHtml);
|
|
1035
|
+
}, rw);
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1011
1038
|
function gaBrowseStates() {
|
|
1012
1039
|
var current = ($('#gaLinkInput').val() || '').trim();
|
|
1013
1040
|
showSelectIdDialog(current, function (newId) {
|
|
@@ -1027,24 +1054,21 @@
|
|
|
1027
1054
|
$('.ga-folder > span > i').text('chevron_right');
|
|
1028
1055
|
return;
|
|
1029
1056
|
}
|
|
1057
|
+
// First expand all so :visible checks work correctly
|
|
1058
|
+
$('.ga-children').removeClass('collapsed');
|
|
1030
1059
|
// Filter leaves
|
|
1031
1060
|
$('.ga-leaf').each(function () {
|
|
1032
1061
|
var text = $(this).text().toLowerCase();
|
|
1033
1062
|
$(this).toggle(text.indexOf(filter) !== -1);
|
|
1034
1063
|
});
|
|
1035
|
-
//
|
|
1036
|
-
$('.ga-folder').each(function () {
|
|
1064
|
+
// Hide folders without visible leaves, process innermost first
|
|
1065
|
+
$($('.ga-folder').get().reverse()).each(function () {
|
|
1037
1066
|
var hasVisible = $(this).find('.ga-leaf:visible').length > 0;
|
|
1038
1067
|
$(this).toggle(hasVisible);
|
|
1039
1068
|
if (hasVisible) {
|
|
1040
|
-
// Expand all ancestor ga-children
|
|
1041
|
-
$(this).find('.ga-children').removeClass('collapsed');
|
|
1042
|
-
$(this).parents('.ga-children').removeClass('collapsed');
|
|
1043
1069
|
$(this).find('> span > i').text('expand_more');
|
|
1044
1070
|
}
|
|
1045
1071
|
});
|
|
1046
|
-
// Also expand parents of visible folders
|
|
1047
|
-
$('.ga-folder:visible').parents('.ga-folder').show().find('> span > i').text('expand_more');
|
|
1048
1072
|
}
|
|
1049
1073
|
</script>
|
|
1050
1074
|
</head>
|
package/admin/roles.json
CHANGED
|
@@ -1,104 +1,109 @@
|
|
|
1
|
-
|
|
2
|
-
"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
{
|
|
2
|
+
"read": [
|
|
3
|
+
"value", "value.temperature", "value.temperature.dewpoint", "value.temperature.feelslike",
|
|
4
|
+
"value.temperature.max", "value.temperature.min", "value.temperature.windchill",
|
|
5
|
+
"value.humidity", "value.co2", "value.brightness",
|
|
6
|
+
"value.min", "value.max", "value.default",
|
|
7
|
+
"value.battery", "value.valve", "value.time", "value.timer", "value.interval",
|
|
8
|
+
"value.gps.longitude", "value.gps.latitude", "value.gps.elevation", "value.gps", "value.gps.accuracy", "value.gps.radius",
|
|
9
|
+
"value.energy", "value.energy.active", "value.energy.reactive", "value.energy.consumed", "value.energy.produced",
|
|
10
|
+
"value.power", "value.power.active", "value.power.reactive", "value.power.consumed", "value.power.produced",
|
|
11
|
+
"value.direction", "value.curtain", "value.blind", "value.tilt", "value.lock",
|
|
12
|
+
"value.speed", "value.pressure", "value.distance", "value.distance.visibility",
|
|
13
|
+
"value.severity", "value.warning",
|
|
14
|
+
"value.sun.elevation", "value.sun.azimuth",
|
|
15
|
+
"value.voltage", "value.current", "value.frequency", "value.fill",
|
|
16
|
+
"value.blood.sugar", "value.window", "value.state", "value.position", "value.gate",
|
|
17
|
+
"value.water", "value.waste",
|
|
18
|
+
"value.direction.wind", "value.speed.wind", "value.speed.wind.gust",
|
|
19
|
+
"value.speed.max.wind", "value.speed.min.wind",
|
|
20
|
+
"value.precipitation", "value.precipitation.chance", "value.precipitation.hour", "value.precipitation.today",
|
|
21
|
+
"value.rain", "value.rain.hour", "value.rain.today",
|
|
22
|
+
"value.snow", "value.snow.hour", "value.snow.today", "value.snowline",
|
|
23
|
+
"value.radiation", "value.uv",
|
|
24
|
+
"value.clouds",
|
|
25
|
+
"value.health.fat", "value.health.weight", "value.health.bmi", "value.health.calories", "value.health.steps", "value.health.bpm",
|
|
26
|
+
"value.mode.airconditioner",
|
|
9
27
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
28
|
+
"indicator", "indicator.working", "indicator.reachable", "indicator.connected",
|
|
29
|
+
"indicator.direction", "indicator.error",
|
|
30
|
+
"indicator.maintenance", "indicator.maintenance.lowbat", "indicator.maintenance.unreach",
|
|
31
|
+
"indicator.maintenance.alarm", "indicator.maintenance.waste",
|
|
32
|
+
"indicator.lowbat",
|
|
33
|
+
"indicator.alarm", "indicator.alarm.fire", "indicator.alarm.flood",
|
|
34
|
+
"indicator.alarm.secure", "indicator.alarm.health",
|
|
17
35
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"value.sun.elevation", "value.sun.azimuth",
|
|
30
|
-
"value.voltage", "value.current", "value.frequency", "value.fill",
|
|
31
|
-
"value.blood.sugar", "value.window", "value.state", "value.position", "value.gate",
|
|
32
|
-
"value.water", "value.waste",
|
|
33
|
-
"value.direction.wind", "value.speed.wind", "value.speed.wind.gust",
|
|
34
|
-
"value.speed.max.wind", "value.speed.min.wind",
|
|
35
|
-
"value.precipitation", "value.precipitation.chance", "value.precipitation.hour", "value.precipitation.today",
|
|
36
|
-
"value.rain", "value.rain.hour", "value.rain.today",
|
|
37
|
-
"value.snow", "value.snow.hour", "value.snow.today", "value.snowline",
|
|
38
|
-
"value.radiation", "value.uv",
|
|
39
|
-
"value.clouds",
|
|
40
|
-
"value.health.fat", "value.health.weight", "value.health.bmi", "value.health.calories", "value.health.steps", "value.health.bpm",
|
|
41
|
-
"value.mode.airconditioner",
|
|
36
|
+
"sensor", "sensor.contact", "sensor.window", "sensor.door",
|
|
37
|
+
"sensor.alarm", "sensor.alarm.flood", "sensor.alarm.fire", "sensor.alarm.secure", "sensor.alarm.power",
|
|
38
|
+
"sensor.light", "sensor.lock", "sensor.motion", "sensor.rain", "sensor.noise", "sensor.switch"
|
|
39
|
+
],
|
|
40
|
+
"write": [
|
|
41
|
+
"switch", "switch.lock", "switch.lock.door", "switch.lock.window",
|
|
42
|
+
"switch.mode.boost", "switch.mode.party", "switch.power", "switch.light",
|
|
43
|
+
"switch.comfort", "switch.enable", "switch.mode", "switch.mode.auto",
|
|
44
|
+
"switch.mode.manual", "switch.mode.silent", "switch.mode.moonlight",
|
|
45
|
+
"switch.mode.color", "switch.gate", "switch.power.zone", "switch.pause",
|
|
46
|
+
"switch.setting",
|
|
42
47
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
"level.color.hue", "level.color.saturation", "level.color.rgb", "level.color.rgbw",
|
|
54
|
-
"level.color.cie", "level.color.luminance", "level.color.temperature",
|
|
55
|
-
"level.effect", "level.timer", "level.timer.sleep",
|
|
56
|
-
"level.volume", "level.volume.group",
|
|
57
|
-
"level.speed", "level.bass", "level.treble",
|
|
58
|
-
"level.mode.fan", "level.mode.swing", "level.mode.airconditioner", "level.mode.thermostat",
|
|
59
|
-
"level.mode.cleanup", "level.mode.work",
|
|
60
|
-
"level.setting.color.temperature",
|
|
48
|
+
"button", "button.long", "button.stop", "button.stop.tilt",
|
|
49
|
+
"button.start", "button.resume", "button.open.door", "button.open.window",
|
|
50
|
+
"button.open.blind", "button.open.tilt", "button.close.blind", "button.close.tilt",
|
|
51
|
+
"button.mode", "button.mode.auto", "button.mode.manual", "button.mode.silent",
|
|
52
|
+
"button.press", "button.play", "button.next", "button.prev", "button.pause",
|
|
53
|
+
"button.forward", "button.reverse", "button.fastforward", "button.fastreverse",
|
|
54
|
+
"button.volume.up", "button.volume.down"
|
|
55
|
+
],
|
|
56
|
+
"both": [
|
|
57
|
+
"state",
|
|
61
58
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
59
|
+
"level", "level.dimmer", "level.blind", "level.curtain", "level.tilt",
|
|
60
|
+
"level.temperature", "level.humidity", "level.valve",
|
|
61
|
+
"level.pressure", "level.pressure.min", "level.pressure.max",
|
|
62
|
+
"level.voltage", "level.voltage.min", "level.voltage.max",
|
|
63
|
+
"level.current", "level.current.min", "level.current.max",
|
|
64
|
+
"level.frequency", "level.frequency.min", "level.frequency.max",
|
|
65
|
+
"level.battery", "level.battery.min", "level.battery.max",
|
|
66
|
+
"level.fill", "level.brightness",
|
|
67
|
+
"level.min", "level.max", "level.default",
|
|
68
|
+
"level.color.red", "level.color.green", "level.color.blue", "level.color.white",
|
|
69
|
+
"level.color.hue", "level.color.saturation", "level.color.rgb", "level.color.rgbw",
|
|
70
|
+
"level.color.cie", "level.color.luminance", "level.color.temperature",
|
|
71
|
+
"level.effect", "level.timer", "level.timer.sleep",
|
|
72
|
+
"level.volume", "level.volume.group",
|
|
73
|
+
"level.speed", "level.bass", "level.treble",
|
|
74
|
+
"level.mode.fan", "level.mode.swing", "level.mode.airconditioner", "level.mode.thermostat",
|
|
75
|
+
"level.mode.cleanup", "level.mode.work",
|
|
76
|
+
"level.setting.color.temperature",
|
|
69
77
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
78
|
+
"text", "text.url", "text.phone",
|
|
79
|
+
"html", "json", "list", "date",
|
|
80
|
+
"date.start", "date.end", "date.forecast.1", "date.sunrise", "date.sunset",
|
|
81
|
+
"dayofweek", "location",
|
|
82
|
+
"url", "url.icon", "url.cam", "url.blank", "url.same", "url.audio",
|
|
73
83
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
84
|
+
"media.state", "media.mute", "media.mute.group", "media.seek",
|
|
85
|
+
"media.mode.shuffle", "media.mode.repeat",
|
|
86
|
+
"media.artist", "media.album", "media.title", "media.title.next",
|
|
87
|
+
"media.cover", "media.cover.big", "media.cover.small",
|
|
88
|
+
"media.duration", "media.duration.text", "media.elapsed", "media.elapsed.text",
|
|
89
|
+
"media.broadcastDate", "media.season", "media.episode",
|
|
90
|
+
"media.tts", "media.bitrate", "media.genre", "media.date", "media.track",
|
|
91
|
+
"media.playid", "media.add", "media.clear", "media.playlist",
|
|
92
|
+
"media.url", "media.url.announcement", "media.jump", "media.content",
|
|
93
|
+
"media.link", "media.input", "media.browser",
|
|
79
94
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
"media.tts", "media.bitrate", "media.genre", "media.date", "media.track",
|
|
87
|
-
"media.playid", "media.add", "media.clear", "media.playlist",
|
|
88
|
-
"media.url", "media.url.announcement", "media.jump", "media.content",
|
|
89
|
-
"media.link", "media.input", "media.browser",
|
|
95
|
+
"weather.title", "weather.title.short", "weather.title.forecast.0",
|
|
96
|
+
"weather.state", "weather.state.forecast.0", "weather.state.forecast.1",
|
|
97
|
+
"weather.icon", "weather.icon.forecast.1", "weather.icon.name", "weather.icon.wind",
|
|
98
|
+
"weather.chart.url", "weather.chart.url.forecast",
|
|
99
|
+
"weather.html", "weather.json", "weather.type",
|
|
100
|
+
"weather.direction.wind", "weather.direction.wind.forecast.0",
|
|
90
101
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"weather.chart.url", "weather.chart.url.forecast",
|
|
95
|
-
"weather.html", "weather.json", "weather.type",
|
|
96
|
-
"weather.direction.wind", "weather.direction.wind.forecast.0",
|
|
102
|
+
"info.ip", "info.mac", "info.name", "info.address", "info.serial",
|
|
103
|
+
"info.firmware", "info.hardware", "info.port", "info.standby",
|
|
104
|
+
"info.status", "info.display", "info.model",
|
|
97
105
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
"time.span", "time.interval", "time.timeout",
|
|
103
|
-
"chart", "adapter.messagebox", "adapter.wakeup"
|
|
104
|
-
]
|
|
106
|
+
"time.span", "time.interval", "time.timeout",
|
|
107
|
+
"chart", "adapter.messagebox", "adapter.wakeup"
|
|
108
|
+
]
|
|
109
|
+
}
|
package/io-package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "openknx",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.3",
|
|
5
5
|
"news": {
|
|
6
|
-
"1.1.
|
|
6
|
+
"1.1.3": {
|
|
7
7
|
"en": "**breaking:** KNX communication switched to KNXUltimate\n**breaking:** DPT21 property names changed (outofservice → outOfService, inalarm → inAlarm, alarmeunack → alarmUnAck), values must be boolean\n**breaking:** DPT237 property names changed to camelCase\nfeature: KNX Secure support\nfeature: Native .knxproj import (ETS4/5/6, password-protected) with flags, DPT inference, room assignment\nfeature: Extended DPT coverage (9 additional DPTs, including DPT-22, 213, 222, 235, 242, 249, 251)\nfeature: Improved connection stability\nfeature: Improved role detection (switch, level, value, text, date) based on DPT type\nfeature: Direct Link all iobroker states to a KNX state\nfeature: GA-Tools: all GA properties editable (DPT, type, role, flags) with compact layout",
|
|
8
8
|
"de": "**breaking:** KNX-Kommunikation auf KNXUltimate umgestellt\n**breaking:** DPT21 Eigenschaftsnamen geändert (outofservice → outOfService, inalarm → inAlarm, alarmeunack → alarmUnAck), Werte müssen boolean sein\n**breaking:** DPT237 Eigenschaftsnamen auf camelCase geändert\nFeature: KNX Secure Unterstützung\nFeature: Nativer .knxproj Import (ETS4/5/6, passwortgeschützt) mit Flags, DPT-Erkennung, Raumzuordnung\nFeature: Erweiterte DPT-Abdeckung (9 zusätzliche DPTs, u.a. DPT-22, 213, 222, 235, 242, 249, 251)\nFeature: Verbesserte Verbindungsstabilität\nFeature: Verbesserte Rollenerkennung (switch, level, value, text, date) basierend auf DPT-Typ\nFeature: Direct Link – beliebige ioBroker-States mit KNX-Gruppenadressen verknüpfen\nFeature: GA-Tools: alle GA-Eigenschaften editierbar (DPT, Typ, Rolle, Flags) mit kompaktem Layout",
|
|
9
9
|
"ru": "**breaking:** KNX-коммуникация переключена на KNXUltimate\n**breaking:** Имена свойств DPT21 изменены (outofservice → outOfService, inalarm → inAlarm, alarmeunack → alarmUnAck), значения должны быть boolean\n**breaking:** Имена свойств DPT237 изменены на camelCase\nFeature: Поддержка KNX Secure\nFeature: Нативный импорт .knxproj (ETS4/5/6, с паролем) с флагами, определением DPT, назначением комнат\nFeature: Расширенное покрытие DPT (9 дополнительных DPT, включая DPT-22, 213, 222, 235, 242, 249, 251)\nFeature: Улучшенная стабильность соединения\nFeature: Улучшенное определение ролей (switch, level, value, text, date) на основе типа DPT\nFeature: Direct Link – привязка любых состояний ioBroker к групповым адресам KNX\nFeature: GA-Tools: все свойства GA редактируемы (DPT, тип, роль, флаги) с компактным макетом",
|
package/lib/tools.js
CHANGED
|
@@ -102,12 +102,12 @@ function isTriggerDPT(dpt) {
|
|
|
102
102
|
//used to exclude from autoread
|
|
103
103
|
//scene is a trigger, do not request trigger on start, more to add
|
|
104
104
|
return (
|
|
105
|
-
dpt.startsWith("
|
|
106
|
-
dpt.startsWith("
|
|
107
|
-
dpt.startsWith("
|
|
108
|
-
dpt.startsWith("
|
|
109
|
-
dpt.startsWith("
|
|
110
|
-
dpt.startsWith("
|
|
105
|
+
dpt.startsWith("DPT1.001") || //DPT_Switch
|
|
106
|
+
dpt.startsWith("DPT1.007") || //DPT_Step
|
|
107
|
+
dpt.startsWith("DPT1.008") || //DPT_UpDown
|
|
108
|
+
dpt.startsWith("DPT1.010") || //DPT_Start
|
|
109
|
+
dpt.startsWith("DPT1.017") || //DPT_Trigger
|
|
110
|
+
dpt.startsWith("DPT2.001") || //Switch_Control
|
|
111
111
|
dpt == "DPT17" ||
|
|
112
112
|
dpt.startsWith("DPT17.") ||
|
|
113
113
|
dpt == "DPT18" ||
|
package/main.js
CHANGED
|
@@ -627,7 +627,11 @@ class openknx extends utils.Adapter {
|
|
|
627
627
|
this.log.debug(
|
|
628
628
|
`Direct Link [${mode}]: ${id} changed to ${JSON.stringify(state.val)}, writing ${JSON.stringify(writeVal)} to GA ${gaData.native.address}`,
|
|
629
629
|
);
|
|
630
|
-
|
|
630
|
+
try {
|
|
631
|
+
this.knxConnection.write(gaData.native.address, writeVal, gaData.native.dpt);
|
|
632
|
+
} catch (e) {
|
|
633
|
+
this.log.warn(`Direct Link write failed for ${gaData.native.address}: ${e.message}`);
|
|
634
|
+
}
|
|
631
635
|
// Update KNX object state
|
|
632
636
|
if (this.isForeign) {
|
|
633
637
|
this.setForeignState(linkedKnxId, { val: writeVal, ack: true });
|
|
@@ -736,7 +740,11 @@ class openknx extends utils.Adapter {
|
|
|
736
740
|
if (state.c == "GroupValue_Read" || state.q == 0x10) {
|
|
737
741
|
// interface to trigger GrouValue_Read is this object comment or StateQuality 16
|
|
738
742
|
this.log.debug(`Outbound GroupValue_Read to GA ${ga}`);
|
|
739
|
-
|
|
743
|
+
try {
|
|
744
|
+
this.knxConnection.read(ga);
|
|
745
|
+
} catch (e) {
|
|
746
|
+
this.log.warn(`GroupValue_Read failed for ${ga}: ${e.message}`);
|
|
747
|
+
}
|
|
740
748
|
// ack is generated with GroupValue_Response via indication event
|
|
741
749
|
return "read";
|
|
742
750
|
} else if (gaData.common.write) {
|
|
@@ -854,6 +862,9 @@ class openknx extends utils.Adapter {
|
|
|
854
862
|
// Clean up previous connection (reconnect case)
|
|
855
863
|
if (this.knxConnection) {
|
|
856
864
|
this.knxConnection.removeAllListeners();
|
|
865
|
+
this.knxConnection.Disconnect().catch(() => {
|
|
866
|
+
// ignore - old connection may already be in broken state
|
|
867
|
+
});
|
|
857
868
|
this.knxConnection = undefined;
|
|
858
869
|
}
|
|
859
870
|
|
|
@@ -1107,6 +1118,8 @@ class openknx extends utils.Adapter {
|
|
|
1107
1118
|
`Could not decode GA ${dest} (${data.native.dpt}), raw=[${rawData.toString("hex")}]. Check DPT configuration in ETS (buffer length mismatch?).`,
|
|
1108
1119
|
);
|
|
1109
1120
|
convertedVal = rawData.toString("hex");
|
|
1121
|
+
} else if (typeof jsValue === "bigint") {
|
|
1122
|
+
convertedVal = jsValue.toString();
|
|
1110
1123
|
} else if (tools.isStringDPT(data.native.dpt)) {
|
|
1111
1124
|
convertedVal = jsValue;
|
|
1112
1125
|
} else {
|