node-red-contrib-knx-ultimate 6.1.0 → 6.2.0
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 +16 -0
- package/examples/KNX AI - Conversational Control with Confirmation.json +374 -0
- package/examples/KNX AI - Telegrambot Direct Chat.json +221 -0
- package/examples/Matter Controller - Semantic Flow Input.json +248 -0
- package/nodes/commonFunctions.js +0 -174
- package/nodes/knxUltimateAI.html +254 -90
- package/nodes/knxUltimateAI.js +1286 -61
- package/nodes/knxUltimateMatterBridge.html +144 -11
- package/nodes/knxUltimateMatterControllerDevice.html +80 -55
- package/nodes/locales/de/knxUltimateAI.html +38 -2
- package/nodes/locales/de/knxUltimateAI.json +16 -3
- package/nodes/locales/de/knxUltimateMatterBridge.html +1 -1
- package/nodes/locales/de/knxUltimateMatterBridge.json +14 -0
- package/nodes/locales/de/knxUltimateMatterControllerDevice.html +2 -2
- package/nodes/locales/de/knxUltimateMatterControllerDevice.json +2 -1
- package/nodes/locales/en/knxUltimateAI.html +38 -2
- package/nodes/locales/en/knxUltimateAI.json +16 -3
- package/nodes/locales/en/knxUltimateMatterBridge.html +1 -1
- package/nodes/locales/en/knxUltimateMatterBridge.json +14 -0
- package/nodes/locales/en/knxUltimateMatterControllerDevice.html +2 -2
- package/nodes/locales/en/knxUltimateMatterControllerDevice.json +2 -1
- package/nodes/locales/es/knxUltimateAI.html +38 -2
- package/nodes/locales/es/knxUltimateAI.json +16 -3
- package/nodes/locales/es/knxUltimateMatterBridge.html +1 -1
- package/nodes/locales/es/knxUltimateMatterBridge.json +14 -0
- package/nodes/locales/es/knxUltimateMatterControllerDevice.html +2 -2
- package/nodes/locales/es/knxUltimateMatterControllerDevice.json +2 -1
- package/nodes/locales/fr/knxUltimateAI.html +38 -2
- package/nodes/locales/fr/knxUltimateAI.json +16 -3
- package/nodes/locales/fr/knxUltimateMatterBridge.html +1 -1
- package/nodes/locales/fr/knxUltimateMatterBridge.json +14 -0
- package/nodes/locales/fr/knxUltimateMatterControllerDevice.html +2 -2
- package/nodes/locales/fr/knxUltimateMatterControllerDevice.json +2 -1
- package/nodes/locales/it/knxUltimateAI.html +38 -2
- package/nodes/locales/it/knxUltimateAI.json +16 -3
- package/nodes/locales/it/knxUltimateMatterBridge.html +1 -1
- package/nodes/locales/it/knxUltimateMatterBridge.json +14 -0
- package/nodes/locales/it/knxUltimateMatterControllerDevice.html +2 -2
- package/nodes/locales/it/knxUltimateMatterControllerDevice.json +2 -1
- package/nodes/locales/zh-CN/knxUltimateAI.html +38 -2
- package/nodes/locales/zh-CN/knxUltimateAI.json +16 -3
- package/nodes/locales/zh-CN/knxUltimateMatterBridge.html +1 -1
- package/nodes/locales/zh-CN/knxUltimateMatterBridge.json +14 -0
- package/nodes/locales/zh-CN/knxUltimateMatterControllerDevice.html +2 -2
- package/nodes/locales/zh-CN/knxUltimateMatterControllerDevice.json +2 -1
- package/nodes/utils/sysLogger.js +0 -109
- package/package.json +1 -2
- package/resources/KNXAIChatAdapterMappings.js +87 -0
- package/nodes/plugins/knxUltimateMonitor-sidebar-plugin.html +0 -922
|
@@ -19,11 +19,11 @@ Il remplace les nœuds Matter séparés non publiés et conserve toute l'UI lumi
|
|
|
19
19
|
| Capteurs | Les endpoints capteur affichent leur GA de mesure/état uniquement si elle est supportée : température, humidité, éclairement, occupation, contact et batterie. |
|
|
20
20
|
| Read at startup | Publie la valeur Matter en cache au déploiement/démarrage ou quand le périphérique se reconnecte. |
|
|
21
21
|
| 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. |
|
|
22
|
-
| Node Input/Output PINs | Affiche les pins entrée/sortie Node-RED. Les
|
|
22
|
+
| Node Input/Output PINs | Affiche les pins entrée/sortie Node-RED et la section **Entrée du flow** juste sous ce champ. Les lumières affichent leurs messages d'état pris en charge au premier niveau ; les autres endpoints affichent le format simple `{function,value}` et les champs Matter avancés. |
|
|
23
23
|
|
|
24
24
|
## Entrée du flow
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
Activez **Node Input/Output PINs** pour afficher la section **Entrée du flow** juste sous le sélecteur. Pour une lumière, elle propose des exemples copiables des propriétés prises en charge au premier niveau, comme `msg.on`, `msg.dimming`, `msg.color_temperature` et `msg.color`. Pour les autres endpoints, elle est construite depuis la structure annoncée et affiche l'Endpoint ID, tous les attributs lisibles/inscriptibles et toutes les commandes acceptées. Elle reste disponible sans passerelle KNX.
|
|
27
27
|
|
|
28
28
|
Une écriture simple utilise `msg.payload = {function:"position",value:35}`. Omettez `value` pour lire un état, par exemple `{function:"temperature"}` ; la sortie utilise des unités lisibles et place les détails bruts dans `msg.matter`. Les fonctions `onoff`, `level`, `position`, `open`, `close`, `stop`, consignes, ventilateur et capteurs ne sont proposées que si l'endpoint les annonce. Une serrure accepte `{function:"lock",value:true|false}`.
|
|
29
29
|
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"input_help_endpoint_hint": "Le nœud connaît déjà le Node ID et l'Endpoint ID ; les messages simples n'en ont pas besoin.",
|
|
18
18
|
"input_help_simple_title": "Messages simples",
|
|
19
19
|
"input_help_simple_hint": "Ces fonctions utilisent des unités lisibles et sont traduites vers le cluster, la commande ou l'attribut Matter de l'endpoint sélectionné.",
|
|
20
|
+
"input_help_light_hint": "Les endpoints de type lumière acceptent les propriétés d'état directement dans msg (pas dans msg.payload). Seules les commandes prises en charge par la lumière sélectionnée sont affichées.",
|
|
20
21
|
"input_help_advanced_title": "Détails Matter avancés",
|
|
21
22
|
"input_help_advanced_hint": "Seuls les attributs et commandes annoncés sont affichés. Les exemples d'écriture utilisent 0 comme valeur provisoire ; les arguments des commandes peuvent devoir être adaptés au type Matter.",
|
|
22
23
|
"input_help_operation": "Opération",
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
"input_help_no_simple": "Cet endpoint ne possède aucune fonction d'entrée simple connue.",
|
|
32
33
|
"input_help_no_structure": "La structure Matter est indisponible. Actualisez la liste des appareils lorsque l'endpoint est en ligne.",
|
|
33
34
|
"input_functions": {
|
|
34
|
-
"onoff": "Marche / Arrêt", "level": "Niveau", "position": "Position du volet", "tiltposition": "Inclinaison du volet", "open": "Ouvrir", "close": "Fermer", "stop": "Arrêter", "setpoint": "Consigne chauffage", "coolingsetpoint": "Consigne refroidissement", "currenttemp": "Température actuelle", "fanspeed": "Vitesse du ventilateur", "temperature": "Température", "humidity": "Humidité", "illuminance": "Éclairement", "occupancy": "Occupation", "contact": "Contact", "battery": "Batterie", "activepower": "Puissance active", "importedenergy": "Énergie importée", "identify": "Identifier", "lock": "Verrouiller", "unlock": "Déverrouiller"
|
|
35
|
+
"onoff": "Marche / Arrêt", "on": "Allumer", "off": "Éteindre", "level": "Niveau", "brightness": "Luminosité", "color_temperature": "Température de couleur", "xy_color": "Couleur XY", "position": "Position du volet", "tiltposition": "Inclinaison du volet", "open": "Ouvrir", "close": "Fermer", "stop": "Arrêter", "setpoint": "Consigne chauffage", "coolingsetpoint": "Consigne refroidissement", "currenttemp": "Température actuelle", "fanspeed": "Vitesse du ventilateur", "temperature": "Température", "humidity": "Humidité", "illuminance": "Éclairement", "occupancy": "Occupation", "contact": "Contact", "battery": "Batterie", "activepower": "Puissance active", "importedenergy": "Énergie importée", "identify": "Identifier", "lock": "Verrouiller", "unlock": "Déverrouiller"
|
|
35
36
|
},
|
|
36
37
|
"tabs": {
|
|
37
38
|
"switch": "Changer",
|
|
@@ -1,18 +1,48 @@
|
|
|
1
1
|
<script type="text/markdown" data-help-name="knxUltimateAI">
|
|
2
2
|
Questo nodo ascolta **tutti i telegrammi KNX** dal gateway KNX Ultimate selezionato, costruisce statistiche di traffico, rileva anomalie e può interrogare opzionalmente un LLM.
|
|
3
3
|
|
|
4
|
+
Le sezioni dell'editor utilizzano le stesse tab verticali a sinistra dei nodi Matter. **Configurazione rapida** contiene soltanto le scelte AI più comuni (abilitazione, provider, credenziali, modello, lettura stati/comando attuatori KNX e conferma); i parametri tecnici sono raggruppati per argomento nelle altre tab.
|
|
5
|
+
|
|
4
6
|
## Output
|
|
5
7
|
1. **Summary/Statistiche** (`msg.payload` JSON)
|
|
6
8
|
2. **Anomalie** (`msg.payload` JSON)
|
|
7
9
|
3. **Assistente AI** (`msg.payload` testo, con `msg.summary`)
|
|
10
|
+
4. **Operazioni KNX** (un messaggio Universal Mode per ogni lettura o scrittura validata)
|
|
11
|
+
|
|
12
|
+
Ogni messaggio emesso dalle uscite 3 e 4 contiene anche una copia del messaggio originale in ingresso in `msg.inputMessage`. In questo modo payload, topic, metadati della chat e qualsiasi altra proprietà di ingresso restano disponibili per i nodi successivi. Gli errori di clonazione o di invio vengono intercettati e segnalati senza propagarsi al runtime di Node-RED.
|
|
8
13
|
|
|
9
14
|
## Comandi (input)
|
|
10
15
|
Invia `msg.topic`:
|
|
11
16
|
- `summary` (o vuoto): emette subito la summary
|
|
12
17
|
- `reset`: azzera storico e contatori interni
|
|
13
18
|
- `ask`: invia una domanda all'LLM configurato
|
|
19
|
+
- `confirm` / `cancel`: conferma o annulla i comandi KNX in attesa senza richiamare l'LLM
|
|
20
|
+
- `clear_chat`: azzera la memoria della conversazione per la sessione corrente
|
|
21
|
+
|
|
22
|
+
Per `ask`, passa la domanda in `msg.prompt` (consigliato), in `msg.payload` (stringa), oppure nei comuni campi Telegram `msg.payload.content` / `msg.payload.text`.
|
|
23
|
+
|
|
24
|
+
Quando il controllo KNX è abilitato, i turni recenti sono conservati in RAM per `msg.knxAi.sessionId`, `msg.sessionId` o per il chat ID Telegram rilevato. Collega l'uscita 3 al nodo di risposta della chat e l'uscita 4 a un nodo KNX Ultimate configurato in **Modalità Universale**. Con la conferma attiva, la prima risposta mostra GA, DPT e payload delle scritture senza emetterle; la stessa sessione deve poi rispondere `CONFERMA`/`ANNULLA` entro 5 minuti. Una nuova richiesta sostituisce l'eventuale piano precedente. Ogni comando confermato contiene `msg.destination`, `msg.dpt`, `msg.payload` e `msg.event = "GroupValue_Write"`.
|
|
25
|
+
Per le scritture DPT 1.xxx, gli equivalenti sicuri prodotti dall'AI `true`/`false`, `1`/`0` e `on`/`off` vengono normalizzati in un vero booleano prima della validazione locale e dell'uscita.
|
|
26
|
+
|
|
27
|
+
### Letture KNX aggiornate
|
|
28
|
+
Quando l'utente chiede esplicitamente uno stato attuale o aggiornato, l'AI può interrogare gli oggetti esatti del catalogo ETS importato, compresi gli oggetti di stato e di sola lettura. L'uscita 4 emette `msg.destination`, `msg.dpt`, `msg.event = "GroupValue_Read"` e `msg.readstatus = true`. Il nodo attende fino a 6 secondi ogni `GroupValue_Response` o scrittura fresca, poi restituisce i valori decodificati sull'uscita 3 e i dettagli in `msg.knxAi.readResults`. Le letture non richiedono mai conferma e non vengono mai trasformate in scritture.
|
|
29
|
+
|
|
30
|
+
### Richiesta di conferma per pulsanti chat
|
|
31
|
+
Quando un piano è in attesa, l'uscita 3 contiene `msg.knxAi.confirmationRequest`. L'oggetto include `required`, `status`, `sessionId`, `expiresAt`, `commandCount` e due elementi in `actions`. Usa `action.label` per il testo del pulsante Telegram, `action.callbackData` per il callback e reinvia `action.message` al nodo KNX AI per confermare o annullare senza digitare testo.
|
|
32
|
+
|
|
33
|
+
### Preset adattatori chat
|
|
34
|
+
La tab **Adattatori chat** carica le mappature selezionabili da `resources/KNXAIChatAdapterMappings.js`. Scegliendo un preset vengono inserite due mappature JavaScript sincrone e modificabili in caselle di testo a larghezza piena: una eseguita prima che KNX AI elabori l'ingresso e una prima dell'emissione sull'uscita 3. Restituisci `msg` per continuare oppure nessun valore per scartare il messaggio. Errori di sintassi o esecuzione vengono intercettati e segnalati senza arrestare Node-RED.
|
|
35
|
+
|
|
36
|
+
Il preset incluso **windkh/node-red-contrib-telegrambot** segue il contratto receiver/sender del pacchetto. Collega direttamente un `telegram receiver` a KNX AI e l'uscita 3 direttamente a un `telegram sender`; per usare i pulsanti inline di conferma, collega allo stesso ingresso KNX AI anche un `telegram event` configurato come `callback_query`. La mappatura d'ingresso estrae `msg.payload.content`, `msg.payload.chatId` e la lingua Telegram. Quella d'uscita crea i campi richiesti `msg.payload.chatId`, `type` e `content`, aggiungendo `options.reply_markup` da `msg.knxAi.confirmationRequest` quando una scrittura attende conferma. Il pacchetto Telegram resta una dipendenza opzionale separata.
|
|
14
37
|
|
|
15
|
-
|
|
38
|
+
## Workflow rapido: controllo KNX
|
|
39
|
+
1. Importa il CSV ETS nel gateway e configura provider, modello e credenziali LLM.
|
|
40
|
+
2. Abilita **Assistente LLM** e **lettura stati e controllo attuatori KNX**; lascia attiva la conferma.
|
|
41
|
+
3. Collega l'ingresso della chat al nodo KNX AI mantenendo un ID sessione/chat stabile.
|
|
42
|
+
4. Collega l'uscita 3 alla risposta della chat e l'uscita 4 a KNX Ultimate in **Modalità Universale**.
|
|
43
|
+
5. L'utente invia una richiesta; gli stati aggiornati vengono letti subito, mentre per le scritture l'AI mostra prima GA, DPT e valore senza scrivere sul bus.
|
|
44
|
+
6. Entro 5 minuti, la stessa chat risponde esattamente `CONFERMA` oppure `ANNULLA`.
|
|
45
|
+
7. Solo `CONFERMA` rivalida ed emette i comandi sull'uscita 4; verifica l'esecuzione tramite una GA di stato.
|
|
16
46
|
|
|
17
47
|
## Campi di configurazione
|
|
18
48
|
Di seguito sono elencati tutti i campi presenti nell'editor del nodo KNX AI.
|
|
@@ -53,7 +83,13 @@ Di seguito sono elencati tutti i campi presenti nell'editor del nodo KNX AI.
|
|
|
53
83
|
- **URL endpoint**: URL endpoint chat/completions.
|
|
54
84
|
- **API key**: chiave API (non necessaria con Ollama locale).
|
|
55
85
|
- **Modello**: ID/nome modello.
|
|
86
|
+
- **Compatibilità modello chat**: il modello selezionato deve supportare l'endpoint Chat Completions configurato. I modelli legacy disponibili solo tramite completions, come `gpt-3.5-turbo-instruct`, vengono esclusi quando si aggiorna la lista. Se il provider rifiuta un valore personalizzato di temperature o il parametro del limite token, KNX AI riprova rimuovendo o sostituendo soltanto il campo incompatibile.
|
|
56
87
|
- **Prompt di sistema**: istruzione globale del comportamento analisi KNX (Advanced).
|
|
88
|
+
- **Consenti all'AI di leggere stati KNX e comandare attuatori**: abilita l'uscita 4 ed è disattivato per default. Gli oggetti esatti del catalogo ETS possono essere letti; le scritture sono accettate solo per gli oggetti classificati come `command`. Operazioni sconosciute, con DPT discordante, non valide o eccessive e scritture verso oggetti di stato/neutrali vengono rifiutate localmente.
|
|
89
|
+
- **Chiedi conferma prima di inviare comandi KNX**: attivo per default. Mostra prima le modifiche validate e non emette comandi KNX finché la stessa sessione chat non le conferma. Quando ci sono comandi in attesa, la risposta aggiunge sempre le istruzioni esatte per confermare o annullare nella lingua della richiesta corrente. I comandi vengono validati nuovamente subito prima dell'uscita.
|
|
90
|
+
- **Preset adattatore**: carica una coppia di mappature ingresso/uscita dal file degli adattatori chat incluso. La selezione sostituisce intenzionalmente entrambe le caselle di testo; il codice resta modificabile.
|
|
91
|
+
- **Mappatura ingresso (chat → KNX AI)**: JavaScript sincrono applicato prima dell'elaborazione del comando in ingresso.
|
|
92
|
+
- **Mappatura uscita (KNX AI → chat)**: JavaScript sincrono applicato solo ai messaggi dell'uscita 3.
|
|
57
93
|
- Se l'archivio su disco e' attivo, **Ask** lo usa di default: rispetta date/intervalli espliciti e, se non presenti, cerca nelle ultime 24 ore piu' gli eventi correnti in RAM.
|
|
58
94
|
- **Includi payload raw in hex**: include payload raw esadecimale nel prompt.
|
|
59
95
|
- **Includi inventario del progetto Node-RED**: include nel prompt l'inventario dell'intero progetto Node-RED, compresi nodi KNX e altri nodi utili come function/change/inject/template quando contengono logica KNX o group address.
|
|
@@ -84,5 +120,5 @@ Di seguito sono elencati tutti i campi presenti nell'editor del nodo KNX AI.
|
|
|
84
120
|
- Se Node-RED gira in Docker, usa `host.docker.internal` al posto di `localhost` nell'endpoint.
|
|
85
121
|
|
|
86
122
|
## Nota sicurezza
|
|
87
|
-
Se l'LLM è abilitato, il contesto traffico KNX può essere inviato all'endpoint configurato. Per privacy on-prem, usa provider locali.
|
|
123
|
+
Se l'LLM è abilitato, il contesto traffico KNX può essere inviato all'endpoint configurato. Per privacy on-prem, usa provider locali. Un comando emesso sull'uscita 4 ha superato la validazione locale ed è stato inoltrato al flow, ma non prova che l'attuatore lo abbia eseguito. Per la conferma usa una GA di stato KNX.
|
|
88
124
|
</script>
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
"knxUltimateAI": {
|
|
3
3
|
"title": "KNX AI (Analisi Traffico)",
|
|
4
4
|
"sections": {
|
|
5
|
+
"quickSetup": "Configurazione rapida",
|
|
5
6
|
"capture": "Cattura",
|
|
6
7
|
"storage": "Storico e Summary",
|
|
7
8
|
"detection": "Rilevamento e Avvisi",
|
|
8
9
|
"llmConnection": "Connessione Assistente AI",
|
|
9
10
|
"llmContext": "Contesto Assistente AI",
|
|
10
|
-
"
|
|
11
|
+
"chatAdapter": "Adattatori chat",
|
|
12
|
+
"advanced": "AI avanzata"
|
|
11
13
|
},
|
|
12
14
|
"properties": {
|
|
13
15
|
"server": "Gateway",
|
|
@@ -39,19 +41,28 @@
|
|
|
39
41
|
"llmSystemPrompt": "Prompt di sistema",
|
|
40
42
|
"llmIncludeRaw": "Includi payload raw in hex",
|
|
41
43
|
"llmIncludeFlowContext": "Includi inventario del progetto Node-RED",
|
|
44
|
+
"llmAllowKnxCommands": "Consenti all'AI di leggere stati KNX e comandare attuatori",
|
|
45
|
+
"llmRequireCommandConfirmation": "Chiedi conferma prima di inviare comandi KNX",
|
|
46
|
+
"chatAdapterPreset": "Preset adattatore",
|
|
47
|
+
"chatInputCode": "Mappatura ingresso (chat → KNX AI)",
|
|
48
|
+
"chatOutputCode": "Mappatura uscita (KNX AI → chat)",
|
|
42
49
|
"llmIncludeDocsSnippets": "Includi estratti documentazione (help/README/esempi)",
|
|
43
50
|
"llmDocsLanguage": "Lingua documentazione"
|
|
44
51
|
},
|
|
45
52
|
"outputs": {
|
|
46
53
|
"summary": "Summary/Statistiche",
|
|
47
54
|
"anomalies": "Anomalie",
|
|
48
|
-
"assistant": "Assistente AI"
|
|
55
|
+
"assistant": "Assistente AI",
|
|
56
|
+
"knxCommands": "Operazioni KNX"
|
|
49
57
|
},
|
|
50
58
|
"selectlists": {
|
|
51
59
|
"llmProvider": {
|
|
52
60
|
"openai_compat": "Compatibile OpenAI (chat/completions)",
|
|
53
61
|
"anthropic": "Anthropic (Claude)",
|
|
54
62
|
"ollama": "Ollama (locale, beta)"
|
|
63
|
+
},
|
|
64
|
+
"chatAdapter": {
|
|
65
|
+
"none": "Nessun adattatore"
|
|
55
66
|
}
|
|
56
67
|
},
|
|
57
68
|
"buttons": {
|
|
@@ -69,7 +80,9 @@
|
|
|
69
80
|
"installedOllamaModel": "Modello Ollama installato",
|
|
70
81
|
"installOllamaModelFailed": "Installazione modello Ollama non riuscita",
|
|
71
82
|
"ollamaInstallSteps": "1) Apri la libreria, scegli un modello e copiane il nome (es. llama3.1). 2) Inserisci il nome nel campo Modello e clicca Installalo.",
|
|
72
|
-
"ollamaStartedAuto": "Server Ollama avviato automaticamente."
|
|
83
|
+
"ollamaStartedAuto": "Server Ollama avviato automaticamente.",
|
|
84
|
+
"chatAdapterIntro": "Scegli un preset per inserire il codice di mappatura in ingresso e in uscita. La lista viene caricata dal file degli adattatori chat incluso nel pacchetto; il codice generato resta modificabile.",
|
|
85
|
+
"chatAdapterCodeHelp": "Le mappature sono sincrone. Restituisci msg per continuare oppure nessun valore per scartarlo. Gli errori vengono intercettati e segnalati senza arrestare Node-RED."
|
|
73
86
|
},
|
|
74
87
|
"placeholder": {
|
|
75
88
|
"llmBaseUrl": "https://api.openai.com/v1/chat/completions (o endpoint compatibile)",
|
|
@@ -45,7 +45,7 @@ Queste opzioni sono nascoste finché non servono al tipo selezionato. I disposit
|
|
|
45
45
|
|
|
46
46
|
## PIN del nodo
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
Il selettore dei PIN si trova fuori dalle TAB dell'editor. Abilitandolo compare subito sotto una sezione contestuale **Input/output del flow**, con esempi copiabili filtrati per il tipo di dispositivo selezionato:
|
|
49
49
|
|
|
50
50
|
- **Input**: aggiorna lo stato Matter dal flow, senza passare dal bus KNX: `msg.payload = { function: "onoff", value: true }` (`function` è una tra `onoff`, `level`, `rgb`, `colortemp`, `position`, `temperature`, `humidity`, `illuminance`, `occupancy`, `contact`, `currenttemp`, `setpoint`, `fanspeed`, `smoke`, `co`, `leak`, `co2`, `rvcstate`, `rvcmode`). Utile per esporre ad Alexa & Co. valori calcolati nel flow (es. un sensore virtuale).
|
|
51
51
|
- **Output**: ogni comando ricevuto da un controller Matter viene inoltrato al flow: `msg.topic` = nome del dispositivo, `msg.payload` = valore, `msg.matter` = il comando grezzo. Un dispositivo senza GA di comando diventa un **dispositivo solo-flow**.
|
|
@@ -36,6 +36,20 @@
|
|
|
36
36
|
"mappings": "Mappature KNX",
|
|
37
37
|
"advanced": "Opzioni avanzate"
|
|
38
38
|
},
|
|
39
|
+
"flow_help": {
|
|
40
|
+
"title": "Input/output del flow",
|
|
41
|
+
"intro": "Questi esempi corrispondono al tipo di dispositivo selezionato e sono disponibili quando i PIN input/output del nodo sono abilitati.",
|
|
42
|
+
"input_title": "Flow → Matter (input del nodo)",
|
|
43
|
+
"input_hint": "Invia uno di questi messaggi per aggiornare lo stato Matter esposto senza scrivere sul bus KNX.",
|
|
44
|
+
"output_title": "Matter → Flow (output del nodo)",
|
|
45
|
+
"output_hint": "I comandi ricevuti da un controller Matter vengono emessi con il valore in msg.payload e i dettagli raw in msg.matter.",
|
|
46
|
+
"function": "Funzione",
|
|
47
|
+
"message": "Messaggio di esempio",
|
|
48
|
+
"copy": "Copia",
|
|
49
|
+
"copied": "Messaggio copiato",
|
|
50
|
+
"no_input": "Questo tipo di dispositivo non ha esempi di aggiornamento stato dal flow.",
|
|
51
|
+
"no_output": "Questo tipo di dispositivo non emette comandi dal controller; il suo output rimane inattivo."
|
|
52
|
+
},
|
|
39
53
|
"functions": {
|
|
40
54
|
"fn_onoff_cmd": "GA comando On/Off",
|
|
41
55
|
"fn_onoff_status": "GA stato On/Off",
|
|
@@ -19,11 +19,11 @@ Sostituisce i nodi Matter separati non pubblicati e mantiene tutta la UI luce qu
|
|
|
19
19
|
| Sensori | Gli endpoint sensore mostrano il relativo GA di misura/stato solo quando supportato: temperatura, umidità, illuminamento, presenza, contatto e batteria. |
|
|
20
20
|
| Read at startup | Pubblica il valore Matter in cache al deploy/avvio o quando il dispositivo si riconnette. |
|
|
21
21
|
| Update local state from KNX write | Aggiorna la cache locale Matter/KNX quando arriva una scrittura su un GA KNX configurato. |
|
|
22
|
-
| Node Input/Output PINs | Mostra i pin input/output Node-RED.
|
|
22
|
+
| Node Input/Output PINs | Mostra i pin input/output Node-RED e la sezione **Input dal flow** subito sotto questo campo. Per le luci sono mostrati i messaggi di stato luce supportati al primo livello; per gli endpoint non luce sono mostrati il formato semplice `{function,value}` e i campi Matter avanzati. La selezione viene mantenuta alla riapertura dell'editor. |
|
|
23
23
|
|
|
24
24
|
## Input dal flow
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
Abilita **PIN di Input/Output del nodo** per mostrare la sezione **Input dal flow** subito sotto il selettore. Per le luci contiene esempi copiabili delle proprietà supportate al primo livello, come `msg.on`, `msg.dimming`, `msg.color_temperature` e `msg.color`. Per gli endpoint non luce viene costruita dalla struttura annunciata e mostra l'Endpoint ID selezionato, tutti gli attributi leggibili/scrivibili e tutti i comandi accettati. Rimane disponibile anche quando il nodo viene usato soltanto dal flow senza gateway KNX.
|
|
27
27
|
|
|
28
28
|
Le scritture semplici usano `msg.payload = {function:"position",value:35}`. Ometti `value` per leggere uno stato supportato, ad esempio `{function:"temperature"}`; l'output usa unità comprensibili e include i dettagli raw in `msg.matter`. Le funzioni comprendono `onoff`, `level`, `position`, `tiltposition`, `open`, `close`, `stop`, `setpoint`, `coolingsetpoint`, `currenttemp`, `fanspeed`, letture sensore e `identify`, ma soltanto se annunciate dall'endpoint. La serratura accetta `{function:"lock",value:true|false}`.
|
|
29
29
|
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"input_help_endpoint_hint": "Il nodo conosce già Node ID ed Endpoint ID, quindi non servono nei messaggi semplici.",
|
|
18
18
|
"input_help_simple_title": "Messaggi semplici",
|
|
19
19
|
"input_help_simple_hint": "Queste funzioni usano unità comprensibili e vengono tradotte nel cluster, comando o attributo Matter esposto dall'endpoint selezionato.",
|
|
20
|
+
"input_help_light_hint": "Gli endpoint luce accettano le proprietà dello stato luce direttamente in msg (non dentro msg.payload). Sono mostrati solo i controlli supportati dalla luce selezionata.",
|
|
20
21
|
"input_help_advanced_title": "Dettagli Matter avanzati",
|
|
21
22
|
"input_help_advanced_hint": "Sono elencati soltanto attributi e comandi annunciati. Gli esempi di scrittura usano 0 come segnaposto; gli argomenti dei comandi possono richiedere un adattamento al tipo Matter.",
|
|
22
23
|
"input_help_operation": "Operazione",
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
"input_help_no_simple": "Questo endpoint non espone funzioni semplici conosciute.",
|
|
32
33
|
"input_help_no_structure": "La struttura Matter non è disponibile. Aggiorna la lista dei dispositivi mentre l'endpoint è online.",
|
|
33
34
|
"input_functions": {
|
|
34
|
-
"onoff": "On / Off", "level": "Livello", "position": "Posizione tapparella", "tiltposition": "Inclinazione tapparella", "open": "Apri", "close": "Chiudi", "stop": "Stop", "setpoint": "Setpoint riscaldamento", "coolingsetpoint": "Setpoint raffrescamento", "currenttemp": "Temperatura corrente", "fanspeed": "Velocità ventilatore", "temperature": "Temperatura", "humidity": "Umidità", "illuminance": "Illuminamento", "occupancy": "Presenza", "contact": "Contatto", "battery": "Batteria", "activepower": "Potenza attiva", "importedenergy": "Energia importata", "identify": "Identifica", "lock": "Blocca", "unlock": "Sblocca"
|
|
35
|
+
"onoff": "On / Off", "on": "Accendi", "off": "Spegni", "level": "Livello", "brightness": "Luminosità", "color_temperature": "Temperatura colore", "xy_color": "Colore XY", "position": "Posizione tapparella", "tiltposition": "Inclinazione tapparella", "open": "Apri", "close": "Chiudi", "stop": "Stop", "setpoint": "Setpoint riscaldamento", "coolingsetpoint": "Setpoint raffrescamento", "currenttemp": "Temperatura corrente", "fanspeed": "Velocità ventilatore", "temperature": "Temperatura", "humidity": "Umidità", "illuminance": "Illuminamento", "occupancy": "Presenza", "contact": "Contatto", "battery": "Batteria", "activepower": "Potenza attiva", "importedenergy": "Energia importata", "identify": "Identifica", "lock": "Blocca", "unlock": "Sblocca"
|
|
35
36
|
},
|
|
36
37
|
"tabs": {
|
|
37
38
|
"switch": "On/Off",
|
|
@@ -1,18 +1,48 @@
|
|
|
1
1
|
<script type="text/markdown" data-help-name="knxUltimateAI">
|
|
2
2
|
此节点会监听所选 KNX Ultimate 网关上的**所有 KNX 电报**,生成流量统计、检测异常,并可选调用 LLM。
|
|
3
3
|
|
|
4
|
+
编辑器各部分使用与 Matter 节点相同的左侧垂直选项卡。**快速配置**仅包含常用 AI 选项(启用、提供商、凭据、模型、KNX 状态读取/执行器控制和确认);技术参数按主题归入其他选项卡。
|
|
5
|
+
|
|
4
6
|
## 输出
|
|
5
7
|
1. **摘要/统计**(`msg.payload` 为 JSON)
|
|
6
8
|
2. **异常**(`msg.payload` 为 JSON)
|
|
7
9
|
3. **AI 助手**(`msg.payload` 为文本,包含 `msg.summary`)
|
|
10
|
+
4. **KNX 操作**(每个通过验证的读取或写入输出一条 Universal Mode 消息)
|
|
11
|
+
|
|
12
|
+
输出 3 和输出 4 发出的每条消息还会在 `msg.inputMessage` 中包含原始输入消息的副本。因此,原始 payload、topic、聊天元数据及其他输入属性都可供后续节点使用。克隆或输出错误会被捕获并报告,不会传播到 Node-RED 运行时。
|
|
8
13
|
|
|
9
14
|
## 命令(输入)
|
|
10
15
|
发送 `msg.topic`:
|
|
11
16
|
- `summary`(或空):立即输出摘要
|
|
12
17
|
- `reset`:清空内部历史与计数器
|
|
13
18
|
- `ask`:向已配置的 LLM 提问
|
|
19
|
+
- `confirm` / `cancel`:无需再次调用 LLM,即可确认或取消待处理的 KNX 命令
|
|
20
|
+
- `clear_chat`:清除当前会话的对话记忆
|
|
21
|
+
|
|
22
|
+
`ask` 的问题建议放在 `msg.prompt`,也可放在 `msg.payload`(字符串)或常见 Telegram 字段 `msg.payload.content` / `msg.payload.text`。
|
|
23
|
+
|
|
24
|
+
启用 KNX 控制后,最近的对话会按 `msg.knxAi.sessionId`、`msg.sessionId` 或检测到的 Telegram 聊天 ID 保存在 RAM 中。将输出 3 连接到聊天发送节点,将输出 4 连接到配置为**通用模式**的 KNX Ultimate 节点。启用确认后,第一条回复会显示 GA、DPT 和 payload,但不会发送写入;同一会话必须在 5 分钟内回复“确认”或“取消”。新请求会替换旧的待处理计划。每条已确认命令都包含 `msg.destination`、`msg.dpt`、`msg.payload` 和 `msg.event = "GroupValue_Write"`。
|
|
25
|
+
对于 DPT 1.xxx 写入,AI 生成的安全等价值 `true`/`false`、`1`/`0` 和 `on`/`off` 会在本地校验和输出前统一转换为真正的布尔值。
|
|
26
|
+
|
|
27
|
+
### 最新 KNX 读取
|
|
28
|
+
当用户明确要求当前或最新状态时,AI 可以查询已导入 ETS 目录中的精确对象,包括状态对象和其他只读对象。输出 4 会发送 `msg.destination`、`msg.dpt`、`msg.event = "GroupValue_Read"` 和 `msg.readstatus = true`。节点会为每个 `GroupValue_Response` 或最新写入等待最多 6 秒,然后在输出 3 返回解码值,并在 `msg.knxAi.readResults` 中提供详细信息。读取从不需要确认,也绝不会转换为写入。
|
|
29
|
+
|
|
30
|
+
### 用于聊天按钮的确认请求
|
|
31
|
+
计划等待确认时,输出 3 包含 `msg.knxAi.confirmationRequest`。该对象包括 `required`、`status`、`sessionId`、`expiresAt`、`commandCount`,以及 `actions` 中的两个项目。使用 `action.label` 作为 Telegram 按钮文本,使用 `action.callbackData` 作为回调,并将 `action.message` 发送回 KNX AI,即可在无需输入文本的情况下确认或取消。
|
|
32
|
+
|
|
33
|
+
### 聊天适配器预设
|
|
34
|
+
**聊天适配器**选项卡从 `resources/KNXAIChatAdapterMappings.js` 加载可选映射。选择预设会在全宽文本框中插入两段可编辑的同步 JavaScript 映射:一段在 KNX AI 处理输入前运行,另一段在输出 3 发出消息前运行。返回 `msg` 以继续,或不返回值以丢弃消息。语法和执行错误会被捕获并报告,不会停止 Node-RED。
|
|
35
|
+
|
|
36
|
+
随附的 **windkh/node-red-contrib-telegrambot** 预设遵循该包的 receiver/sender 消息约定。把 `telegram receiver` 直接连接到 KNX AI,并把输出 3 直接连接到 `telegram sender`。如需内联确认按钮,还要把配置为 `callback_query` 的 `telegram event` 连接到同一个 KNX AI 输入。输入映射会提取 `msg.payload.content`、`msg.payload.chatId` 和 Telegram 语言;输出映射会创建所需的 `msg.payload.chatId`、`type` 和 `content`,并在写入等待确认时从 `msg.knxAi.confirmationRequest` 添加 `options.reply_markup`。Telegram 包仍是独立的可选依赖项。
|
|
14
37
|
|
|
15
|
-
|
|
38
|
+
## 快速工作流程:KNX 控制
|
|
39
|
+
1. 将 ETS CSV 导入网关,并配置 LLM 提供商、模型和凭据。
|
|
40
|
+
2. 启用 **LLM 助手**和 **读取 KNX 状态并控制执行器**;保持确认选项启用。
|
|
41
|
+
3. 将聊天输入连接到 KNX AI,并保留稳定的会话/聊天 ID。
|
|
42
|
+
4. 将输出 3 连接到聊天回复,将输出 4 连接到处于**通用模式**的 KNX Ultimate。
|
|
43
|
+
5. 用户发送请求;当前状态会立即读取,而写入会先显示 GA、DPT 和值,不会立即写入总线。
|
|
44
|
+
6. 同一聊天必须在 5 分钟内准确回复“确认”或“取消”。
|
|
45
|
+
7. 只有“确认”会重新验证并在输出 4 发送命令;请通过 KNX 状态 GA 验证执行结果。
|
|
16
46
|
|
|
17
47
|
## 配置字段
|
|
18
48
|
以下是编辑器里用户可见的全部字段名称。
|
|
@@ -53,7 +83,13 @@
|
|
|
53
83
|
- **Endpoint URL**:chat/completions 接口 URL。
|
|
54
84
|
- **API key**:API Key(本地 Ollama 可不填)。
|
|
55
85
|
- **Model**:模型 ID/名称。
|
|
86
|
+
- **聊天模型兼容性**:所选模型必须支持已配置的 Chat Completions 端点。刷新模型列表时,会排除仅支持旧版 completions 的模型,例如 `gpt-3.5-turbo-instruct`。如果提供商拒绝自定义 temperature 值或令牌限制参数,KNX AI 会仅移除或替换不兼容字段后重试。
|
|
56
87
|
- **System prompt**:KNX 分析全局系统提示词(Advanced)。
|
|
88
|
+
- **允许 AI 读取 KNX 状态并控制执行器**:启用输出 4,默认关闭。可以读取 ETS 目录中的精确对象;仅接受写入明确标记为 `command` 的对象。未知、DPT 不匹配、无效或数量过多的操作,以及向状态或中性对象的写入,都会在本地被拒绝。
|
|
89
|
+
- **发送 KNX 命令前请求确认**:默认启用。先显示已验证的修改,在同一聊天会话确认前不会发送任何 KNX 命令。有命令等待确认时,回复始终会使用当前请求的语言附加准确的确认或取消说明。命令会在输出前再次验证。
|
|
90
|
+
- **适配器预设**:从随附的聊天适配器文件加载一对输入/输出映射。选择预设会有意替换两个文本框,之后仍可编辑代码。
|
|
91
|
+
- **输入映射(聊天 → KNX AI)**:在处理输入命令前运行的同步 JavaScript。
|
|
92
|
+
- **输出映射(KNX AI → 聊天)**:仅应用于输出 3 消息的同步 JavaScript。
|
|
57
93
|
- 如果启用了磁盘归档,**Ask** 默认会查询该归档:若问题里写了明确日期/时间范围就按其查询,否则默认查询最近 24 小时并补上当前 RAM 事件。
|
|
58
94
|
- **Include raw payload hex**:在提示词中包含原始十六进制 payload。
|
|
59
95
|
- **包含 Node-RED 项目清单**:在提示词中加入整个 Node-RED 项目的节点清单,不仅包含 KNX 节点,也包含 function/change/inject/template 等在内且带有 KNX 逻辑或组地址的有用节点。
|
|
@@ -84,5 +120,5 @@
|
|
|
84
120
|
- 若 Node-RED 运行在 Docker 中,endpoint 请使用 `host.docker.internal` 替代 `localhost`。
|
|
85
121
|
|
|
86
122
|
## 安全说明
|
|
87
|
-
启用 LLM 后,KNX 流量上下文可能发送到所配置的 endpoint。若需严格本地化,请使用本地 provider。
|
|
123
|
+
启用 LLM 后,KNX 流量上下文可能发送到所配置的 endpoint。若需严格本地化,请使用本地 provider。输出 4 上的命令仅表示已通过本地验证并转发到 flow,并不能证明执行器已执行;需要确认时请使用 KNX 状态 GA。
|
|
88
124
|
</script>
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
"knxUltimateAI": {
|
|
3
3
|
"title": "KNX AI (Traffic Analyzer)",
|
|
4
4
|
"sections": {
|
|
5
|
+
"quickSetup": "快速配置",
|
|
5
6
|
"capture": "Capture",
|
|
6
7
|
"storage": "历史与摘要",
|
|
7
8
|
"detection": "检测与告警",
|
|
8
9
|
"llmConnection": "AI 助手连接",
|
|
9
10
|
"llmContext": "AI 助手上下文",
|
|
10
|
-
"
|
|
11
|
+
"chatAdapter": "聊天适配器",
|
|
12
|
+
"advanced": "AI 高级设置"
|
|
11
13
|
},
|
|
12
14
|
"properties": {
|
|
13
15
|
"server": "Gateway",
|
|
@@ -39,19 +41,28 @@
|
|
|
39
41
|
"llmSystemPrompt": "System prompt",
|
|
40
42
|
"llmIncludeRaw": "Include raw payload hex",
|
|
41
43
|
"llmIncludeFlowContext": "包含 Node-RED 项目清单",
|
|
44
|
+
"llmAllowKnxCommands": "允许 AI 读取 KNX 状态并控制执行器",
|
|
45
|
+
"llmRequireCommandConfirmation": "发送 KNX 命令前请求确认",
|
|
46
|
+
"chatAdapterPreset": "适配器预设",
|
|
47
|
+
"chatInputCode": "输入映射(聊天 → KNX AI)",
|
|
48
|
+
"chatOutputCode": "输出映射(KNX AI → 聊天)",
|
|
42
49
|
"llmIncludeDocsSnippets": "Include documentation snippets (help/README/examples)",
|
|
43
50
|
"llmDocsLanguage": "Docs language"
|
|
44
51
|
},
|
|
45
52
|
"outputs": {
|
|
46
53
|
"summary": "摘要/统计",
|
|
47
54
|
"anomalies": "异常",
|
|
48
|
-
"assistant": "AI 助手"
|
|
55
|
+
"assistant": "AI 助手",
|
|
56
|
+
"knxCommands": "KNX 操作"
|
|
49
57
|
},
|
|
50
58
|
"selectlists": {
|
|
51
59
|
"llmProvider": {
|
|
52
60
|
"openai_compat": "OpenAI-compatible (chat/completions)",
|
|
53
61
|
"anthropic": "Anthropic (Claude)",
|
|
54
62
|
"ollama": "Ollama (local, beta)"
|
|
63
|
+
},
|
|
64
|
+
"chatAdapter": {
|
|
65
|
+
"none": "无适配器"
|
|
55
66
|
}
|
|
56
67
|
},
|
|
57
68
|
"messages": {
|
|
@@ -61,7 +72,9 @@
|
|
|
61
72
|
"installedOllamaModel": "Ollama model installed",
|
|
62
73
|
"installOllamaModelFailed": "Failed to install Ollama model",
|
|
63
74
|
"ollamaInstallSteps": "1) Open the model library and copy the model name (for example llama3.1). 2) Put the name in the Model field and click Install it.",
|
|
64
|
-
"ollamaStartedAuto": "Ollama server started automatically."
|
|
75
|
+
"ollamaStartedAuto": "Ollama server started automatically.",
|
|
76
|
+
"chatAdapterIntro": "选择预设即可插入输入和输出映射代码。列表从随包提供的聊天适配器文件加载;生成的代码仍可编辑。",
|
|
77
|
+
"chatAdapterCodeHelp": "映射同步运行。返回 msg 以继续,或不返回值以丢弃消息。错误会被捕获并报告,不会停止 Node-RED。"
|
|
65
78
|
},
|
|
66
79
|
"placeholder": {
|
|
67
80
|
"llmBaseUrl": "https://api.openai.com/v1/chat/completions (or your compatible endpoint)",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
|
|
46
46
|
## 节点引脚
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
引脚选择器位于编辑器选项卡之外。启用后,其下方会显示与所选设备类型匹配的 **Flow 输入/输出** 区域,并提供可复制示例:
|
|
49
49
|
|
|
50
50
|
- **输入**:从 Flow 更新 Matter 状态,无需经过 KNX 总线:`msg.payload = { function: "onoff", value: true }`(`function` 为 `onoff`、`level`、`rgb`、`colortemp`、`position`、`temperature`、`humidity`、`illuminance`、`occupancy`、`contact`、`currenttemp`、`setpoint`、`fanspeed`、`smoke`、`co`、`leak`、`co2`、`rvcstate`、`rvcmode` 之一)。适合把 Flow 中计算的值(如虚拟传感器)公开给 Alexa 等。
|
|
51
51
|
- **输出**:从 Matter 控制器收到的每个命令都转发到 Flow:`msg.topic` = 设备名称,`msg.payload` = 值,`msg.matter` = 原始命令。没有命令 GA 的设备成为**纯 Flow 设备**。
|
|
@@ -36,6 +36,20 @@
|
|
|
36
36
|
"mappings": "KNX 映射",
|
|
37
37
|
"advanced": "高级选项"
|
|
38
38
|
},
|
|
39
|
+
"flow_help": {
|
|
40
|
+
"title": "Flow 输入/输出",
|
|
41
|
+
"intro": "这些示例与所选设备类型匹配,并在启用节点输入/输出引脚时显示。",
|
|
42
|
+
"input_title": "Flow → Matter(节点输入)",
|
|
43
|
+
"input_hint": "发送以下消息之一,无需写入 KNX 即可更新所公开的 Matter 状态。",
|
|
44
|
+
"output_title": "Matter → Flow(节点输出)",
|
|
45
|
+
"output_hint": "Matter 控制器收到的命令会输出,值位于 msg.payload,原始路由详情位于 msg.matter。",
|
|
46
|
+
"function": "功能",
|
|
47
|
+
"message": "示例消息",
|
|
48
|
+
"copy": "复制",
|
|
49
|
+
"copied": "消息已复制",
|
|
50
|
+
"no_input": "此设备类型没有 Flow 状态更新示例。",
|
|
51
|
+
"no_output": "此设备类型不会输出控制器命令;其输出保持静默。"
|
|
52
|
+
},
|
|
39
53
|
"functions": {
|
|
40
54
|
"fn_onoff_cmd": "开/关 命令 GA",
|
|
41
55
|
"fn_onoff_status": "开/关 状态 GA",
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
| 传感器 | 传感器 endpoint 只在支持时显示对应测量/状态 GA:温度、湿度、照度、占用、接触和电池。 |
|
|
20
20
|
| Read at startup | 在部署/启动或设备重新连接时发布缓存的 Matter 值。 |
|
|
21
21
|
| Update local state from KNX write | 当配置的 KNX GA 收到写入 telegram 时,更新本地 Matter/KNX 缓存。 |
|
|
22
|
-
| Node Input/Output PINs | 显示 Node-RED
|
|
22
|
+
| Node Input/Output PINs | 显示 Node-RED 输入/输出端口,并在该字段下方显示 **流程输入** 区域。灯光会显示其支持的顶层灯光状态消息;其他端点会显示简单的 `{function,value}` 格式和高级 Matter 字段。 |
|
|
23
23
|
|
|
24
24
|
## 流程输入
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
启用 **Node Input/Output PINs** 后,**流程输入** 区域会直接显示在选择器下方。对于灯光,它提供所支持顶层属性的可复制示例,例如 `msg.on`、`msg.dimming`、`msg.color_temperature` 和 `msg.color`。对于其他端点,该区域根据公布的结构生成,并显示 Endpoint ID、所有可读/可写属性以及接受的命令。未选择 KNX 网关时仍然可用。
|
|
27
27
|
|
|
28
28
|
简单写入使用 `msg.payload = {function:"position",value:35}`。省略 `value` 即可读取支持的状态,例如 `{function:"temperature"}`;输出使用易懂单位,并在 `msg.matter` 中保留原始详情。`onoff`、`level`、`position`、`open`、`close`、`stop`、设定点、风扇和传感器功能仅在端点公布支持时出现。门锁接受 `{function:"lock",value:true|false}`。
|
|
29
29
|
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"input_help_endpoint_hint": "节点已知 Node ID 和 Endpoint ID,因此简单消息无需提供它们。",
|
|
18
18
|
"input_help_simple_title": "简单消息",
|
|
19
19
|
"input_help_simple_hint": "这些功能使用易懂的单位,并自动转换为所选端点公开的 Matter 集群、命令或属性。",
|
|
20
|
+
"input_help_light_hint": "灯光端点直接在 msg 上接收灯光状态属性(而不是放在 msg.payload 中)。这里只显示所选灯具支持的控制项。",
|
|
20
21
|
"input_help_advanced_title": "高级 Matter 详情",
|
|
21
22
|
"input_help_advanced_hint": "仅列出设备公布的属性和命令。写入示例中的 0 是占位值;命令参数可能需要按 Matter 数据类型调整。",
|
|
22
23
|
"input_help_operation": "操作",
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
"input_help_no_simple": "此端点没有已知的简单输入功能。",
|
|
32
33
|
"input_help_no_structure": "Matter 结构不可用。请在端点在线时刷新设备列表。",
|
|
33
34
|
"input_functions": {
|
|
34
|
-
"onoff": "开 / 关", "level": "亮度", "position": "窗帘位置", "tiltposition": "百叶角度", "open": "打开", "close": "关闭", "stop": "停止", "setpoint": "制热设定点", "coolingsetpoint": "制冷设定点", "currenttemp": "当前温度", "fanspeed": "风扇速度", "temperature": "温度", "humidity": "湿度", "illuminance": "照度", "occupancy": "占用", "contact": "触点", "battery": "电池", "activepower": "有功功率", "importedenergy": "输入电能", "identify": "识别", "lock": "上锁", "unlock": "解锁"
|
|
35
|
+
"onoff": "开 / 关", "on": "打开", "off": "关闭", "level": "亮度", "brightness": "亮度", "color_temperature": "色温", "xy_color": "XY 颜色", "position": "窗帘位置", "tiltposition": "百叶角度", "open": "打开", "close": "关闭", "stop": "停止", "setpoint": "制热设定点", "coolingsetpoint": "制冷设定点", "currenttemp": "当前温度", "fanspeed": "风扇速度", "temperature": "温度", "humidity": "湿度", "illuminance": "照度", "occupancy": "占用", "contact": "触点", "battery": "电池", "activepower": "有功功率", "importedenergy": "输入电能", "identify": "识别", "lock": "上锁", "unlock": "解锁"
|
|
35
36
|
},
|
|
36
37
|
"tabs": {
|
|
37
38
|
"switch": "开关",
|
package/nodes/utils/sysLogger.js
CHANGED
|
@@ -1,86 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* (C) 2024 Supergiovane
|
|
3
3
|
*/
|
|
4
|
-
const util = require('util')
|
|
5
4
|
const logger = require('node-color-log')
|
|
6
5
|
|
|
7
|
-
const DEBUG_BUFFER_LIMIT = 5000
|
|
8
|
-
const debugBuffer = []
|
|
9
|
-
let debugSequence = 0
|
|
10
|
-
|
|
11
|
-
const cloneEntry = (entry) => ({
|
|
12
|
-
seq: entry.seq,
|
|
13
|
-
level: entry.level,
|
|
14
|
-
prefix: entry.prefix,
|
|
15
|
-
message: entry.message,
|
|
16
|
-
timestamp: entry.timestamp,
|
|
17
|
-
isoTimestamp: entry.isoTimestamp,
|
|
18
|
-
sessionStart: entry.sessionStart
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
const normaliseLevel = (level) => {
|
|
22
|
-
const allowed = ['success', 'debug', 'info', 'warn', 'error']
|
|
23
|
-
if (allowed.includes(level)) return level
|
|
24
|
-
return 'info'
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const stringifyArg = (arg) => {
|
|
28
|
-
if (arg === null) return 'null'
|
|
29
|
-
if (arg === undefined) return 'undefined'
|
|
30
|
-
if (arg instanceof Error) return arg.stack || `${arg.name || 'Error'}: ${arg.message}`
|
|
31
|
-
const type = typeof arg
|
|
32
|
-
if (type === 'string') return arg
|
|
33
|
-
if (type === 'number' || type === 'boolean' || type === 'bigint') return String(arg)
|
|
34
|
-
if (type === 'symbol') return arg.toString()
|
|
35
|
-
try {
|
|
36
|
-
return util.inspect(arg, { depth: 6, breakLength: 120, compact: false })
|
|
37
|
-
} catch (error) {
|
|
38
|
-
return String(arg)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const formatArgs = (args) => {
|
|
43
|
-
if (!args || !args.length) return ''
|
|
44
|
-
return args.map(stringifyArg).join(' ')
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const pushDebugEntry = (level, prefix, args, meta = {}) => {
|
|
48
|
-
try {
|
|
49
|
-
const effectiveLevel = normaliseLevel(level)
|
|
50
|
-
const timestamp = Date.now()
|
|
51
|
-
const isoTimestamp = new Date(timestamp).toISOString()
|
|
52
|
-
const message = formatArgs(args)
|
|
53
|
-
debugSequence += 1
|
|
54
|
-
debugBuffer.push({
|
|
55
|
-
seq: debugSequence,
|
|
56
|
-
level: effectiveLevel,
|
|
57
|
-
prefix: prefix || '',
|
|
58
|
-
message,
|
|
59
|
-
timestamp,
|
|
60
|
-
isoTimestamp,
|
|
61
|
-
sessionStart: !!meta.sessionStart
|
|
62
|
-
})
|
|
63
|
-
if (debugBuffer.length > DEBUG_BUFFER_LIMIT) {
|
|
64
|
-
debugBuffer.splice(0, debugBuffer.length - DEBUG_BUFFER_LIMIT)
|
|
65
|
-
}
|
|
66
|
-
} catch (error) {
|
|
67
|
-
// As a last resort, make sure the failure itself is recorded.
|
|
68
|
-
debugSequence += 1
|
|
69
|
-
debugBuffer.push({
|
|
70
|
-
seq: debugSequence,
|
|
71
|
-
level: 'error',
|
|
72
|
-
prefix: prefix || '',
|
|
73
|
-
message: `Logger buffer failure: ${error.message || error}`,
|
|
74
|
-
timestamp: Date.now(),
|
|
75
|
-
isoTimestamp: new Date().toISOString(),
|
|
76
|
-
sessionStart: false
|
|
77
|
-
})
|
|
78
|
-
if (debugBuffer.length > DEBUG_BUFFER_LIMIT) {
|
|
79
|
-
debugBuffer.splice(0, debugBuffer.length - DEBUG_BUFFER_LIMIT)
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
6
|
class loggerClass {
|
|
85
7
|
logLevel = 'info'
|
|
86
8
|
prefix = ''
|
|
@@ -99,62 +21,31 @@ class loggerClass {
|
|
|
99
21
|
this.logger.setLevel(requestedLevel)
|
|
100
22
|
this.logger.setDate(() => (new Date()).toLocaleString())
|
|
101
23
|
this.logLevel = requestedLevel
|
|
102
|
-
pushDebugEntry('info', this.prefix, [`--- Logger session started (level: ${this.logLevel}) ---`], { sessionStart: true })
|
|
103
24
|
}
|
|
104
25
|
|
|
105
26
|
destroy = () => {
|
|
106
27
|
// Placeholder for backward compatibility; kept for API symmetry.
|
|
107
28
|
}
|
|
108
29
|
|
|
109
|
-
record = (level, args) => {
|
|
110
|
-
pushDebugEntry(level, this.prefix, args)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
30
|
success = (...args) => {
|
|
114
|
-
this.record('success', args)
|
|
115
31
|
this.logger.success(...args)
|
|
116
32
|
}
|
|
117
33
|
|
|
118
34
|
debug = (...args) => {
|
|
119
|
-
this.record('debug', args)
|
|
120
35
|
this.logger.debug(...args)
|
|
121
36
|
}
|
|
122
37
|
|
|
123
38
|
info = (...args) => {
|
|
124
|
-
this.record('info', args)
|
|
125
39
|
this.logger.info(...args)
|
|
126
40
|
}
|
|
127
41
|
|
|
128
42
|
warn = (...args) => {
|
|
129
|
-
this.record('warn', args)
|
|
130
43
|
this.logger.warn(...args)
|
|
131
44
|
}
|
|
132
45
|
|
|
133
46
|
error = (...args) => {
|
|
134
|
-
this.record('error', args)
|
|
135
47
|
this.logger.error(...args)
|
|
136
48
|
}
|
|
137
49
|
}
|
|
138
50
|
|
|
139
|
-
loggerClass.getDebugSnapshot = (options = {}) => {
|
|
140
|
-
const sinceSeqRaw = options.sinceSeq
|
|
141
|
-
const sinceSeq = Number.isInteger(sinceSeqRaw) ? sinceSeqRaw : null
|
|
142
|
-
const source = sinceSeq === null ? debugBuffer : debugBuffer.filter((entry) => entry.seq > sinceSeq)
|
|
143
|
-
const entries = source.map(cloneEntry)
|
|
144
|
-
const latestSeq = debugBuffer.length ? debugBuffer[debugBuffer.length - 1].seq : (sinceSeq || 0)
|
|
145
|
-
return {
|
|
146
|
-
entries,
|
|
147
|
-
latestSeq,
|
|
148
|
-
total: debugBuffer.length,
|
|
149
|
-
limit: DEBUG_BUFFER_LIMIT
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
loggerClass.clearDebugBuffer = () => {
|
|
154
|
-
debugBuffer.length = 0
|
|
155
|
-
debugSequence = 0
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
loggerClass.DEBUG_BUFFER_LIMIT = DEBUG_BUFFER_LIMIT
|
|
159
|
-
|
|
160
51
|
module.exports = loggerClass
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=20.18.1"
|
|
5
5
|
},
|
|
6
|
-
"version": "6.
|
|
6
|
+
"version": "6.2.0",
|
|
7
7
|
"description": "KNX Ultimate is the most advanced KNX integration for Node-RED, providing secure KNX/IP communication, routing, ETS project import, Philips Hue, Matter Controller and Matter Bridge (control matter device via KNX and expose KNX GA via Matter), MQTT, diagnostics with AI, virtual devices, and powerful automation nodes. Build professional, reliable, and scalable smart home and building automation projects with minimal effort.",
|
|
8
8
|
"files": [
|
|
9
9
|
"nodes/",
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
"version": ">=3.1.1",
|
|
33
33
|
"plugins": {
|
|
34
34
|
"commonFunctions": "/nodes/commonFunctions.js",
|
|
35
|
-
"knxUltimateMonitorSidebar": "/nodes/plugins/knxUltimateMonitor-sidebar-plugin.html",
|
|
36
35
|
"knxUltimateFlowBubbles": "/nodes/plugins/knxUltimate-flow-bubbles-plugin.html"
|
|
37
36
|
},
|
|
38
37
|
"nodes": {
|