Demo FishinoHomeAuto

Cos'è FishinoHomeAuto ?

FishinoHomeAuto
è un'applicazione abbastanza semplice di Fishino nel campo della domotica.
Viene creato un semplice server web tramite il quale si possono controllare alcune uscite digitali della scheda e leggerne gli ingressi sia analogici che digitali.
Nell'esempio abbiamo creato una pagina web con il disegno di un appartamento tipo, con inserite alcune luci con le quali è possibile interagire ed un termometro che mostra la temperatura in una delle stanze.
La demo come vedremo a breve è molto configurabile tramite un semplice file di testo inserito nella microSD sulla quale sono contenuti anche alcuni files html, immagini e componenti in javascript.
Iniziamo con l'installazione della demo ed un suo primo utilizzo, per poi mostrarne i vari elementi e le possibilità di personalizzazione.
Installazione della demo




Per prima cosa occorre procurarsi una scheda microSD in cui inserire i files della demo.
L'esempio è dentro la libreria Fishino, nella cartella esempi/FishinoHomeAuto. I files da copiare nella microSD si trovano nella cartella STATIC e vanno copiati nella directory radice della scheda; NON copiate tutta la cartella STATIC ma i singoli files, in modo da ottenere il risultato che si vede nell'immagine di sinistra.
Per il momento non modifichiamo nulla; possiamo intravedere l'immagine della casa e le immagini delle lampadine e del termometro, oltre ad alcuni file di contorno

Caricamento dello sketch

Apriamo ora lo sketch FishinoHomeAuto.ino nell'ide, scegliendolo dagli esempi della libreria Fishino; qui utilizziamo la nostra FishIDE, ma potete usare tranquillamente l'IDE di Arduino.
Qui a fianco vediamo lo sketch aperto con l'editor posizionato in corrispondenza degli elementi da modificare per adattarli alla vostra rete WiFi.
La prima cosa da decidere è se vogliamo agganciarci alla nostra rete WiFi oppure se ne vogliamo fare creare una a Fishino; per questo nello sketch abbiamo previsto la
#define STANDALONE_MODE
Se l'attiviamo, togliendo le due barre // del commento, Fishino opererà in modalità autonoma creando la propria rete WiFi a seconda dei parametri che seguono; lasciandola disattivata, invece, cercherà di collegarsi al nostro router.
Successivamente troviamo i consueti SSID e PASSWORD :
#define MY_SSID "casamia"
#define MY_PASS "1234"​
 
Qui dobbiamo ovviamente inserire i dati del nostro router, se vogliamo collegarci a quello, oppure un nome ed una password a scelta se vogliamo operare in modalità standalone.
Per ultimi abbiamo la definizione di IP, GATEWAY e NETMASK:
#define IPADDR  192, 168,   1,  10
#define GATEWAY 192, 168,   1,   1
#define NETMASK 255, 255, 255,   0
 
Se operiamo in modalità STANDALONE dobbiamo inserire un IP ed il corrispondente GATEWAY in una sottorte DIVERSA da quella di casa nostra, altrimenti ci saranno dei conflitti e qualcosa non funzionerà. Ad esempio, se la rete di casa è del tipo 192.168.1.XXX noi possiamo scegliere un 192.168.100.xxx.
Se invece, come normale, vogliamo connetterci all'access point di casa, dobbiamo scegliere la STESSA SOTTORETE di casa ed un IP libero, oppure possiamo commentare le 3 linee ed operare in modalità DHCP, ovvero facendoci assegnare un IP dinamico dal router.
L'IP dinamico ci semplifica le cose da un lato ma ce le complica quando dobbiamo accedere al nostro Fishino; in quel caso occorrerà guardare nel monitor seriale l'IP che il router ci ha assegnato.
Esecuzione dello sketch

Inseriamo la scheda microSD nel nostro Fishino e colleghiamo il tutto al pc; apriamo quindi il monito seriale e vediamo cosa appare!
Se è andato tutto bene, verranno visualizzate alcune informazione sulla connessione e sugli elementi interattivi abilitati nel programma :
Log del monitor seriale :

