node-red-contrib-knx-ultimate 4.3.9 → 4.3.10

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,6 +6,12 @@
6
6
 
7
7
  # CHANGELOG
8
8
 
9
+ **Version 4.3.10** - April 2026<br/>
10
+
11
+ - CHANGE: **KNX Function** `getGAValue(...)` now accepts an optional `readIfMissing` boolean. Default is `true` to preserve the current behaviour; pass `false` to use cache-only mode and immediately return `undefined` when the GA value is not available locally.<br/>
12
+ - PERF: **KNX Function** `getGAValue(...)` and KNX cache lookups now use indexed GA access plus deduplicated pending reads, reducing overhead and avoiding duplicate simultaneous `GroupValue_Read` requests for the same GA.<br/>
13
+ - Docs/help/wiki: updated **KNX DEVICE / KNX Function** help HTML and **Device** wiki pages in all supported languages (**EN/IT/DE/FR/ES/zh-CN**) to document the new `getGAValue(..., readIfMissing)` signature and cache-only mode.<br/>
14
+
9
15
  **Version 4.3.9** - April 2026<br/>
10
16
 
11
17
  - Bump KNX Engine to 5.5.3 (fixed umlaut issue in dpt16)<br/>
@@ -200,6 +200,7 @@ module.exports = (RED) => {
200
200
  node.stopETSImportIfNoDatapoint = typeof config.stopETSImportIfNoDatapoint === 'undefined' ? 'stop' : config.stopETSImportIfNoDatapoint // 09/01/2020 Stop, Import Fake or Skip the import if a group address has unset datapoint
201
201
  node.userDir = path.join(RED.settings.userDir, 'knxultimatestorage') // 04/04/2021 Supergiovane: Storage for service files
202
202
  node.exposedGAs = []
203
+ node.exposedGAsByGa = new Map()
203
204
  node.loglevel = config.loglevel !== undefined ? config.loglevel : 'error' // 18/02/2020 Loglevel default error
204
205
  if (node.loglevel === 'trace') node.loglevel = 'debug' // Backward compatibility
205
206
  if (node.loglevel === 'silent') node.loglevel = 'disable' // Backward compatibility
@@ -208,6 +209,44 @@ module.exports = (RED) => {
208
209
  node.sysLogger = new loggerClass({ loglevel: node.loglevel, setPrefix: node.type + ' <' + (node.name || node.id || '') + '>' })
209
210
  } catch (error) { console.log(error.stack) }
210
211
  node.csv = readCSV(config.csv) // Array from ETS CSV Group Addresses {ga:group address, dpt: datapoint, devicename: full device name with main and subgroups}
212
+ node.csvByGa = new Map()
213
+ if (Array.isArray(node.csv)) {
214
+ node.csv.forEach((entry) => {
215
+ if (entry && typeof entry.ga === 'string' && entry.ga !== '') node.csvByGa.set(entry.ga, entry)
216
+ })
217
+ }
218
+
219
+ node.rebuildExposedGAIndex = () => {
220
+ node.exposedGAsByGa = new Map()
221
+ if (!Array.isArray(node.exposedGAs)) return
222
+ node.exposedGAs.forEach((entry) => {
223
+ if (entry && typeof entry.ga === 'string' && entry.ga !== '') node.exposedGAsByGa.set(entry.ga, entry)
224
+ })
225
+ }
226
+
227
+ node.getExposedGAEntry = (ga) => {
228
+ if (typeof ga !== 'string' || ga === '') return undefined
229
+ return node.exposedGAsByGa.get(ga)
230
+ }
231
+
232
+ node.upsertExposedGAEntry = (entry) => {
233
+ if (!entry || typeof entry.ga !== 'string' || entry.ga === '') return undefined
234
+ const existing = node.exposedGAsByGa.get(entry.ga)
235
+ if (existing) {
236
+ Object.assign(existing, entry)
237
+ return existing
238
+ }
239
+ node.exposedGAs.push(entry)
240
+ node.exposedGAsByGa.set(entry.ga, entry)
241
+ return entry
242
+ }
243
+
244
+ node.removeExposedGAEntry = (ga) => {
245
+ if (typeof ga !== 'string' || ga === '') return
246
+ node.exposedGAsByGa.delete(ga)
247
+ const index = node.exposedGAs.findIndex((item) => item.ga === ga)
248
+ if (index > -1) node.exposedGAs.splice(index, 1)
249
+ }
211
250
 
212
251
  // 12/11/2021 Connect at start delay
213
252
  node.autoReconnect = true // 20/03/2022 Default
@@ -764,10 +803,12 @@ module.exports = (RED) => {
764
803
  const sFile = path.join(node.userDir, 'knxpersistvalues', 'knxpersist' + node.id + '.json')
765
804
  try {
766
805
  node.exposedGAs = JSON.parse(fs.readFileSync(sFile, 'utf8'))
806
+ if (!Array.isArray(node.exposedGAs)) node.exposedGAs = []
767
807
  } catch (err) {
768
808
  node.exposedGAs = []
769
809
  node.sysLogger?.info('unable to read peristent file ' + sFile + ' ' + err.message)
770
810
  }
811
+ node.rebuildExposedGAIndex()
771
812
  }
772
813
 
773
814
  // ************************
@@ -856,7 +897,7 @@ module.exports = (RED) => {
856
897
  } else {
857
898
  try {
858
899
  if (node.exposedGAs.length > 0) {
859
- const oExposedGA = node.exposedGAs.find((a) => a.ga === _oClient.topic)
900
+ const oExposedGA = node.getExposedGAEntry(_oClient.topic)
860
901
  if (oExposedGA !== undefined) {
861
902
  // Retrieve the value from exposedGAs
862
903
  const msg = buildInputMessage({
@@ -885,7 +926,7 @@ module.exports = (RED) => {
885
926
  if (msg.payload === null) {
886
927
  _oClient._hasCurrentPayload = false
887
928
  // Delete the exposedGA
888
- node.exposedGAs = node.exposedGAs.filter((item) => item.ga !== _oClient.topic)
929
+ node.removeExposedGAEntry(_oClient.topic)
889
930
  _oClient.setNodeStatus({
890
931
  fill: 'yellow',
891
932
  shape: 'dot',
@@ -1384,16 +1425,14 @@ module.exports = (RED) => {
1384
1425
  if (typeof _dest === 'string' && _rawValue !== undefined && (_evt === 'GroupValue_Write' || _evt === 'GroupValue_Response')) {
1385
1426
  try {
1386
1427
  const ret = { ga: _dest, rawValue: _rawValue, dpt: undefined, devicename: undefined, updatedAt: Date.now() }
1387
- node.exposedGAs = node.exposedGAs.filter((item) => item.ga !== _dest) // Remove previous
1388
- if (node.csv !== undefined && node.csv !== '' && node.csv.length !== 0) {
1389
- // Add the dpt
1390
- const found = node.csv.find(a => a.ga === _dest)
1428
+ if (node.csvByGa.size > 0) {
1429
+ const found = node.csvByGa.get(_dest)
1391
1430
  if (found !== undefined) {
1392
1431
  ret.dpt = found.dpt
1393
1432
  ret.devicename = found.devicename
1394
1433
  }
1395
1434
  }
1396
- node.exposedGAs.push(ret) // add the new
1435
+ node.upsertExposedGAEntry(ret)
1397
1436
  } catch (error) { }
1398
1437
  }
1399
1438
 
@@ -271,10 +271,10 @@
271
271
  const knxFunctionHelperItems = [
272
272
  {
273
273
  id: 'getGAValue',
274
- label: 'getGAValue(address, dpt?)',
275
- aceValue: "getGAValue('1/1/1', '1.001')",
276
- snippet: "getGAValue('${1:1/1/1}', '${2:1.001}')",
277
- doc: 'Read the cached value of another group address. Provide the datapoint if the ETS import is not available.'
274
+ label: 'getGAValue(address, dpt?, readIfMissing?)',
275
+ aceValue: "getGAValue('1/1/1', '1.001', false)",
276
+ snippet: "getGAValue('${1:1/1/1}', '${2:1.001}', ${3:false})",
277
+ doc: 'Read another group address. By default, if the value is not cached, a KNX read is sent. Pass false as third parameter to use cache-only mode.'
278
278
  },
279
279
  {
280
280
  id: 'setGAValue',
@@ -465,8 +465,8 @@ return msg;`
465
465
  });
466
466
 
467
467
  monaco.languages.typescript.javascriptDefaults.addExtraLib([
468
- '/** Read the cached value of a KNX group address. */',
469
- 'declare function getGAValue(address: string, dpt?: string): any;',
468
+ '/** Read a KNX group address. By default, if the value is not cached, a KNX read is sent. Pass false as third parameter to use cache-only mode. */',
469
+ 'declare function getGAValue(address: string, dptOrReadIfMissing?: string | boolean, readIfMissing?: boolean): any;',
470
470
  '/** Send a value to a KNX group address. */',
471
471
  'declare function setGAValue(address: string, value: any, dpt?: string): void;',
472
472
  '/** Toggle (invert) this node\'s current value on the KNX bus. */',
@@ -505,13 +505,33 @@ module.exports = function (RED) {
505
505
  }
506
506
  }
507
507
 
508
+ const pendingGAReads = new Map()
509
+ const findExposedGA = (ga) => {
510
+ if (!node.serverKNX) return undefined
511
+ if (typeof node.serverKNX.getExposedGAEntry === 'function') return node.serverKNX.getExposedGAEntry(ga)
512
+ return Array.isArray(node.serverKNX.exposedGAs) ? node.serverKNX.exposedGAs.find(a => a.ga === ga) : undefined
513
+ }
514
+
508
515
  // Used in the KNX Function TAB
509
- const getGAValue = async function getGAValue(_ga = undefined, _dpt = undefined) {
516
+ const getGAValue = async function getGAValue(_ga = undefined, _dpt = undefined, _requestReadIfMissing = undefined) {
510
517
  if (_ga === undefined) return null
511
518
  // Strip devicename if present (e.g. "1/1/1 Light name" → "1/1/1")
512
519
  const blankSpacePosition = _ga.indexOf(' ')
513
520
  if (blankSpacePosition > -1) _ga = _ga.substring(0, blankSpacePosition)
514
521
 
522
+ // Overloads:
523
+ // - getGAValue('1/1/1')
524
+ // - getGAValue('1/1/1', '1.001')
525
+ // - getGAValue('1/1/1', '1.001', false)
526
+ // - getGAValue('1/1/1', false)
527
+ let dptRequested = _dpt
528
+ let requestReadIfMissing = _requestReadIfMissing
529
+ if (typeof dptRequested === 'boolean' && requestReadIfMissing === undefined) {
530
+ requestReadIfMissing = dptRequested
531
+ dptRequested = undefined
532
+ }
533
+ if (requestReadIfMissing === undefined) requestReadIfMissing = true
534
+
515
535
  const tryDecode = (rawValue, dpt) => {
516
536
  try {
517
537
  if (rawValue === null || rawValue === undefined) return undefined
@@ -531,30 +551,43 @@ module.exports = function (RED) {
531
551
  }
532
552
 
533
553
  // Check cache first
534
- let found = node.serverKNX.exposedGAs.find(a => a.ga === _ga)
554
+ let found = findExposedGA(_ga)
535
555
  if (found !== undefined) {
536
- const dptFinal = _dpt || found.dpt
556
+ const dptFinal = dptRequested || found.dpt
537
557
  if (!dptFinal) {
538
558
  RED.log.error('getGAValue: no DPT for ' + _ga + '. Provide it as second parameter.')
539
559
  return null
540
560
  }
541
561
  const val = tryDecode(found.rawValue, dptFinal)
542
562
  if (val !== undefined) return val
543
- // rawValue present but decode failed (bad format) — fall through to read
563
+ // rawValue present but decode failed (bad format) — fall through to read, unless cache-only mode is requested.
564
+ if (requestReadIfMissing === false) return undefined
544
565
  RED.log.warn('getGAValue: cached rawValue for ' + _ga + ' could not be decoded, sending read request')
545
566
  }
546
567
 
547
- // Not cached or decode failed: send read and poll up to 3 seconds
548
- sendRead()
549
- for (let i = 0; i < 30; i++) {
550
- await new Promise(resolve => setTimeout(resolve, 100))
551
- found = node.serverKNX.exposedGAs.find(a => a.ga === _ga)
552
- if (found !== undefined) {
553
- const dptFinal = _dpt || found.dpt
554
- if (!dptFinal) return null
555
- const val = tryDecode(found.rawValue, dptFinal)
556
- if (val !== undefined) return val
557
- }
568
+ if (requestReadIfMissing === false) return undefined
569
+
570
+ // Not cached or decode failed: send read and poll up to 3 seconds.
571
+ // Deduplicate concurrent reads to the same GA to avoid repeated bus reads and repeated polling loops.
572
+ let pendingRead = pendingGAReads.get(_ga)
573
+ if (!pendingRead) {
574
+ pendingRead = (async () => {
575
+ sendRead()
576
+ for (let i = 0; i < 30; i++) {
577
+ await new Promise(resolve => setTimeout(resolve, 100))
578
+ const updated = findExposedGA(_ga)
579
+ if (updated !== undefined) return updated
580
+ }
581
+ return null
582
+ })().finally(() => pendingGAReads.delete(_ga))
583
+ pendingGAReads.set(_ga, pendingRead)
584
+ }
585
+ found = await pendingRead
586
+ if (found !== null && found !== undefined) {
587
+ const dptFinal = dptRequested || found.dpt
588
+ if (!dptFinal) return null
589
+ const val = tryDecode(found.rawValue, dptFinal)
590
+ if (val !== undefined) return val
558
591
  }
559
592
  RED.log.warn('getGAValue: no response from KNX bus for ' + _ga + ' within 3 seconds')
560
593
  return null
@@ -569,7 +602,7 @@ module.exports = function (RED) {
569
602
  if (blankSpacePosition > -1) _ga = _ga.substring(0, blankSpacePosition)
570
603
  if (_dpt === undefined) {
571
604
  // Try getting dpt from ETS CSV
572
- const found = node.serverKNX.exposedGAs.find(a => a.ga === _ga)
605
+ const found = findExposedGA(_ga)
573
606
  if (found === undefined || found.dpt === undefined) {
574
607
  const errM = 'setGAValue: node ID:' + node.id + ' ' + 'No CSV file imported. Please provide the dpt manually'
575
608
  RED.log.error(errM)
@@ -71,7 +71,7 @@ Der Code läuft bei jeder Eingangs-Nachricht und bei jedem BUS-Telegramm. Bei Ak
71
71
  |Objekt/Funktion|Beschreibung|
72
72
  |--|--|
73
73
  | `msg` | Aktuelle Nachricht. |
74
- | `getGAValue(GA, DPT?)` | Liest den Wert einer GA, z. B. `'1/0/1'` oder `'1/0/1 Bed table light'` (Text nach Leerzeichen wird ignoriert). DPT nur ohne ETS erforderlich. |
74
+ | `getGAValue(GA, DPT?, readIfMissing?)` | Liest den Wert einer GA, z. B. `'1/0/1'` oder `'1/0/1 Bed table light'` (Text nach Leerzeichen wird ignoriert). Mit importierter ETS ist DPT optional; sonst muss es angegeben werden. Standardmäßig sendet die Funktion bei fehlendem Cache-Wert ein `GroupValue_Read` und wartet auf die Antwort. Mit `false` als drittem Parameter, oder als zweitem wenn kein DPT nötig ist, arbeitet die Funktion nur mit dem Cache und liefert `undefined`, wenn lokal kein Wert vorhanden ist. |
75
75
  | `setGAValue(GA, value, DPT?)` | Setzt den Wert der GA; DPT wie oben. |
76
76
  | `self(value)` | Setzt den eigenen Node-Wert und sendet ihn an den BUS (Achtung Schleifen). |
77
77
  | `toggle()` | Toggeln wie `self`. |
@@ -77,7 +77,7 @@ If enabled, "f(x)" indication will be added to node's name.
77
77
  |Object or Function|Description|
78
78
  |--|--|
79
79
  | msg (object) | The current msg object received by the node. |
80
- | getGAValue (string GA, optional string DPT) | Get the specified GA's value, for example **'1/0/1'**, or also **'1/0/1 Bed table light'** (all text after a blank space will be ignored by the function). With the ETS file imported, you can also copy and paste the GA and GA Name directly from the **Search GA** field. **DPT** is optional if you've imported the ETS file, otherwise you must specify it (for example '1.001'). |
80
+ | getGAValue (string GA, optional string DPT, optional bool readIfMissing) | Get the specified GA's value, for example **'1/0/1'**, or also **'1/0/1 Bed table light'** (all text after a blank space will be ignored by the function). With the ETS file imported, you can also copy and paste the GA and GA Name directly from the **Search GA** field. **DPT** is optional if you've imported the ETS file, otherwise you must specify it (for example '1.001'). By default, if the value is not cached, the function sends a `GroupValue_Read` and waits for the reply. Pass `false` as the third parameter, or as the second one when no DPT is needed, to use cache-only mode and return `undefined` when the value is not available locally. |
81
81
  | setGAValue (string GA, any value, optional string DPT) | Set the specified GA's value. The GA can be wrote for example **'1/0/1'**, or also **'1/0/1 Bed table light'** (all text after a blank space will be ignored by the function). With the ETS file imported, you can also copy and paste the GA and GA Name directly from the **Search GA** field. The **value** is mandatory (boolean/number/string/object). **DPT** is optional if you've imported the ETS file, otherwise you must specify it (for example '1.001'). |
82
82
  | self (any value) | Set the currend node's value and sends the value to the KNX BUS as well. For example, _self(false)_. Caution using **self** function in the _From KNX BUS to node's OUTPUT PIN_ code, because the code will be executed everytime a KNX telegram is received, so you coud have recurrency loops. |
83
83
  | toggle (nothing) | Toggle the currend node's value and sends the value to the KNX BUS as well. For example, _toggle()_. Caution using **toggle** function in the _From KNX BUS to node's OUTPUT PIN_ code, because the code will be executed everytime a KNX telegram is received, so you coud have recurrency loops. |
@@ -77,7 +77,7 @@ Si está habilitado, la indicación "F (x)" se agregará al nombre del nodo.
77
77
  | Objeto o función | Descripción |
78
78
  |-|-|
79
79
  | msg (objeto) | El objeto MSG actual recibido por el nodo. |
80
- | getGavalue (String ga, string opcional dpt) | Obtenga el valor de GA especificado, por ejemplo **'1/0/1'** o **'1/0/1 Luz mesilla'** (el texto tras un espacio se ignora). Con el archivo ETS importado, también puede copiar y pegar la GA desde el campo **Búsqueda GA**. **DPT** es opcional con ETS; si no, debe indicarlo (por ejemplo `'1.001'`). |
80
+ | getGavalue (String ga, string opcional dpt, bool opcional readIfMissing) | Obtenga el valor de la GA especificada, por ejemplo **'1/0/1'** o **'1/0/1 Luz mesilla'** (el texto tras un espacio se ignora). Con el archivo ETS importado, también puede copiar y pegar la GA desde el campo **Búsqueda GA**. **DPT** es opcional con ETS; si no, debe indicarlo (por ejemplo `'1.001'`). Por defecto, si el valor no está en caché, la función envía un `GroupValue_Read` y espera la respuesta. Pase `false` como tercer parámetro, o como segundo si no necesita DPT, para usar el modo solo caché y devolver `undefined` cuando el valor no esté disponible localmente. |
81
81
  | setgavalue (cadena ga, cualquier valor, cadena opcional dpt) | Establezca el valor de GA especificado, por ejemplo **'1/0/1'** o **'1/0/1 Luz mesilla'** (el texto tras un espacio se ignora). Con el archivo ETS importado, también puede copiar y pegar la GA desde el campo **Búsqueda GA**. El valor es obligatorio; **dpt** es opcional con ETS. |
82
82
  | yo (cualquier valor) | Establezca el valor del nodo de Currend y envía el valor al bus KNX también. Por ejemplo, _Self (False) _. PRECAUCIÓN Uso de ** Función ** ** En la _From KNX Bus hasta el código PIN_ de salida del nodo, porque el código se ejecutará cada vez que se reciba un telegrama KNX, por lo que usted tiene bucles de recurrencia. |
83
83
  | alternar (nada) | Alterne el valor del nodo de Currend y envía el valor al bus KNX también. Por ejemplo, _Toggle () _. PRECAUCIÓN Uso de la función ** Toggle** En el código _From KNX BUS al Código PIN_ de salida del nodo, porque el código se ejecutará cada vez que se reciba un Telegrama KNX, por lo que usted tiene bucles de recurrencia. |
@@ -77,7 +77,7 @@ S'il est activé, l'indication "f (x)" sera ajoutée au nom du nœud.
77
77
  | Objet ou fonction | Description |
78
78
  |-|-|
79
79
  | msg (objet) | L'objet MSG actuel reçu par le nœud. |
80
- | getGavalue (String GA, String facultatif DPT) | Obtenez la valeur de GA spécifiée, par exemple **'1/0/1'** ou **'1/0/1 Light'** (le texte après un espace est ignoré). Avec le fichier ETS importé, vous pouvez également copier et coller le nom GA et GA directement dans le champ **Recherche GA**. **DPT** est facultatif avec ETS; sinon vous devez le spécifier (par exemple `'1.001'`). |
80
+ | getGavalue (String GA, String DPT facultatif, bool readIfMissing facultatif) | Obtenez la valeur de la GA spécifiée, par exemple **'1/0/1'** ou **'1/0/1 Light'** (le texte après un espace est ignoré). Avec le fichier ETS importé, vous pouvez également copier et coller le nom GA et GA directement dans le champ **Recherche GA**. **DPT** est facultatif avec ETS; sinon vous devez le spécifier (par exemple `'1.001'`). Par défaut, si la valeur n'est pas en cache, la fonction envoie un `GroupValue_Read` et attend la réponse. Passez `false` comme troisième paramètre, ou comme deuxième si aucun DPT n'est nécessaire, pour utiliser le mode cache uniquement et retourner `undefined` si la valeur n'est pas disponible localement. |
81
81
  | setGavalue (String ga, n'importe quelle valeur, chaîne facultative dpt) | Définissez la valeur de GA spécifiée, par exemple **'1/0/1'** ou **'1/0/1 Light'** (le texte après un espace est ignoré). Avec le fichier ETS importé, vous pouvez également copier et coller le nom GA et GA directement depuis le champ **Recherche GA**. La valeur est obligatoire; **dpt** est facultatif avec ETS. |
82
82
  | self (toute valeur) | Définissez la valeur du nœud Currend et envoie également la valeur au bus KNX. Par exemple, _self (false) _. ATTENTION UTILISATION ** Self** Fonction dans le code Pin_ de sortie du bus KNX _From pour le nœud, car le code sera exécuté à chaque fois qu'un télégramme KNX est reçu, vous avez donc Coud ayant des boucles de récurrence. |
83
83
  | basculer (rien) | Basculez la valeur du nœud Currend et envoie également la valeur au bus KNX. Par exemple, _toggle () _. ATTENTION en utilisant ** Toggle** Fonction dans le code Pin_ de sortie du bus KNX _From à la sortie du nœud, car le code sera exécuté à chaque fois qu'un télégramme KNX est reçu, de sorte que vous avez des boucles de récurrence. |
@@ -76,7 +76,7 @@ Lo script viene eseguito a ogni msg in ingresso o a ogni telegramma ricevuto dal
76
76
  |Oggetto/Funzione|Descrizione|
77
77
  |--|--|
78
78
  | `msg` (object) | Il msg corrente ricevuto dal nodo. |
79
- | `getGAValue` (string GA, string DPT opz.) | Restituisce il valore del GA, ad es. `'1/0/1'` o `'1/0/1 Bed table light'` (tutto dopo lo spazio viene ignorato). Con ETS importato, DPT è opzionale; altrimenti va specificato, per es. `'1.001'`. |
79
+ | `getGAValue` (string GA, string DPT opz., bool readIfMissing opz.) | Restituisce il valore del GA, ad es. `'1/0/1'` o `'1/0/1 Bed table light'` (tutto dopo lo spazio viene ignorato). Con ETS importato, DPT è opzionale; altrimenti va specificato, per es. `'1.001'`. Per default, se il valore non è in cache, viene inviato un `GroupValue_Read` e la funzione attende la risposta. Passando `false` come terzo parametro, oppure come secondo se il DPT non serve, la funzione lavora in modalità solo-cache e restituisce `undefined` se il valore non è disponibile localmente. |
80
80
  | `setGAValue` (string GA, any value, string DPT opz.) | Imposta il valore del GA indicato. Valgono le stesse regole di notazione del GA; il valore può essere boolean/number/string; DPT opzionale con ETS, altrimenti obbligatorio. |
81
81
  | `self` (any) | Imposta il valore del nodo corrente e lo invia anche al BUS KNX (es.: `self(false)`). Attenzione nell'handler "From KNX BUS to OUTPUT”, per evitare loop. |
82
82
  | `toggle`() | Inverte il valore del nodo e lo invia al BUS. Stesse cautele di `self`. |
@@ -71,7 +71,7 @@
71
71
  |对象/函数|说明|
72
72
  |--|--|
73
73
  | `msg` | 当前消息对象。|
74
- | `getGAValue(GA, DPT?)` | 读取 GA 值,如 `'1/0/1'` 或 `'1/0/1 Bed table light'`(空格后的文字被忽略)。未导入 ETS 时需提供 DPT。|
74
+ | `getGAValue(GA, DPT?, readIfMissing?)` | 读取 GA 的值,例如 `'1/0/1'` 或 `'1/0/1 Bed table light'`(空格后的文字会被忽略)。导入 ETS 后,DPT 为可选;未导入时则必须提供。默认情况下,如果缓存中没有该值,函数会发送一个 `GroupValue_Read` 并等待响应。若将第三个参数设为 `false`,或者在不需要 DPT 时将第二个参数设为 `false`,则函数只使用缓存;如果本地没有值,则返回 `undefined`。|
75
75
  | `setGAValue(GA, value, DPT?)` | 设置 GA 值;DPT 同上。|
76
76
  | `self(value)` | 设置当前节点的值并发送到总线(注意循环)。|
77
77
  | `toggle()` | 切换当前值并发送到总线。|
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "engines": {
4
4
  "node": ">=20.18.1"
5
5
  },
6
- "version": "4.3.9",
6
+ "version": "4.3.10",
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, and KNX routing between interfaces. Easy to use and highly configurable.",
8
8
  "files": [
9
9
  "nodes/",
@@ -117,4 +117,4 @@
117
117
  "vite": "^7.1.3",
118
118
  "vue": "^3.5.21"
119
119
  }
120
- }
120
+ }