Visto che vengo spesso accusato di essere poco coinvolto negli addobbi natalizi quest'anno ho deciso di partecipare attivamente all'allestimento dell'albero.
Avendo appena ricevuto un Intel Edison non potevo non sfruttarlo per rendere l'albero piu' divertente ed intelligente.
Ne approfitto quindi per scrivere questo articolo, in cui illustrero' passo passo come creare due prese elettriche facilmente comandabili da Edison, utili in questo caso per comandare le luci dell'albero, ma altrettanto per mille altre applicazioni. Mostrero' anche il codice utilizzato per gestirle usando javascript e node.js (quindi facilmente utilizzabile attraverso l'Intel XDK), integrando anche delle richieste ad un webservice REST, trattando dunque con un solo esempio, alcune tecniche che possono rivelarsi utili in diversi campi di utilizzo.
Partiamo subito dal'hardware. Abbiamo bisogno di poter comandare le luci dell'albero, farle accendere e spegnere a nostro piacimento. Invece di modificare le luci, ho pensato di creare due prese elettriche controllabili, che potranno essere riutilizzate per diversi progetti.
Avete bisogno di:
- Una scatola per cestelli elettrici esterni.
- Un cestello
- Due B-prese
- Una placchetta di copertura.
- Un cavo elettrico e una presa (Maschio)
- Per ogni presa serve un relay, io ho utilizzato quelli del Kit Groove.
Partiamo dalla realizzazione delle prese elettriche comandabili.
Qui invece si puo' vedere come ho collegato i relays alle prese.
Un cavo della linea va ad una delle prese, poi ho fatto un piccolo ponte con un altro cavo all'altra presa.
L'altra cavo di linea va ad uno dei relays, con un ponte verso l'altro.
Infine ho collegato gli altri due cavi provenienti dal relays all'altro polo delle b-prese.
Poi ho inserito tutti i componenti all'interno della scatolina ed ecco, le nostre prese controllabili.
Sono poi passato al software.
L'idea e' di visualizzare un countdown sul display LCD dell'albero con il tempo che manca a natale (o a qualunque data vogliate) e controllare periodicamente il meteo e far accendere le luce dell'albero se nevica. Ovviamente vogliamo che le luci si accendano a natale. Inoltre ho aggiunto anche un pulsante che permette il controllo manuale dell'albero. Io ho utilizzato due strisce di luci, ognuna controllata da una presa, ma potete adattare il codice a quante ne volete.
Ma analizziamo ora passo passo il codice utilizzato.
Cominciamo ad includere le librerie che andremo ad utilizzare:
var mraa = require("mraa"); var http = require('http'); var LCD = require('jsupm_i2clcd');
libmraa: ci sara' utile per accedere facilmente ai sensori e alle uscite di Edison.
http: verra' utilizzata per fare il fetch del feed meteo con coi controlleremo se nevica o meno.
jsupm_i2clcd : viene utilizzata per scrivere facilmente sul display LCD
Ora vediamo le funzioni di cui avremo bisogno, ho inserito i commenti nel codice sperando di spiegare a sufficienza cosa succede passo passo.
Per prima cosa, creiamo alcune variabili di supporto:
// numero del pin a cui connetteremo un pulsante per accendere // e spegnere manualmente le luci dell'albero var buttonGpio = 8; // i pin a cui collegeremo i nostri relays, io ne ho usati due, potete aggiungere quelli che preferite. var relayGpio = [2,3]; // vettore che useremo per inizializzare i relays var relay = Array(); // variabile che conterra' l'handler del nostro pulsante var button; // url di base di openweathermap per accedere al feed meteo var owmUrl = "http://api.openweathermap.org"; // query da utilizzare per il meteo var owmPath = "/data/2.5/weather?unit=metric&q=" // la citta dove viviamo var yourCity = "Brescia,it"; // variabile di supporto che contiene lo stato relativo alla neve var isSnowing = false; // variabile che corrispondera' al nostro dislay lcd var myLcd; // flag per l'uso manuale var turnOnLight = false;
Definiamo ora una funzione setup, che inizializzera' tutte le nostre variabili:
// Questa funzione serve a inizializzare le variabili, i pin etc function setup() { // il bottone per accendere e spegnere le luci manualmente // lo inizializziamo e indichiamo che e' un ingresso button = new mraa.Gpio(buttonGpio); button.dir(mraa.DIR_IN); // inizializziamo tutti i relays, come output for ( var i=0; i<relayGpio.length; i++) { relay[i] = new mraa.Gpio(relayGpio[i]); relay[i].dir(mraa.DIR_OUT); relay[i].write(0); } // ed infine l'lcd myLcd = new LCD.Jhd1313m1 (6, 0x3E, 0x62); }
Ora la funzione per il conto alla rovescia:
// funzione che serve per il conto alla rovescia // fino ad arrivare a natale. function countDown() { // natale 2014, ma potete metterci la data che volete var end = new Date('12/24/2014 00:00 AM'); var _second = 1000; var _minute = _second * 60; var _hour = _minute * 60; var _day = _hour * 24; var timer; var now = new Date(); // la data di oggi // calcoliamo ora la distanza tra oggi e la data di fine var distance = end - now; if (distance < 0) { // l'attesa e' finita. // definiamo il messaggio da visualizzare se la data di fine e' raggiunta lcdMessage = " !! Merry Christmas !!"; // scriviamola sull riga 1 dell'lcd myLcd.setCursor(1,1); myLcd.write(lcdMessage); //accendiamo anche le luci! turnOnLight = true; return; } // Formattiamo il tempo mancante var days = Math.floor(distance / _day); var hours = Math.floor((distance % _day) / _hour); var minutes = Math.floor((distance % _hour) / _minute); var seconds = Math.floor((distance % _minute) / _second); // Creiamo la stringa da visualizzare lcdMessage = "-" + days + "d:" + hours + "h:" + minutes + "m:" + seconds + "s"; // Visualizzaimola sul display myLcd.setCursor(1,0); myLcd.write(lcdMessage); }
Passiamo ora a scrivere la funzione che scarica un feed json per il meteo, utilizzando le api di openweathermap.org :
// Questa funzione controlla il meteo e // riporta lo stato attuale sul display function checkWeather() { // costruiamo l'url per la richiesta var url = owmUrl + owmPath + yourCity try { // maggiori info sull'api utilizzata qui : http://openweathermap.org/api // creiamo una richiesta http all'url sopra http.get(url, function(res) { // qui salviamo il contenuto della risposta del server var body = ''; // leggiamo la risposta pezzo per pezzo res.on('data', function(chunk) { body += chunk; }); // e alla fine della richiesta, leggiamo il risultato res.on('end', function() { //facciamo il parsing del risultato per avere un oggetto javascript var weather = JSON.parse(body) // il webservice chiamato restituisce un file json, dobbiamo farne il parsing // qui trovate la tabelle dei codici che vengono restituiti dal webservice: // http://openweathermap.org/weather-conditions var id = weather.weather[0].id; // prendiamo il codice delle condizioni per la giornata corrente if(id>=600 && id<623) { // i valori compresi tra 600 e 623 indicano neve isSnowing = true; // settiamo la variabile che indica la neve turnOnLight = true; // e si, nevica! vogliamo le luci scintillanti! } else { isSnowing = false; // niente neve, almeno per ora. } // riportiamo le condizioni meteo sul display lcdMessage = "Weather: "+weather.weather[0].description; myLcd.setCursor(0,0); myLcd.write(lcdMessage); }); }).on('error', function(e) { // se qualcosa va storto nella richiesta http lo scriviamo sul display lcdMessage = "Weather: ERROR"; myLcd.setCursor(0,0); myLcd.write(lcdMessage); console.log("Got error: ", e); }); } catch(e) { // anche qui, se abbiamo una eccezione segnaliamolo lcdMessage = "Weather: ERROR"; myLcd.setCursor(0,0); myLcd.write(lcdMessage); console.log("can't fecth the weather feed") } };
Ci siamo quasi, abbiamo quasi tutti i pezzi che ci occorrono, scriviamo due funzioni, una che accenda tutte le luci ed una che le spenga:
// piccola funzione che accende tutte le luci connesse ai relays function turnOn(){ for(var i=0; i<relay.length; i++) relay[i].write(1); } // funzione per spegnere i relays function turnOff(){ for(var i=0; i<relay.length; i++) relay[i].write(0); }
Ok, ora manca solo la funzione che controlli il bottone, e verifichi se sia il caso o meno di accendere le luci:
// questa e' la funzione che controlla se e' stato premuto il bottone // ed in caso accende o spegne le luci. // verifica inoltre se sta nevicando o se e' gia' natale ed in caso accende le luci function makeChristmas() { // controlliamo lo stato del bottone if (button.read() == 1) { // se premuto, cambio lo stato delle luci turnOnLight = !turnOnLight; } // ora verifico se devo accendere le luci o meno if(turnOnLight || isSnowing) { turnOn(); // FESTA } else { turnOff(); // NOIA } }
ed infine creiamo una funzione di init, e usiamo alcuni timer per far partire tutto quanto:
// funzione di init, inizializza le variabile necessarie // e avvia il primo controllo meteo function init() { setup() checkWeather(); } // setup di tutte le variabili init(); // controlliamo ogni 10 millisecondi il bottone, e lo stato setInterval(makeChristmas, 10) // ogni secondo aggiorniamo il conto alla rovescia setInterval(countDown, 1000); // ogni ora controlliamo il meteo setInterval(checkWeather, 360000);
E abbiamo finito, potete eseguire il codice con l'Intel XDK o da shell richiamando lo script con node.js!
Io mi sono permesso di addobbare creativamente l'albero...
Ecco qualche foto dello splendido IOTree!!
Spero di aver stimolato un po' di curiosita' e fantasia, per i vostri prossimi progetti, per le prossime IOFeste!
Michele