Domotica facile: Gestione IO, rele´ e ingressi analogici da rete LAN e Internet – Parte 1 – Comunicazione Client/Server

In questi articoli vi illustrerò un programma che ho scritto per poter controllare relè e leggere degli ingressi analogici tramite un’interfaccia web attraverso una rete LAN (e quindi anche attraverso Internet disponendo delle opportune conoscenze). Premetto che si trovano molti esempi del genere in giro ma, devo dire la verità… ho trovato soltanto esempi “mozzicati”, scopiazzati e poco professionali. In questo esempio come interfaccia hardware utilizzo il chipKIT™ MAX32 con il chipKIT™ Network Shield e qualche 2Relay Board.

Probabilmente non è possibile utilizzare il sorgente di esempio, che pubblicherò nella seconda parte, con Arduino e l’Ethernet shield: il ChipKIT™ MAX32 ha una quantità di memoria ram e programma che permettono di implementare numerosissime funzioni (tanto per fare un esempio, ho incluso nella pagina web anche un’immagine caricata nella rom), senza tener conto dell’elevato numero di IO che ci permettono di automatizzare via web anche un intero condominio. E aggiungiamoci pure che sul network shield abbiamo a disposizione il can-bus e la possibilità di utilizzare una pendrive usb, che potremmo sempre decidere di voler utilizzare nella nostra applicazione domotica. Forse potrete farlo ma dopo una massiccia modifica al codice.

Questo progetto mi ha permesso di mettere insieme le varie conoscenze che ho accumulato nel corso degli anni: programmazione per sistemi embedded, conoscenza dell’HTML e programmazione per web (javascript), per cui penso che possa risultare interessante sotto parecchi punti di vista, e sinceramente spero di non pentirmi di pubblicare questi due articoli a causa dei soliti stupidi sostenitori delle raccolte a punti.

Il concetto di base è il seguente: sul PIC32MX del ChipKIT™ MAX32 gira un firmware che gli permette di agire come server web, grazie anche all’interfaccia PHY fornita dall’integrato LAN8720 presente sul Network Shield. Digitando l’indirizzo IP assegnato al PIC32MX, collegato in una rete LAN, il pic fornisce una pagina html costruita al volo in cui riporta lo stato delle porte analogiche e dei relè. La pagina web generata è dinamica: è possibile interagire con essa per modificare, ad esempio, lo stato dei relè. Il modo con cui si interagisce con la pagina è presto illustrato in questa prima parte dell’articolo.

Il valore degli ingressi analogici è ovvio che è destinato a cambiare nel tempo, così come lo stato dei relè se a qualcun altro è concesso di accedere alla pagina di controllo. Esempi di lettura sensori via web ce ne sono, dicevo, ma si tratta spesso di esempi “statici”: bisogna aggiornare manualmente la pagina web per poter visualizzare sempre i valori più recenti. Altri esempi invece implementano nella pagina html un meta tag di refresh in questo modo:

<meta http-equiv="refresh" content="1">

che nella fattispecie dice al browser di eseguire il refresh della pagina ogni secondo: in pratica la stessa cosa che premere il pulsante “aggiorna” ma  fatto in maniera automatica. Anche questo sistema non mi piace per niente e lo trovo poco professionale, basti pensare già che quando si esegue il refresh della pagina si ode spesso il “click” oltre che il rapido sfarfallamento della finestra.

La mia idea è pertanto partita dall’inizio con la decisione  di implementare l’utilizzo di  AJAX nell’interfaccia web, il che permette di eseguire l’aggiornamento soltanto di alcune parti della pagina, senza quindi ricaricarla tutta daccapo ogni volta consentendo anche un aggiornamento fluido. Per ulteriori informazioni su cos’è AJAX rimando alla pagina di wikipedia che ho linkato.

Tengo a precisare che AJAX non è un nuovo linguaggio di programmazione, bensì un sistema di interazione tra HTML, Javascript, client e server. Ad ogni modo, per proseguire, è bene avere delle nozioni anche minime di HTML (che ricordo: non è un linguaggio di programmazione, ma un linguaggio di formattazione!) e Javascript (che lo è, ma non è il JAVA, che è una cosa diversa, ok?).

