node-red-contrib-knx-ultimate 8.0.2 → 8.0.4

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,18 @@
6
6
 
7
7
  # CHANGELOG
8
8
 
9
+ **Version 8.0.4** - September 2026
10
+
11
+ - Automatic migration now validates only the HUE, Matter and KNX Utility nodes it converts. Invalid nodes from unrelated packages no longer block the upgrade.
12
+ - Unrelated invalid nodes are preserved unchanged while the converted flow is deployed and verified.
13
+ - Added regression coverage for the reported Alarm Ultimate flow with unconfigured Alarm State and Alarm Siren nodes.
14
+
15
+ **Version 8.0.3** - September 2026
16
+
17
+ - Allows incomplete legacy HUE and Matter nodes that belong to the active migration plan to be converted without weakening validation for unrelated invalid nodes.
18
+ - Adds an explicit **OK** button to persistent migration-error notifications so they can always be dismissed.
19
+ - Adds an end-to-end regression fixture for direct migration of the Alarm Ultimate flow reported by a user.
20
+
9
21
  **Version 8.0.2** - September 2026
10
22
 
11
23
  - Published version 8 on the stable `latest` channel for installations that only need the current KNX nodes.
@@ -34,6 +34,7 @@
34
34
  "cancel": "Abbrechen",
35
35
  "start": "Sichern und aktualisieren",
36
36
  "close": "Schließen",
37
+ "ok": "OK",
37
38
  "backup_failed": "Die Flow-Sicherung konnte nicht gestartet werden. Es wurde nichts geändert:",
38
39
  "progress_start": "Automatisches Update wird vorbereitet…",
39
40
  "progress_install_hue": "HUE Ultimate wird installiert…",
@@ -34,6 +34,7 @@
34
34
  "cancel": "Cancel",
35
35
  "start": "Back up and upgrade",
36
36
  "close": "Close",
37
+ "ok": "OK",
37
38
  "backup_failed": "Flow backup could not be started. Nothing was changed:",
38
39
  "progress_start": "Preparing the automatic upgrade…",
39
40
  "progress_install_hue": "Installing HUE Ultimate…",
@@ -34,6 +34,7 @@
34
34
  "cancel": "Cancelar",
35
35
  "start": "Copia y actualización",
36
36
  "close": "Cerrar",
37
+ "ok": "OK",
37
38
  "backup_failed": "No se pudo iniciar la copia de seguridad de los flujos. No se modificó nada:",
38
39
  "progress_start": "Preparando la actualización automática…",
39
40
  "progress_install_hue": "Instalando HUE Ultimate…",
@@ -34,6 +34,7 @@
34
34
  "cancel": "Annuler",
35
35
  "start": "Sauvegarder et mettre à jour",
36
36
  "close": "Fermer",
37
+ "ok": "OK",
37
38
  "backup_failed": "Impossible de démarrer la sauvegarde des flux. Rien n’a été modifié :",
38
39
  "progress_start": "Préparation de la mise à jour automatique…",
39
40
  "progress_install_hue": "Installation de HUE Ultimate…",
@@ -34,6 +34,7 @@
34
34
  "cancel": "Annulla",
35
35
  "start": "Backup e aggiornamento",
36
36
  "close": "Chiudi",
37
+ "ok": "OK",
37
38
  "backup_failed": "Impossibile avviare il backup dei flow. Non è stato modificato nulla:",
38
39
  "progress_start": "Preparazione dell’aggiornamento automatico…",
39
40
  "progress_install_hue": "Installazione di HUE Ultimate…",
@@ -34,6 +34,7 @@
34
34
  "cancel": "取消",
35
35
  "start": "备份并升级",
36
36
  "close": "关闭",
37
+ "ok": "OK",
37
38
  "backup_failed": "无法启动流程备份。未进行任何更改:",
38
39
  "progress_start": "正在准备自动升级…",
39
40
  "progress_install_hue": "正在安装 HUE Ultimate…",
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "engines": {
4
4
  "node": ">=20.18.1"
5
5
  },
6
- "version": "8.0.2",
6
+ "version": "8.0.4",
7
7
  "description": "KNX integration for Node-RED with KNX/IP and KNX Secure, ETS import, routing, diagnostics, automation utilities, MQTT and Modbus adapters. Optional Hue Ultimate and Matter Ultimate packages connect through the KNX gateway.",
