Stanco delle limitazioni di SmartLife? IoTwebUI 2.1 è arrivato per dare nuova linfa alla tua casa intelligente, con un arsenale di funzionalità che ti faranno dire "finalmente!".
La filosofia 'open' è nel DNA di questa APP, che esalta la customizzazione ed il controllo da parte dell'utente.
Cosa puoi fare?
👀 Controlla tutto: Interfaccia intuitiva e personalizzabile, dati sempre a portata di mano, visualizzazione flessibile.
🔬 Esportazione dati: Salva le serie storiche per le tue analisi, nel formato più utile
⚡️ Automazioni potenti: Crea automazioni complesse con tap-to-run e RULE, impossibili con SmartLife!
⏱️ Alert personalizzati: Monitora ogni aspetto della tua domotica e ricevi avvisi realtime, anche vocali.
🎙 Comandi vocali: integrati con tap-to-run e RULE, in un'unica APP
👌 Integrazione perfetta: Combina device, proprietà, voce, RULE e Tuya tap-to-run per un'automazione fluida e completa.
- Portabile, può essere installata ovunque: su uno smartphone o tablet, come interfaccia alternativa a SmartLife, per voi e per gli altri componenti della famiglia. Su un PC (Windows, Apple, Linux...) per avere Tuya anche su questi computer. Su un top-box Android, per usare la TV come interfaccia Tuya!.
- Scegli tra il tema chiaro o scuro, a seconda dei tuoi gusti.
- Naviga tra i tuoi dispositivi e le 'home' con un albero trascinabile e zoommabile, perfetto per tenere tutto sotto controllo.
- Popup informativi con nuove icone ti terranno aggiornato sullo stato di ogni proprietà di un device, senza perderti neanche un dettaglio.
- Un menu a scomparsa con informazioni sulla configurazione e opzioni dinamiche ti darà accesso rapido a tutto ciò che ti serve.
- Comandi vocale e Navigazione vocale tra le varie pagine.
- E se vuoi personalizzare ancora di più, libera la tua creatività con icone, colori e popup informativi a tua scelta.
- Registra i dati delle proprietà che ti interessano su file, così avrai sempre un archivio completo della tua domotica.
- Calcola medie mobili, valori decodificati o normalizzati per un'analisi ancora più approfondita.
- Scegli il salvataggio automatico o manuale, con opzioni di formato dati (CSV o JSON), periodo di campionamento e cadenza di salvataggio per adattarsi alle tue esigenze.
- Gestione al runtime: flessibilità senza limiti
- Una pagina dedicata con un tab per ogni "home" ti permette di avere tutto sotto controllo.
- Caricamento automatico all'avvio per una domotica sempre pronta all'azione.
- Lancia i tap-to-run Tuya con un semplice click e personalizza i colori dei pulsanti per un'esperienza ancora più intuitiva.
- Escludi i tap-to-run che non ti servono per avere un'interfaccia pulita e ordinata.
- Un tab è dedicato alle RULE per poterle lanciare quando serve.
- puoi attivare una funzione di controllo su qualsiasi proprietà dei dispositivi e scegliere i test "maggiore", "uguale" o "minore" per monitorare ogni aspetto della tua domotica.
- Stessa logica delle condizioni Tuya, per un linguaggio comune ed affidabile.
- Scegli tra diverse azioni conseguenziali: silente, beep, frase registrata, pop-up, messaggio vocale, lancio di URL o RULE|tap-to-run Tuya.
- Real Time, con un ritardo medio pari al 50% del periodo di campionamento Tuya, per un equilibrio perfetto tra rapidità e precisione: gli alert sempre visualizzati con pop-up o finestra.
- Definizione degli Alert al runtime: controllo totale in tempo reale
- Effettuare operazioni logiche ed aritmetiche e utilizzare variabili per una flessibilità senza limiti.
- Confrontare i valori di due proprietà diverse, per automazioni ancora più libere.
- Eseguire azioni complesse, come realizzare controlli PID, schedulare annualmente, o inviare comandi ad altre applicazioni via REST.
- Attivate in base a condizioni (come le 'Automazioni' Tuya, ma più flessibile) oppure su comando (come i 'tap-to-run' Tuya).
- Per i casi più semplici (una sola condizione) si possono usare gli 'alert' (che possono attivare 'tap-to-run').
- Il linguaggio delle RULE soddisfa le condizioni Bohm/Jacopini e quindi è 'Turing completo'. Più potenza espressiva vuol dire per l'utente concentrarsi su 'che cosa si vuol fare' e non 'su come farlo'!
- Come funziona?
- Crea le RULE al runtime con un'interfaccia user-friendly, anche se non sei un programmatore esperto.
- Utilizza MACRO predefinite per i compiti comuni e ripetitivi, risparmiando tempo e fatica.
- Provare le tue RULE in tempo reale per assicurarti che funzionino perfettamente.
- In caso di errore durante il test, un popup ti indicherà la riga e il tipo di errore per una risoluzione rapida e precisa.
- Esporta le tue RULE per inserirle nel file di configurazione e renderle permanenti.
- Attiva ogni tap-to-run o RULE con "Ehi Tuya, esegui ... "
- Controlla la navigazione nell'APP IoTwebUI: "Ehi Tuya, vai alle scene"
- Controlla la voce con la voce: puoi attivare il riconoscimento continuo oppure disattivarlo del tutto.
La modalità EXPERT offre un controllo totale sulla personalizzazione di IoTwebUI.
- Accedi alle interfacce di configurazione e apporta modifiche che saranno valide solo per quel run.
- Copia i dati dal "pad" di esportazione nei file di configurazione per rendere stabili le tue scelte.
- Puoi disattivare la modalità EXPERT nella configurazione quando hai finito di personalizzare.
-
IoTwebUI deriva da un'interfaccia analoga progettata per TuyaDAEMON.
-
La scelta della libreria di visualizzazione è caduta su Vis-Network per la buona flessibilità unita a semplicità di uso.
-
Un primo problema è il protocollo di sicurezza CORS, implementato sui moderni browser. Una applicazione (anche in js, node-red, etc) non ha questo problema, ma una APP che gira in un browser sì. E' necessario disabilitare CORS al memento del lancio del browser - testato Chrome (Versione 125.0.6422.61 - 64 bit):
chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security
(vedi filerun-me.bat
). Vale solo per questa istanza, le altre resteranno protette.
Come alternativa al file 'bat', con alcuni browser si può usare l'estensione 'Cross Domains - CORS', vedi ISSUE4. -
Con un Mac (IOS 10.11.6) ha funzionato la seguente riga di comando:
xxx:~ yyyy$ open -n -a /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --args --user-data-dir="/tmp/chrome_dev_test" --disable-web-security --disable-popup-blocking --auto-accept-camera-and-microphone-capture --app=file:///Applications/IoTwebUI/IoTwebUI.html
-
Tuya pone dei limiti alla frequenza degli accessi al cloud. IoTwebUI ne tiene conto, e la fase iniziale (quando legge tutti i dati dal Cloud) è bloccante e non brevissima (3-5 s, in funzione del numero di device). Come anche in SmartLife.
-
Un secondo problema è l'impossibilità di creare file direttamente da una pagina HTML, sempre per motivi di sicurezza. Per l'export dei dati sono ricorso ad una libreria di logging su file debugout.js. Per questo motivo il controllo sui file generati non è completo e sono necessari piccoli interventi manuali sui file esportati.
-
I file di datalog sono salvati nella dir
download
, con il nometuyalogDYYYYMMGGThhmmss.csv|json.txt
. -
Per lo stesso motivo non è possibile aggiornare dall'APP i file di configurazione. Ho scelto una soluzione di compromesso, che prevede l'intervento dell'utente con un semplice copia-incolla.
-
Sempre per problemi di sicurezza, può venire richiesta ogni volta l'autorizzazione all'uso del microfono: dipende dal browser e dalla configurazione; ma
run-me.bat
evita l'inconveniente. -
Il funzionamento continua regolarmente anche con la finestra del browser iconizzata.
-
Usare una sola istanza dell'APP, altrimenti si hanno problemi con i token Tuya.
Nei tooltip, che si aprono al passaggio del mouse su un'icona di device, sono presenti tutte le proprietà incluse nello 'status' del device, con i nomi ed i valori usati da Tuya Cloud. Alcuni valori possono essere codificati.
Alcune piccole icone forniscono ulteriori informazioni all'utente.Esempi (vedi figure sopra):
tuya_bridge.switch_1
è sotto osservazione per un 'alert'tuya_bridge.switch_inching
è un esempio di valore codificato ('AAAC
'). Decodificato è un oggetto:nota: Se siete interessati alla decodifica dei valori Tuya, molte funzioni sono state sviluppate per tuyaDAEMON (vedi 'core_device', nodo 'ENCODE/DECODE user library').{ "inching": false, "delay": 2 }
temperatura studio.va_temperature
è salvato sul datafile, insieme agli altri dati inlogList
.- Per il device
temperatura soggiorno
è scattato l'Alert (icona speciale) temperatura soggiorno.va _humidity
è la causa dell'Alert, ed è anche indicata la condizione (>40) che lo ha causato.- Il tooltip
termo studio
è customizzato, per presentare le temperature con i corretti decimali e unità. (nota: solo nel tooltip: Alert e RULE usano sempre il valore fornito da Tuya Cloud, i.e. 222 e 190). - In modo EXPERT sono aggiunti nei tooltip i seguenti valori:
isa
: nome del 'tipo' Tuya del device (in codice èdevice.category
). In totale circa 600 tipi.id
:device.id
, richiesto da alcuni HUB (e.g. TuyaDAEMON, Homebridge, HA, etc..).key
:device.local_key
, richiesto da alcuni HUB
I 'tap-to-run sono presentati per 'home' (max 100) nella apposita pagina, e poi in ordine alfabetico, come una serie di bottoni. I nomi dei 'tap-to-run' possono avere i seguenti vincoli:
- Limite di 3 parole se usati con i comandi vocali di IoTwebUI.
- Utilizare prefissi per raggruppare in IoTwebUI i comandi correlati.
- Essere facili da ricordare e da riconosere (se si usano i comandi vocali).
Un pad è dedicato alle 'user RULE' identificate con un nome: sono trattate come i 'tap-to-run': possono essere usate negli alert, oppure attivate con bottoni o tramite comando vocale, oppure lanciate da un altro RULE.
Naturalmente 'RULE' e 'tap-to-run' devono avere nomi unici per poter essere identificati.
E' possibile esportare su un file alcuni dati: l'utente deve specificare solo device
e status
(proprietà) per identificare i dati che interessano e questi sono salvati ad intervalli regolari (minimo 1 minuto) in un buffer interno (max 5000 records - pari a 80h @1 rec/min), esportato poi su file automaticamente o su comando utente.
L'utente può scegliere in configurazione tra due formati: CSV
(indicato, per esempio, per DB e spreadsheet tipo Excel) oppure JSON
(per elaborazioni più complesse con programmi ad hoc) con pochissimi interventi di editing sui file (vedi oltre i formati).
extra: In modalità EXPERT è disponibile nel menu un comando per avere nella console l'intera struttura dati ottenuta da Tuya Cloud ('Dump data'): può essere esplorata a ogni livello nel pad della console oppure può essere copiata con copy&paste in formato JSON.
In modo EXPERT cliccando su un device si apre un dialogo che nella parte inferiore permette la definizione degli 'Alert':
note:
- Se non si sceglie nessuna azione e si lascia vuoto 'message', l'azione di default è il cambio dell'icona del device e l'aggiornamento del tooltip, sempre eseguiti.
- Gli 'alert' non hanno, per semplicità, un filtro a tempo: se definiti sono attivi 24/7. Se occorre qualche condizionamento, è possibile creare RULE ad hoc ed attivarle dall'alert (nota: le RULE possono attivare le stesse azioni attivate dagli 'alert').
- Notare che 'connected' non è mai incluso nelle proprietà Tuya, e quindi non si possono definire 'Alert'. Ma è disponibile come MACRO nelle RULE.
- Avendo un solo messaggio, le regole di precedenza sono: SOUND() e URL (auto) sono esaminati per primi, poi Tap-to-run e RULE (auto), e solo per ultimo POP e VOICE (compatibili: lo stesso messaggio può essere usato per entranbi); Beep è sempre utilizzabile.
- Quindi, per avere sia 'pop' che 'tap-to-run', occerre creare due Alert con le stesse condizioni: in uno 'message' sarà il testo per il 'pop-up', nell'altro il nome del 'tap-to-run'.
- La visualizzazione dei pop-up può dipendere dalla configurazione del browser: usando 'run_me.bat' si ha un aggiornamento automatico della configurazione per la nuova istanza del browser. Azioni utente (e.g. bottoni) possono abilitare momentaneamente i pop-up.
Comunque, per non perdere informazioni, se i pop-up sono disabilitati per qualche motivo, il messaggio è presentato lo stesso in una finestra dell'APP: la differenza è che i pop-up possono essere molti, mentre la finestra è unica e viene riusata con un contatore. - Tutti gli Alert sono memorizzati e visibili nel 'registro Alert', dal menu principale.
Comandi:
- newTest - aggiunge un nuovo Alert (solo per il run corrente)
- clear dev - elimina tutti gli Alert del device (solo per il run corrente)
- config - apre pop-up per vedere le definizioni di tutti alert attuali.
Gli 'Alert' permanenti sono nel file `config.js`: possono essere editati direttamente oppure copiati da questo pop-up. - cancel - chiude il dialogo.
In modo EXPERT il menu presenta l'opzione "RULE page" che apre una pagina dedicata alla gestione delle RULE:
-
La disponibilità di questa funzione dipende dal browser usato.
-
Non è facile raggiungere l'efficienza che si ha con HW specializzato (smart speakers: Google, Alexa), perché il risultato dipende da vari fattori, tra cui ualità del microfono usato, le relative regolazioni, la riduzione dei rumori di fondo, etc... Nelle prove sono passato da oltre il 90% di riconoscimenti ad un pessimo 20%!
-
Molto importante è altresì la scelta delle parole chiave e dei nomi per 'tap-to-run' e 'RULE': per esempio 'nome tre parole' è di difficile riconoscimento, mentre 'accendi la luce' è facilmente riconosciuto.
Ritengo che questo dipenda dai modelli linguistici usati: sono più riconoscibili frasi corrette, con un significato comune, rispetto a parole isolate. Per esempio 'Tuya' è spesso confuso con 'Giulia'. -
La presenza di articoli e/o preposizioni facilita il riconoscimento.
-
Il comando vocale è opzionale, e può essere disabilitato nella configurazione.
-
Se abilitato, voiceRecognition può essere usata in due modi, o continuo oppure premendo un pulsante. Il modo di default è impostato in configurazione, ma può essere cambiato con comandi vocali.
-
la grammatica (italiana) di default è la seguente - tra parentesi (alle): parole opzionali; barra verticale a|su: parole alternative-:
- 'Ehi Tuya, esegui|attiva (la|un*) xxx ((la|un*) xxx ((la|un*) xxx))' => lancia 'tap-to-run' o RULE, nome max 3 parole nota sui nomi: parlando si possono aggiungere articoli o preposizioni (*) alle 3 parole, che quindi NON fanno parte del'nome' del 'tap-to-run' o 'RULE'. Esempio: "Hey Tuya, esegui accendi una luce" => nome: "ACCENDI LUCE"
- 'Ehi Tuya, (in|al) modo esperto' => apre EXPERT mode
- 'Ehi Tuya, (in|al) modo utente' => torna in USER mode
- 'Ehi Tuya, vai (alle*) scene' => navigazione alla pagina dei 'tap-to-run' e RULE
- 'Ehi Tuya, vai (alle*) regole' => navigazione alla pagina edit RULE (se in EXPERT mode)
- 'Ehi Tuya, vai (alla*) home' => navigazione alla pagina con albero device
- 'Ehi Tuya, ritorna|home' => navigazione alla pagina con albero device
- 'Ehi Tuya, modo (della*) voce continuo' => start del modo riconoscimento senza soste.
- 'Ehi Tuya, modo (della*) voce a|su richiesta|domanda' => start del modo riconoscimento con bottone.
- 'Ehi Tuya, basta voce' => stop del modo riconoscimento senza soste.
(*) nota: la lista di preposizioni ed articoli accettati ed ignorati in quarta e successive posizioni è molto lunga: 'il','lo','la', 'le', 'a', 'ad', 'ai', 'al', 'all', 'allo', 'alla', 'alle', 'di', 'del', 'della', 'dei','un', 'una', 'con', 'colla'
: scegliete quelle che facilitano il riconoscimento.
-
nota: L'implementazione tollera anche qualche imprecisione nel riconoscimento (e.g. 'Giulia' invece di 'Tuya', etc..): questo può essere facilmente customizzato. Vedi file speech21.js.
-
nota: Per una migliore comprensione, le frasi possono essere divise in due: "Ehi Tuya" + pausa: appare il feedback 'Ehi Tuya...' che conferma la comprensione della prima parte; ora può essere detta la seconda parte.
-
nota: la navigazione tra pagine è analoga al menu: dalla 'home' si può andare alle pagine 'tap-to-run' o 'edit RULE' (in modo EXPERT), ma da queste si può solo tornare alla 'home'.
nota: la richiesta di consenso all'uso del microfono dipende dal browser e dalla configurazione: usando 'run_me.bat' non dovrebbero esserci richieste.
NOTE sulla sicurezza
Per garantire la massima sicurezza, IoTwebUI opera esclusivamente in modalità di sola lettura, senza apportare alcuna modifica ai tuoi dati su Tuya Cloud.
Questa APP è totalmente aperta, priva di ogni protezione, e contiene nei file le vostre credenziali in chiaro!
NON rendetela accessibile dall'esterno o da terzi, altrimenti tutti i vostri dati, credenziali Tuya incluse, sono esposti!
-
2.1.1 Correzione bugs ISSUE10: Token scaduto. ISSUE11: refuso.
-
2.1 Miglioramento dell'esperienza utente:
- Aggiunto SpeechRecognition (file speech21.js) customizzabile
- Aggiunte RULE con 'nome', attivabili con bottoni e comandi vocali
- Aggiunte nuove MACRO
- Migliorata la funzione 'test': al termine ripristina il contesto in uso.
- Fallback: se i pop-up sono bloccati, gli avvisi sono mostrati in una finestra. Nessun messaggio perso.
- Aggiunta data al nome dei file di datalog.
-
2.0 Importante aggiornamento funzionale.
- Aggiunta la possibilità di attivare le scene "Tap-to-Run" di Tuya da questa APP.
- Aggiunto 'Avvisi' (Alert): controlla valori ed eseguire azioni (opzioni): segnale acustico, pop-up, messaggio vocale, apertura URL, esecuzione 'Tap-to-Run'
- Aggiunte "REGOLE utente" (RULE) per automazioni utente senza limiti (richiede competenze js di base)
- Aggiunto "Registro avvisi" (Alert register) per avvisi e regole
- Aggiunta interfaccia per la definizione dei dati da registrare sul file dataLog, con esportazione nella configurazione, per una facile manutenzione
- Aggiunta interfaccia per la definizione degli avvisi, con esportazione nella configurazione, per una facile manutenzione
- Aggiunta interfaccia per l'editing e il test delle regole al run-time, con esportazione nella configurazione, per una facile manutenzione
- Interfaccia ridisegnata con Bootstrap 5.3, fluida e con modalità chiara/scura, per una migliore esperienza utente
- Menu dinamico a scomparsa, per avere il massimo spazio a disposizione del grafo.
-
1.2 Aggiornamento funzionale.
- Aggiunta in 'config' la possibilità di escludere alcune 'home'
- Introdotti due modi: normale | expert
- Il DUMP dei dati Tuya in console è possibile solo in modo expert
- In modo 'expert' sono aggiunti al tooltip 3 nuovi dati (se disponibili)
-
1.1 Correzione bugs
-
1.0 Versione iniziale
- Scaricare e dezippare il file
IoTwebUI.x.x.zip
in una dir (con le autorizzazioni richieste dal S.O.). - Eseguire le operazioni di configurazione (vedi oltre).
- Il file principale è
IoTwebUI.html
. NON è necessario un server WEB, in quanto il codice è tutto in javaScript, eseguito dal browser. Per lanciarlo vedi filerun_me.bat
(per Windows - Chrome). Per altri S.O. creare uno script analogo. (Ignorare il messaggio Chrome: "stai utilizzando una segnalazione della riga di comando non supportata: - disable-web-security...": non supportata ma funzionante).
nota: L'addon "Cross Domain - CORS" sembra risolvere il problema CORS senza file BAT, vedi ISSUE4. - In fase di installazione e setup è utile la console (nel browser - strumenti per programmatori -, o menu contestuale 'ispeziona') perchè lì vanno i messaggi di informazione e di errore di IoTwebUI.
Nelle immagini: a sinistra avvio OK (Chrome, CORS disattivato) a destra in caso di errore CORS (Opera):
L'app IoTwebUI non è per utenti alle prime armi, pertanto è accettabile che la configurazione avvenga direttamente editando un file (config
.js). Le solite avvertenze: fare una copia del file prima di ogni modifica, usare un editor UTF8 (io uso Notepad-plusplus), e attenzione a NON ALTERARE niente altro (soprattutto virgole ',' ed apici '"' e "`").
-
I dati INDISPENSABILI da inserire sono le proprie
credenziali Tuya
per la 'platform.tuya'.
Gli utenti di tuyaDAEMON, Homebridge, HA ed altri hub simili dovrebbero già averle, ma i nuovi utenti si devono iscrivere, ci sono molte guide nel web. Questa è una delle più chiare, altre sono elencate qui. Un vantaggio è che così si ha accesso alla piattaforma Tuya, con molti dati sui propri device, ed alla documentazione tecnica. -
E' altresì INDISPENSABILE aggiornare la var 'data_center' in funzione di quello usato al momento di installazione di Tuya/SmatLife. Su 'SmartLife/me/Configurare/Account e sicurezza' trovate la Regione (e.g, Italia), e in questa guida: https://github.com/tuya/tuya-home-assistant/wiki/Countries-Regions-and-Tuya-Data-Center trovate l'URL corrispondente. Come alternativa potete accedere su
platform.tuya.com
, selezionare 'Cloud' e 'open project'. Ora selezionare il tab 'devices' e in alto a dx trovate il data-center che avete usato. Poi in: 'Tuya documentation' - 'Cloud Development > API Request > Request Structure': trovate l'elenco degli 'endpoints' (URLs). -
Altre opzioni riguardano: timing (Cloud e log) e configurazione del log: il formato, l'autosave, i valori richiesti, oppure il look&feel, come la presenza dei bottoni di pan/zoom.
Dalla versione 1.2 la possibilità di escludere alcune home (hide_homes
array), e dalla versione 2.0 quella di escludere alcuni tap-to-run (hide_scenes
array). -
Le opzioni disponibili per il riconoscimento vocale sono (sempre in config.js):
- se con il vostro HW funziona male, potete disabilitarlo del tutto:
SpeechRecognitionEnabled = false;
- se invece vi funziona bene, potete eliminare la necessità di premere il pulsante ogni volta:
SpeechRecognitionNeverEnds = true;
.
- se con il vostro HW funziona male, potete disabilitarlo del tutto:
-
Ancora in
config.js
, la variabileexpertModeEnabled = false
permette di disabilitare del tutto il modo 'EXPERT'. -
Dalla versione 2.0 le definizioni per 'dataLog' (
logList
inconfig.js
), 'Alert'(testList
inconfig.js
) e RULE (usrRules
inusrrulesXX.X.js
) possono essere create nella APP, con semplici interfacce utente, e poi esportate per essere copiate nei rispettivi file. -
Aggiornare con i path del sistema ospite il file di lancio
run_me.bat
, per lanciare Chrome con una configurazione ottimizzata.
Il IoTwebUI è OpenSource, in HTML+Javascript, è abbastanza documentato e modulare. Quindi è possibile ogni intervento.
Alcune aree sono state privilegiate e le rispettive funzioni poste per semplicità in file separati -custom.js
e usrrulesXX.X.js
con dettagliate istruzioni ed esempi:
- Tuya non permette più di cambiare le icone, per una opinabile interpretazione dei suoi consulenti legali delle attuali leggi sul copyright.
Per questa APP, invece, ho scelto le iconeawesome4
, con un'ampissima scelta e di libero uso. Di default tutti i device hanno la stessa icona, un cubo.
Ma sono facilmente personalizzabili dall'utente: basta fornire un criterio di selezione dei device e l'indicazione dell'iconaawesome4
da usare. Come esempio, hanno icone speciali (vedi immagini):- i Termometri (device con nome 'Temp...').
- le Valvole termostatiche (device con nome 'Termo...').
- i Gateway (device con 'Gateway' nel nome).
Anche l'icona speciale che indica un'alert è customizzabile: vedi alertIcon
in 'config.js'.
-
Il contenuto dei tooltip, varia a seconda del device. E' un settore dove è utile la possibilità di personalizzazioni, il metodo scelto (un filtro) permette ogni libertà:
- Alcuni valori sono criptati: si può scegliere di non farli vedere - oppure di decodificarli; il codice necessario è disponibile in TuyaDAEMON, ma ho scartato questa opzione sia perchè sono di solito dati di configurazione gestiti da SmartLife, sia per non avere tooltip troppo grandi.
- In altri casi occorre dividere per 10 o 100 per avere il valore in unità SI.
- Come sviluppatore preferisco avere i nomi delle proprietà originali Tuya, ma si possono rendere più frendly traducendoli.
- Se si desidera si possono anche aggiungere nuove informazioni per esempio derivandole da quelle del device (e.g. temperatura sia in °C che in °F).
-
Per i 'tap-to-run' Tuya, è possibile personalizzare il colore dei pulsanti modificando
sceneColor(scene)
incustom.js
. -
Per le RULE, i più avventurosi possono aggiungere le loro MACRO personali nel file
usrrulesXX.X.js
. -
Per VoiceRecognition, nel file "speech0X.X.js" è semplice modificare le parole della grammatica proposta: esempio sostituire 'vai' con 'raggiungi'. L'obiettivo deve essere sempre quello di migliorare la comprensione dei comandi.
-
L'adattamento del riconoscimento vocale ad altre lingue è complesso, e richiede profonda competenza della lingua sia nella grammatica che nel vocabolario. Mi affido alla collaborazione di utenti volenterosi. Da parte mia completerò l'intornazionalizzazione delle varie pagine dell'APP asap (ver. 2.2).
-
Un po' più complesso è aggiungere nuovi comandi vocali, non tanto per la definizione della grammatica (il codice attuale può servire da esempio) quanto l'implementazione delle azioni, che spesso dipendono dal codice esitente.
Direi che per nuovi comandi vocali, la strada migliore è fare una proposta di implementazione nelle 'issue', e, in base al consenso ed alla fattibibilità, potrebbe essere implementata nella release successiva.
Queste customizzazioni NON sono necessarie, ma redono più utile e gradevole l'uso di TuyaUIweb.
Questo è un esempio di file di log in formato CSV:
[date, time, ROMA.TF_frigo.va_temperature, ROMA.Temperatura studio.va_temperature]
[2024-05-17, 06:35:28, 71, 22]
[2024-05-17, 06:37:28, 71, 22]
... more ...
La prima riga contiene l'intestazione delle colonne, le righe succesive i dati. Le operazioni da fare sono le seguenti (in un editor ASCII, ad esempio Notepad++, con 'global find&replace'):
- Eliminare la parentesi quadra '[' all'inizio di ogni riga.
- Sostituire la parentesi quadra finale di ogni riga con un punto e virgola ';'.
Il risultato CSV corretto è il seguente, importabile in molti DB e spreadsheet:
date, time, ROMA.TF_frigo.va_temperature, ROMA.Temperatura studio.va_temperature;
2024-05-17, 06:35:28, 71, 22;
2024-05-17, 06:37:28, 71, 22;
... more ...
Questo è un esempio di file di log in formato JSON:
[{"home":"ROMA","device":"TF_frigo","status":"va_temperature","result":70,"day":"2024-05-17","time":"19:37:51"},
{"home":"ROMA","device":"Temperatura studio","status":"va_temperature","result":25,"day":"2024-05-17","time":"19:37:51"}],
[{"home":"ROMA","device":"TF_frigo","status":"va_temperature","result":70,"day":"2024-05-17","time":"19:39:51"},
{"home":"ROMA","device":"Temperatura studio","status":"va_temperature","result":25,"day":"2024-05-17","time":"19:39:51"}],
Notare che tutti i dati identificativi sono aggiunti ad ogni misura, ottenendo un risultato più verboso del caso CSV. L'operazioni da fare è la seguente (in un editor ASCII, ad esempio Notepad++):
- Aggiungere una coppia di parentesi quadre '[]' per racchiudere tutto il contenuto.
Il risultato JSON corretto è il seguente, utilizzabile con parser JSON per ricreare gli oggetti:
[
[{"home":"ROMA","device":"TF_frigo","status":"va_temperature","result":70,"day":"2024-05-17","time":"19:37:51"},
{"home":"ROMA","device":"Temperatura studio","status":"va_temperature","result":25,"day":"2024-05-17","time":"19:37:51"}],
[{"home":"ROMA","device":"TF_frigo","status":"va_temperature","result":70,"day":"2024-05-17","time":"19:39:51"},
{"home":"ROMA","device":"Temperatura studio","status":"va_temperature","result":25,"day":"2024-05-17","time":"19:39:51"}],
]
E' un array di array contenenti le singole misure (oggetti).
Il particolare ambiente in cui sono valutate le RULE comporta qualche limite alla sintassi JavaScript (js) standard:
- Le RULE sono esegute ciclicamente, dopo ogni pollig di dati dal Cloud Tuya, quindi ogni
TuyaInterval
(vedi config.js). Talora si hanno delle esecuzione extra, per esempio in occasione di attivazioni per nome delle RULE. - importante: il codice è eseguito una riga alla volta, non è possibile scrivere blocchi js che occuppino più righe! Per contenere la lunghezza delle righe, usare delle variabili volatili intermedie (vedi esempi).
- Definire le variabili volatili (valide per un solo run delle RULE) sempre con la sintassi: var
_tizio
=... , poi possono essere usate liberamente. - E' anche possibile definire più variabili contemporaneamente, Esempio
var _var1, _var2 = 0;
: sia_var1
che_var2
sono inizializzate a 0. - Per definire variabili permanenti (valide per tutti i run) usare le MACRO: VSET(name, value) e VGET(name).
- Usare sempre un underscore "_" come primo carattere nel nome delle variabili: si evitano così interferenze con altre variabili del programma. Non usare caratteri 'strani' nei nomi delle variabili: meglio limitarsi a [A..Za..z0..9] e '_'.
- Il 'punto e virgola' ";" a fine riga è opzionale, ma consiglio vivamente di usarlo sempre.
- JavaScript è 'case sensitive', cioè distingue tra Maiuscole e minuscole, quindi attenzione a scrivere le variabili sempre nello stesso modo (consiglio tutte minuscole, oppure la tecnica 'camel' per i nomi compositi:
_variabilePocoUsata
) per distinguerle a colpo d'occhio dalle MACRO (sempre MAIUSCOLE). - Valori predefiniti:
true
(vero) efalse
(falso) per le condizioni; le costanti numeriche sono con il punto, all'inglese (3.14
). Tutte le stringhe vogliono gli apici ("oggi "
oppure'domani '
). Un apice può essere inserito in una stringa se si usa l'altro tipo di apice per tutta la stringa. Esempio:"All'alba "
OK ,'Disse: "sono stanco"'
OK, ma NON'All'alba'
!. - Usare // per i commenti, continuano fino a fine riga
- Le operazioni js più utili sono quelle aritmetiche (+, -, *, /), quelle logiche per le condizioni: (&& -and, || -or, ! -negazione) e le operazioni di confronto ( >, ==, !=, <, >=, <=); la concatenazione delle stringhe è fatta semplicemente con il + ("ore " + "10:30").
- Non confondere '=' (assegnazione - effetto: il contenuto della variabile a sx è modificata), con '==' (confronto - risultato: true (uguali) o false (diversi)). Esempio:
var _pippo = 32;
eif (_pippo == 32)...
( NB:if(_pippo = 32)
è un errore comune ma insidioso, difficile da trovare e correggere) - Nota: La condizione opposta (negata) di 'uguale'
(a == b)
è 'diverso'(a != b)
. La condizione opposta (negata) di 'maggiore'(a > b)
NON è 'minore'(a < b)
bensì è 'minore o uguale'(a <= b)
! Analogamente l'opposto di(a < b)
è(a >= b)
. - Attenzione al '+'. In
a + b
, sea
eb
sono numeri, fa la somma, ma se uno dei due è una stringa non convertibile in numero, automaticamente anche l'altro è convertito in stringa. E la conversione 'numero => stringa' può portare a sorprese (cioè a molte cifre decimali) quando non sono numeri interi! Usare sempre ROUND() quando dovete aggiungere dei numeri con la virgola nelle stringhe Esempio:
var _tf = GET("TF_frigo","va_temperature"); // read temperature sensor, saves it in _tf (number)
var _tm = AVG(_tf, 12); // get average from last 12 values (_tm is a string, see AVG())
var _tr = ROUND( _tm/10, -1); // round to the nearest ten, _tr is a string
if(TRIGEVERY(8)) POP( "FRIGO", "Frigo: "+ ROUND(_tf/10, 1) + "°C, media: "+ ROUND(_tm/10, 2) +"°C, round: " + _tr +"°C");
// note: using ROUND() to convert to string, also for _tm/10 (again number)
DATALOG("frigo.media", _tm/10); // saves average on file (saved as number).
-
Come già detto, JavaScript è elastico a proposito delle conversioni dei valori: numeri in formato 'stringa' (cioè "3.14" invece di 3.14 o Math.PI) sono convertiti automaticamente in numeri in caso di operazioni aritmetiche. Ancora, numeri e stringhe sono convertiti in valori logici quando serve (ad esempio se usati come condizione in un
if()
). Regole: zero (0) valefalse
, qualsiasi altro numero:true
. Una stringa vuota ("") onull
, oundefined
valgonofalse
, qualunque altra stringa valetrue
. Esempi:if ("caio")...
è true.var _test = null; if(_test)...
è false. (nota. Meglio non abusare di questi automatismi del linguaggio, è preferibile scrivere sempre le condizioni estese, più chiare:if (_test != null)
...) -
importante è anche l'uso delle parentesi, "()", sempre a coppie. Parentesi sono obbligatorie dopo ogni MACRO - nota, anche se non ci sino parametri, e.g.
BEEP()
- e dopo unif()
, per racchiudere la condizione. Comunque usatele liberamente per raggruppare i risultati intermedi nelle espressioni e.g.if((_a > 10) && (_b/2 == 0))...
-
Molte MACRO devono conservare lo stato tra un run ed il successivo, (e.g AVG(), MAX() etc...) e sono individuate con (*).
-
Il costrutto js più utile nelle RULE è l'if() (esecuzione condizionale), che assume varie forme:
if(condizione
)azione;
//azione
è eseguita solo secondizione
è vera
if(condizione
)azione1
,azione2;
// due (o più) azioni, separate da ',' virgola.
if(condiz1 && condiz2 && ...
)azione;
// AND: 'tutte',condiz1
econdiz2
e ... devono essere vere contemporaneamente.
if(condiz1 || condiz2 || ...
)azione;
// OR: 'almeno una',condiz1
oppurecondiz2
, oppure ... deve essere vera.
if (condizione
)azione1
elseazione2;
// esegueazione1
(se vero) oppureazione2
(se falso).
nota: contrariamente alle automazioni Tuya, Google, Alexa, che nelle condizioni permettono o solo AND (tutte) o solo OR (basta una) (e poi cercano di mitigare questo limite aggiungendo l'extra condizione 'ambito' - e.g. Tuya) nelle RULE si possono avere condizioni più complesse (miste) usando con cura le parentesi per indicare l'ordine di calcolo: esempio: if ( (condiz1 || condiz2) && (condiz3 || condiz4) ) - a parole: "deve essere vera almeno una tra (condiz1, condiz2) ED anche almeno una tra (condiz3, condiz4)". -
Se una
condizione
è vera a lungo (livello), unif()
sarà eseguito più volte, ad ogni ciclo. Per evitare questo le macro TRIGGER sono vere per un solo ciclo, il primo, e poi sono false. -
nota sui messaggi di errore: Non sempre i messaggi di errore identificano la VERA causa del problema. Esempio, una variabile mal scritta è trovata subito come 'non definita', ma una parentesi non chiusa, può portare a messaggi poco chiari righe dopo, quando il compilatore trova un problema! Quindi attenzione!
-
importante: per come sono implementate, le MACRO che usano memoria (*) devono essere eseguite ad ogni run: quindi NON possono essere presenti nella parte
azione
di un if(). Per ragioni analoghe non sono ammessi if nidificati (un if() nella zona azione di un altro if(): non potrebbe usare le MACRO (*)). Sono vincoli che non pongono, però, serie limitazioni.
ESEMPIO - Un caso concreto di controllo del riscaldamento
Ho il riscaldamento centralizzato, con valvole termostatiche su ogni radiatore: ogni stanza ha il suo profilo di temperatura desiderato (Ttarget). Tutto funziona molto bene, tranne in casi eccezionali (esempio, impianto spento per manutezione).
Vorrei implementare con Tuya una strategia di questo tipo: se la temperatura ambiente è minore di un 'tot' rispetto al Ttarget, accendere il condizionatore come pompa di calore impostando come temperatura proprio Ttarget. Cioè:
Se (( Ttarget - Tambiente ) > tot) => clima.warm( Ttarget )
Questa strategia NON è realizzabile con le 'automazioni' di Smartlife, nè con Alexa o Google o HomeKit..., per diversi motivi:
- nelle automazioni non si possono usare operazioni aritmetiche,
- i confronti, nelle automazioni, si possono fare solo con valori costanti,
- non esistono tap-to-run parametrici od almeno con nomi dinamici.
Chiedo troppo? Un sistema 'open' dovrebbe permettere queste automazioni. O no? Infatti con IoTwebUI e le RULE si può fare!
Vediamo come l'ho realizzata. Alcune precondizioni: la mia termovalvola ('Termo letto') ha le proprietà 'temp_set' e 'temp_current'.
Per semplicità ho utilizzato come temperatura Target solo i valori 16, 20, 21 °C: in questo modo mi occorrono solo 3 tap-to-run chiamati Tletto16, Tletto20 e Tletto21, per accendere ed impostare il climatizzatore alle temperature volute.
Ecco le RULE necessarie, dove uso alcune variabili intermedie per ridurre la complessità. La macro ISTRIGGERH() è vera una sola volta, quando la condizione passa da falso a vero (vedi oltre), ROUND() arrotonda un numero e lo trasforma in testo, per formare le stringhe "TLetto16","TLetto20",... cioè il nome del 'tap-to-run', che così ora dipende da Ttarget. L'accensione è anche memorizzata nel 'registro degli Alert'.
var _tot = 2.3; // da tarare il prossimo inverno
var _Ttarget = GET("Termo letto", "temp_set") ; // varia a seconda dell'orario
var _nowClima = ISTRIGGERH( ( _Ttarget - GET("Termo letto", "temp_current") ) > _tot); // condizione
if (_nowClima) SCENA("TLetto" + ROUND( _Ttarget, 0) ), ALERTLOG("RULE Tletto", "acceso clima") ; // esecuzione
nota: i nomi dei tap-to-run come 'TLetto16' sono impossibili da usare con il riconoscimento vocale, ma servono così per poterli gestire dinamicamente. Se utile, basta creare dei 'tap-to-run' con nomi semplici come alias, tipo 'riscaldamento camera letto', che si limitano a utilizzare quelli con i nomi irriconoscibili.
Tutto sommato semplice, nevvero? Secondo i progettisti di APP per domotica (tutti: si copiano l'un l'altro le prestazioni) noi utenti siamo solo in grado di gestire " Se .... Poi ....". Che mancanza di fantasia e fiducia!. Che poi, avere a disposizione strumenti sofisticati, non vuol dire essere obbligati ad usarli! Se non si devono usare, meglio. Ma quando servono le RULE sono lì, pronte a risolvere i nostri problemi.
Volete fare delle prove ma non sapete da dove cominciare? Consiglio di copiare le seguenti 3 RULE nell'area di edit delle RULE (modo EXPERT), e poi premere TEST.
- Nella pagina tap-to-run, tab 'user RULE' trovate tre nuovi bottoni: 'spegni luce'. 'Pippo' e 'chiamata Pippo': potete verificare il funzionamento delle tre RULE.
- Attivate il 'comando vocale', e provate "Ehi Tuya, esegui Pippo", "Ehi Tuya, esegui spegni la luce" "Ehi Tuya, esegui una chiamata per Pippo"...
if (TRIGBYNAME('spegni luce')) VOICE ("Fatto: 'spegni la luce'");
if (TRIGBYNAME("Pippo")) POP ("Test", "Trovato Pippo");
if (TRIGBYNAME("chiamata Pippo")) TRIGRULE("Pippo"), VOICE("chiamo Pippo");
le MACRO rispondono a varie esigenze:
- Fornire accesso alle risorse e funzionalità di IoTwebUI, per poterle usare nelle RULE
- L'ambiente (run ripetuti ad intervalli regolari) e i suoi limiti (codice in una sola riga) rendono più ardua la scrittura di funzioni complesse: le MACRO semplificano il compito dell'utente.
- Alcune operazioni richiedono la memorizzazione di informazioni tra un run ed il successivo, e le MACRO (*) risolvono questo problema, senza ricorrere esplicitamente a VSET() VGET().
- Importante è la distinzione tra un livello - lo stesso valore (e.g. true) uguale per più run, generato, per esempio, da un confronto - e un TRIGGER - vero per un solo run, quando inizia o finisce un evento -: Le macro con TRIG nel nome generano TRIGGER, le altre generano LIVELLI.
nota: questa selezione iniziale di MACRO è naturalmente condizionata dalle mie abitudini ed interessi: in questo settore il contributo di altri utenti è prezioso.
Possiamo dividere le MACRO in due gruppi: il primo che gestisce le interazioni con le risorse disponibili in IoTwebUI (una sorta di API interna). Il secondo gruppo di MACRO sono invece generali, modificando in qualche modo utile i dati in input o fornendo utili output.
nota: obiettivo delle MACRO non è quello di duplicare le funzionalità delle automazioni Tuya (anche se a volte c'è sovrapposizione), quanto quello di fornire strumenti più avanzati di calcolo, per ottenere 'automazioni' fin'ora impossibili. L'uso di device virtuali e di tap-to-run permette di suddividere i compiti tra scene Tuya (automazioni e tap-to-run) e RULE nel modo più efficiente.
Ovviamente si possono sempre aggiungere nuove MACRO, o come customizzazione (se create nuove MACRO comunicatemelo) oppure in nuove release di IoTwebUI (segnalatemi le vostre esigenze su GitHub, nelle ISSUE).
- ISCONNECTED(device)
- Ritorna 'true' se il device (nome o ID) è connesso.
nota: il dato proviene dal Cloud, può differire dal valore locale mostrato da SmartLife.
Esempio:if (! ISCONNECTED("Tuya bridge")) VOICE ("Attenzione! 'tuya bridge' attualmente disconnesso");
- GET(device, property)
- Ritorna il valore di 'property' (usare i nomi originali mostrati nei tooltip) del device (nome o ID)
Esempio:var _tf = GET("TF_frigo","va_temperature");
- DATALOG(name, value) (*)
- Aggiunge un nuovo 'value' al file di log dati, con il 'name' indicato. Utile per salvare risultati di elaborazioni (e.g. medie). Questa MACRO 'prenota' il salvataggio di un valore, ma il salvataggio avviene con i tempi e i modi impostati in config per il file log dati.
nota: il salvataggio dati durante un test inizia subito, ma, nel formato CSV, la prima riga con i nomi è già stata creata e non è aggiornata. Eventualmente salvare il file di log per avere un nuovo file aggiornato. Questo solo in fase di test: con le RULE in uso dall'avvio non c'è problema.
Esempio:DATALOG("Temperatura Frigo", GET("TF_frigo","va_temperature")/10);
- ALERTLOG(name, message)
- Aggiunge il 'message' al registro degli avvisi, identificato da 'name'.
Esempio:if(ISTRIGGERL(GET("tuya_bridge", "switch_1"))) ALERTLOG("tuya_bridge", "Aperto adesso");
> - BEEP()
- Segnale di avviso.
Esempio:if(GET("TF_frigo","va_temperature") > 100) BEEP();
- POP(device, message)
- Segnale di avviso.
Esempio:if(ISTRIGGERH(GET("TF_frigo","va_temperature") > 100)) POP("Frigo", "TEMPERATURA oltre 10°C" );
- XURL(url)
- Apre un URL nel browser.
Esempio:XURL("https://www.google.com/");
- REST(url)
- Per servizi web API REST (GET) che tornano come risposta un testo semplice.
Esempio:// see https://www.ipify.org/
if(TRIGBYNAME("my IP")) POP( "My IP", REST("https://api.ipify.org/?format=txt")); - RESTJSON(url)
- Per servizi web API REST (GET), che forniscono la risposta in formato JSON (la maggior parte). Questa funzione restituisce, per semplificare l'uso, direttamente un oggetto.
Esempio:// see https://open-meteo.com/
var _meteo, _urlm ="https://api.open-meteo.com/v1/forecast?latitude=41.9030&longitude=12.4663¤t=temperature_2m";
if(TRIGBYNAME("meteo")) _meteo = RESTJSON(_urlm), POP("ROMA", "temperatura = " + _meteo .current.temperature_2m );
nota: questa è la struttura completa dell'oggetto-risposta (_meteo
), che si può vedere in console con'console.log(_meteo)'
. Si è utilizzata in POP() solo la temperatura (_meteo.current.temperature_2m
):current: interval: 900 temperature_2m: 33.7 time: "2024-06-20T17:00" current_units: interval: "seconds" temperature_2m: "°C" time: "iso8601" elevation: 15 generationtime_ms: 0.01800060272216797 latitude: 41.9 longitude: 12.469999 timezone: "GMT" timezone_abbreviation:"GMT" utc_offset_seconds: 0
- VOICE(message)
- Segnale di avviso.
Esempio:if (! ISCONNECTED("Tuya bridge")) VOICE ("Attenzione! 'tuya bridge' attualmente disconnesso")
- SOUND(url)
- Riproduce musica o messaggio audio: formato MP3 o WAV.
_Esempio:_SOUND("https://assets.mixkit.co/active_storage/sfx/918/918.wav");
- SCENE(scenaNome)
- Esegue un 'tap-to-Run', presente nell'elenco letto dal Cloud.
Esempio:if(ISTRIGGERH(_alarm)) SCENE('sirena suona');
- TRIGRULE(name)
- Esegue un RULE individuato da un nome.
nota: Se la definizione TRIGBYNAME(name) precede l'uso di TRIGRULE(name), l'esecuzione non è immediata, ma avviene subito dopo il termine del run attuale delle RULE, in un run EXTRA.
Esempio:if (TRIGBYNAME("pippo")) VOICE (" Trovato pippo");
// RULE 'pippo' if (TRIGBYNAME("chiama pippo")) TRIGRULE("pippo"), VOICE("chiamo pippo") // RULE 'chiama pippo'
- ISTRIGGERH(condition) (*)
- Ritorna 'true' solo al passaggio della "condizione" da 'false a true', evita che la "condizione" 'true' agisca ad ogni run. Ovvero trasforma un livello true in TRIGGER (vedi figura).
Esempio:if(ISTRIGGERH(GET("TF_frigo","va_temperature") > 100)) POP("Frigo", "TEMPERATURA oltre 10°C" );
Nota: l'implementazione Tuya di più condizioni (livelli) in AND (tutte) in una automazione è come se fosse scritta così:
if( ISTRIGGERH(condiz1 && condiz2 && ...) ...
cioè un'automazione Tuya scatta nel momento in cui TUTTE le condizioni diventano true. Con più condizioni in OR, basta UN trigger:
if( ISTRIGGERH(condiz1) || ISTRIGGERH(condiz2) || ...) ...
.
Nota: più condizioni (livelli) + ambito (livello) + abilitazione delle automazioni Tuya, può essere implementato nelle RULE così:
if( (ISTRIGGERH(condiz1...) ...) && (ambito...) && abilitata)...
.
Si vede come Ambito NON intervenga nel TRIGGER ma che comunque DEVE essere vero! - ISTRIGGERL(condition) (*)
- Ritorna 'true' solo al passaggio della "condizione" da 'true a false' (inverso di ISTRIGGERH): trasforma un livello false in TRIGGER.
Nota: l'uscita è invertita rispetto a 'condizione' (vedi figura).
Esempio:if(ISTRIGGERL(GET("tuya_bridge", "switch_1"))) ALERTLOG("tuya_bridge", "Aperto adesso");
- CONFIRMH(condition, time) (*)
- Ritorna 'true' solo se la "condizione" rimane 'true' per almeno il tempo 'time'. Poi resta 'true' fino a quando la 'condizione' è 'true'. Caso tipico una porta aperta. Serve a filtrare 'livelli' true di breve durata che non interessano (vedi figura).
time = costante nei formati "hh:mm:ss" oppure "mm:ss" oppure "ss". Lmite inferiore: TuyaInterval.
Esempio:
var _doorev = GET("Sensore porta", "doorcontact_state") ;
// true a porta apertaif(ISTRIGGERH( CONFIRMH(_doorev, "01:20"))) VOICE("chiudere la porta, grazie");
- CONFIRML(condition, time) (*)
- Ritorna 'true' solo se la "condizione" rimane 'false' per almeno il tempo 'time' (inverso di CONFIRMH): Serve a filtrare 'livelli' false di breve durata che non interessano.
Nota: l'uscita è invertita rispetto a 'condizione' (vedi figura).
Esempio:if(ISTRIGGERH(CONFIRML(ISCONNECTED("relay"), "02:30"))) VOICE("Allarme disconnessione");
- TRIGCHANGED(value) (*)
- ritorna 'true' ogni volta che 'value' cambia rispetto al valore precedente.
Esempio:var _tf = GET("TF_frigo","va_temperature");
var _annonce = "Alle ore " + TIME(hrs)+" la temperatura è cambiata. Il frigo è a " + ROUND(_tf/10, 1) + " gradi";
if(TRIGCHANGED(_tf)) VOICE(_annonce); - TRIGEVERY(n) (*)
- Semplice timer: ritorna 'true' solo dopo "n" esecuzioni, ciclico.
E' garantito un singolo valore 'true' per ogni n-simo loop, 'n' è in numero di loop, in tempo: t <= n x tuyaInterval (definito in 'config.js' file).
Esempio:if(TRIGEVERY(8)) POP( "FRIGO", "Temperatura interna: "+ ROUND(_tf/10, 1) + "°C");
- TRIGBYNAME(name)
- Associa un 'nome' (max 3 parole) ad un RULE, permettendo di attivarlo con un comando utente (bottone o comando vocale) o in caso di 'Alert', oppure con TRIGRULE(name) da un'altra RULE (analogo ai 'tap-to-run' Tuya).
Torna true quando deve essere eseguita.
Esempio:if (TRIGBYNAME('spegni la luce')) VOICE (" Hai attivato: 'spegni la luce'")
- VGET(name)
- GET di una variabile permanente - conservata per tutti i run delle RULE.
Se la variabilename
NON è stata inizializzata con un VSET, ritornanull
.
Esempio:if( VGET('inizio') == null ) VSET('inizio', TIME(hrs));
- VSET(name, value)
- SET di una variabile permanente - conservata per tutti i run delle RULE.
Esempio:if( TRIGEVERY(10) ) VSET('prova', VGET('prova') + 2);
- ROUND(number, pos)
- Torna una stringa con 'pos' cifre decimali (se 'pos' >0)
oppure un numero intero ('pos' = 0)
oppure un numero intero con zeri ('pos' < 0)
Esempi:'ROUND (123.567, 2)' => "123.57"; 'ROUND(123.567, 0)' => "124"; 'ROUND(123.567, -2)' => "100";
- ADDCOUNT(event, restart) (*)
- Quando restart è true ritorna il totale di volte che event è stato true, altrimenti torna
null
, Può essere usato in due modi: se 'event' è un TRIGGER conta il numero di volte. Altrimenti, se è un 'livello' valuta la durata dello stato vero (come il duty cycle). Esempio:var _tot = ADDCOUNT(ISCONNECTED("HUB_zigbee"), TRIGEVERY(100));
if (_tot) POP("Affidabilità", "L'HUB Zigbee è stato connesso il "+ _tot +"% del tempo");
- HYSTERESIS (value, test, delta) (*)
- Confronta 'value' con 'test', usando come intervallo di isteresi 'delta'. L'output diventa 'true' se 'value > test + delta/2', oppure 'false' se 'value < test - delta/2'.
Esempio:if(ISTRIGGERH(HYSTERESIS(GET("T_letto","va_temperature"), 320, 10))) SCENA("Condizionatore ON");
- AVG(value, n) (*)
- Media mobile degli ultimi 'n' valori: torna una stringa con 2 decimali.
'n' è in numero di loop, in tempo: t = n x tuyaInterval (definito in 'config.js' file).
Esempio:DATALOG("Temperatura media Frigo", AVG(GET("TF_frigo","va_temperature")/10, 20));
- MAX(value, n) (*)
- Ritorna il più grande degli ultimi 'n' valori.
'n' è in numero di loop, in tempo: t = n x tuyaInterval (definito in config.js file).
Esempio:var _Tmax = MAX(GET("TF_frigo","va_temperature")/10, 1440);
(24h = 1440 min) - DERIVATIVE(value) (*)
- Ritorna la derivata (meglio: il rapporto incrementale) di value.
Esempio:if (DERIVATIVE(GET("TF_frigo","va_temperature")) > 0) VOICE("Temperatura Frigo crescente");
Esempio: per valutare la bontà dei calcolivar _integ = INTEGRAL(1, 300); var _deriv = DERIVATIVE(_integ); console.log ( _integ , _deriv);
- INTEGRAL(value, limite) o INTEGRAL(value)(*)
- Ritorna l'integrale (meglio: la somma integrale) di value. Limite è opzionale, e riporta a 0 l'integrale quando è raggiunto.
nota: E' possibile usareINTEGRAL
per creare timer più precisi diTRIGEVERY()
che si basa sul conteggio dei cicli.
L'integrale di una costante è una retta crescente: usando 1 come costante, e unlimite
in secondi, si ha un'andamento a denti di sega. L'integrale vale 0 all'avvio e poi ognilimite
secondi (errore: 0..+TuyaInterval) con ottima precisione. Questo esempio è un timer periodico di durata 1h:var _integ = INTEGRAL(1, 3600); if (_integ == 0) ...more...
- TIME(wath)
- ritorna una stringa, "hh:mm:ss" oppure "mm:ss" oppure "ss" calcolata dall'ora attuale, a seconda di 'wath'.
'wath': una delle costanti così definite: hrs = 11, min = 14, sec = 17 (senza apici, non sono stringhe).
Esempio:var _message = "Alle ore " + TIME(hrs);
- DAYMAP(val1, time1, val2, time2, ... more)
- Programmazione giornaliera, ritorna un valore che varia nel tempo: fino a 'time1' l'output è 'val1', da 'time1' a 'time2' l'output è 'val2'... avanti così fino all'ultimo 'time' dopo di che l'output è di nuovo 'val1'.
Naturalmente i valori 'val' e 'time' devono essere presenti a coppie, tanti quanti ne servono. Tutti i 'time' in formato "hh:mm:ss".
Usi: profili di temperatura giornalieri, eventi ad orario o abilitazione per intervalli di tempo, etc., a seconda se 'val' sono temperature, oppure 'buongiorno'/'buonasera', oppure true/false, etc..
Esempio:if(DAYMAP(false,"12:30", true, "14:00")) BEEP();
- WEEKMAP(map)
- Programmazione settimanale: 'map' è una stringa di sette caratteri qualsiasi, uno per giorno della settimana, partendo dalla Domenica (e.g.: 'DLMMGVS' o 'SMTWTFS' o '1234567'). Solo se il carattere corrispondente ad oggi è '-' (trattino) ritorna 'false' altrimenti torna 'true'.
Esempio:WEEKMAP("DLMM-VS")
è falso solo ogni Giovedì. - YEARMAP(mese, giorno)
- Programmazione annuale: 'mese' e 'giorno' sono due stringhe di 12 e 31 caratteri qualsiasi, per identificare mesi e giorni (e.g.: 'GFMAMGLASOND' e '1234567890123456789012345678901'). Solo se il mese e il giorno di oggi sono '-' (trattino) ritorna 'false' (per 24h) altrimenti torna 'true'.
Esempio:YEARMAP( 'GFMAMGLASON-', '12345678901234567890123-5678901')
è falso solo a Natale.
input ed output di: ISTRIGGERH(evento), ISTRIGGERL(evento), CONFIRMH(evento, T), CONFIRML(evento, T)
(*): identifica le MACRO che fanno uso di memoria per salvare lo stato: NON usarle nella parte azione di un if())
Progetto OpenSource, Licenza MIT, (c)2024 marco sillano
Questo progetto è un work-in-progress: viene fornito "così com'è", senza garanzie di alcun tipo, implicite o esplicite.
- Se sviluppate qualche estensione o applicazione interessante con IoTwebUI fatemelo sapere: possiamo inserirla qui, o nella prossima release.
- Per problemi riguardanti il codice ed il funzionamento di IoTwebUI, aprite un 'issue' qui (github).
- Per problemi più generali riguardanti Tuya, SmartLife (Tuya smart) e IoTwebUI, che possono interessare anche altri utenti, postate pure nel gruppo Tuya e Smart Life Italia
Grazie per l'interesse
m.s.
Tutti i marchi riportati appartengono ai legittimi proprietari.