node-red-contrib-knx-ultimate 6.0.11 → 6.0.12
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/CHANGELOG.md +5 -1
- package/nodes/knxUltimateHueLight.html +1 -5
- package/nodes/knxUltimateMatterControllerDevice.html +318 -41
- package/nodes/locales/de/knxUltimateMatterBridge.html +0 -2
- package/nodes/locales/de/knxUltimateMatterControllerDevice.html +10 -2
- package/nodes/locales/de/knxUltimateMatterControllerDevice.json +17 -1
- package/nodes/locales/en/knxUltimateMatterBridge.html +0 -2
- package/nodes/locales/en/knxUltimateMatterControllerDevice.html +10 -2
- package/nodes/locales/en/knxUltimateMatterControllerDevice.json +17 -1
- package/nodes/locales/es/knxUltimateMatterBridge.html +0 -2
- package/nodes/locales/es/knxUltimateMatterControllerDevice.html +10 -2
- package/nodes/locales/es/knxUltimateMatterControllerDevice.json +17 -1
- package/nodes/locales/fr/knxUltimateMatterBridge.html +0 -2
- package/nodes/locales/fr/knxUltimateMatterControllerDevice.html +10 -2
- package/nodes/locales/fr/knxUltimateMatterControllerDevice.json +17 -1
- package/nodes/locales/it/knxUltimateMatterBridge.html +0 -2
- package/nodes/locales/it/knxUltimateMatterControllerDevice.html +10 -2
- package/nodes/locales/it/knxUltimateMatterControllerDevice.json +17 -1
- package/nodes/locales/zh-CN/knxUltimateMatterBridge.html +0 -2
- package/nodes/locales/zh-CN/knxUltimateMatterControllerDevice.html +10 -2
- package/nodes/locales/zh-CN/knxUltimateMatterControllerDevice.json +17 -1
- package/nodes/matter-config.js +5 -4
- package/nodes/utils/matterControllerProfiles/index.js +3 -1
- package/nodes/utils/matterControllerProfiles/universal.js +462 -0
- package/nodes/utils/matterEngine.mjs +2 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,8 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
|
-
**Version 6.0.
|
|
9
|
+
**Version 6.0.12** - July 2026<br/>
|
|
10
10
|
|
|
11
|
+
- **Control Matter from KNX — Universal Mode**: a dedicated **Mode** selector now switches between a single Matter device and controller-wide Universal Mode. Its **Universal Battery Monitor** scans every commissioned node and endpoint for battery Power Source clusters, maintains a normalized cache, publishes an optional aggregate KNX alarm as DPT 1.005, cycles low-battery device names every 2 seconds as DPT 16.001, and answers `getAllBatteries` flow queries. The alternative **All Matter events** service preserves the generic attribute/event stream and dynamic read/write/command input.<br/>
|
|
12
|
+
- **Universal Battery Monitor — KNX editor and diagnostics**: battery options now use the same vertical-tab and ETS/CSV group-address selectors as single-device profiles. Alarm and text mappings are aligned as Function/GA/DPT/Name rows, support editable names and KNX read responses, ignore wired Power Source endpoints, and show an aggregate battery status instead of per-device `unknown` states.<br/>
|
|
13
|
+
- **Matter light capability refresh**: Color Control `featureMap` and the endpoint device type now drive the Tunable White and RGB/HSV tabs. New selections, changed devices and previously saved nodes normalize stale capabilities so Tunable White lights no longer retain unsupported colour mappings.<br/>
|
|
14
|
+
- **Matter editor/help cleanup**: decorative animated light icons and duplicate localized help headings were removed from the Matter Controller, Matter Bridge and shared light editor where applicable.<br/>
|
|
11
15
|
- **Matter Bridge — editor tab orientation**: the device editor now uses the same left-hand vertical tab layout as Matter Controller, keeping Mappings and Advanced options visually consistent without changing saved configuration.<br/>
|
|
12
16
|
- **Control Matter from KNX — dedicated controller profiles**: Window Covering (`0x0102`), Thermostat (`0x0201`), Fan Control (`0x0202`) and Switch (`0x003B`) endpoints are now selected into explicit capability-driven profiles instead of the anonymous mapped fallback. They share the guarded mapping lifecycle while enforcing their native input/event cluster boundary and presenting semantic canvas status; Switch initial/long/multi-press events are filtered to the selected endpoint and exposed on the optional flow output. Simple actuators and sensors remain on the generic mapped profile.<br/>
|
|
13
17
|
- **Control Matter from KNX — flow attribute reads and persistent Door Lock status**: mapped endpoints now use an unambiguous top-level flow contract: `msg.clusterId` plus `msg.attribute` reads an attribute, `msg.value` makes it an attribute write, and `msg.command` plus `msg.args` invokes a command. Reads return the value in `msg.payload`, may force a remote request with `msg.requestFromRemote = true`, and accept numeric attribute ID `0`. Door Lock nodes now retain their last `locked`/`unlocked` canvas status when generic Matter or KNX notifications arrive.<br/>
|
|
@@ -1777,10 +1777,6 @@
|
|
|
1777
1777
|
target="_blank" href="https://youtu.be/jjEUI1J8bkA"><u><span data-i18n="common.youtube_sample"></span></u></a>
|
|
1778
1778
|
<br />
|
|
1779
1779
|
<br />
|
|
1780
|
-
<p align="center">
|
|
1781
|
-
<i class="fa-regular fa-lightbulb fa-bounce fa-2x"></i>
|
|
1782
|
-
</p>
|
|
1783
|
-
<br />
|
|
1784
1780
|
<label for="node-input-server">
|
|
1785
1781
|
<img
|
|
1786
1782
|
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAKnRFWHRDcmVhdGlvbiBUaW1lAEZyIDYgQXVnIDIwMTAgMjE6NTI6MTkgKzAxMDD84aS8AAAAB3RJTUUH3gYYCicNV+4WIQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAARnQU1BAACxjwv8YQUAAACUSURBVHjaY2CgFZg5c+Z/ZEyWAZ8+f/6/ZsWs/xoamqMGkGrA6Wla/1+fVARjEBuGsSoGmY4eZSCNL59d/g8DIDbIAHR14OgFGQByKjIGKX5+6/T///8gGMQGiV1+/B0Fg70GIkD+RMYgxf/O5/7//2MSmAZhkBi6OrgB6Bg5DGB4ajr3f2xqsYYLSDE2THJUDg0AAAqyDVd4tp4YAAAAAElFTkSuQmCC"></img>
|
|
@@ -2487,4 +2483,4 @@ Use the **Hue native effects** table to map your KNX values to the effects suppo
|
|
|
2487
2483
|
The Dimming function works in **KNX mode `start` and`stop` ** . To start dimming, send only one "start" KNX telegram. To stop dimming, send a "stop" KNX telegram. Please**remember that** , when you set your wall swiches properties.
|
|
2488
2484
|
|
|
2489
2485
|
<br/>
|
|
2490
|
-
</script>
|
|
2486
|
+
</script>
|
|
@@ -14,6 +14,16 @@
|
|
|
14
14
|
//buttonState: {value: true},
|
|
15
15
|
server: { type: "knxUltimate-config", required: false },
|
|
16
16
|
serverMatter: { type: "matter-config", required: true },
|
|
17
|
+
matterControllerMode: { value: "single" },
|
|
18
|
+
universalService: { value: "batteryMonitor" },
|
|
19
|
+
universalBatteryThreshold: { value: 20, validate: RED.validators.number() },
|
|
20
|
+
universalLowBatteryGA: { value: "" },
|
|
21
|
+
universalLowBatteryGAName: { value: "" },
|
|
22
|
+
universalLowBatteryTextGA: { value: "" },
|
|
23
|
+
universalLowBatteryTextGAName: { value: "" },
|
|
24
|
+
universalBatteryOnlyLow: { value: true },
|
|
25
|
+
universalEmitInitialState: { value: true },
|
|
26
|
+
universalIncludeRawEvent: { value: true },
|
|
17
27
|
matterNodeId: { value: "" },
|
|
18
28
|
matterEndpointId: { value: 1 },
|
|
19
29
|
matterDeviceName: { value: "" },
|
|
@@ -221,6 +231,8 @@
|
|
|
221
231
|
const KNX_EMPTY_VALUES = new Set(['', 'none', '_ADD_', '__NONE__']);
|
|
222
232
|
// Historical variable names are retained for saved-flow compatibility; they point to Matter widgets.
|
|
223
233
|
const $hueServerInput = $("#node-input-serverMatter");
|
|
234
|
+
const $matterControllerModeInput = $("#node-input-matterControllerMode");
|
|
235
|
+
const $universalServiceInput = $("#node-input-universalService");
|
|
224
236
|
const $hueDeviceInput = $("#node-input-matterNodeId");
|
|
225
237
|
const $deviceNameInput = $("#node-input-matterDeviceName");
|
|
226
238
|
const $matterEndpointInput = $("#node-input-matterEndpointId");
|
|
@@ -229,6 +241,9 @@
|
|
|
229
241
|
const $refreshDevicesButton = $(".hue-refresh-devices");
|
|
230
242
|
const $locateDeviceButton = $(".hue-locate-device");
|
|
231
243
|
const $hueDevicesLoading = $(".hue-devices-loading");
|
|
244
|
+
const UNIVERSAL_NODE_ID = '__UNIVERSAL__';
|
|
245
|
+
const isUniversalMode = () => $matterControllerModeInput.val() === 'universal';
|
|
246
|
+
$matterControllerModeInput.val(node.matterControllerMode || 'single');
|
|
232
247
|
let cachedHueDevices = Array.isArray(node._cachedHueLightDevices) ? node._cachedHueLightDevices : [];
|
|
233
248
|
node._cachedHueLightDevices = cachedHueDevices;
|
|
234
249
|
const defaultHueDevicePlaceholder = $deviceNameInput.attr('placeholder') || '';
|
|
@@ -289,7 +304,10 @@
|
|
|
289
304
|
const title = locateSessionActive
|
|
290
305
|
? (node._('knxUltimateMatterControllerDevice.locate_stop_title') || 'Stop Matter locate')
|
|
291
306
|
: (node._('knxUltimateMatterControllerDevice.locate_start_title') || 'Locate selected Matter device');
|
|
292
|
-
$locateDeviceButton.attr('title',
|
|
307
|
+
$locateDeviceButton.attr('title', isUniversalMode()
|
|
308
|
+
? (node._('knxUltimateMatterControllerDevice.universal_mode_locate_disabled') || 'Locate is unavailable in Universal Mode.')
|
|
309
|
+
: title);
|
|
310
|
+
$locateDeviceButton.prop('disabled', isUniversalMode());
|
|
293
311
|
};
|
|
294
312
|
|
|
295
313
|
const removeNodeRemovalListener = () => {
|
|
@@ -340,6 +358,10 @@
|
|
|
340
358
|
};
|
|
341
359
|
|
|
342
360
|
const performLocateRequest = ({ silent = false, allowStoredContext = false, action } = {}) => {
|
|
361
|
+
if (isUniversalMode()) {
|
|
362
|
+
if (!silent) RED.notify(node._('knxUltimateMatterControllerDevice.universal_mode_locate_disabled') || 'Locate is unavailable in Universal Mode.', 'warning');
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
343
365
|
const context = buildLocateContext({ allowStored: allowStoredContext });
|
|
344
366
|
if (!context) {
|
|
345
367
|
if (!silent) {
|
|
@@ -419,7 +441,7 @@
|
|
|
419
441
|
}).always(() => {
|
|
420
442
|
locatePendingRequest = null;
|
|
421
443
|
if ($locateDeviceButton.length) {
|
|
422
|
-
$locateDeviceButton.prop('disabled',
|
|
444
|
+
$locateDeviceButton.prop('disabled', isUniversalMode());
|
|
423
445
|
}
|
|
424
446
|
});
|
|
425
447
|
return request;
|
|
@@ -593,43 +615,75 @@
|
|
|
593
615
|
}
|
|
594
616
|
const hasColorTemperatureType = /colortemperature|extendedcolor/.test(typeText);
|
|
595
617
|
const hasColorType = /extendedcolor/.test(typeText);
|
|
618
|
+
const isTunableWhiteOnly = hasColorTemperatureType && !hasColorType;
|
|
596
619
|
const hasLevelType = /dimmable|colortemperature|extendedcolor/.test(typeText);
|
|
620
|
+
const colorFeatureMapAttribute = (colorCluster?.attributes || []).find((attribute) => normalizeMatterToken(attribute.name) === 'featuremap');
|
|
621
|
+
const colorFeatureMap = Number(colorFeatureMapAttribute?.value);
|
|
622
|
+
const hasColorFeatureMap = Number.isFinite(colorFeatureMap);
|
|
597
623
|
const hasColorTemperature = !!colorCluster && (
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
624
|
+
hasColorFeatureMap
|
|
625
|
+
? (colorFeatureMap & 0x10) !== 0
|
|
626
|
+
: (
|
|
627
|
+
hasColorTemperatureType ||
|
|
628
|
+
hasMatterAttribute(colorCluster, ['colorTemperatureMireds', 'colorTempPhysicalMinMireds', 'colorTempPhysicalMaxMireds']) ||
|
|
629
|
+
hasMatterCommand(colorCluster, ['moveToColorTemperature'])
|
|
630
|
+
)
|
|
601
631
|
);
|
|
602
632
|
const hasColor = !!colorCluster && (
|
|
603
|
-
|
|
604
|
-
|
|
633
|
+
!isTunableWhiteOnly && (
|
|
634
|
+
hasColorFeatureMap
|
|
635
|
+
? (colorFeatureMap & 0x09) !== 0
|
|
636
|
+
: (
|
|
637
|
+
hasColorType ||
|
|
638
|
+
hasMatterCommand(colorCluster, ['moveToColor', 'moveToHue', 'moveToSaturation', 'moveToHueAndSaturation'])
|
|
639
|
+
)
|
|
640
|
+
)
|
|
605
641
|
);
|
|
606
642
|
return {
|
|
607
643
|
known: true,
|
|
608
644
|
deviceTypeDisplay,
|
|
609
|
-
|
|
645
|
+
matterLightType: isTunableWhiteOnly ? 'colorTemperature' : (hasColorType ? 'extendedColor' : 'other'),
|
|
646
|
+
colorDetectionVersion: 3,
|
|
610
647
|
onOff: !!onOffCluster || /onoff|dimmable|colortemperature|extendedcolor/.test(typeText),
|
|
611
648
|
level: !!levelCluster || hasLevelType,
|
|
612
649
|
colorTemperature: hasColorTemperature,
|
|
613
650
|
color: hasColor
|
|
614
651
|
};
|
|
615
652
|
};
|
|
653
|
+
const normalizeMatterCapabilities = (capabilities) => {
|
|
654
|
+
if (!capabilities || typeof capabilities !== 'object') return capabilities;
|
|
655
|
+
const normalized = Object.assign({}, capabilities);
|
|
656
|
+
const displayType = normalizeMatterToken(normalized.deviceTypeDisplay);
|
|
657
|
+
const tunableWhiteOnly = normalized.matterLightType === 'colorTemperature' ||
|
|
658
|
+
displayType === 'tunablewhite' ||
|
|
659
|
+
displayType === 'colortemperaturelight';
|
|
660
|
+
if (tunableWhiteOnly) {
|
|
661
|
+
normalized.colorTemperature = true;
|
|
662
|
+
normalized.color = false;
|
|
663
|
+
normalized.colorDetectionVersion = 3;
|
|
664
|
+
} else if (normalized.known === true && normalized.color === true &&
|
|
665
|
+
normalized.colorDetectionVersion !== 2 && normalized.colorDetectionVersion !== 3) {
|
|
666
|
+
normalized.color = false;
|
|
667
|
+
}
|
|
668
|
+
return normalized;
|
|
669
|
+
};
|
|
616
670
|
const parseMatterCapabilities = (raw) => {
|
|
617
671
|
if (raw && typeof raw === 'object') {
|
|
618
|
-
|
|
619
|
-
return raw;
|
|
672
|
+
return normalizeMatterCapabilities(raw);
|
|
620
673
|
}
|
|
621
674
|
if (typeof raw !== 'string' || raw.trim() === '') return null;
|
|
622
675
|
try {
|
|
623
|
-
|
|
624
|
-
if (parsed && parsed.known === true && parsed.color === true && parsed.colorDetectionVersion !== 2) {
|
|
625
|
-
parsed.color = false;
|
|
626
|
-
}
|
|
627
|
-
return parsed;
|
|
676
|
+
return normalizeMatterCapabilities(JSON.parse(raw));
|
|
628
677
|
} catch (error) {
|
|
629
678
|
return null;
|
|
630
679
|
}
|
|
631
680
|
};
|
|
632
681
|
const serializeMatterCapabilities = (capabilities) => JSON.stringify(capabilities || {});
|
|
682
|
+
const universalMatterCapabilities = () => ({
|
|
683
|
+
known: true,
|
|
684
|
+
profile: 'universal',
|
|
685
|
+
deviceTypeDisplay: node._('knxUltimateMatterControllerDevice.universal_mode') || 'Universal Mode'
|
|
686
|
+
});
|
|
633
687
|
const getJSONPromise = (url) => new Promise((resolve, reject) => { $.getJSON(url, resolve).fail(reject); });
|
|
634
688
|
|
|
635
689
|
// Filters Matter items shaped as { value, matterNodeId, matterEndpointId }.
|
|
@@ -742,13 +796,22 @@
|
|
|
742
796
|
|
|
743
797
|
|
|
744
798
|
const $tabs = $("#tabs");
|
|
799
|
+
const $universalTabs = $("#matter-universal-tabs");
|
|
745
800
|
const $pinSectionRow = $("#node-input-enableNodePINS").closest('.form-row');
|
|
746
801
|
const $pinSelect = $("#node-input-enableNodePINS");
|
|
747
802
|
let currentMatterCapabilities = parseMatterCapabilities($matterCapabilitiesInput.val() || node.matterDeviceCapabilities);
|
|
803
|
+
if (currentMatterCapabilities) {
|
|
804
|
+
$matterCapabilitiesInput.val(serializeMatterCapabilities(currentMatterCapabilities));
|
|
805
|
+
node.matterDeviceCapabilities = $matterCapabilitiesInput.val();
|
|
806
|
+
}
|
|
748
807
|
$tabs.addClass('hue-vertical-tabs');
|
|
749
808
|
$tabs.tabs(); // Tabs gestione KNX
|
|
750
809
|
$tabs.find('ul').addClass('ui-tabs-nav');
|
|
751
810
|
$tabs.find('li').removeClass('ui-corner-top').addClass('ui-corner-left');
|
|
811
|
+
$universalTabs.addClass('hue-vertical-tabs');
|
|
812
|
+
$universalTabs.tabs();
|
|
813
|
+
$universalTabs.find('ul').addClass('ui-tabs-nav');
|
|
814
|
+
$universalTabs.find('li').removeClass('ui-corner-top').addClass('ui-corner-left');
|
|
752
815
|
|
|
753
816
|
function getDPT(_dpt, _destinationWidget) {
|
|
754
817
|
// DPT Switch command
|
|
@@ -835,7 +898,49 @@
|
|
|
835
898
|
} catch (e) { }
|
|
836
899
|
}
|
|
837
900
|
|
|
901
|
+
function getFixedDptGroupAddress(_sourceWidgetAutocomplete, _destinationWidgetName, _dptPrefix) {
|
|
902
|
+
const $source = $(_sourceWidgetAutocomplete);
|
|
903
|
+
if ($source.data('ui-autocomplete')) {
|
|
904
|
+
try { $source.autocomplete('destroy'); } catch (error) { /* empty */ }
|
|
905
|
+
}
|
|
906
|
+
$source.autocomplete({
|
|
907
|
+
minLength: 0,
|
|
908
|
+
source: function (request, response) {
|
|
909
|
+
if (!hasKnxServerSelected()) {
|
|
910
|
+
response([]);
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
const serverId = resolveKnxServerValue();
|
|
914
|
+
$.getJSON(`knxUltimatecsv?nodeID=${serverId}&_=${Date.now()}`, (data) => {
|
|
915
|
+
response($.map(data, function (value) {
|
|
916
|
+
const searchable = `${value.ga} (${value.devicename}) DPT${value.dpt}`;
|
|
917
|
+
if (!htmlUtilsfullCSVSearch(searchable, `${request.term || ''} ${_dptPrefix}`)) return null;
|
|
918
|
+
return {
|
|
919
|
+
label: `${value.ga} # ${value.devicename} # ${value.dpt}`,
|
|
920
|
+
value: value.ga,
|
|
921
|
+
deviceName: value.devicename
|
|
922
|
+
};
|
|
923
|
+
}));
|
|
924
|
+
});
|
|
925
|
+
},
|
|
926
|
+
select: function (event, ui) {
|
|
927
|
+
$(_destinationWidgetName).val(ui.item.deviceName || '');
|
|
928
|
+
}
|
|
929
|
+
}).focus(function () {
|
|
930
|
+
$(this).autocomplete('search', `${$(this).val()}exactmatch`);
|
|
931
|
+
});
|
|
932
|
+
try {
|
|
933
|
+
if (hasKnxServerSelected()) {
|
|
934
|
+
const srv = RED.nodes.node(resolveKnxServerValue());
|
|
935
|
+
if (srv && srv.id) KNX_enableSecureFormatting($source, srv.id);
|
|
936
|
+
}
|
|
937
|
+
} catch (error) { /* empty */ }
|
|
938
|
+
}
|
|
939
|
+
|
|
838
940
|
const refreshKnxBindings = () => {
|
|
941
|
+
getFixedDptGroupAddress("#node-input-universalLowBatteryGA", "#node-input-universalLowBatteryGAName", "1.");
|
|
942
|
+
getFixedDptGroupAddress("#node-input-universalLowBatteryTextGA", "#node-input-universalLowBatteryTextGAName", "16.");
|
|
943
|
+
|
|
839
944
|
getDPT("1.", "#node-input-dptLightSwitch");
|
|
840
945
|
getGroupAddress("#node-input-GALightSwitch", "#node-input-nameLightSwitch", "#node-input-dptLightSwitch", ["1."]);
|
|
841
946
|
|
|
@@ -991,7 +1096,7 @@
|
|
|
991
1096
|
};
|
|
992
1097
|
|
|
993
1098
|
const applyMatterCapabilities = (capabilities) => {
|
|
994
|
-
currentMatterCapabilities = capabilities || null;
|
|
1099
|
+
currentMatterCapabilities = normalizeMatterCapabilities(capabilities) || null;
|
|
995
1100
|
const caps = getEffectiveMatterCapabilities();
|
|
996
1101
|
const hasHueDevice = getHueDeviceValue() !== '';
|
|
997
1102
|
const supportsSwitch = hasHueDevice && caps.onOff !== false;
|
|
@@ -1001,14 +1106,18 @@
|
|
|
1001
1106
|
const hasRichBehaviour = supportsDim && (supportsTemperature || supportsColor);
|
|
1002
1107
|
const isDoorLock = caps.profile === 'doorLock';
|
|
1003
1108
|
const isMapped = ['mapped', 'windowCovering', 'thermostat', 'fan', 'switch'].includes(caps.profile);
|
|
1109
|
+
const isUniversal = caps.profile === 'universal' || isUniversalMode();
|
|
1004
1110
|
const deviceTypeDisplay = String(caps.deviceTypeDisplay || '').trim();
|
|
1005
1111
|
|
|
1006
|
-
setMatterTabVisible('tabs-1', supportsSwitch);
|
|
1007
|
-
setMatterTabVisible('tabs-2', supportsDim);
|
|
1008
|
-
setMatterTabVisible('tabs-3', supportsTemperature);
|
|
1009
|
-
setMatterTabVisible('tabs-4', supportsColor);
|
|
1010
|
-
setMatterTabVisible('tabs-mapped', isMapped);
|
|
1011
|
-
setMatterTabVisible('tabs-6', hasHueDevice);
|
|
1112
|
+
setMatterTabVisible('tabs-1', !isUniversal && supportsSwitch);
|
|
1113
|
+
setMatterTabVisible('tabs-2', !isUniversal && supportsDim);
|
|
1114
|
+
setMatterTabVisible('tabs-3', !isUniversal && supportsTemperature);
|
|
1115
|
+
setMatterTabVisible('tabs-4', !isUniversal && supportsColor);
|
|
1116
|
+
setMatterTabVisible('tabs-mapped', !isUniversal && isMapped);
|
|
1117
|
+
setMatterTabVisible('tabs-6', !isUniversal && hasHueDevice);
|
|
1118
|
+
$('#matter-universal-description').toggle(isUniversal);
|
|
1119
|
+
$pinSelect.val(isUniversal ? 'yes' : $pinSelect.val()).prop('disabled', isUniversal);
|
|
1120
|
+
updateLocateButtonState(false);
|
|
1012
1121
|
$('#matter-door-lock-options').toggle(isDoorLock);
|
|
1013
1122
|
$('#matter-switch-command-label').text(isDoorLock
|
|
1014
1123
|
? (node._('knxUltimateMatterControllerDevice.door_lock_command') || 'Lock / unlock')
|
|
@@ -1079,7 +1188,7 @@
|
|
|
1079
1188
|
const updateTabsVisibility = () => {
|
|
1080
1189
|
const knxSelected = hasKnxServerSelected();
|
|
1081
1190
|
const hueDeviceSelected = getHueDeviceValue() !== '';
|
|
1082
|
-
const shouldShowTabs = knxSelected && hueDeviceSelected;
|
|
1191
|
+
const shouldShowTabs = !isUniversalMode() && knxSelected && hueDeviceSelected;
|
|
1083
1192
|
|
|
1084
1193
|
if (shouldShowTabs) {
|
|
1085
1194
|
$tabs.show();
|
|
@@ -1093,7 +1202,47 @@
|
|
|
1093
1202
|
$pinSectionRow.show();
|
|
1094
1203
|
}
|
|
1095
1204
|
};
|
|
1205
|
+
|
|
1206
|
+
const refreshUniversalServiceVisibility = () => {
|
|
1207
|
+
const universal = $matterControllerModeInput.val() === 'universal';
|
|
1208
|
+
$('#matter-universal-options').toggle(universal);
|
|
1209
|
+
$universalTabs.toggle(universal && $universalServiceInput.val() === 'batteryMonitor');
|
|
1210
|
+
if ($universalTabs.is(':visible')) {
|
|
1211
|
+
try { $universalTabs.tabs('refresh'); } catch (error) { /* empty */ }
|
|
1212
|
+
}
|
|
1213
|
+
};
|
|
1214
|
+
|
|
1215
|
+
const applyControllerMode = () => {
|
|
1216
|
+
const universal = $matterControllerModeInput.val() === 'universal';
|
|
1217
|
+
$('#matter-device-section-title, #matter-device-row').toggle(!universal);
|
|
1218
|
+
if (universal) {
|
|
1219
|
+
const universalName = node._('knxUltimateMatterControllerDevice.universal_mode') || 'Universal Mode';
|
|
1220
|
+
currentMatterCapabilities = universalMatterCapabilities();
|
|
1221
|
+
selectedMatterDeviceName = universalName;
|
|
1222
|
+
$deviceNameInput.val(universalName);
|
|
1223
|
+
$hueDeviceInput.val(UNIVERSAL_NODE_ID);
|
|
1224
|
+
$matterEndpointInput.val('');
|
|
1225
|
+
$matterCapabilitiesInput.val(serializeMatterCapabilities(currentMatterCapabilities));
|
|
1226
|
+
$nodeNameInput.val(node._('knxUltimateMatterControllerDevice.universal_controller_name') || 'Matter Universal Controller');
|
|
1227
|
+
$pinSelect.val('yes');
|
|
1228
|
+
} else if (String($hueDeviceInput.val() || '') === UNIVERSAL_NODE_ID) {
|
|
1229
|
+
currentMatterCapabilities = null;
|
|
1230
|
+
selectedMatterDeviceName = '';
|
|
1231
|
+
$deviceNameInput.val('');
|
|
1232
|
+
$hueDeviceInput.val('');
|
|
1233
|
+
$matterEndpointInput.val('');
|
|
1234
|
+
$matterCapabilitiesInput.val('');
|
|
1235
|
+
}
|
|
1236
|
+
refreshUniversalServiceVisibility();
|
|
1237
|
+
applyMatterCapabilities(currentMatterCapabilities);
|
|
1238
|
+
updateTabsVisibility();
|
|
1239
|
+
};
|
|
1240
|
+
|
|
1096
1241
|
updateTabsVisibility();
|
|
1242
|
+
applyControllerMode();
|
|
1243
|
+
|
|
1244
|
+
$matterControllerModeInput.on('change.knxUltimateMatterControllerDevice', applyControllerMode);
|
|
1245
|
+
$universalServiceInput.on('change.knxUltimateMatterControllerDevice', refreshUniversalServiceVisibility);
|
|
1097
1246
|
|
|
1098
1247
|
$knxServerInput.on('change.knxUltimateMatterControllerDevice', () => {
|
|
1099
1248
|
refreshKnxBindings();
|
|
@@ -1417,9 +1566,12 @@
|
|
|
1417
1566
|
} catch (error) { }
|
|
1418
1567
|
|
|
1419
1568
|
//RED.sidebar.removeTab("tabNRColor");
|
|
1420
|
-
|
|
1569
|
+
const universalMode = $("#node-input-matterControllerMode").val() === 'universal';
|
|
1570
|
+
this.matterControllerMode = universalMode ? 'universal' : 'single';
|
|
1571
|
+
if (universalMode || $("#node-input-enableNodePINS").val() === "yes") {
|
|
1421
1572
|
this.outputs = 1;
|
|
1422
1573
|
this.inputs = 1;
|
|
1574
|
+
this.enableNodePINS = 'yes';
|
|
1423
1575
|
} else {
|
|
1424
1576
|
this.outputs = 0;
|
|
1425
1577
|
this.inputs = 0;
|
|
@@ -1428,7 +1580,7 @@
|
|
|
1428
1580
|
this.updateLocalStateFromKNXWrite = $("#node-input-updateLocalStateFromKNXWrite").is(":checked"); // Starting from v 4.1.31
|
|
1429
1581
|
this.matterDeviceName = ($("#node-input-matterDeviceName").val() || '').trim();
|
|
1430
1582
|
this.matterNodeId = ($("#node-input-matterNodeId").val() || '').trim();
|
|
1431
|
-
this.matterEndpointId = Number($("#node-input-matterEndpointId").val() || 1);
|
|
1583
|
+
this.matterEndpointId = universalMode ? '' : Number($("#node-input-matterEndpointId").val() || 1);
|
|
1432
1584
|
this.matterDeviceCapabilities = ($("#node-input-matterDeviceCapabilities").val() || '').trim();
|
|
1433
1585
|
const mappedMappings = [];
|
|
1434
1586
|
const $mappedRows = $('#matter-mapped-profile-body .matter-mapped-row');
|
|
@@ -1444,7 +1596,9 @@
|
|
|
1444
1596
|
? JSON.stringify(mappedMappings)
|
|
1445
1597
|
: ($('#node-input-matterMappings').val() || this.matterMappings || '[]');
|
|
1446
1598
|
$('#node-input-matterMappings').val(this.matterMappings);
|
|
1447
|
-
this.name =
|
|
1599
|
+
this.name = universalMode
|
|
1600
|
+
? ($("#node-input-name").val() || this._('knxUltimateMatterControllerDevice.universal_controller_name') || 'Matter Universal Controller')
|
|
1601
|
+
: (this.matterDeviceName || this.name || '');
|
|
1448
1602
|
$("#node-input-name").val(this.name);
|
|
1449
1603
|
const parseSavedMatterCapabilities = (raw) => {
|
|
1450
1604
|
if (typeof raw !== 'string' || raw.trim() === '') return null;
|
|
@@ -1631,10 +1785,6 @@
|
|
|
1631
1785
|
target="_blank" href="https://youtu.be/jjEUI1J8bkA"><u><span data-i18n="common.youtube_sample"></span></u></a>
|
|
1632
1786
|
<br />
|
|
1633
1787
|
<br />
|
|
1634
|
-
<p align="center">
|
|
1635
|
-
<i class="fa-regular fa-lightbulb fa-bounce fa-2x"></i>
|
|
1636
|
-
</p>
|
|
1637
|
-
<br />
|
|
1638
1788
|
<label for="node-input-server">
|
|
1639
1789
|
<img
|
|
1640
1790
|
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAKnRFWHRDcmVhdGlvbiBUaW1lAEZyIDYgQXVnIDIwMTAgMjE6NTI6MTkgKzAxMDD84aS8AAAAB3RJTUUH3gYYCicNV+4WIQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAARnQU1BAACxjwv8YQUAAACUSURBVHjaY2CgFZg5c+Z/ZEyWAZ8+f/6/ZsWs/xoamqMGkGrA6Wla/1+fVARjEBuGsSoGmY4eZSCNL59d/g8DIDbIAHR14OgFGQByKjIGKX5+6/T///8gGMQGiV1+/B0Fg70GIkD+RMYgxf/O5/7//2MSmAZhkBi6OrgB6Bg5DGB4ajr3f2xqsYYLSDE2THJUDg0AAAqyDVd4tp4YAAAAAElFTkSuQmCC"></img>
|
|
@@ -1651,12 +1801,116 @@
|
|
|
1651
1801
|
<input type="text" id="node-input-serverMatter" />
|
|
1652
1802
|
</div>
|
|
1653
1803
|
|
|
1804
|
+
<div class="form-row">
|
|
1805
|
+
<label for="node-input-matterControllerMode">
|
|
1806
|
+
<i class="fa fa-list"></i>
|
|
1807
|
+
<span data-i18n="knxUltimateMatterControllerDevice.controller_mode"></span>
|
|
1808
|
+
</label>
|
|
1809
|
+
<select id="node-input-matterControllerMode">
|
|
1810
|
+
<option value="single" data-i18n="knxUltimateMatterControllerDevice.single_mode"></option>
|
|
1811
|
+
<option value="universal" data-i18n="knxUltimateMatterControllerDevice.universal_mode"></option>
|
|
1812
|
+
</select>
|
|
1813
|
+
</div>
|
|
1814
|
+
|
|
1815
|
+
<div id="matter-universal-description" class="form-tips" style="display:none; margin:8px 0;"
|
|
1816
|
+
data-i18n="knxUltimateMatterControllerDevice.universal_mode_description"></div>
|
|
1817
|
+
|
|
1818
|
+
<div id="matter-universal-options" style="display:none;">
|
|
1819
|
+
<div class="form-row">
|
|
1820
|
+
<label for="node-input-universalService">
|
|
1821
|
+
<i class="fa fa-bell"></i>
|
|
1822
|
+
<span data-i18n="knxUltimateMatterControllerDevice.universal_service"></span>
|
|
1823
|
+
</label>
|
|
1824
|
+
<select id="node-input-universalService">
|
|
1825
|
+
<option value="batteryMonitor" data-i18n="knxUltimateMatterControllerDevice.universal_service_battery_monitor"></option>
|
|
1826
|
+
<option value="allEvents" data-i18n="knxUltimateMatterControllerDevice.universal_service_all_events"></option>
|
|
1827
|
+
</select>
|
|
1828
|
+
</div>
|
|
1829
|
+
<div id="matter-universal-tabs" style="display:none; width:900px;">
|
|
1830
|
+
<ul>
|
|
1831
|
+
<li>
|
|
1832
|
+
<a href="#matter-universal-battery-options">
|
|
1833
|
+
<i class="fa fa-battery-quarter"></i>
|
|
1834
|
+
<span data-i18n="knxUltimateMatterControllerDevice.universal_service_battery_monitor"></span>
|
|
1835
|
+
</a>
|
|
1836
|
+
</li>
|
|
1837
|
+
</ul>
|
|
1838
|
+
<div id="matter-universal-battery-options">
|
|
1839
|
+
<div class="form-row">
|
|
1840
|
+
<label for="node-input-universalBatteryThreshold">
|
|
1841
|
+
<i class="fa fa-battery-quarter"></i>
|
|
1842
|
+
<span data-i18n="knxUltimateMatterControllerDevice.universal_battery_threshold"></span>
|
|
1843
|
+
</label>
|
|
1844
|
+
<input type="number" id="node-input-universalBatteryThreshold" min="0" max="100" step="1" style="width:100px;" />
|
|
1845
|
+
<span style="margin-left:5px;">%</span>
|
|
1846
|
+
</div>
|
|
1847
|
+
<div class="form-row" style="display:flex; align-items:center; flex-wrap:nowrap; gap:5px;">
|
|
1848
|
+
<label for="node-input-universalLowBatteryGA" style="width:155px; flex:0 0 155px; margin:0;">
|
|
1849
|
+
<i class="fa fa-bell"></i>
|
|
1850
|
+
<span data-i18n="knxUltimateMatterControllerDevice.universal_low_battery_ga"></span>
|
|
1851
|
+
</label>
|
|
1852
|
+
|
|
1853
|
+
<label for="node-input-universalLowBatteryGA" style="width:25px; flex:0 0 25px; margin:0;"><span data-i18n="common.ga"></span></label>
|
|
1854
|
+
<input type="text" id="node-input-universalLowBatteryGA" placeholder="Ex: 1/1/1"
|
|
1855
|
+
style="width:70px; flex:0 0 70px; margin:0; text-align:left;" />
|
|
1856
|
+
|
|
1857
|
+
<label for="node-input-universalLowBatteryDPT" style="width:38px; flex:0 0 38px; margin:0; text-align:right;"><span data-i18n="common.dpt"></span></label>
|
|
1858
|
+
<input type="text" id="node-input-universalLowBatteryDPT" value="1.005" readonly
|
|
1859
|
+
style="width:75px; flex:0 0 75px; margin:0;" />
|
|
1860
|
+
|
|
1861
|
+
<label for="node-input-universalLowBatteryGAName" style="width:45px; flex:0 0 45px; margin:0; text-align:right;"><span data-i18n="common.name"></span></label>
|
|
1862
|
+
<input type="text" id="node-input-universalLowBatteryGAName"
|
|
1863
|
+
style="width:auto; min-width:90px; flex:1 1 auto; margin:0; text-align:left;" />
|
|
1864
|
+
</div>
|
|
1865
|
+
<div class="form-row" style="display:flex; align-items:center; flex-wrap:nowrap; gap:5px;">
|
|
1866
|
+
<label for="node-input-universalLowBatteryTextGA" style="width:155px; flex:0 0 155px; margin:0;">
|
|
1867
|
+
<i class="fa fa-font"></i>
|
|
1868
|
+
<span data-i18n="knxUltimateMatterControllerDevice.universal_low_battery_text_ga"></span>
|
|
1869
|
+
</label>
|
|
1870
|
+
|
|
1871
|
+
<label for="node-input-universalLowBatteryTextGA" style="width:25px; flex:0 0 25px; margin:0;"><span data-i18n="common.ga"></span></label>
|
|
1872
|
+
<input type="text" id="node-input-universalLowBatteryTextGA" placeholder="Ex: 1/1/1"
|
|
1873
|
+
style="width:70px; flex:0 0 70px; margin:0; text-align:left;" />
|
|
1874
|
+
|
|
1875
|
+
<label for="node-input-universalLowBatteryTextDPT" style="width:38px; flex:0 0 38px; margin:0; text-align:right;"><span data-i18n="common.dpt"></span></label>
|
|
1876
|
+
<input type="text" id="node-input-universalLowBatteryTextDPT" value="16.001" readonly
|
|
1877
|
+
style="width:75px; flex:0 0 75px; margin:0;" />
|
|
1878
|
+
|
|
1879
|
+
<label for="node-input-universalLowBatteryTextGAName" style="width:45px; flex:0 0 45px; margin:0; text-align:right;"><span data-i18n="common.name"></span></label>
|
|
1880
|
+
<input type="text" id="node-input-universalLowBatteryTextGAName"
|
|
1881
|
+
style="width:auto; min-width:90px; flex:1 1 auto; margin:0; text-align:left;" />
|
|
1882
|
+
</div>
|
|
1883
|
+
<div class="form-row">
|
|
1884
|
+
<label for="node-input-universalBatteryOnlyLow" style="width:260px;">
|
|
1885
|
+
<i class="fa fa-filter"></i>
|
|
1886
|
+
<span data-i18n="knxUltimateMatterControllerDevice.universal_battery_only_low"></span>
|
|
1887
|
+
</label>
|
|
1888
|
+
<input type="checkbox" id="node-input-universalBatteryOnlyLow" style="display:inline-block; width:auto;" />
|
|
1889
|
+
</div>
|
|
1890
|
+
<div class="form-row">
|
|
1891
|
+
<label for="node-input-universalEmitInitialState" style="width:260px;">
|
|
1892
|
+
<i class="fa fa-camera"></i>
|
|
1893
|
+
<span data-i18n="knxUltimateMatterControllerDevice.universal_emit_initial"></span>
|
|
1894
|
+
</label>
|
|
1895
|
+
<input type="checkbox" id="node-input-universalEmitInitialState" style="display:inline-block; width:auto;" />
|
|
1896
|
+
</div>
|
|
1897
|
+
<div class="form-row">
|
|
1898
|
+
<label for="node-input-universalIncludeRawEvent" style="width:260px;">
|
|
1899
|
+
<i class="fa fa-code"></i>
|
|
1900
|
+
<span data-i18n="knxUltimateMatterControllerDevice.universal_include_raw"></span>
|
|
1901
|
+
</label>
|
|
1902
|
+
<input type="checkbox" id="node-input-universalIncludeRawEvent" style="display:inline-block; width:auto;" />
|
|
1903
|
+
</div>
|
|
1904
|
+
</div>
|
|
1905
|
+
</div>
|
|
1906
|
+
</div>
|
|
1907
|
+
|
|
1654
1908
|
<br />
|
|
1655
|
-
<p>
|
|
1909
|
+
<p id="matter-device-section-title">
|
|
1656
1910
|
<b><span data-i18n="knxUltimateMatterControllerDevice.matter_section"></span></b>
|
|
1657
1911
|
</p>
|
|
1658
1912
|
|
|
1659
|
-
<div class="form-row">
|
|
1913
|
+
<div class="form-row" id="matter-device-row">
|
|
1660
1914
|
<label for="node-input-matterDeviceName">
|
|
1661
1915
|
<i class="fa fa-play-circle"></i> <span data-i18n="knxUltimateMatterControllerDevice.matter_device"></span>
|
|
1662
1916
|
</label>
|
|
@@ -2125,18 +2379,19 @@
|
|
|
2125
2379
|
</div>
|
|
2126
2380
|
<br/>
|
|
2127
2381
|
</div>
|
|
2128
|
-
<div class="form-row">
|
|
2129
|
-
<label for="node-input-enableNodePINS" style="width:260px;">
|
|
2130
|
-
<i class="fa fa-circle"></i> <span data-i18n="knxUltimateMatterControllerDevice.node_pins"></span>
|
|
2131
|
-
</label>
|
|
2132
|
-
<select id="node-input-enableNodePINS">
|
|
2133
|
-
<option value="no" data-i18n="knxUltimateMatterControllerDevice.node_pins_hide"></option>
|
|
2134
|
-
<option value="yes" data-i18n="knxUltimateMatterControllerDevice.node_pins_show"></option>
|
|
2135
|
-
</select>
|
|
2136
|
-
</div>
|
|
2137
2382
|
</p>
|
|
2138
2383
|
</div>
|
|
2139
2384
|
</div>
|
|
2385
|
+
|
|
2386
|
+
<div class="form-row" style="margin-top:12px;">
|
|
2387
|
+
<label for="node-input-enableNodePINS" style="width:260px;">
|
|
2388
|
+
<i class="fa fa-circle"></i> <span data-i18n="knxUltimateMatterControllerDevice.node_pins"></span>
|
|
2389
|
+
</label>
|
|
2390
|
+
<select id="node-input-enableNodePINS">
|
|
2391
|
+
<option value="no" data-i18n="knxUltimateMatterControllerDevice.node_pins_hide"></option>
|
|
2392
|
+
<option value="yes" data-i18n="knxUltimateMatterControllerDevice.node_pins_show"></option>
|
|
2393
|
+
</select>
|
|
2394
|
+
</div>
|
|
2140
2395
|
</div>
|
|
2141
2396
|
|
|
2142
2397
|
<br/>
|
|
@@ -2159,6 +2414,28 @@ the device picker. Door Lock, Window Covering, Thermostat, Fan and Switch endpoi
|
|
|
2159
2414
|
dedicated profiles. Switch press, long-press and multi-press events are emitted on the
|
|
2160
2415
|
optional flow output; simpler endpoints continue through the generic mapped fallback.
|
|
2161
2416
|
|
|
2417
|
+
**Universal Mode**
|
|
2418
|
+
|
|
2419
|
+
Select **Universal Mode** in the **Mode** selector to listen to every attribute report,
|
|
2420
|
+
cluster event and device initialization from this controller. It always exposes one input
|
|
2421
|
+
and one output, does not require a KNX gateway, and does not use endpoint KNX mappings.
|
|
2422
|
+
Output values are in `msg.payload`; routing metadata is in `msg.matter`, including
|
|
2423
|
+
`source`, `nodeId`, `endpointId`, `clusterId` and the attribute/event name.
|
|
2424
|
+
The **Universal Battery Monitor** scans every node and endpoint for Power Source,
|
|
2425
|
+
emits an initial snapshot, and maintains complete battery state. It can emit only
|
|
2426
|
+
batteries below the configured threshold or every battery update. `msg.payload`
|
|
2427
|
+
contains normalized percent, charge level, replacement state, replaceability and
|
|
2428
|
+
voltage; raw Matter metadata remains in `msg.matter`. Send
|
|
2429
|
+
`{payload:{action:"getAllBatteries"}}` to retrieve the cached inventory.
|
|
2430
|
+
|
|
2431
|
+
Use `msg.nodeId`, `msg.endpointId`, `msg.clusterId` and either `msg.command` plus
|
|
2432
|
+
`msg.args`, or `msg.attribute`. Add `msg.value` for an attribute write; omit it for a
|
|
2433
|
+
read. The same selectors may be placed under `msg.matter`. For example, read battery
|
|
2434
|
+
with `{nodeId:"100", endpointId:1, clusterId:47, attribute:"batPercentRemaining"}` or
|
|
2435
|
+
switch on with `{nodeId:"100", endpointId:1, clusterId:6, command:"on", args:{}}`.
|
|
2436
|
+
Battery is emitted in Matter's raw half-percent units and can be divided by two in a
|
|
2437
|
+
Function node.
|
|
2438
|
+
|
|
2162
2439
|
|Property|Description|
|
|
2163
2440
|
|--|--|
|
|
2164
2441
|
| KNX GW | Select the KNX gateway to be used |
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
<script type="text/markdown" data-help-name="knxUltimateMatterControllerDevice">
|
|
2
|
-
# Control Matter from KNX (BETA)
|
|
3
|
-
|
|
4
2
|
> Dieser Knoten ist **BETA**: das Verhalten kann sich ändern, während die Matter-Implementierung weiter verfeinert wird.
|
|
5
3
|
|
|
6
4
|
Dieser Knoten steuert einen bereits gekoppelten Matter-Endpunkt über KNX. Wähle das Matter-Gerät aus; der Editor erkennt die Fähigkeiten des Endpunkts und zeigt nur die passenden KNX-Zuordnungen.
|
|
@@ -23,6 +21,16 @@ Er ersetzt die unveröffentlichten getrennten Matter-Controller-Nodes und behäl
|
|
|
23
21
|
| Update local state from KNX write | Aktualisiert den lokalen Matter/KNX-Cache, wenn ein Telegramm auf eine konfigurierte KNX-GA geschrieben wird. |
|
|
24
22
|
| Node Input/Output PINs | Zeigt Node-RED-Eingangs-/Ausgangspins. Der Eingang akzeptiert boolesche Payloads sowie Matter-ähnliche `msg.payload` oder `msg.on.on`; der Ausgang sendet Statusupdates. Die Auswahl bleibt beim erneuten Öffnen des Editors erhalten. |
|
|
25
23
|
|
|
24
|
+
## Universeller Modus
|
|
25
|
+
|
|
26
|
+
Wähle **Universeller Modus**, um alle Geräte zu überwachen. Der Node hat immer einen Eingang und einen Ausgang und verwendet keine Endpunkt-Zuordnungen. Ein KNX-Gateway ist optional und wird nur für die Alarm-/Text-GAs des Batteriemonitors benötigt.
|
|
27
|
+
|
|
28
|
+
Der **Universelle Batteriemonitor** speichert den vollständigen Batteriestatus. Optionale KNX-GAs senden den Sammelalarm als DPT 1.005 und wechseln alle 2 Sekunden die Gerätenamen als DPT 16.001. `{payload:{action:"getAllBatteries"}}` liefert das Cache-Inventar.
|
|
29
|
+
|
|
30
|
+
Ausgaben enthalten den Rohwert in `msg.payload` und Routingdaten in `msg.matter` (`source`, `nodeId`, `endpointId`, `clusterId`, Attribut-/Ereignisname). Eingaben verwenden `msg.nodeId`, `msg.endpointId`, `msg.clusterId` und entweder `msg.command` mit `msg.args` oder `msg.attribute`; `msg.value` schreibt, ohne `msg.value` wird gelesen. Die Felder können auch unter `msg.matter` stehen.
|
|
31
|
+
|
|
32
|
+
Beispiele: `{nodeId:"100",endpointId:1,clusterId:6,command:"on",args:{}}` schaltet ein; `{nodeId:"100",endpointId:1,clusterId:47,attribute:"batPercentRemaining"}` liest die Batterie. Batteriewerte bleiben in Matter-Halbprozenteinheiten und können in einem Function-Node durch zwei geteilt werden.
|
|
33
|
+
|
|
26
34
|
## Verhalten
|
|
27
35
|
|
|
28
36
|
Der Knoten pflegt einen lokalen Cache aus Matter-Updates und KNX-Schreibtelegrammen, beantwortet KNX-Leseanfragen aus diesem Cache und kann Werte beim Start lesen/ausgeben. Er hört nur auf konfigurierte Gruppenadressen, daher wird fremder KNX-Verkehr ignoriert.
|
|
@@ -92,7 +92,23 @@
|
|
|
92
92
|
"matter_controller": "Matter-Controller",
|
|
93
93
|
"matter_device": "Matter-Gerät",
|
|
94
94
|
"device_type": "Gerätetyp",
|
|
95
|
-
"matter_section": "Matter-Gerät"
|
|
95
|
+
"matter_section": "Matter-Gerät",
|
|
96
|
+
"controller_mode": "Modus",
|
|
97
|
+
"single_mode": "Einzelnes Gerät",
|
|
98
|
+
"universal_mode": "Universeller Modus (alle Matter-Geräte)",
|
|
99
|
+
"universal_mode_description": "Alle mit diesem Controller verbundenen Matter-Geräte überwachen und steuern. Der universelle Modus funktioniert ohne KNX-Zuordnungen.",
|
|
100
|
+
"universal_service": "Dienst",
|
|
101
|
+
"universal_service_battery_monitor": "Universeller Batteriemonitor",
|
|
102
|
+
"universal_service_all_events": "Alle Matter-Ereignisse",
|
|
103
|
+
"universal_battery_threshold": "Schwelle für niedrigen Batteriestand",
|
|
104
|
+
"universal_low_battery_ga": "GA Batteriealarm",
|
|
105
|
+
"universal_low_battery_text_ga": "GA Gerätename",
|
|
106
|
+
"universal_battery_only_low": "Nur niedrige Batteriestände ausgeben",
|
|
107
|
+
"universal_emit_initial": "Anfänglichen Batterie-Snapshot ausgeben",
|
|
108
|
+
"universal_include_raw": "Rohes Matter-Ereignis einschließen",
|
|
109
|
+
"universal_mode_status": "Universeller Matter-Modus",
|
|
110
|
+
"universal_mode_locate_disabled": "„Suchen“ ist im universellen Modus nicht verfügbar.",
|
|
111
|
+
"universal_controller_name": "Universeller Matter-Controller"
|
|
96
112
|
},
|
|
97
113
|
"common": {
|
|
98
114
|
"ga": "GA",
|