Resetting Fishino...OK
Connecting AP...OK
Waiting for IP.........OK
IP Address :192.168.1.251
Setting up SD card...
Found 12 appliances
l1:0:2
l2:0:3
l3:0:5
l4:0:6
l5:0:8
l6:0:9
l7:0:15
l8:0:16
l9:0:17
l10:0:18
l11:0:19
t1:3:0
Init done
Web server starting...
Ready to accept HTTP requests...​
Spiegazione del log

Il log del monitor seriale mostra che :
  • Ci siamo connessi al nostro access point con l'IP 192.168.1.251
  • Abbiamo rilevato 12 componenti del nostro sistema domotico ('appliances')
  • I primi 11, nominati da L1 a L11 sono connessi ad uscite digitali (:0) alle porte 2, 3, 5, 6, 8, 9, 15, 16, 17, 18 e 19
  • L'ultimo, nominato T1, è un ingresso analogico (:3) connesso alla porta analogica A0 del Fishino
  • L'inizializzazione è avvenuta con successo (Init Done)
  • Il sistema è pronto ad accettare connessioni dal browser (Web server starting...Ready to accept HTTP requests...)
I messaggi di log possono apparire un po' criptici, ma sono stati volutamente abbreviati, così come i nomi dei componenti, per risparmiare memoria. Quest'applicazione, infatti, raggiunge quasi i limiti di memoria RAM del nostro Fishino UNO; utilizzando un Mega o un Fishino32, invece, c'è spazio in abbondanza per ampliamenti!
Possiamo ora collaudare il nostro sistema aprendo il browser.

Tenendo aperto il monitor seriale, apriamo ora il browser ed inseriamoci il nostro indirizzo IP; sul monitor seriale apparirà un log dei files scaricati dal browser:

 

Vista sul browser

Sul browser appare l'immagine della casa, con le lampadine inizialmente spente ed il termometro che indica una temperatura fittizia, visto che non abbiamo connesso nessun sensore; premendo i vari simboli delle lampadine queste si accenderanno e/o spegneranno,  e contemporaneamente le uscite sul Fishino cambieranno stato, cosa che potremmo vedere se avessimo connesso dei LED alle uscite:

Log del monitor seriale al caricamento :

File: INDEX.HTM
Read file INDEX.HTM
File: JQUERY.JS
Read file JQUERY.JS
File: MAIN.JS
Read file MAIN.JS
File: FLOOR.JPG
Read file FLOOR.JPG
File: MAP.TXT
Read file MAP.TXT
File: FAVICON.ICO
File: LAMPOFF.PNG
Read file LAMPOFF.PNG
File: TERMO.PNG
Read file TERMO.PNG​
Come possiamo vedere nel riquadro del log, questo mostrerà i cambi di stato tramite delle linee tipo :

TOGGLED APPLIANCE lx

