Bentornato nel secondo esperimento della rubrica “Raspberry Pi, la domotica con Node-Red” . Hai fatto i compiti per casa del precedente articolo?
Per partire tutti con lo stesso progetto, che ne dici di aprire il menu import-> selezionare new flow ed incollare questo.
[{"id":"b313a11e.083d4","type":"tab","label":"Gestione Rpi","disabled":false,"info":""},{"id":"3b9b99af.191326","type":"tab","label":"Giardino","disabled":false,"info":""},{"id":"410cbd5e.a67d54","type":"tab","label":"Camere","disabled":false,"info":""},{"id":"a56bea5e.7d34e8","type":"tab","label":"Cucina","disabled":false,"info":""},{"id":"3d5177aa.ced968","type":"tab","label":"Soggiorno","disabled":false,"info":""},{"id":"6958a417.a71d7c","type":"tab","label":"Garage","disabled":false,"info":""},{"id":"ec5c73e5.37c23","type":"tab","label":"Ingresso","disabled":false,"info":""},{"id":"9f6c0c56.d3882","type":"ui_base","theme":{"name":"theme-dark","lightTheme":{"default":"#0094CE","baseColor":"#0094CE","baseFont":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif","edited":true,"reset":false},"darkTheme":{"default":"#097479","baseColor":"#04c0e1","baseFont":"Gill Sans,Geneva,sans-serif","edited":true,"reset":false},"customTheme":{"name":"Untitled Theme 1","default":"#4B7930","baseColor":"#4B7930","baseFont":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif"},"themeState":{"base-color":{"default":"#097479","value":"#04c0e1","edited":true},"page-titlebar-backgroundColor":{"value":"#04c0e1","edited":false},"page-backgroundColor":{"value":"#111111","edited":false},"page-sidebar-backgroundColor":{"value":"#ffffff","edited":false},"group-textColor":{"value":"#36defb","edited":false},"group-borderColor":{"value":"#555555","edited":false},"group-backgroundColor":{"value":"#333333","edited":false},"widget-textColor":{"value":"#eeeeee","edited":false},"widget-backgroundColor":{"value":"#04c0e1","edited":false},"widget-borderColor":{"value":"#333333","edited":false},"base-font":{"value":"Gill Sans,Geneva,sans-serif"}},"angularTheme":{"primary":"indigo","accents":"blue","warn":"red","background":"grey"}},"site":{"name":"Casa in città","hideToolbar":"false","allowSwipe":"true","lockMenu":"true","allowTempTheme":"true","dateFormat":"DD/MM/YYYY","sizes":{"sx":48,"sy":48,"gx":6,"gy":6,"cx":6,"cy":6,"px":0,"py":0}}},{"id":"1d57abec.c27e64","type":"ui_tab","z":"","name":"Gestione Rpi","icon":"fa-gear","order":2,"disabled":false,"hidden":false},{"id":"f67d8e98.208ce","type":"ui_group","z":"","name":"Comandi","tab":"1d57abec.c27e64","order":2,"disp":true,"width":"6","collapse":false},{"id":"dd6e7407.c24778","type":"ui_tab","z":"","name":"Giardino","icon":"fa-tree","order":3,"disabled":false,"hidden":false},{"id":"83400738.e95138","type":"ui_group","z":"","name":"Grafici","tab":"dd6e7407.c24778","order":1,"disp":true,"width":"6","collapse":false},{"id":"70c6ceff.19408","type":"ui_group","z":"","name":"Comandi","tab":"dd6e7407.c24778","order":2,"disp":true,"width":"6","collapse":false},{"id":"103d5cef.f351e3","type":"ui_tab","z":"","name":"Camere","icon":"fa-bed","order":4,"disabled":false,"hidden":false},{"id":"9bdd5115.fdbfb","type":"ui_group","z":"","name":"Grafici","tab":"103d5cef.f351e3","order":1,"disp":true,"width":"6","collapse":false},{"id":"3be54e01.71e4f2","type":"ui_group","z":"","name":"Comandi","tab":"103d5cef.f351e3","order":2,"disp":true,"width":"6","collapse":false},{"id":"274e796c.c9bd96","type":"ui_group","z":"","name":"Grafici","tab":"1d57abec.c27e64","order":2,"disp":true,"width":"6","collapse":false},{"id":"c74430ac.40f9a","type":"ui_tab","z":"","name":"Cucina","icon":"fa-coffe","order":5,"disabled":false,"hidden":false},{"id":"6f473ac0.004394","type":"ui_group","z":"","name":"Grafici","tab":"c74430ac.40f9a","order":1,"disp":true,"width":"6","collapse":false},{"id":"f0b70fb4.d0fc9","type":"ui_group","z":"","name":"Comandi","tab":"c74430ac.40f9a","order":2,"disp":true,"width":"6","collapse":false},{"id":"7dff101e.6c44a","type":"ui_tab","z":"","name":"Soggiorno","icon":"fa-tv","order":6,"disabled":false,"hidden":false},{"id":"5fd73eb6.46957","type":"ui_group","z":"","name":"Grafici","tab":"7dff101e.6c44a","order":1,"disp":true,"width":"6","collapse":false},{"id":"f925a233.8d765","type":"ui_group","z":"","name":"Comandi","tab":"7dff101e.6c44a","order":2,"disp":true,"width":"6","collapse":false},{"id":"3c43d956.bf4706","type":"ui_tab","z":"","name":"Garage","icon":"fa-car","order":7,"disabled":false,"hidden":false},{"id":"5f9e413d.39565","type":"ui_group","z":"","name":"Grafici","tab":"3c43d956.bf4706","order":1,"disp":true,"width":"6","collapse":false},{"id":"f91f386f.884fb8","type":"ui_group","z":"","name":"Comandi","tab":"3c43d956.bf4706","order":2,"disp":true,"width":"6","collapse":false},{"id":"b458edff.701f3","type":"ui_tab","z":"","name":"Ingresso","icon":"fa-road","order":8,"disabled":false,"hidden":false},{"id":"c7e7a411.5ea8e8","type":"ui_group","z":"","name":"Grafici","tab":"b458edff.701f3","order":1,"disp":true,"width":"6","collapse":false},{"id":"6ca369fc.8383f8","type":"ui_group","z":"","name":"Comandi","tab":"b458edff.701f3","order":2,"disp":true,"width":"6","collapse":false},{"id":"dc5de6b6.b88888","type":"ui_link","z":"","name":"MoreWare","link":"https://www.moreware.org/wp/","icon":"open_in_browser","target":"iframe","order":1},{"id":"f389c16c.07142","type":"ui_button","z":"b313a11e.083d4","name":"Spegnimento","group":"f67d8e98.208ce","order":1,"width":0,"height":0,"passthru":false,"label":"spegni il Raspberry Pi","tooltip":"spegni il Raspberry Pi","color":"yellow","bgcolor":"red","icon":"fa-power-off","payload":"","payloadType":"str","topic":"","x":110,"y":60,"wires":[["3f531577.edd70a"]]},{"id":"3f531577.edd70a","type":"exec","z":"b313a11e.083d4","command":"sudo shutdown now","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"sudo shutdown now","x":300,"y":60,"wires":[[],[],[]]}]
Lo scopo della mia nuova rubrica sarà sperimentare insieme la gestione di una casa domotica.
Penseremo un po’ alla volta, zona per zona, cosa implementare e come, nel modo più semplice possibile ed evitando il più possibile di scrivere codice.
Il bello di Node-Red è eseguire una gran quantità di operazioni, senza scrivere codice, ma solo creando flussi.
Backup Node Red
Il file coi nostri flussi, usando l’installazione di default, li troveremo nella home dell’utente, in una cartella nascosta. Nel caso di Raspberry Pi /home/pi/.node-red/flows_<nome host>.json .
La configurazione sarà contenuta nel file settings.js .
Quindi ogni tanto ricordiamoci di fare un backup della cartella. Un semplice esempio di backup si può fare con rsync
rsync -av /home/pi/.node-red/ /home/pi/backup/
Eseguire comandi shell
Nella scorsa puntata, oltre ad un rapida introduzione a Node-Red, abbiamo visto come eseguire comandi da shell.
L’esecuzione di comandi da shell permette di ottenere e gestire informazioni di ogni genere con una sola riga di codice.
Il node Exec, ha la fantastica caratteristica di avere tre uscite, lo standard output, lo standard error, ed il return code.
In parole molto semplici, lo standard output, stdout, è il mesaggio che restituisce un programma eseguito da riga di comando, ad esempio per leggere la temperatura del nostro Raspberry Pi, useremo
vcgencmd measure_temp
Lo stardard output sarà
temp=43.5'C
Nel caso di errori, nel nodo exec, potremmo proseguire il flusso in una diramazione legata solo ai casi di errore.
La terza uscita del nodo, è il return code, che come standard è 0 se l’operazione è andata a buon fine, ed un numero a scelta dai programmatori in base al software richiamato.
Ad esempio questi sono gli exit code di rsync
0 Success 1 Syntax or usage error 2 Protocol incompatibility 3 Errors selecting input/output files, dirs 4 Requested action not supported: an attempt was made to manipulate 64-bit files on a platform that cannot support them; or an option was specified that is supported by the client and not by the server. 5 Error starting client-server protocol 6 Daemon unable to append to log-file 10 Error in socket I/O 11 Error in file I/O 12 Error in rsync protocol data stream 13 Errors with program diagnostics 14 Error in IPC code 20 Received SIGUSR1 or SIGINT 21 Some error returned by waitpid() 22 Error allocating core memory buffers 23 Partial transfer due to error 24 Partial transfer due to vanished source files 25 The --max-delete limit stopped deletions 30 Timeout in data send/receive 35 Timeout waiting for daemon connection
Posizioniamo i nodi
La mia idea è creare un Tab nella Dashboard di Node-Red in grado di gestire una serie di comandi shell assegnati a determinati pulsanti.
Partiamo con il primo Flow, chiamato “Gestione RPI”, aggiungiamo alcuni pulsanti, collegati al nodo exec.
La prima uscita stout porterà ad un nodo file, per creare un file di log dei comandi ricevuti.
L’uscita standard error, creerà un file di log dedicato ai soli errori. Volendo anche un avviso a video dell’errore, colleghiamo il nodo notification dopo il log errori, come da immagine precedente.
Configurare i pulsanti
Passiamo alla configurazione dei singoli nodi.
Il pulsante “Test Log errori” è abbastanza esplicativo e dovrà eseguire un comando errato. Al contrario dell’articolo precedente, i comando sarà contenuto nel pulsante ed inviato come msg.payload nel flusso, arrivando al nodo exec per venire eseguito.
- Group: è il gruppo in cui la Dashboard posiziona gli elementi. Lo troverai nel menù dashboard in alto a destra.
- Size: sarà la dimensione del pulsante nella griglia responsive.
- Icon: l’icona a scelta tra le Material Design icon (e.g. ‘check’, ‘close’) o Font Awesome icon (e.g. ‘fa-fire’), o Weather icon.
- Label: il testo all’interno del pulsante.
- Tooltip: il testo che comparirà lasciando la freccia del mouse sopra al pulsante.
- Colour: il colore del testo, accetta nomi semplici come red, grey, green…
- Background: il colore dello sfondo.
- Payload: è il messaggio che invierà nel flusso, nel nostro caso il comando che il nodo exec dovrà eseguire.
- Topic: è una parte del sistema di messaggi, e si potrà sfruttare in altre occasioni.
- If msg arrives on input, emulate a button click: si può simulare la pressione del pulsante, per evitare di creare un doppione della stessa sequenza di nodi.
- Name: il nome che comparirà nel pannello di programmazione.
Alla pressione del pulsante, il flusso invierà il msg.payload, in questo caso il comando, al nodo successivo, exec.
Eseguiamo i comandi
Analizziamo il nodo exec, il quale eseguirà nella shell del nostro Raspberry Pi, i comandi che arriveranno nel msg.payload.
- Command: il comando a cui verrà appeso il msg.payload. Non abbiamo necessità di aggiungere qualcosa prima del messaggio in arrivo.
- Output: sceglieremo se aspettare o no, il completamento del comando.
- TimeOut: il tempo di attesa.
- Name: è sempre il nome nel pannello di programmazione.
Log in Node Red
Il messaggio prosegue il suo viaggio nel flusso, è stato attivato, eseguito ed ora è il momento di gestirne l’esito.
Raggiunto il nodo file, lo standard output, che in sostanza è il testo che uscirà nella shell a comando eseguito, verrà “appeso” al file da noi indicato in Filename.
Selezionando la prima casellina, verrà scritto un comando per riga, mentre la seconda provvederà a creare la cartella in caso mancasse.
Riassumendo abbiamo un pulsante, che esegue un comando bash e scrive l’output in un file, ma noi vogliamo un file di log errori separato.
Semplicemente eseguiamo la stessa procedura, collegandoci all’uscita sterr del nodo exec, niente di più semplice. Ovviamente nulla vieta di proseguire il flusso con una gestione completa degli errori, ma ciò non fa parte dell’idea di questa rubrica, magari la prossima…
Pensiamo di gestire tutta la nostra casa domotica da smartphone, semplicemente aprendo la pagina web http://<ip del raspberry>:1880/ui . In caso di erorre lo voglio sapere subito, ma come? La via più semplice è il nodo notification che farà apparire l’avviso.
Nulla vieta di usare il nodo Play audio, perchè non lo provi?
Layout: è la posizione del messaggio.
Timeout: per quanto tempo resterà visibile. Attenzione che se ne verrà attivato un altro, questo verrà nascosto.
Border: il colore del bordo.
Al posto di notification, si potrebbe inviare un email, o attivare un serie di azioni con IFTTT.
Il limite è sempre la tua fantasia.
Abbiamo visto come con pochi nodi, senza scrivere codice, otteniamo una dashboard web responsive, in grado di eseguire ogni nostro comando e gestendo eventuali errori e return code.
Quante righe di codice bisognerebbe scrivere per ottenere lo stesso risultato usando altri sistemi?
Per importare i nodi di questo articolo, dal menu import, incolla questo codice.
[{"id":"f389c16c.07142","type":"ui_button","z":"b313a11e.083d4","name":"Spegnimento","group":"f67d8e98.208ce","order":2,"width":0,"height":0,"passthru":false,"label":"spegni il Raspberry Pi","tooltip":"spegni il Raspberry Pi","color":"yellow","bgcolor":"red","icon":"fa-power-off","payload":"sudo shutdown now","payloadType":"str","topic":"","x":150,"y":80,"wires":[["3f531577.edd70a"]]},{"id":"3f531577.edd70a","type":"exec","z":"b313a11e.083d4","command":"","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"Shell","x":350,"y":120,"wires":[["1fb675ee.829aba"],["9ebc05d7.6344b8"],[]]},{"id":"e98bc1fd.ae496","type":"ui_toast","z":"b313a11e.083d4","position":"top right","displayTime":"10","highlight":"red","sendall":true,"outputs":0,"ok":"OK","cancel":"","raw":false,"topic":"","name":"Errori","x":670,"y":120,"wires":[]},{"id":"9ebc05d7.6344b8","type":"file","z":"b313a11e.083d4","name":"Log Errori","filename":"/home/pi/domotica/gestione_rpi/domoticaErrori.log","appendNewline":true,"createDir":true,"overwriteFile":"true","encoding":"none","x":520,"y":120,"wires":[["e98bc1fd.ae496"]]},{"id":"121483f3.88414c","type":"ui_button","z":"b313a11e.083d4","name":"Test Log Errori","group":"f67d8e98.208ce","order":1,"width":0,"height":0,"passthru":false,"label":"Test Log Errori","tooltip":"","color":"","bgcolor":"grey","icon":"","payload":"comandoSbagliato","payloadType":"str","topic":"","x":160,"y":120,"wires":[["3f531577.edd70a"]]},{"id":"1fb675ee.829aba","type":"file","z":"b313a11e.083d4","name":"Output Comandi","filename":"/home/pi/domotica/gestione_rpi/OutputComandi.log","appendNewline":true,"createDir":true,"overwriteFile":"false","encoding":"none","x":540,"y":80,"wires":[[]]},{"id":"91ce293.b9640d8","type":"comment","z":"b313a11e.083d4","name":"Comandi","info":"","x":460,"y":40,"wires":[]},{"id":"f67d8e98.208ce","type":"ui_group","z":"","name":"Comandi","tab":"1d57abec.c27e64","order":2,"disp":true,"width":4,"collapse":false},{"id":"1d57abec.c27e64","type":"ui_tab","z":"","name":"Gestione Rpi","icon":"fa-gear","order":1,"disabled":false,"hidden":false}]
Ci vediamo alla prossima, per iniziare con i grafici di monitoraggio della temperatura del Raspberry Pi 4, e lo stato di altri dispositivi in rete tramite un ping.
Compiti per casa
- Fai leggere a voce i messaggi di errore.
- Crea un pulsante per salvare il tuo lavoro con node red.
- Analizza con un solo nodo debug le tre uscite del nodo exec.