Oltre alla lettura degli ingressi analogici, in questo esempio, c’è anche il controllo ON/OFF di 8 relè, per cui risulta un’ottima base di partenza per realizzare un sistema domotico a basso costo. In pratica la pagina di controllo generata sarà questa:

Come vedete nella pagina è anche inclusa un’immagine, il logo di settorezero.com, che ho caricato nella rom del PIC32 sfruttando il concetto dei Data URLs che ho esposto tempo fa in questo articolo. L’esempio io l’ho provato nell’ambito della mia rete lan domestica. Per poter controllare il tutto dall’esterno, attraverso internet, è necessario un account su dyndns o simili e fare vari aggiustamenti sul router di casa: questo argomento, a parte il fatto che comporta numerose considerazioni relative alla sicurezza, non sarà trattato in questo articolo, anzi se qualcuno di voi l’ha già fatto e vuole illustrare come si fa in stile settorezero.com, si faccia avanti.

Potrei partire direttamente con il download del codice, ma dato che come dicevo ci ho messo parecchi giorni per tirare fuori una cosa fatta bene e non il solito esempio rimasticato che si trova in giro, permettetemi di illustrarvi il funzionamento. Partirò pertanto da un concetto di base che è importantissimo per capire in che modo un qualsiasi browser comunica con un server e riceve le risposte.

Request & Response

Quando nel browser digitiamo un indirizzo per poter visualizzare una pagina web, stiamo eseguendo una richiesta (request) ad un server. Una request è un semplice trasferimento di dati e contiene tutta una serie di informazioni che il server interpreta per poter rispondere e quindi fornire la risorsa che gli abbiamo richiesto. Per risorsa non intendo soltanto una pagina web, ma anche un’immagine, un filmato, un documento o un file qualsiasi : tutti trasferimenti di dati possibili attraverso il protocollo HTTP.

Tutto questo scambio di informazioni avviene in maniera pressochè invisibile: nella vita di tutti i giorni vediamo soltanto che:  abbiamo digitato un indirizzo, premuto invio e il browser ha visualizzato una pagina web o ha scaricato un file. Per poter “costruire” un sistema di automazione che ci visualizzi una pagina web con lo stato di alcuni sensori e permetta di attivare dei relè sempre attraverso la stessa pagina web è importante capire il meccanismo che sta alla base della comunicazione tra client (il browser) e il server, altrimenti è inutile anche caricare uno sketch già pronto sul nostro sistema di sviluppo: così non abbiamo creato nè capito nulla e soprattutto se vogliamo adattarlo alle nostre esigenze non riusciremo mai e poi mai a farlo.

Supponiamo di digitare www.settorezero.com nella barra indirizzi del browser: non appena premiamo invio, il browser invia al server al quale siamo collegati una richiesta simile a questa:

GET / HTTP/1.1
Host: www.settorezero.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.78 Safari/535.11
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: http://www.google.it
Accept-Encoding: gzip,deflate,sdch
Accept-Language: it-IT,it;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

La prima riga di una richiesta contiene il metodo (che illustrerò tra poco: GET o POST sono i metodi più utilizzati ma ce ne sono anche altri, vedi approfondimenti) seguito eventualmente dalla Querystring (questo solo per il metodo GET, è una parte che segue lo slash dopo GET, non presente in questo esempio, vedremo dopo) e la versione del protocollo HTTP utilizzato (1.1 in questo esempio). Seguono quindi numerose altre informazioni tra cui il tipo di risorse che il browser è in grado di accettare (immagini, filmati flash ecc), l’User-Agent che identifica il browser utilizzato + sistema operativo, l’host richiesto. Importante anche Il Referer (purtroppo scritto con una sola R anche se è sbagliato!), che contiene l’indirizzo che ci ha portato alla pagina richiesta (questa parte non è presente se abbiamo digitato l’indirizzo direttamente nel browser) e altre informazioni.

Quando l’indirizzo di un sito, di una pagina, viene digitato direttamente nella barra degli indirizzi del browser, il metodo di richiesta utilizzato è GET. Il metodo GET, come accennavo prima, consente di passare variabili alla pagina attraverso la Querystring, esempio:

www.settorezero.com/?var1=10&var2=200

tutto quello che segue il punto interrogativo viene chiamato querystring e il server è in grado di comunicare alla pagina richiesta che le stiamo passando delle variabili (in questo esempio due variabili chiamate var1 e var2 ognuna con un proprio valore dopo l’uguale). In pratica la request di prima ora sarebbe così:

GET /?var1=10&var2=200 HTTP/1.1
Host: www.settorezero.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.78 Safari/535.11
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: https://www.settorezero.com
[...]

Il metodo GET in pratica è assimilabile al sistema che si utilizza per comunicare ai programmi tramite riga di comando, chi usava il DOS sa di cosa parlo. Il metodo POST, invece, è il sistema che utilizzano i form (i moduli) delle pagine web per trasferire le variabili: con il metodo post la richiesta in pratica non è visibile nella barra degli indirizzi e il trasferimento avviene in background. Il vantaggio del metodo POST è che può trasferire un gran numero di variabili anche contenenti molti dati. Il metodo GET è invece sicuramente più semplice da implementare ma molti server impongono (o forse è meglio dire: imponevano) un limite sulla quantità di dati trasferibile con questo metodo.

Nel mio esempio utilizzerò il metodo GET per l’attivazione/disattivazione dei relè utilizzando ad esempio link del tipo:

192.168.1.190/?relay2=0

che comunica al firmware di spegnere (0) il relay numero 2. Una cosa più semplice, e che avrebbe risparmiato parecchie righe di codice (soprattutto nella parte di generazione automatica della pagina web) sarebbe stata quella di eseguire soltanto il toggle del relè passando un indirizzo del tipo:

192.168.1.190/?relay2

che poteva essere interpretato dal server come “inverti lo stato del relè 2”. Ma immaginate che la visualizzazione della pagina si blocchi, perchè può capitare, e premete il pulsante refresh per ricaricarla… cosa accadrebbe? Il relè invertirà nuovamente lo stato e non avremmo certo fatto una cosa da professionisti. In questo modo, invece, pure premendo refresh, il relè rimarrà spento.

Una volta che il server (il PIC32 in questo caso) ha ricevuto una richiesta e l’ha elaborata, deve fornire una risposta (response). Il response è costituito da un header e da un body separati da una linea vuota.  L’header contiene informazioni sulla risorsa richiesta. Esempio:

HTTP/1.1 200 OK
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Content-Type: text/html; charset=iso-8859-1

la prima riga in particolare contiene la versione del protocollo HTTP (1.1 in questo esempio) seguito da uno status code (200) e da un messaggio associato allo status code (OK). In questo esempio lo status code 200 indica che il server ha interpretato correttamente la request ed è in grado di rispondere. Seguono numerose altre informazioni tra cui il controllo cache che permette di fare/non fare in modo che il browser salvi la pagina in cache per poterla visualizzare più rapidamente ad una prossima richiesta, e il content-type che comunica al browser cosa deve aspettarsi nel corpo (body) rel response (una pagina html in questo caso).

Il content-type condiziona il browser a comportarsi in un certo modo piuttosto che in un altro: visualizzare una pagina piuttosto che avviare una finestra di download ad esempio. Dopo l’header, come dicevo, segue una linea vuota e quindi il corpo del response che in questo caso sarà il contenuto di una pagina html, che il browser visualizzerà (ecco perchè l’HTML è un linguaggio di formattazione e  non di programmazione, a differenza del Javascript -contenuto nell’HTML- che invece deve essere eseguito).

In Italia i prodotti della Digilent vengono distribuiti da Mirifica, e il mio consiglio è di andare sul loro sito per l’acquisto del chipKIT™ Network Shield e del chipKIT™ MAX32.

Approfondimenti

Vi consiglio di leggere le pagine riportate a questi link, che vi permetteranno di capire meglio, ma soprattutto approfondire, i concetti appena esposti:

Vai alla seconda parte.

Se questo articolo ti è piaciuto, condividilo su un social:
Se l'articolo ti è piaciuto o ti è stato utile, potresti dedicare un minuto a leggere questa pagina, dove ho elencato alcune cose che potrebbero farmi contento? Grazie :)