(Stato dell'utenza lx cambiato), dove lx indica il nome dell'utenza.

Log quando clicchiamo le lampadine sull'immagine :

TOGGLED APPLIANCE l1
TOGGLED APPLIANCE l4
TOGGLED APPLIANCE l9​
Alla pagina seguente vedremo come modificare i parametri della nostra demo agendo su pochi, semplici files.
Configurazione dell'applicazione

L'applicazione viene configurata tramite pochi files; il file index.htm contenente il codice html e, dentro questo, il collegamento all'immagine della casa, il file map.txt che mappa gli I/O di Arduino con le utenze e le posizioni delle stesse sull'immagine ed alcuni files con le immagini (floor.jpg, lampon.png, lampoff.png, termo.png).
I rimanenti files, i 2 javascript, contengono rispettivamente la libreria jquery che ci permette di comunicare col server tramite richieste Ajax (jquery.js) ed un piccolo codice che gestisce il tutto sulla pagina (main.js), e non vanno modificati, a meno di non voler implementare qualche funzionalità aggiuntiva.
Prima di iniziare, ricordiamoci che sui modelli più piccoli di Fishino, l'UNO ed il GUPPY, la memoria RAM è molto risicata e con la demo siamo vicinissimi al limite massimo, quindi potremo cambiare poco, a meno di non ridurre il numero delle utenze gestite; su un MEGA o su un Fishino32 il problema non si pone e, volendo, potremmo implementare un sistema su più pagine senza problemi.

Vediamo in dettaglio i vari files, nei punti principali.

Il file map.txt

Vediamo per primo il file map.txt, che è un semplice file di testo contenente dati in formato JSON :

{
"l1"  : {"kind":"do", "io" :  "2", "imageoff" : "lampoff.png", "imageon" : "lampon.png", "x" :  93, "y" : 367 },
"l2"  : {"kind":"do", "io" :  "3", "imageoff" : "lampoff.png", "imageon" : "lampon.png", "x" : 230, "y" : 374 },
"l3"  : {"kind":"do", "io" :  "5", "imageoff" : "lampoff.png", "imageon" : "lampon.png", "x" : 179, "y" : 469 },
"l4"  : {"kind":"do", "io" :  "6", "imageoff" : "lampoff.png", "imageon" : "lampon.png", "x" : 237, "y" : 504 },
"l5"  : {"kind":"do", "io" :  "8", "imageoff" : "lampoff.png", "imageon" : "lampon.png", "x" : 286, "y" : 224 },
"l6"  : {"kind":"do", "io" :  "9", "imageoff" : "lampoff.png", "imageon" : "lampon.png", "x" : 326, "y" : 353 },
"l7"  : {"kind":"do", "io" : "15", "imageoff" : "lampoff.png", "imageon" : "lampon.png", "x" : 348, "y" : 461 },
"l8"  : {"kind":"do", "io" : "16", "imageoff" : "lampoff.png", "imageon" : "lampon.png", "x" : 323, "y" : 183 },
"l9"  : {"kind":"do", "io" : "17", "imageoff" : "lampoff.png", "imageon" : "lampon.png", "x" : 428, "y" : 171 },
"l10" : {"kind":"do", "io" : "18", "imageoff" : "lampoff.png", "imageon" : "lampon.png", "x" : 428, "y" : 398 },
"l11" : {"kind":"do", "io" : "19", "imageoff" : "lampoff.png", "imageon" : "lampon.png", "x" : 573, "y" : 403 },
"t1"  : {"kind":"ai", "io" : "0", "image" : "termo.png", "x" : 520, "y" : 211, "scale" : 0.1, "delta" : -5, "prec" : 1, "textpref" : "", "textsuff" : "°C", "textx": 20, "texty" : 15 }
}


Come si nota, sono presenti 2 parentesi graffe che racchiudono tutto il blocco, ed una serie di linee che descrivono le varie utenze. Vediamo in dettaglio una linea relativa ad una lampadina:

"l1"  : {"kind":"do", "io" :  "2", "imageoff" : "lampoff.png", "imageon" : "lampon.png", "x" :  93, "y" : 367 },

La linea inizia col nome dell'utenza tra virgolette ("l1"), seguita da un carattere di due punti (:) ed una lista di elementi racchiusi tra parentesi graffe, il tutto terminato da una virgola (,). Il formato del file è determinante; anche un solo piccolo errore, come ad esempio la mancanza di una virgola o un carattere sbagliato e non funziona nulla.
Tra le parentesi graffe gli elementi sono del tipo chiave:valore, dove la chiave è un nome tra virgolette (stringa) ed il valore è o una stringa, sempre tra virgolette, o un numero. Tutte le utenze iniziano col descrivere il tipo di utenza (kind) e l'I/O alla quale è connessa (io):

"kind":"do", "io" :  "2", .....

Come si può facilmente intuire, "do" sta per "Digital Output", ovvero uscita digitale. Per il termometro avremo "ai", che sta per "Analog Input", ovvero ingresso analogico. Nella linea di esempio abbiamo quindi un'uscita digitale connessa all'I/O 2 di Fishino.
Attualmente nel codice javascript in main.js sono implementati i soli I/O digitali e l'input analogico; è comunque relativamente semplice imlementare anche un controllo tipo slider o potenziometro per un output analogico.
I valori successivi dipendono dal tipo di controllo; per i controlli di tipo digitale abbiamo 2 nomi di immagini, uno che rappresenta il valore LOW, in questo caso una lampadina spenta, l'altro che rappresenta l'immagine del valore HIGH, in questo caso una lampadina accesa :

"imageoff" : "lampoff.png", "imageon" : "lampon.png", ...

In questo caso abbiamo le immagini "lampoff.png" e "lampon.png". Per ultimo abbiamo la posizione della lampadina sull'immagine relative all'angolo in basso a sinistra della stessa; in questo caso al punto 93;367. La posizione si riferisce al centro dell'immagine dell'elemento, per facilitarne il posizionamento. Sempre in questo caso, al centro del cerchio che rappresenta le lampadine

Per gli input analogici, ovvero il nostro termometro, cambia poco :

"t1"  : {"kind":"ai", "io" : "0", "image" : "termo.png", "x" : 520, "y" : 211, "scale" : 0.1, "delta" : -5, "prec" : 1, "textpref" : "", "textsuff" : "°C", "textx": 20, "texty" : 15 }

Qui l'immagine è una sola ("image"), in questo caso il file "termo.png"; successivamente abbiamo la posizione sull'immagine della casa (520, 211) e 2 valori di conversione che servono a trasformare il valore analogico letto (che va, sulle schede Fishino, da 0 a 1023) in un valore che rappresenta la temperatura. La formula utilizzata è :

temp = val · scale + delta

Dove 'temp' è la temperatura visualizzata, 'val' è il valore letto con digitalRead e 'delta' è una costante aggiuntiva. Modificando i valori di 'scale' e 'delta' possiamo quindi adattare la lettura a qualsiasi sensore analogico a disposizione. Per capire come fare, supponiamo che il nostro sensore di temperatura ci restituisca i seguenti valori :

 220   per una temperatura di -10 gradi
1100   per una temperatura di 50 gradi

Ricaviamo il valore di 'scale' tramite :

scale = (50 - (-10)) / (1100 - 220) = 0.0681818

E successivamente il valore di 'delta' :

delta = temp - val · scale = 50 - 1100 · 0.06818 = -25

Ovviamente il discorso funziona bene con sensori che rispondono in modo lineare alla temperatura; una NTC, per esempio, NON è lineare se non per un campo sistretto di temperatura, per cui occorrerebbe un'interpolazione più complicata (quadratica o cubica), con l'introduzione di più costanti nel file e conseguente modifica del javascript in main.js.
A seguire abbiamo 2 stringhe, che costituiscono il prefisso ed il suffisso del valore da visualizzare ('textpref' e 'textsuff'); in questo caso vogliamo visualizzare il numero senza alcun prefisso e con l'indicazione dei gradi centigradi "°C" come suffisso.
Per ultimo abbiamo ancora 2 coordinate, che rappresentano dove poszionare il testo con la temperatura rispetto all'immagine del termometro; se le mettiamo entrambe a 0 ci troveremo il testo posizionato al centro del termometro, cosa non bellissima; in questo caso l'abbiamo spostato di 20 e 15 pixels rispettivamente verso destra e verso il basso per avere una visualizzazione più chiara.

Il file index.htm

Questo file è un semplicissimo file HTML contenente lo stretto indispensabile per visualizzare l'immagine, il richiamo ai nostri 2 javascript di gestione ed un paio di stili CSS per ottimizzare il posizionamento degli elementi :

<html>
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
		<meta name="HandheldFriendly" content="True" />

		<script type="text/javascript" src="jquery.js"></script>
		<script type="text/javascript" src="main.js"></script>

		<title>Fishino Home Automation Demo</title>
	</head>
	<body>
		<h1><center>FishinoHomeAuto demo application</center></h1>
		<style>
			#container {
				position:relative;
				display:table;
				margin: 0 auto;
			}
			.itemcontainer {
				position:absolute;
				display:block;
			}
			.imtip {
				position:relative;
			}
			.texttip {
				position:absolute;
			}
		</style>
		<div id="container" align="center" border-color="red" border-width=2>
			<img src="floor.jpg"/>
		</div>
	</body>
</html>


In questo file potete cambiare praticamente tutto, dall'immagine di sfondo in poi. Con un po di modifiche allo sketch ed al formato del file map.txt è possibile anche realizzare un'applicazione completa su più pagine.