8
8
  "files": [
9
9
  "nodes/",
@@ -339,19 +339,23 @@
339
339
  if (remaining.length) throw new Error('Legacy node types remain after conversion: ' + remaining.map(node => node.type).join(', '))
340
340
  }
341
341
 
342
- function validateDeployable (RED) {
343
- const invalid = []
342
+ function validateDeployable (RED, plan) {
343
+ const migrating = new Set((plan && plan.entries ? plan.entries : []).map(entry => entry.node))
344
344
  const unknown = []
345
345
  collectAllNodes(RED).forEach(node => {
346
346
  if (node.type === 'unknown' || (node._def && node._def.category === 'unknown')) {
347
347
  unknown.push(node.id)
348
348
  return
349
349
  }
350
- if (RED.editor && typeof RED.editor.validateNode === 'function') RED.editor.validateNode(node)
351
- if (node.valid === false && node.d !== true) invalid.push(node.id)
350
+ if (migrating.has(node) && RED.editor && typeof RED.editor.validateNode === 'function') RED.editor.validateNode(node)
351
+ // A legacy node can be incomplete (for example, a placeholder without a
352
+ // HUE/Matter config reference). It must first be persisted with its new
353
+ // type before the user can open and complete it. Keep its invalid marker
354
+ // in the editor, but do not let it deadlock the migration. Nodes outside
355
+ // the migration plan are preserved verbatim and are deliberately not
356
+ // validated: their configuration is unrelated to this upgrade.
352
357
  })
353
358
  if (unknown.length) throw new Error('Unknown nodes must be resolved before the automatic upgrade: ' + unknown.join(', '))
354
- if (invalid.length) throw new Error('Invalid nodes must be corrected before the automatic upgrade: ' + invalid.join(', '))
355
359
  }
356
360
 
357
361
  function validatePreflight (RED, plan) {
@@ -360,19 +364,14 @@
360
364
  ...((plan && plan.missingStandalone && plan.missingStandalone.hue) || []),
361
365
  ...((plan && plan.missingStandalone && plan.missingStandalone.matter) || [])
362
366
  ])
363
- const invalid = []
364
367
  const unknown = []
365
368
  collectAllNodes(RED).forEach(node => {
366
369
  if (migrating.has(node) || expectedUnknown.has(node) || (plan && plan.ai && plan.ai.includes(node))) return
367
370
  if (node.type === 'unknown' || (node._def && node._def.category === 'unknown')) {
368
371
  unknown.push(node.id)
369
- return
370
372
  }
371
- if (RED.editor && typeof RED.editor.validateNode === 'function') RED.editor.validateNode(node)
372
- if (node.valid === false && node.d !== true) invalid.push(node.id)
373
373
  })
374
374
  if (unknown.length) throw new Error('Unknown nodes must be resolved before the automatic upgrade: ' + unknown.join(', '))
375
- if (invalid.length) throw new Error('Invalid nodes must be corrected before the automatic upgrade: ' + invalid.join(', '))
376
375
  }
377
376
 
378
377
  function requestError (xhr, fallback) {
@@ -877,7 +876,7 @@
877
876
  let deployed = false
878
877
  try {
879
878
  assertNoLegacyNodes(RED)
880
- validateDeployable(RED)
879
+ validateDeployable(RED, plan)
881
880
  progress('deploy')
882
881
  await deployFlows(RED, {
883
882
  ...options,
@@ -1183,7 +1182,16 @@
1183
1182
  ? t('recovery_failed', 'Automatic migration stopped safely:') + ' ' + error.message
1184
1183
  : t('failed', 'Automatic upgrade stopped safely. KNX Ultimate 8 was not activated:') + ' ' + error.message
1185
1184
  }
1186
- RED.notify(failureMessage, { type: 'error', fixed: true })
1185
+ let failureNotice
1186
+ failureNotice = RED.notify(failureMessage, {
1187
+ type: 'error',
1188
+ fixed: true,
1189
+ buttons: [{
1190
+ text: t('ok', 'OK'),
1191
+ class: 'primary',
1192
+ click: () => failureNotice.close()
1193
+ }]
1194
+ })
1187
1195
  if (!keepDeployBlocked) offerRecoveryRetry()
1188
1196
  })
1189
1197
  .finally(() => unlockEditor({ keepDeployBlocked }))