node-red-contrib-knx-ultimate 6.0.7 → 6.0.9

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 CHANGED
@@ -6,8 +6,12 @@
6
6
 
7
7
  # CHANGELOG
8
8
 
9
- **Version 6.0.7** - July 2026<br/>
9
+ **Version 6.0.9** - July 2026<br/>
10
10
 
11
+ - **Matter Controller — post-commission naming**: assigning a name immediately after pairing now waits for matter.js to finish exposing the root `BasicInformation` cluster. Root endpoint 0 is resolved explicitly, preventing the misleading `BasicInformation cluster not found` warning seen when re-adding devices such as Shelly Plug.<br/>
12
+ - **Control Matter from KNX — profile deploy crash**: Door Lock and multi-purpose profiles now expose the KNX status callback before registering with `knxUltimate-config`, preventing `_Node.setNodeStatus is not a function` during deploy.<br/>
13
+ - **Control Matter from KNX — flow PIN persistence**: the **Node Input/Output PINs** selection is no longer overwritten from the KNX gateway presence when reopening the editor. The saved choice remains authoritative and `inputs`/`outputs` are updated coherently on save.<br/>
14
+ - **Matter terminology cleanup**: removed leftover Philips Hue wording from Matter controller labels, notifications, runtime status, localized strings and help. Backward-compatible saved configuration keys remain unchanged.<br/>
11
15
  - **Control Matter from KNX (BETA) — Door Lock support**: commissioned Door Lock endpoints (including locks bridged by a vendor Matter hub) are now detected from their real `0x0101` cluster and expose KNX DPT 1 command/status mappings. `true` invokes `lockDoor`, `false` invokes `unlockDoor`, and subscribed `lockState` feedback updates KNX without command reflection. `NotFullyLocked` and `Unlatched` remain explicit flow states and are never collapsed into an unsafe binary KNX value. The optional remote-operation PIN is stored as a Node-RED credential; endpoints that do not advertise a requested command are rejected instead of receiving an invented operation. This is the first controller-side device profile in the extensible profile architecture requested in [discussion #519](https://github.com/Supergiovane/node-red-contrib-knx-ultimate/discussions/519).<br/>
12
16
  - **Control Matter from KNX (BETA) — multi-purpose endpoint profiles**: the controller node now keeps its established light path unchanged while routing non-light endpoints through a separate capability-driven mapped profile. Selecting a plug/On-Off actuator, cover, thermostat, fan, environmental/contact/occupancy sensor, battery, electrical-power or energy endpoint builds only the KNX mappings backed by clusters, attributes and supported commands actually reported by that endpoint. These mappings now live inside a dedicated **Mappings** tab beside **Behaviour**, matching the established light editor layout. Each mapping can be disabled by leaving its GA empty; cached status supports KNX read responses and startup publication, attribute reports never reflect commands back to Matter, and cluster events remain available on the optional flow output. Saved mappings survive an untouched editor save even when the Matter endpoint is temporarily offline.<br/>
13
17
  - **Matter nodes — cleaner editors**: long pairing, storage, cache and endpoint-structure explanations were removed from the Matter node forms and consolidated in the localized HTML help, keeping the editors focused on fields, actions and live operational status.<br/>
@@ -157,6 +157,8 @@ module.exports = function (RED) {
157
157
  }
158
158
 
159
159
  const safeSendToKNX = (telegram, context = 'write') => {
160
+ // Matter command handlers are asynchronous and shared by many endpoints. Guard
161
+ // each KNX dispatch so one unavailable gateway cannot break other device routes.
160
162
  try {
161
163
  if (!node.serverKNX || typeof node.serverKNX.sendKNXTelegramToKNXEngine !== 'function') {
162
164
  node.setNodeStatus({ fill: 'red', shape: 'dot', text: `KNX server missing (${context})` })
@@ -219,7 +219,7 @@
219
219
  ensureVerticalTabsStyle();
220
220
  const $knxServerInput = $("#node-input-server");
221
221
  const KNX_EMPTY_VALUES = new Set(['', 'none', '_ADD_', '__NONE__']);
222
- // Variable names kept from the Hue-born code; they now point to the Matter widgets.
222
+ // Historical variable names are retained for saved-flow compatibility; they point to Matter widgets.
223
223
  const $hueServerInput = $("#node-input-serverMatter");
224
224
  const $hueDeviceInput = $("#node-input-matterNodeId");
225
225
  const $deviceNameInput = $("#node-input-matterDeviceName");
@@ -287,8 +287,8 @@
287
287
  $icon.removeClass('fa-stop fa-play').addClass(locateSessionActive ? 'fa fa-stop' : 'fa fa-play');
288
288
  }
289
289
  const title = locateSessionActive
290
- ? (node._('knxUltimateMatterControllerDevice.locate_stop_title') || 'Stop Hue locate')
291
- : (node._('knxUltimateMatterControllerDevice.locate_start_title') || 'Locate selected Hue device');
290
+ ? (node._('knxUltimateMatterControllerDevice.locate_stop_title') || 'Stop Matter locate')
291
+ : (node._('knxUltimateMatterControllerDevice.locate_start_title') || 'Locate selected Matter device');
292
292
  $locateDeviceButton.attr('title', title);
293
293
  };
294
294
 
@@ -344,8 +344,8 @@
344
344
  if (!context) {
345
345
  if (!silent) {
346
346
  const message = !resolveHueServerValue({ allowStored: true })
347
- ? (node._('knxUltimateMatterControllerDevice.locate_no_bridge') || 'Select a Hue bridge first')
348
- : (node._('knxUltimateMatterControllerDevice.locate_no_device') || 'Select a Hue device first');
347
+ ? (node._('knxUltimateMatterControllerDevice.locate_no_bridge') || 'Select a Matter controller first')
348
+ : (node._('knxUltimateMatterControllerDevice.locate_no_device') || 'Select a Matter device first');
349
349
  RED.notify(message, 'warning');
350
350
  }
351
351
  updateLocateButtonState(false);
@@ -414,7 +414,7 @@
414
414
  updateLocateButtonState(false);
415
415
  clearLocateAutoReset();
416
416
  if (!silent) {
417
- RED.notify(message || (node._('knxUltimateMatterControllerDevice.locate_error') || 'Unable to locate Hue device'), 'error');
417
+ RED.notify(message || (node._('knxUltimateMatterControllerDevice.locate_error') || 'Unable to locate Matter device'), 'error');
418
418
  }
419
419
  }).always(() => {
420
420
  locatePendingRequest = null;
@@ -627,7 +627,7 @@
627
627
  const serializeMatterCapabilities = (capabilities) => JSON.stringify(capabilities || {});
628
628
  const getJSONPromise = (url) => new Promise((resolve, reject) => { $.getJSON(url, resolve).fail(reject); });
629
629
 
630
- // Same name/contract as the Hue filter, on Matter items { value, matterNodeId, matterEndpointId }.
630
+ // Filters Matter items shaped as { value, matterNodeId, matterEndpointId }.
631
631
  const filterHueDevices = (devices, term) => {
632
632
  const cleaned = (term || '').replace(/exactmatch/gi, '').trim();
633
633
  return $.map(devices, (item) => {
@@ -757,11 +757,11 @@
757
757
  $.getJSON(`knxUltimateDpts?serverId=${serverId}&_=${Date.now()}`, (data) => {
758
758
  data.forEach((dpt) => {
759
759
  if (prefixes.some((prefix) => prefix === "" || dpt.value.startsWith(prefix))) {
760
- // Adjustment for HUE Temperature
760
+ // Adjustment for Matter color temperature
761
761
  if (dpt.value.startsWith("7.600")) {
762
762
  $(_destinationWidget).append($("<option></option>").attr("value", dpt.value).text(dpt.text + " - KNX Kelvin range 2000-6535k (Homeassistant color_temperature_mode: absolute)"));
763
763
  } else if (dpt.value.startsWith("9.002")) {
764
- $(_destinationWidget).append($("<option></option>").attr("value", dpt.value).text(dpt.text + " - HUE Kelvin range 2000-6535k (Homeassistant color_temperature_mode: absolute_float)"));
764
+ $(_destinationWidget).append($("<option></option>").attr("value", dpt.value).text(dpt.text + " - Matter Kelvin range 2000-6535 K (Home Assistant color_temperature_mode: absolute_float)"));
765
765
  } else if (dpt.value.startsWith("5.001")) {
766
766
  $(_destinationWidget).append($("<option></option>").attr("value", dpt.value).text(dpt.text + " - Homeassistant color_temperature_mode: relative"));
767
767
  } else {
@@ -1084,13 +1084,6 @@
1084
1084
  }
1085
1085
  applyMatterCapabilities(currentMatterCapabilities);
1086
1086
 
1087
- if ($pinSelect.length) {
1088
- const desiredPins = knxSelected ? 'no' : 'yes';
1089
- if ($pinSelect.val() !== desiredPins) {
1090
- $pinSelect.val(desiredPins).trigger('change');
1091
- }
1092
- }
1093
-
1094
1087
  if ($pinSectionRow.length) {
1095
1088
  $pinSectionRow.show();
1096
1089
  }
@@ -1236,7 +1229,7 @@
1236
1229
  .append($("<option>").val("temperature").text(node._("knxUltimateMatterControllerDevice.select_temperature_brightness")));
1237
1230
  $("#node-input-specifySwitchOnBrightness").val(node.specifySwitchOnBrightness);
1238
1231
  $("#node-input-enableDayNightLighting").val(node.enableDayNightLighting);
1239
- // "Get current" reads the state from the Hue bridge: not available on Matter.
1232
+ // Live "Get current" reads are not available on this Matter path.
1240
1233
  $("#getColorAtSwitchOnDayTimeButton").hide();
1241
1234
  $("#getColorAtSwitchOnNightTimeButton").hide();
1242
1235
  applyMatterCapabilities(currentMatterCapabilities);
@@ -1261,8 +1254,8 @@
1261
1254
  if ($("#node-input-enableDayNightLighting").val() === "yes") blinkBackground("#colorPickerNight");
1262
1255
  });
1263
1256
 
1264
- // "Get current" (reading the live state from the Hue bridge) does not exist on
1265
- // Matter: the buttons are hidden by populateSwitchOnCombos above.
1257
+ // Live "Get current" reads do not exist on this Matter path; the buttons are
1258
+ // hidden by populateSwitchOnCombos above.
1266
1259
 
1267
1260
  // Fill options for minDimLevel and maxDimLevel and comboBrightnessAtSwitchOn (for color brightness at switch on, with temperature toghedher)
1268
1261
  for (let index = 100; index >= 0; index -= 5) {
@@ -2151,14 +2144,13 @@
2151
2144
 
2152
2145
 
2153
2146
  <script type="text/markdown" data-help-name="knxUltimateMatterControllerDevice">
2154
- <p>This node controls Philips Hue lights (single or grouped) and maps their commands/states to KNX.</p>
2147
+ <p>This node controls commissioned Matter endpoints and maps their commands and states to KNX.</p>
2155
2148
 
2156
2149
  **General**
2157
2150
 
2158
- This node was born from the Hue Light node: same KNX group-address model and behaviour,
2159
- with the Philips Hue engine replaced by the **Matter controller** engine. A Matter bridge
2160
- (for example a Hue Bridge paired via Matter) is expanded into its lamps in the picker.
2161
- Hue-only features (native effects, locate) are not available on Matter.
2151
+ The editor detects the selected endpoint capabilities and exposes only the corresponding
2152
+ Matter functions. Bridged Matter devices are expanded into their individual endpoints in
2153
+ the device picker.
2162
2154
 
2163
2155
  |Property|Description|
2164
2156
  |--|--|
@@ -2170,14 +2162,14 @@ Hue-only features (native effects, locate) are not available on Matter.
2170
2162
 
2171
2163
  **OPTIONS**
2172
2164
 
2173
- Here you can link KNX Group Addresses to the available Hue commands/states.<br/>
2165
+ Here you can link KNX Group Addresses to the available Matter commands and states.<br/>
2174
2166
  Start typing in the GA field (name or Group Address); suggestions appear while you type.
2175
2167
 
2176
2168
  **Switch**
2177
2169
 
2178
2170
  |Property|Description|
2179
2171
  |--|--|
2180
- | Control | This GA is used to turn on/off the Hue light via a boolean KNX value true/false|
2172
+ | Control | This GA turns the Matter light on or off via a boolean KNX value true/false. |
2181
2173
  | Status | Link this to the light's switch status group address|
2182
2174
 
2183
2175
  <br/>
@@ -2186,8 +2178,8 @@ Start typing in the GA field (name or Group Address); suggestions appear while y
2186
2178
 
2187
2179
  |Property|Description|
2188
2180
  |--|--|
2189
- | Control dim | Relative DIM of the Hue light. You can set the dimming speed in the **Behaviour** tab. |
2190
- | Control % | Changes the absolute Hue light's brightness (0-100%)|
2181
+ | Control dim | Relative DIM of the Matter light. You can set the dimming speed in the **Behaviour** tab. |
2182
+ | Control % | Changes the absolute Matter light brightness (0-100%). |
2191
2183
  | Status % | Link this to the light's brightness status KNX group address |
2192
2184
  | Dim Speed (ms) | Dimming speed in milliseconds. Applies to both the light brightness and the tunable-white datapoints. Calculated over the 0%→100% range. |
2193
2185
  | Min Dim brightness | Tha Minimum brightness that the lamp can reach. For example, if you are dimming the light down, the light will stop dimming at the specified brightness %. |
@@ -2202,8 +2194,8 @@ Start typing in the GA field (name or Group Address); suggestions appear while y
2202
2194
  | Control dim | Change white temperature using DPT 3.007 dimming. Speed is set in the **Behaviour** tab.|
2203
2195
  | Control % | Change white temperature using DPT 5.001. 0 = full warm, 100 = full cold.|
2204
2196
  | Status %| Temperature status GA. DPT 5.001 absolute value: 0 = full warm, 100 = full cold.|
2205
- | Control kelvin | **DPT 7.600: ** set temperature in Kelvin using the KNX range 2000-6535 (converted to Hue mirek).<br/>**DPT 9.002:** set temperature using Hue range 2000-6535 K (Ambiance starts at 2200 K). Conversions may introduce small deviations.|
2206
- | Status kelvin | **DPT 7.600: ** read temperature in Kelvin using KNX range 2000-6535 (converted from Hue).<br/>**DPT 9.002:** read temperature using Hue range 2000-6535 K (Ambiance starts at 2200 K). Conversions may introduce small deviations. |
2197
+ | Control kelvin | **DPT 7.600:** set the Matter color temperature in Kelvin in the supported endpoint range.<br/>**DPT 9.002:** set the temperature as a KNX floating-point value. Conversions may introduce small deviations. |
2198
+ | Status kelvin | **DPT 7.600:** read the Matter color temperature in Kelvin.<br/>**DPT 9.002:** read the temperature as a KNX floating-point value. |
2207
2199
  | Invert dim direction | Inverts the DIM direction. |
2208
2200
  <br/>
2209
2201
 
@@ -2227,12 +2219,12 @@ For controlling the HSV "V” (brightness), use the standard controls under the
2227
2219
 
2228
2220
  **Effects**
2229
2221
 
2230
- _Non-Hue basic effects_
2222
+ _Basic Matter effects_
2231
2223
 
2232
2224
  |Property|Description|
2233
2225
  |--|--|
2234
- | Blink | _true_ Blink the light, _false_ Stop blinking. Blinks the light on and off. Useful for signalling. Works with all Hue lights. |
2235
- | Color Cycle | _true_ start cycle, _false_ Stop cycle. Randomly changes the Hue light's color at regular interval. Works with all Hue lights having color capabilities. The color effect will start 10 seconds after set. |
2226
+ | Blink | _true_ blinks the light, _false_ stops blinking. Useful for signalling and available on compatible Matter lights. |
2227
+ | Color Cycle | _true_ starts the cycle, _false_ stops it. Randomly changes the Matter light color at regular intervals when color control is supported. |
2236
2228
 
2237
2229
  <br/>
2238
2230
 
@@ -2240,16 +2232,16 @@ _Non-Hue basic effects_
2240
2232
 
2241
2233
  | Property | Description |
2242
2234
  | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2243
- | Read status at startup | Read the Hue light status at node-red's startup or node-red's full deploy, and send that status to the KNX BUS |
2244
- | KNX Brightness Status | Updates the KNX brightness group address status, whenever the Hue lamp is switched ON/OFF. The options are **When Hue light is Off send 0%. When Hue On, restore previous value (Default KNX behaviour) ** and**Leave as is (default Hue behaviour) ** . If you have KNX dimmer with brightness status, like MDT, the suggested option is _**When Hue light is Off send 0%. When Hue On, restore previous value (Default KNX behaviour)** _ |
2245
- | Update local cached Hue state from KNX bus writes | Advanced option, enabled by default. When enabled, writes arriving from the KNX bus also update the node's local cached Hue state immediately, without waiting for feedback/events from the Hue bridge. This gives faster local reactions and more consistent immediate KNX read responses, especially while the light or grouped light is OFF. Disable it if you prefer the cache to follow only real feedback/events from the Hue bridge. |
2235
+ | Read status at startup | Read the Matter endpoint status at Node-RED startup or full deploy and send it to the KNX bus. |
2236
+ | KNX Brightness Status | Updates the KNX brightness status whenever the Matter light switches ON/OFF. It can send 0% while OFF and restore the previous value when ON, or leave the brightness status unchanged. |
2237
+ | Update local cached Matter state from KNX bus writes | When enabled, KNX writes immediately update the local Matter-state cache without waiting for the endpoint report. Disable it if the cache should follow only real Matter reports. |
2246
2238
  | Switch on behaviour | It sets the behaviour of your lights when switched on. You can choose from differents behaviours.<br/> **Select color: ** the light will be switched on with the color of your choice. To change color, just CLICK on the color selector (under the _Select color_ control).<br/>**Select temperature and brightness: ** the light will be switched on with the temperature (Kelvin) and brightness (0-100) of your choice.<br/>**None:** the light will retain its last status. In case you've enable the night lighting, after the night time ends, the lamp will resume the color/temperature/brightness state set at day time. |
2247
2239
  | Night Lighting | It allows to set a particular light color/brightness at nighttime. The options are the same as the daytime. You could select either a temperature/brightness or color. A cozy temperature of 2700 Kelvin, with a brightness of 10% or 20%, is a good choice for bathroom's night light.|
2248
2240
  | Day/Night | Select the group address used to set the day/night behaviour. The group address value is _true_ if daytime, _false_ if nighttime. |
2249
2241
  | Invert day/night value | Invert the values of _Day/Night_ group address. Default value is **unchecked** . |
2250
2242
  | Read status at startup | Read the status at startup and emit the event to the KNX bus at startup/reconnection. (Default "no")|
2251
2243
  | Force day mode | You can force the day mode by manually switching the light as described here: **Switch to DAY mode by rapid switching the ligth off then on (This light only) ** does what described and acts only on this light.**Switch to DAY mode by rapid switching the ligth off then on (apply yo ALL light nodes)** acts to ALL Light nodes, by setting the Day/Night group address to Day mode. |
2252
- | Node Input/Output PINs | Hide or show the input/output PINs. Input/output PINS allow the node to accept msg input from the flow and send msg output to the flow. Input msg must follow the Hue API v.2 Standards. This is an example msg, that turns on the light: <code>msg.on = {"on":true}</code>. Please refer to the [official Hue Api page](https://developers.meethue.com/develop/hue-api-v2/api-reference/#resource_light__id__put) |
2244
+ | Node Input/Output PINs | Hide or show the flow input/output PINs. The input accepts supported Matter commands and the output emits validated Matter endpoint events. The selection is persisted with the node. |
2253
2245
 
2254
2246
  ### Note
2255
2247
 
@@ -23,6 +23,10 @@ module.exports = function (RED) {
23
23
 
24
24
  let matterCapabilities = {}
25
25
  try { matterCapabilities = JSON.parse(config.matterDeviceCapabilities || '{}') } catch (error) { /* empty */ }
26
+ // Non-light endpoints are handled by isolated profiles. A successful profile setup
27
+ // owns the complete node lifecycle and deliberately bypasses the legacy light path.
28
+ // Keeping this boundary here prevents new device types from changing established
29
+ // light behaviour or its saved configuration contract.
26
30
  if (setupMatterControllerProfile(matterCapabilities.profile, RED, node, config)) return
27
31
 
28
32
  // Matter engine (adapter). The manager is resolved lazily at each write, because
@@ -115,8 +119,8 @@ module.exports = function (RED) {
115
119
  config.GADaylightSensor
116
120
  ].map((ga) => String(ga || '').trim()).filter((ga) => ga !== '')
117
121
  const isConfiguredKNXGA = (ga) => node.knxUltimateAcceptedGAs.includes(String(ga || '').trim())
118
- // Synthetic "current device" in Hue shape, kept in sync from the Matter attribute
119
- // reports. It lets the whole Hue-born logic below run untouched on a Matter light.
122
+ // Synthetic current-device compatibility state, kept in sync from Matter attribute
123
+ // reports. It lets the established light logic run untouched on a Matter light.
120
124
  node.currentHUEDevice = {
121
125
  id: node.matterNodeId,
122
126
  type: 'light',
@@ -221,14 +225,14 @@ module.exports = function (RED) {
221
225
  node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') })
222
226
  } catch (error) { }
223
227
  }
224
- // Used to call the status update from the HUE config node.
228
+ // Compatibility callback used to update the Matter node status.
225
229
  node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
226
230
  try {
227
231
  if (node.currentHUEDevice?.on?.on === true) { fill = 'blue'; shape = 'dot' } else { fill = 'blue'; shape = 'ring' };
228
232
  if (payload === undefined) payload = ''
229
233
  const dDate = new Date()
230
234
  payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString()
231
- node.sHUENodeStatusText = `|HUE: ${text} ${payload} (${formatTs(dDate)})`
235
+ node.sHUENodeStatusText = `|Matter: ${text} ${payload} (${formatTs(dDate)})`
232
236
  node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') })
233
237
  } catch (error) { }
234
238
  }
@@ -323,7 +327,7 @@ module.exports = function (RED) {
323
327
  return Math.floor(Math.random() * (max - min + 1) + min) // The maximum is inclusive and the minimum is inclusive
324
328
  }
325
329
 
326
- // This function is called by the hue-config.js
330
+ // Compatibility callback invoked by the Matter controller adapter.
327
331
  node.handleSend = (msg) => {
328
332
  if (!msg || !msg.knx || !isConfiguredKNXGA(msg.knx.destination)) return
329
333
  if (node.currentHUEDevice === undefined && node.serverHue.linkStatus === 'connected') {
@@ -1166,7 +1170,7 @@ module.exports = function (RED) {
1166
1170
  node.setNodeStatusHue({
1167
1171
  fill: 'red',
1168
1172
  shape: 'ring',
1169
- text: "Rejected HUE light settings. I'm still not ready...",
1173
+ text: "Rejected Matter light settings. I'm still not ready...",
1170
1174
  payload: ''
1171
1175
  })
1172
1176
  return
@@ -21,7 +21,7 @@ Er ersetzt die unveröffentlichten getrennten Matter-Controller-Nodes und behäl
21
21
  | Sensoren | Sensor-Endpunkte zeigen ihre Mess-/Status-GA nur bei Unterstützung: Temperatur, Feuchte, Helligkeit, Präsenz, Kontakt und Batterie. |
22
22
  | Read at startup | Veröffentlicht den gecachten Matter-Wert beim Deploy/Start oder wenn sich das Gerät erneut verbindet. |
23
23
  | Update local state from KNX write | Aktualisiert den lokalen Matter/KNX-Cache, wenn ein Telegramm auf eine konfigurierte KNX-GA geschrieben wird. |
24
- | 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. |
24
+ | 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
25
 
26
26
  ## Verhalten
27
27
 
@@ -35,14 +35,14 @@
35
35
  "get_current": "Aktuellen Wert holen",
36
36
  "get_again": "Erneut holen",
37
37
  "wait": "Bitte warten...",
38
- "locate_no_bridge": "Bitte zuerst eine Hue-Bridge auswählen",
39
- "locate_no_device": "Bitte zuerst ein Hue-Gerät auswählen",
38
+ "locate_no_bridge": "Bitte zuerst einen Matter-Controller auswählen",
39
+ "locate_no_device": "Bitte zuerst ein Matter-Gerät auswählen",
40
40
  "locate_success": "Locate-Befehl gesendet",
41
41
  "locate_started": "Locate-Modus gestartet. Nochmal drücken, um zu stoppen (automatisch nach 10 Minuten).",
42
42
  "locate_stopped": "Locate-Modus beendet.",
43
- "locate_start_title": "Ausgewähltes Hue-Gerät lokalisieren",
43
+ "locate_start_title": "Ausgewähltes Matter-Gerät lokalisieren",
44
44
  "locate_stop_title": "Locate-Modus beenden",
45
- "locate_error": "Hue-Gerät konnte nicht lokalisiert werden",
45
+ "locate_error": "Matter-Gerät konnte nicht lokalisiert werden",
46
46
  "day_night": "Tag/Nacht",
47
47
  "invert_day_night": "Tag/Nacht-Wert invertieren",
48
48
  "override_night_mode": "Tagmodus erzwingen",
@@ -56,11 +56,11 @@
56
56
  "opt_no": "Nein",
57
57
  "opt_yes_emit": "Ja, und KNX-Telegramme senden.",
58
58
  "knx_brightness_status": "KNX Helligkeitsstatus",
59
- "knx_brightness_onhueoff": "Wenn HUE aus: 0% senden. Wenn HUE an: vorherigen Wert wiederherstellen (Standard KNX Verhalten)",
60
- "knx_brightness_no": "Unverändert lassen (Standard HUE Verhalten)",
61
- "update_local_state_from_knx_write": "Lokalen Hue-Cache durch KNX-Bus-Schreibtelegramme aktualisieren",
62
- "update_local_state_from_knx_write_hint": "Aktiviert: schnellere lokale Reaktionen und konsistentere sofortige KNX-Leseantworten. Deaktiviert: Cache nur durch echte Hue-Bridge-Ereignisse aktualisieren.",
63
- "use_min_brightness": "Minimale Helligkeit der HUE Lampe verwenden",
59
+ "knx_brightness_onhueoff": "Wenn Matter aus: 0% senden. Wenn Matter an: vorherigen Wert wiederherstellen (Standard-KNX-Verhalten)",
60
+ "knx_brightness_no": "Unverändert lassen (Standard-Matter-Verhalten)",
61
+ "update_local_state_from_knx_write": "Lokalen Matter-Cache durch KNX-Bus-Schreibtelegramme aktualisieren",
62
+ "update_local_state_from_knx_write_hint": "Aktiviert: schnellere lokale Reaktionen und konsistentere sofortige KNX-Leseantworten. Deaktiviert: Cache nur durch echte Matter-Berichte aktualisieren.",
63
+ "use_min_brightness": "Minimale Helligkeit der Matter-Lampe verwenden",
64
64
  "k_suffix": "K",
65
65
  "temp_desc_2200": "(Beginn der Philips White Ambiance Reihe)",
66
66
  "temp_desc_2700": "(Warmweiß, intim, gemütlich, persönlich, für Wohnzimmer)",
@@ -83,12 +83,12 @@
83
83
  "effect_status": "Effekt-Status",
84
84
  "effect_mapping": "Zuordnungen",
85
85
  "effect_autofill": "Mit verfügbaren Effekten füllen",
86
- "effect_tip": "Hinterlege KNX-Wert/Hue-Effekt-Paare. Bei passendem KNX-Wert wird der ausgewählte Effekt ausgelöst.",
86
+ "effect_tip": "Hinterlege KNX-Wert/Matter-Effekt-Paare. Bei passendem KNX-Wert wird der ausgewählte Effekt ausgelöst.",
87
87
  "effect_tip_status": "Ist eine Status-GA gesetzt, sendet der Knoten den aktuellen Effekt (zugeordneter Wert oder Name) auf den KNX-Bus.",
88
- "effect_not_supported": "Diese Leuchte stellt keine Hue-Effekte bereit.",
88
+ "effect_not_supported": "Diese Leuchte stellt keine Matter-Effekte bereit.",
89
89
  "effect_knx_value_placeholder": "Abzugleichender Wert",
90
- "effect_base_label": "Nicht-Hue-Basiseffekte",
91
- "effect_native_label": "Hue-native Effekte",
90
+ "effect_base_label": "Matter-Basiseffekte",
91
+ "effect_native_label": "Native Matter-Effekte",
92
92
  "matter_controller": "Matter-Controller",
93
93
  "matter_device": "Matter-Gerät",
94
94
  "device_type": "Gerätetyp",
@@ -100,8 +100,8 @@
100
100
  "name": "Name",
101
101
  "youtube_sample": "YouTube-Beispiel",
102
102
  "knx_gw": "KNX-Gateway",
103
- "hue_bridge": "Hue Bridge",
104
- "philips_hue": "Philips HUE",
103
+ "hue_bridge": "Matter-Controller",
104
+ "philips_hue": "Matter",
105
105
  "read": "Lesen"
106
106
  }
107
107
  }
@@ -21,7 +21,7 @@ It replaces the unpublished per-device Matter controller nodes and keeps the ful
21
21
  | Sensors | Sensor endpoints expose their measurement/status GA only when supported: temperature, humidity, illuminance, occupancy, contact and battery. |
22
22
  | Read at startup | Publishes the cached Matter value at deploy/startup or when the device reconnects. |
23
23
  | Update local state from KNX write | Updates the local Matter/KNX cache when a telegram is written on a configured KNX GA. |
24
- | Node Input/Output PINs | Shows Node-RED input/output pins. Input accepts boolean payloads and Matter-style `msg.payload` or `msg.on.on`; output emits state updates. |
24
+ | Node Input/Output PINs | Shows Node-RED input/output pins. Input accepts boolean payloads and Matter-style `msg.payload` or `msg.on.on`; output emits state updates. The selection is preserved when the editor is reopened. |
25
25
 
26
26
  ## Behaviour
27
27
 
@@ -35,14 +35,14 @@
35
35
  "get_current": "Get current",
36
36
  "get_again": "Get again",
37
37
  "wait": "Wait...",
38
- "locate_no_bridge": "Select a Hue bridge first",
39
- "locate_no_device": "Select a Hue device first",
38
+ "locate_no_bridge": "Select a Matter controller first",
39
+ "locate_no_device": "Select a Matter device first",
40
40
  "locate_success": "Locate command sent",
41
41
  "locate_started": "Locate mode started. Press again to stop (auto-stops after 10 minutes).",
42
42
  "locate_stopped": "Locate mode stopped.",
43
- "locate_start_title": "Locate selected Hue device",
43
+ "locate_start_title": "Locate selected Matter device",
44
44
  "locate_stop_title": "Stop locate mode",
45
- "locate_error": "Unable to locate Hue device",
45
+ "locate_error": "Unable to locate Matter device",
46
46
  "day_night": "Day/Night",
47
47
  "invert_day_night": "Invert day/night value",
48
48
  "override_night_mode": "Force day mode",
@@ -56,11 +56,11 @@
56
56
  "opt_no": "No",
57
57
  "opt_yes_emit": "Yes, and emit KNX telegrams.",
58
58
  "knx_brightness_status": "KNX Brightness Status",
59
- "knx_brightness_onhueoff": "When Hue light is Off send 0%. When Hue On, restore previous value (Default KNX behaviour)",
60
- "knx_brightness_no": "Leave as is (default Hue behaviour)",
61
- "update_local_state_from_knx_write": "Update local cached Hue state from KNX bus writes",
62
- "update_local_state_from_knx_write_hint": "Enabled: faster local reactions and consistent immediate KNX read responses. Disabled: keep the cache aligned only with real Hue bridge events.",
63
- "use_min_brightness": "Use minimum brightness specified in the Hue light",
59
+ "knx_brightness_onhueoff": "When the Matter light is Off send 0%. When it is On, restore the previous value (default KNX behaviour)",
60
+ "knx_brightness_no": "Leave as is (default Matter behaviour)",
61
+ "update_local_state_from_knx_write": "Update local cached Matter state from KNX bus writes",
62
+ "update_local_state_from_knx_write_hint": "Enabled: faster local reactions and consistent immediate KNX read responses. Disabled: keep the cache aligned only with real Matter reports.",
63
+ "use_min_brightness": "Use minimum brightness specified for the Matter light",
64
64
  "k_suffix": "K",
65
65
  "temp_desc_2200": "(start of Philips White Ambiance lights range)",
66
66
  "temp_desc_2700": "(warm white, intimate, cozy, personal, for living rooms)",
@@ -83,12 +83,12 @@
83
83
  "effect_status": "Effect status",
84
84
  "effect_mapping": "Mappings",
85
85
  "effect_autofill": "Fill with available effects",
86
- "effect_tip": "Provide KNX value / Hue effect pairs. When the incoming KNX payload matches the value, the selected effect is applied to the light.",
87
- "effect_tip_status": "If a status group address is configured, the current Hue effect is emitted using the mapped KNX value or the effect name.",
88
- "effect_not_supported": "This light does not expose Hue effects.",
86
+ "effect_tip": "Provide KNX value / Matter effect pairs. When the incoming KNX payload matches the value, the selected effect is applied to the light.",
87
+ "effect_tip_status": "If a status group address is configured, the current Matter effect is emitted using the mapped KNX value or the effect name.",
88
+ "effect_not_supported": "This light does not expose Matter effects.",
89
89
  "effect_knx_value_placeholder": "Value to match",
90
- "effect_base_label": "Non-Hue basic effects",
91
- "effect_native_label": "Hue native effects",
90
+ "effect_base_label": "Basic Matter effects",
91
+ "effect_native_label": "Native Matter effects",
92
92
  "matter_controller": "Matter controller",
93
93
  "matter_device": "Matter device",
94
94
  "device_type": "Device type",
@@ -100,8 +100,8 @@
100
100
  "name": "Name",
101
101
  "youtube_sample": "Youtube sample",
102
102
  "knx_gw": "KNX GW",
103
- "hue_bridge": "Hue Bridge",
104
- "philips_hue": "Philips HUE",
103
+ "hue_bridge": "Matter controller",
104
+ "philips_hue": "Matter",
105
105
  "read": "Read"
106
106
  }
107
107
  }
@@ -21,7 +21,7 @@ Sustituye a los nodos Matter separados no publicados y conserva toda la UI de lu
21
21
  | Sensores | Los endpoints de sensor muestran su GA de medida/estado solo cuando está soportado: temperatura, humedad, iluminancia, ocupación, contacto y batería. |
22
22
  | Read at startup | Publica el valor Matter en caché al desplegar/iniciar o cuando el dispositivo se reconecta. |
23
23
  | Update local state from KNX write | Actualiza la caché local Matter/KNX cuando se escribe un telegrama en una GA KNX configurada. |
24
- | Node Input/Output PINs | Muestra pines de entrada/salida Node-RED. La entrada acepta payloads booleanos y mensajes Matter en `msg.payload` o `msg.on.on`; la salida emite estados. |
24
+ | Node Input/Output PINs | Muestra pines de entrada/salida Node-RED. La entrada acepta payloads booleanos y mensajes Matter en `msg.payload` o `msg.on.on`; la salida emite estados. La selección se conserva al volver a abrir el editor. |
25
25
 
26
26
  ## Comportamiento
27
27
 
@@ -35,14 +35,14 @@
35
35
  "get_current": "Obtener",
36
36
  "get_again": "Volver a",
37
37
  "wait": "Esperar...",
38
- "locate_no_bridge": "Seleccione primero un bridge Hue",
39
- "locate_no_device": "Seleccione primero un dispositivo Hue",
38
+ "locate_no_bridge": "Seleccione primero un controlador Matter",
39
+ "locate_no_device": "Seleccione primero un dispositivo Matter",
40
40
  "locate_success": "Comando de localización enviado",
41
41
  "locate_started": "Modo de localización iniciado. Pulsa de nuevo para detenerlo (se detiene automáticamente tras 10 minutos).",
42
42
  "locate_stopped": "Modo de localización detenido.",
43
- "locate_start_title": "Localizar el dispositivo Hue seleccionado",
43
+ "locate_start_title": "Localizar el dispositivo Matter seleccionado",
44
44
  "locate_stop_title": "Detener el modo de localización",
45
- "locate_error": "No se pudo localizar el dispositivo Hue",
45
+ "locate_error": "No se pudo localizar el dispositivo Matter",
46
46
  "day_night": "Día/noche",
47
47
  "invert_day_night": "Invertir el valor de día/noche",
48
48
  "override_night_mode": "Forzar el modo diurno",
@@ -58,8 +58,8 @@
58
58
  "knx_brightness_status": "Estado de brillo KNX",
59
59
  "knx_brightness_onhueoff": "Cuando la luz del tono está apagada, envíe 0%. Cuando se enciende, restaure el valor anterior (comportamiento de KNX predeterminado)",
60
60
  "knx_brightness_no": "Salir como está (comportamiento de tono predeterminado)",
61
- "update_local_state_from_knx_write": "Actualizar el estado local en caché de Hue a partir de escrituras del bus KNX",
62
- "update_local_state_from_knx_write_hint": "Activado: reacciones locales mas rapidas y respuestas inmediatas de lectura KNX mas coherentes. Desactivado: la cache se actualiza solo con eventos reales del bridge Hue.",
61
+ "update_local_state_from_knx_write": "Actualizar el estado local en caché de Matter a partir de escrituras del bus KNX",
62
+ "update_local_state_from_knx_write_hint": "Activado: reacciones locales más rápidas y respuestas inmediatas de lectura KNX más coherentes. Desactivado: la caché se actualiza solo con informes Matter reales.",
63
63
  "use_min_brightness": "Use brillo mínimo especificado en la luz del tono",
64
64
  "k_suffix": "K",
65
65
  "temp_desc_2200": "(Inicio de Philips White Ambiance Lights Range)",
@@ -83,7 +83,7 @@
83
83
  "effect_status": "Estado del efecto",
84
84
  "effect_mapping": "Mapeos",
85
85
  "effect_autofill": "Llenar con los efectos disponibles",
86
- "effect_tip": "Proporcione pares de valor KNX / Effect Hue. Cuando la carga útil de KNX entrante coincide con el valor, el efecto seleccionado se aplica a la luz.",
86
+ "effect_tip": "Proporcione pares de valor KNX / efecto Matter. Cuando la carga útil de KNX entrante coincide con el valor, el efecto seleccionado se aplica a la luz.",
87
87
  "effect_tip_status": "Si se configura una dirección de grupo de estado, el efecto de tono actual se emite utilizando el valor KNX asignado o el nombre del efecto.",
88
88
  "effect_not_supported": "Esta luz no expone los efectos del tono.",
89
89
  "effect_knx_value_placeholder": "Valor para coincidir",
@@ -100,8 +100,8 @@
100
100
  "name": "Nombre",
101
101
  "youtube_sample": "Muestra de youtube",
102
102
  "knx_gw": "KNX GW",
103
- "hue_bridge": "Hue Bridge",
104
- "philips_hue": "Tono Philips",
103
+ "hue_bridge": "Controlador Matter",
104
+ "philips_hue": "Matter",
105
105
  "read": "Leer"
106
106
  }
107
107
  }
@@ -21,7 +21,7 @@ Il remplace les nœuds Matter séparés non publiés et conserve toute l'UI lumi
21
21
  | Capteurs | Les endpoints capteur affichent leur GA de mesure/état uniquement si elle est supportée : température, humidité, éclairement, occupation, contact et batterie. |
22
22
  | Read at startup | Publie la valeur Matter en cache au déploiement/démarrage ou quand le périphérique se reconnecte. |
23
23
  | Update local state from KNX write | Met à jour le cache local Matter/KNX lorsqu'un télégramme est écrit sur une GA KNX configurée. |
24
- | Node Input/Output PINs | Affiche les pins entrée/sortie Node-RED. L'entrée accepte les payloads booléens et les messages Matter dans `msg.payload` ou `msg.on.on`; la sortie émet les états. |
24
+ | Node Input/Output PINs | Affiche les pins entrée/sortie Node-RED. L'entrée accepte les payloads booléens et les messages Matter dans `msg.payload` ou `msg.on.on`; la sortie émet les états. La sélection est conservée à la réouverture de l'éditeur. |
25
25
 
26
26
  ## Comportement
27
27
 
@@ -48,10 +48,10 @@
48
48
  "opt_no": "Non",
49
49
  "opt_yes_emit": "Oui, et émettez des télégrammes KNX.",
50
50
  "knx_brightness_status": "Statut de luminosité de KNX",
51
- "knx_brightness_onhueoff": "Lorsque Hue Light est éteint, envoyez 0%. Lorsque Hue On, restaurez la valeur précédente (comportement KNX par défaut)",
51
+ "knx_brightness_onhueoff": "Lorsque la lumière Matter est éteinte, envoyer 0 %. Lorsqu'elle est allumée, restaurer la valeur précédente (comportement KNX par défaut)",
52
52
  "knx_brightness_no": "Laisser tel quel (comportement de teinte par défaut)",
53
- "update_local_state_from_knx_write": "Mettre à jour l'état Hue local en cache à partir des écritures du bus KNX",
54
- "update_local_state_from_knx_write_hint": "Active: reactions locales plus rapides et reponses immediates de lecture KNX plus coherentes. Desactive: le cache ne suit que les evenements reels du bridge Hue.",
53
+ "update_local_state_from_knx_write": "Mettre à jour l'état Matter local en cache à partir des écritures du bus KNX",
54
+ "update_local_state_from_knx_write_hint": "Activé : réactions locales plus rapides et réponses immédiates de lecture KNX plus cohérentes. Désactivé : le cache ne suit que les rapports Matter réels.",
55
55
  "use_min_brightness": "Utilisez une luminosité minimale spécifiée dans la lumière des teintes",
56
56
  "k_suffix": "K",
57
57
  "temp_desc_2200": "(Début de la gamme Philips White Ambiance Lights)",
@@ -75,7 +75,7 @@
75
75
  "effect_status": "État de l'effet",
76
76
  "effect_mapping": "Mappages",
77
77
  "effect_autofill": "Remplissez les effets disponibles",
78
- "effect_tip": "Fournir des paires d'effets KNX Valeur / Hue. Lorsque la charge utile KNX entrante correspond à la valeur, l'effet sélectionné est appliqué à la lumière.",
78
+ "effect_tip": "Fournir des paires valeur KNX / effet Matter. Lorsque la charge utile KNX entrante correspond à la valeur, l'effet sélectionné est appliqué à la lumière.",
79
79
  "effect_tip_status": "Si une adresse de groupe d'état est configurée, l'effet de teinte actuel est émis en utilisant la valeur KNX mappée ou le nom d'effet.",
80
80
  "effect_not_supported": "Cette lumière n'expose pas les effets de la teinte.",
81
81
  "effect_knx_value_placeholder": "Valeur à correspondre",
@@ -92,8 +92,8 @@
92
92
  "name": "Nom",
93
93
  "youtube_sample": "Échantillon YouTube",
94
94
  "knx_gw": "KNX GW",
95
- "hue_bridge": "Hue Bridge",
96
- "philips_hue": "Hue Philips",
95
+ "hue_bridge": "Contrôleur Matter",
96
+ "philips_hue": "Matter",
97
97
  "read": "Lire"
98
98
  }
99
99
  }
@@ -21,7 +21,7 @@ Sostituisce i nodi Matter separati non pubblicati e mantiene tutta la UI luce qu
21
21
  | Sensori | Gli endpoint sensore mostrano il relativo GA di misura/stato solo quando supportato: temperatura, umidità, illuminamento, presenza, contatto e batteria. |
22
22
  | Read at startup | Pubblica il valore Matter in cache al deploy/avvio o quando il dispositivo si riconnette. |
23
23
  | Update local state from KNX write | Aggiorna la cache locale Matter/KNX quando arriva una scrittura su un GA KNX configurato. |
24
- | Node Input/Output PINs | Mostra i pin input/output Node-RED. L'input accetta payload booleani e messaggi stile Matter in `msg.payload` o `msg.on.on`; l'output emette gli aggiornamenti di stato. |
24
+ | Node Input/Output PINs | Mostra i pin input/output Node-RED. L'input accetta payload booleani e messaggi stile Matter in `msg.payload` o `msg.on.on`; l'output emette gli aggiornamenti di stato. La selezione viene mantenuta alla riapertura dell'editor. |
25
25
 
26
26
  ## Comportamento
27
27
 
@@ -35,14 +35,14 @@
35
35
  "get_current": "Ottieni corrente",
36
36
  "get_again": "Ottieni di nuovo",
37
37
  "wait": "Attendere...",
38
- "locate_no_bridge": "Seleziona prima un bridge Hue",
39
- "locate_no_device": "Seleziona prima un dispositivo Hue",
38
+ "locate_no_bridge": "Seleziona prima un controller Matter",
39
+ "locate_no_device": "Seleziona prima un dispositivo Matter",
40
40
  "locate_success": "Comando di localizzazione inviato",
41
41
  "locate_started": "Modalità di localizzazione avviata. Premi di nuovo per fermarla (si ferma automaticamente dopo 10 minuti).",
42
42
  "locate_stopped": "Modalità di localizzazione terminata.",
43
- "locate_start_title": "Localizza il dispositivo Hue selezionato",
43
+ "locate_start_title": "Localizza il dispositivo Matter selezionato",
44
44
  "locate_stop_title": "Ferma la modalità di localizzazione",
45
- "locate_error": "Impossibile localizzare il dispositivo Hue",
45
+ "locate_error": "Impossibile localizzare il dispositivo Matter",
46
46
  "day_night": "Giorno/Notte",
47
47
  "invert_day_night": "Inverti valore giorno/notte",
48
48
  "override_night_mode": "Forza modalità diurna",
@@ -56,11 +56,11 @@
56
56
  "opt_no": "No",
57
57
  "opt_yes_emit": "Sì, ed emetti i telegrammi KNX.",
58
58
  "knx_brightness_status": "Stato luminosità KNX",
59
- "knx_brightness_onhueoff": "Se la luce HUE è spenta invia 0%. Se è accesa, ripristina il valore precedente (Comportamento KNX predefinito)",
60
- "knx_brightness_no": "Lascia invariato (comportamento HUE predefinito)",
61
- "update_local_state_from_knx_write": "Aggiorna lo stato HUE locale in cache dai write provenienti dal bus KNX",
62
- "update_local_state_from_knx_write_hint": "Abilitato: reazioni locali piu rapide e risposte immediate ai read KNX piu coerenti. Disabilitato: la cache si aggiorna solo dagli eventi reali del bridge Hue.",
63
- "use_min_brightness": "Usa la luminosità minima specificata nella luce HUE",
59
+ "knx_brightness_onhueoff": "Se la luce Matter è spenta invia 0%. Se è accesa, ripristina il valore precedente (comportamento KNX predefinito)",
60
+ "knx_brightness_no": "Lascia invariato (comportamento Matter predefinito)",
61
+ "update_local_state_from_knx_write": "Aggiorna lo stato Matter locale in cache dai write provenienti dal bus KNX",
62
+ "update_local_state_from_knx_write_hint": "Abilitato: reazioni locali più rapide e risposte immediate ai read KNX più coerenti. Disabilitato: la cache si aggiorna solo dai report Matter reali.",
63
+ "use_min_brightness": "Usa la luminosità minima specificata per la luce Matter",
64
64
  "k_suffix": "K",
65
65
  "temp_desc_2200": "(inizio della gamma Philips White Ambiance)",
66
66
  "temp_desc_2700": "(bianco caldo, intimo, accogliente, personale, per soggiorni)",
@@ -83,12 +83,12 @@
83
83
  "effect_status": "Stato effetti",
84
84
  "effect_mapping": "Associazioni",
85
85
  "effect_autofill": "Compila con gli effetti disponibili",
86
- "effect_tip": "Definisci le coppie valore KNX / effetto Hue. Quando il valore KNX ricevuto coincide, viene attivato l'effetto selezionato.",
86
+ "effect_tip": "Definisci le coppie valore KNX / effetto Matter. Quando il valore KNX ricevuto coincide, viene attivato l'effetto selezionato.",
87
87
  "effect_tip_status": "Se configuri lo stato, il nodo invierà su KNX l'effetto corrente (valore associato o nome).",
88
- "effect_not_supported": "Questa lampada non espone effetti Hue.",
88
+ "effect_not_supported": "Questa lampada non espone effetti Matter.",
89
89
  "effect_knx_value_placeholder": "Valore da confrontare",
90
- "effect_base_label": "Effetti base non HUE",
91
- "effect_native_label": "Effetti nativi HUE",
90
+ "effect_base_label": "Effetti base Matter",
91
+ "effect_native_label": "Effetti nativi Matter",
92
92
  "matter_controller": "Controller Matter",
93
93
  "matter_device": "Dispositivo Matter",
94
94
  "device_type": "Tipo dispositivo",
@@ -100,8 +100,8 @@
100
100
  "name": "Nome",
101
101
  "youtube_sample": "Esempio YouTube",
102
102
  "knx_gw": "Gateway KNX",
103
- "hue_bridge": "Hue Bridge",
104
- "philips_hue": "Philips HUE",
103
+ "hue_bridge": "Controller Matter",
104
+ "philips_hue": "Matter",
105
105
  "read": "Leggi"
106
106
  }
107
107
  }
@@ -21,7 +21,7 @@
21
21
  | 传感器 | 传感器 endpoint 只在支持时显示对应测量/状态 GA:温度、湿度、照度、占用、接触和电池。 |
22
22
  | Read at startup | 在部署/启动或设备重新连接时发布缓存的 Matter 值。 |
23
23
  | Update local state from KNX write | 当配置的 KNX GA 收到写入 telegram 时,更新本地 Matter/KNX 缓存。 |
24
- | Node Input/Output PINs | 显示 Node-RED 输入/输出端口。输入接受布尔 payload,以及 `msg.payload` 或 `msg.on.on` 中的 Matter 风格消息;输出发送状态更新。 |
24
+ | Node Input/Output PINs | 显示 Node-RED 输入/输出端口。输入接受布尔 payload,以及 `msg.payload` 或 `msg.on.on` 中的 Matter 风格消息;输出发送状态更新。重新打开编辑器时会保留此选择。 |
25
25
 
26
26
  ## 行为
27
27
 
@@ -48,11 +48,11 @@
48
48
  "opt_no": "否",
49
49
  "opt_yes_emit": "是,并发送 KNX 电报。",
50
50
  "knx_brightness_status": "KNX 亮度状态",
51
- "knx_brightness_onhueoff": " HUE 灯关闭时发送 0%。当 HUE 打开时恢复先前值(默认 KNX 行为)",
52
- "knx_brightness_no": "保持不变(默认 HUE 行为)",
53
- "update_local_state_from_knx_write": "根据 KNX 总线写入更新本地缓存的 Hue 状态",
54
- "update_local_state_from_knx_write_hint": "启用:本地响应更快,KNX 即时读回更一致。禁用:缓存只根据 Hue 网关的真实事件更新。",
55
- "use_min_brightness": "使用 HUE 灯中设置的最小亮度",
51
+ "knx_brightness_onhueoff": "Matter 灯关闭时发送 0%。Matter 灯打开时恢复先前值(默认 KNX 行为)",
52
+ "knx_brightness_no": "保持不变(默认 Matter 行为)",
53
+ "update_local_state_from_knx_write": "根据 KNX 总线写入更新本地缓存的 Matter 状态",
54
+ "update_local_state_from_knx_write_hint": "启用:本地响应更快,KNX 即时读回更一致。禁用:缓存只根据真实的 Matter 报告更新。",
55
+ "use_min_brightness": "使用 Matter 灯中设置的最小亮度",
56
56
  "k_suffix": "K",
57
57
  "temp_desc_2200": "(飞利浦 White Ambiance 系列起始)",
58
58
  "temp_desc_2700": "(暖白,温馨、舒适、私密,适合客厅)",
@@ -75,12 +75,12 @@
75
75
  "effect_status": "效果状态",
76
76
  "effect_mapping": "映射",
77
77
  "effect_autofill": "填充可用效果",
78
- "effect_tip": "配置 KNX 数值与 Hue 效果对,收到匹配的 KNX 数值时触发对应效果。",
78
+ "effect_tip": "配置 KNX 数值与 Matter 效果对,收到匹配的 KNX 数值时触发对应效果。",
79
79
  "effect_tip_status": "若配置状态组地址,将把当前效果(映射值或效果名称)发送到 KNX。",
80
- "effect_not_supported": "该灯具不支持 Hue 效果。",
80
+ "effect_not_supported": "该灯具不支持 Matter 效果。",
81
81
  "effect_knx_value_placeholder": "匹配值",
82
- "effect_base_label": " Hue 基础效果",
83
- "effect_native_label": "Hue 原生效果",
82
+ "effect_base_label": "Matter 基础效果",
83
+ "effect_native_label": "Matter 原生效果",
84
84
  "matter_controller": "Matter 控制器",
85
85
  "matter_device": "Matter 设备",
86
86
  "device_type": "设备类型",
@@ -92,8 +92,8 @@
92
92
  "name": "名称",
93
93
  "youtube_sample": "YouTube 示例",
94
94
  "knx_gw": "KNX 网关",
95
- "hue_bridge": "Hue Bridge",
96
- "philips_hue": "飞利浦 HUE",
95
+ "hue_bridge": "Matter 控制器",
96
+ "philips_hue": "Matter",
97
97
  "read": "读取"
98
98
  }
99
99
  }
@@ -31,7 +31,8 @@ module.exports = (RED) => {
31
31
  node.matterInstanceId = `knxultimate-matter-${node.id.replace(/[^a-zA-Z0-9]/g, '')}`
32
32
  node.matterStoragePath = path.join(RED.settings.userDir || '.', 'knxultimatestorage', 'matter')
33
33
 
34
- // Helper like the hue-config one
34
+ // Expose controller connectivity without copying engine state into the config node.
35
+ // Consumers read the latest value lazily, including during asynchronous startup.
35
36
  Object.defineProperty(node, 'linkStatus', {
36
37
  get: function () {
37
38
  return node.matterManager?.matterConnectionStatus ?? 'disconnected'
@@ -39,6 +40,8 @@ module.exports = (RED) => {
39
40
  })
40
41
 
41
42
  const safeClientCall = (client, fn, label) => {
43
+ // One faulty device node must never interrupt event delivery to the remaining
44
+ // Matter clients registered on this shared controller connection.
42
45
  try {
43
46
  if (!client || typeof fn !== 'function') return
44
47
  fn()
@@ -28,12 +28,16 @@ const lockStateName = (value) => {
28
28
  }
29
29
 
30
30
  const lockStateToBoolean = (value) => {
31
+ // KNX DPT 1 can represent only two states. Do not collapse transitional or
32
+ // ambiguous Matter lock states into a potentially unsafe locked/unlocked value.
31
33
  if (Number(value) === LOCK_STATE.LOCKED) return true
32
34
  if (Number(value) === LOCK_STATE.UNLOCKED) return false
33
35
  return undefined
34
36
  }
35
37
 
36
38
  const setupDoorLockProfile = (RED, node, config) => {
39
+ // Profiles initialize the same flags consumed by knxUltimate-config as ordinary
40
+ // KNX nodes. In particular, listenallga must remain enabled for handleSend calls.
37
41
  node.name = config.name || node.matterDeviceName || 'Control Matter door lock from KNX'
38
42
  node.topic = node.name
39
43
  node.notifyreadrequest = true
@@ -53,8 +57,14 @@ const setupDoorLockProfile = (RED, node, config) => {
53
57
  .filter((ga) => ga !== '')
54
58
 
55
59
  const setStatus = (fill, shape, text) => node.status({ fill, shape, text })
60
+ // knxUltimate-config invokes this synchronously from addClient(). Profiles return
61
+ // early from the main light constructor, so they must expose the callback before
62
+ // registering with the shared KNX configuration node.
63
+ node.setNodeStatus = ({ fill = 'grey', shape = 'ring', text = '' } = {}) => setStatus(fill, shape, text)
56
64
 
57
65
  const commandArgs = () => {
66
+ // Matter represents the remote credential as bytes. Keep the PIN in Node-RED's
67
+ // credential store and materialize the Buffer only for the outgoing command.
58
68
  const pin = String(node.credentials?.doorLockPin || '')
59
69
  return pin === '' ? {} : { pinCode: Buffer.from(pin, 'utf8') }
60
70
  }
@@ -91,6 +101,8 @@ const setupDoorLockProfile = (RED, node, config) => {
91
101
  node.currentLockState = Number(rawState)
92
102
  const state = lockStateToBoolean(rawState)
93
103
  const name = lockStateName(rawState)
104
+ // Attribute reports update KNX state only; they never enqueue a Matter command.
105
+ // This one-way path is the primary feedback-loop guard for Door Lock endpoints.
94
106
  if (state !== undefined) writeKnxState(state)
95
107
  sendFlow(source, state, rawState)
96
108
  setStatus(state === undefined ? 'yellow' : 'blue', state === undefined ? 'ring' : 'dot', `Matter: ${name}`)
@@ -102,6 +114,8 @@ const setupDoorLockProfile = (RED, node, config) => {
102
114
  const capabilities = (() => {
103
115
  try { return JSON.parse(config.matterDeviceCapabilities || '{}') } catch (error) { return {} }
104
116
  })()
117
+ // Never invent optional operations: the editor persists the commands actually
118
+ // advertised by this endpoint and runtime validation enforces that snapshot.
105
119
  if (locked && capabilities.lockDoor === false) throw new Error('The Matter endpoint does not expose lockDoor')
106
120
  if (!locked && capabilities.unlockDoor === false) throw new Error('The Matter endpoint does not expose unlockDoor')
107
121
  const queued = manager.writeMatterQueueAdd({
@@ -153,6 +167,8 @@ const setupDoorLockProfile = (RED, node, config) => {
153
167
  node.handleMatterClusterEvent = () => {}
154
168
  node.handleMatterNodeInitialized = () => {
155
169
  try {
170
+ // The controller engine already caches the initial attribute read. Reusing that
171
+ // value avoids an extra request and publishes startup state through the same path.
156
172
  const value = node.serverMatter?.matterManager?.getCachedAttribute(
157
173
  node.matterNodeId,
158
174
  node.matterEndpointId,
@@ -13,7 +13,10 @@ const PROFILE_SETUPS = Object.freeze({
13
13
 
14
14
  const setupMatterControllerProfile = (profile, RED, node, config) => {
15
15
  const setup = PROFILE_SETUPS[profile]
16
+ // Returning false is significant: the caller must continue through the unchanged
17
+ // Matter-light implementation when no specialized profile claims the endpoint.
16
18
  if (typeof setup !== 'function') return false
19
+ // A profile that returns successfully owns input, close, KNX and Matter handlers.
17
20
  setup(RED, node, config)
18
21
  return true
19
22
  }
@@ -13,6 +13,8 @@ const isValidGroupAddress = (value) => {
13
13
  const parseMappings = (value) => {
14
14
  try {
15
15
  const parsed = Array.isArray(value) ? value : JSON.parse(value || '[]')
16
+ // Ignore incomplete or stale editor rows. Only mappings with a valid KNX address,
17
+ // resolvable DPT and explicit Matter target are allowed into runtime routing.
16
18
  return parsed.filter((mapping) => {
17
19
  if (!mapping || !isValidGroupAddress(mapping.ga) || !mapping.target || !mapping.dpt) return false
18
20
  try { dptlib.resolve(mapping.dpt); return true } catch (error) { return false }
@@ -42,6 +44,8 @@ const setupMappedEndpointProfile = (RED, node, config) => {
42
44
  let lastInitialReadTs = 0
43
45
 
44
46
  const status = (fill, shape, text) => node.status({ fill, shape, text })
47
+ // knxUltimate-config calls setNodeStatus synchronously while adding the client.
48
+ node.setNodeStatus = ({ fill = 'grey', shape = 'ring', text = '' } = {}) => status(fill, shape, text)
45
49
  const manager = () => node.serverMatter?.matterManager
46
50
  const sendKnx = (mapping, payload, outputtype = 'write') => {
47
51
  if (payload === undefined || !node.serverKNX) return false
@@ -57,12 +61,16 @@ const setupMappedEndpointProfile = (RED, node, config) => {
57
61
  const sendCached = (mapping, outputtype) => {
58
62
  const currentManager = manager()
59
63
  if (!currentManager) return false
64
+ // Cached reports are authoritative for KNX read responses and startup publication;
65
+ // reading them must not generate a new Matter write or command.
60
66
  const value = currentManager.getCachedAttribute(node.matterNodeId, mapping.endpointId, mapping.clusterId, mapping.target)
61
67
  return sendKnx(mapping, matterToKnx(mapping.clusterId, mapping.target, value), outputtype)
62
68
  }
63
69
  const enqueue = (mapping, value) => {
64
70
  const currentManager = manager()
65
71
  if (!currentManager) throw new Error('Matter controller not ready')
72
+ // Conversion happens before queueing so the Matter manager receives a canonical,
73
+ // cluster-specific command or attribute write rather than a raw KNX payload.
66
74
  const action = knxToMatter(mapping, value)
67
75
  if (!action) return
68
76
  const queued = currentManager.writeMatterQueueAdd({
@@ -96,6 +104,8 @@ const setupMappedEndpointProfile = (RED, node, config) => {
96
104
  }
97
105
  node.handleSendMatter = (event) => {
98
106
  try {
107
+ // Attribute reports travel only toward KNX/flow. Keeping feedback separate from
108
+ // enqueue() prevents programmatic state synchronization from echoing to Matter.
99
109
  if (String(event?.nodeId) !== String(node.matterNodeId) || Number(event?.endpointId) !== Number(node.matterEndpointId)) return
100
110
  node.mappings.filter((mapping) => mapping.direction === 'status' && Number(mapping.clusterId) === Number(event.clusterId) && mapping.target === event.attributeName).forEach((mapping) => {
101
111
  sendKnx(mapping, matterToKnx(event.clusterId, event.attributeName, event.value))
@@ -108,11 +118,15 @@ const setupMappedEndpointProfile = (RED, node, config) => {
108
118
  }
109
119
  }
110
120
  node.handleMatterClusterEvent = (event) => {
121
+ // Cluster events have no implicit KNX mapping. They are exposed as raw flow output
122
+ // only when the user explicitly enables the node pins.
111
123
  if (enablePins && String(event?.nodeId) === String(node.matterNodeId) && Number(event?.endpointId) === Number(node.matterEndpointId)) {
112
124
  node.send({ topic: `${event.clusterId}.${event.eventName}`, payload: event.events, matter: event })
113
125
  }
114
126
  }
115
127
  node.handleMatterNodeInitialized = () => {
128
+ // nodeInitialized can be emitted more than once while sessions recover. Bound the
129
+ // startup publication to avoid duplicate KNX telegram bursts during reconnects.
116
130
  if (config.readStatusAtStartup === 'no' || Date.now() - lastInitialReadTs < 5000) return
117
131
  let sent = 0
118
132
  node.mappings.filter((mapping) => mapping.direction === 'status').forEach((mapping) => { if (sendCached(mapping, 'write')) sent += 1 })
@@ -443,6 +443,15 @@ class classMatter extends EventEmitter {
443
443
  }
444
444
 
445
445
  _findEndpoint = (node, _endpointId) => {
446
+ // getDevices() can expose only functional/bridged endpoints while the root endpoint
447
+ // lives behind getRootEndpoint(). Resolve endpoint 0 explicitly for node clusters
448
+ // such as BasicInformation and GeneralCommissioning.
449
+ if (Number(_endpointId) === 0 && typeof node?.getRootEndpoint === 'function') {
450
+ try {
451
+ const root = node.getRootEndpoint()
452
+ if (root !== undefined) return root
453
+ } catch (error) { /* The legacy endpoint structure may still be initializing. */ }
454
+ }
446
455
  return this._getAllEndpoints(node).find((ep) => Number(ep.number) === Number(_endpointId))
447
456
  }
448
457
 
@@ -564,12 +573,21 @@ class classMatter extends EventEmitter {
564
573
  if (label.length > 64) throw new Error('Matter device name is too long')
565
574
  const node = this.pairedNodes.get(_nodeIdString)
566
575
  if (node === undefined) throw new Error(`Matter node ${_nodeIdString} unknown or not yet connected`)
576
+ // commission() attaches the PairedNode before its first wildcard read/subscription
577
+ // has necessarily built the legacy endpoint structure. A user-supplied name is
578
+ // applied immediately after commissioning, so wait briefly for BasicInformation
579
+ // instead of reporting a misleading permanent-cluster warning.
580
+ const deadline = Date.now() + 10000
567
581
  let clusterClient
568
- try {
569
- if (typeof node.getRootClusterClient === 'function') clusterClient = node.getRootClusterClient(this._api.BasicInformation)
570
- } catch (error) { /* empty */ }
571
- if (clusterClient === undefined) clusterClient = this._findClusterClient(node, 0, 40) // BasicInformation on the root endpoint
572
- if (clusterClient === undefined) throw new Error(`BasicInformation cluster not found on node ${_nodeIdString}`)
582
+ do {
583
+ try {
584
+ if (typeof node.getRootClusterClient === 'function') clusterClient = node.getRootClusterClient(this._api.BasicInformation)
585
+ } catch (error) { /* Endpoint structure is still initializing. */ }
586
+ if (clusterClient === undefined) clusterClient = this._findClusterClient(node, 0, 40) // BasicInformation on the root endpoint
587
+ if (clusterClient !== undefined) break
588
+ await pleaseWait(100)
589
+ } while (Date.now() < deadline)
590
+ if (clusterClient === undefined) throw new Error(`BasicInformation cluster was not available on node ${_nodeIdString} after initialization`)
573
591
  const attribute = clusterClient.attributes.nodeLabel
574
592
  if (attribute === undefined) throw new Error(`nodeLabel attribute not found on node ${_nodeIdString}`)
575
593
  await attribute.set(label)
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "engines": {
4
4
  "node": ">=20.18.1"
5
5
  },
6
- "version": "6.0.7",
6
+ "version": "6.0.9",
7
7
  "description": "Control your KNX and KNX Secure intallation via Node-Red! A bunch of KNX nodes, with integrated Philips HUE control, ETS group address importer, KNX AI for diagnosticsand KNX routing between interfaces. Easy to use and highly configurable.",
8
8
  "files": [
9
9
  "nodes/",
@@ -145,4 +145,4 @@
145
145
  "vite": "^7.1.3",
146
146
  "vue": "^3.5.21"
147
147
  }
148
- }
148
+ }