Come realizzare un server web per visualizzare i dati

Transcript

Come realizzare un server web per visualizzare i dati
Come realizzare un server web per
visualizzare i dati di una stazione
meteo
Come realizzare un server web per visualizzare i dati di una
stazione meteo
Grazie all’avvento di Internet, è diventato ormai semplice poter visualizzare
le previsioni meteo e l’attuale situazione meteorologica. Nella rete sono
presenti tanti siti web che permettono di visualizzare tali valori e la
maggior parte di essere risulta essere attendibile e semplice da usare.
Previsioni meteo, tratti dal sito ilmeteo.it
Tuttavia il detto “chi fa da se fa per tre” mi ha portato a realizzare un
servizio web, per trasformare alcuni dispositivi in una stazione meteo
professionale. Alla fine dell’installazione di tutti i componenti sarà
possibile accedere ad una pagina web, nella quale saranno presenti i valori
di temperatura e umidità attuali, giornalieri e alcuni statistiche, come ad
esempio la temperatura massima e minima registrata nei vari giorni.
Requisiti per il progetto
Hardware
2 Arduino UNO
1 x kit di sensori Wireless 433 Mhz
1 x DHT22
2 x Breadboard per installare i dispositivi
Un po’ di cavi flessibili
1 x PC come basi di dati e server (consiglio caldamente di utilizzare un
Raspberry PI, oppure un UDOO)
Software
I miei codici, disponibili nella repo di Github
Queste librerie per Arduino DHT22, MYSQL, VirtualWire, SendData
MySQL Workbench
Tasksel (software che includi ottimi servizi lato server, come
PHPMyAdmin, Apache e tanto altro)
Sommario del progetto
Ora vedremo in dettaglio tutti i componenti che sono utilizzati in questo
progetto.
Come viene letta la temperatura
Uno dei principali componenti per realizzare una qualsiasi stazione meteo è
un trasduttore in grado di leggere la temperatura e l’umidità.
Un trasduttore/sensore non è altro che un dispositivo elettrico in grado di
trasformare una grandezza fisica quale la temperatura, in una grandezza
elettrica, cioè un valore di tensione, oppure di corrente. La grandezza
elettrica, verrà tratta successivamente a seconda che l’uscita del sensore
sia analogica, oppure digitale, cioè una corrispondenza di 0 e 1. Facciamo un
piccolo esempio;
Dati Numero di bit = 10; Vcc = 5 V GND = 0 V
Se il numero di bit è pari a 10, è possibile rappresentare valori che vanno
da 0 a 2^10-1, cioè fino a 1023. Qualora venga letto un valore, per esempio
con Arduino, pari a 512, per calcolare la tensione effettiva che riceve il
microcontrollore, occorre fare il seguente calcolo:
V_IN = 512/1024 * 5 [V] = 2.5 [V]
Se per esempio, il nostro trasduttore è stato modellizzato in modo tale da
fornire un valore di tensione proporzionale alla temperatura, come ad esempio
V_OUT = 0.1* temperatura, se ci sono 25 gradi, l’uscita sarà pari a 0.1*25 =
2.5 V e quindi Arduino avrà un valore in lettura pari proprio a 512.
Ovviamente questo esempio semplifica abbastanza le dinamiche di funzionamento
di un trasduttore per temperature. Tale trattazione non è troppo importante a
fini di realizzare il progetto; serve solo come conoscenza personale.
Come già utilizzato nei progetti precedenti, anche in questo caso verrà
utilizzato un trasduttore di temperatura e umidità molto semplice, quale il
DHT22. Esso è facilmente acquistabile su Ebay, al costo di qualche Euro.
La modellizzazione del dispositivo è già stata fatta e quindi per poterlo
usare all’interno dei nostri codici, è necessario solamente scaricare la
relativa libreria.
Come indicato all’interno della documentazione, per poter leggere un valore
di temperatura corretto è necessario inserire una resistenza da 10 KOhm in
pull up tra l’alimentazione Vcc e il pin di uscita, come riportato il figura.
Come ogni componente presente in un progetto, conviene testare la lettura
della temperatura, attraverso questo semplice codice:
// Programma che permette di leggere la temperatura, attraverso un sensore
#include "DHT.h"
#define DHTPIN 2
// Il pin a cui è collegato il sensore
// Togli il commmento al sensore che vuoi usare
//#define DHTTYPE DHT11
#define DHTTYPE DHT22
// DHT 11
// DHT 22
//#define DHTTYPE DHT21
(AM2302)
// DHT 21 (AM2301)
// Connettere il pin 1 (a sinistra) a +5V
// Connettere il pin 2 del sensore alla porta 2
// Connettere il pin 4 (a destra) del sensore
a GROUND
// Connettere una resistenza da 10K tra il pin 2 (data) e il pin 1 (power)
del sensore
DHT dht(DHTPIN, DHTTYPE);
voidsetup() {
Serial.begin(9600);
Serial.println("DHTxx test!");
dht.begin();
}
voidloop() {
// Legge la temperatura e l'umidità ogni 250 millisecondi!
// Vengono inizializzate le variabili in cui vengono scritti i valori letti
floath = dht.readHumidity();
floatt = dht.readTemperature();
// Controlla se la lettura è andata a buon fine
if(isnan(t) || isnan(h)) {
Serial.println("Failed to read from DHT");
} else{
Serial.print("Humidity: ");
Serial.print(h); // Stampa nel seriale la percentuale dell'umidità
Serial.print(" %t");
Serial.print("Temperature: ");
Serial.print(t); // Stampa nel seriale il valore della temperatura
Serial.println(" *C");
}
}
Come vengono inviati i valori di temperatura e umidità tra i dispositivi
L’altro aspetto sempre legato alla temperatura, è l’invio dei dati tra
l’Arduino che viene collegato all’interno dell’abitazione e quello posto
all’esterno. Il fatto di dover utilizzare due dispositivi, è dovuto al
semplice fatto che tipicamente non si dispone di una prese Ethernet esterna e
una scheda Wireless ha un costo abbastanza elevato. Per questo motivo
conviene utilizzare i due dispositivi e farli comunicare tra di loro
attraverso un kit wireless, che funziona sulla frequenza 433 Mhz. Tali
dispositivi sono già stati trattati in passato e per ulteriori informazioni,
vi invito a guardare questo articolo, presente sul mio blog.
Il collegamento dei PIN dei dispositivi wireless è riportato in figura.
Se abbiamo correttamente collegato tutti i dispositivi, potremmo inviare i
valori di temperatura e umidità tra l’Arduino posto fuori casa e quello che è
presente in casa, nel quale sarà presente una scheda Ethernet Shield, che gli
permetterà di collegarsi ad Internet ed inviare i dati letti.
Il programma da caricare sull’Arduino client è:
#include "DataCoder.h"
#include "VirtualWire.h"
#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT22
int transmit_pin = 12;
int led_pin = 13;
int baudRate = 800;
int delayTime = 30000;
DHT dht(DHTPIN, DHTTYPE);
void setup()
{
pinMode(led_pin,OUTPUT);
Serial.begin(9600);
SetupRFDataTxnLink(transmit_pin, baudRate);
dht.begin();
}
void loop()
{
float outArray[2];
float h = dht.readHumidity();
float t = dht.readTemperature();
outArray[0] = t;
outArray[1] = h;
union RFData outDataSeq;
EncodeRFData(outArray, outDataSeq);
TransmitRFData(outDataSeq);
delay(delayTime);
}
In questo codice è possibile modificare il tempo che trascorre tra l’invio di
dati.
Il programma da caricare sull’Arduino server è:
/*
This code allow Arduino to send the value of temperature and humidity to a
DB, everty portion of time, setted by the user.
The data of temperature come from an Arduino via wireless, so one Arduino can
stay outside, and the other
one can stay in the home
Version 1.0
Author Giacomo Bellazzi
Copyright (C) 2014 Giacomo Bellazzi (http://ismanettoneblog.altervista.org/)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <SPI.h>
#include <Ethernet.h>
#include <sha1.h>
#include <mysql.h>
#include <avr/dtostrf.h>
#include <DataCoder.h>
#include <VirtualWire.h>
const int rx_pin = 11; // the Pin of the RX
const int baudRate = 800;
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress server_addr(192,168,1,20); // MySQL Server IP
char user[] = "username";
char password[] = "password";
Connector my_conn; // The Connector/Arduino reference
const char INSERT_DATA[] = "INSERT INTO WeatherStation.Data VALUES
(1,%s,%s,CURRENT_DATE,CURRENT_TIME)";
void setup(){
Ethernet.begin(mac_addr);
//Serial.begin(9600); for DEBUG
Serial.println("Connecting...");
SetupRFDataRxnLink(rx_pin, baudRate);
if (my_conn.mysql_connect(server_addr, 3306, user, password)) {
delay(1000);
}
else
Serial.println("Connection failed.");
}
void loop(){
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
union RFData inDataSeq;//To store incoming data
float inArray[2];//To store decoded information
if(RFLinkDataAvailable(buf, &buflen))
{
for(int i =0; i< buflen; i++)
{
inDataSeq.s[i] = buf[i];
}
DecodeRFData(inArray, inDataSeq);
float temperature = inArray[0];
float humidity = inArray[1];
//DEBUG
//Serial.println("Temperature: ");
//Serial.print(temperature);
//Serial.print(" ° Humidity: ");
//Serial.println(humidity);
sendToDB(inArray[0],inArray[1]);
}
}
// This code send the values of the temperature and humidity to the DB
void sendToDB(float temperature,float humidity){
char query[64];
char t[6];
char h[6];
dtostrf(temperature, 1, 2, t);
dtostrf(humidity, 1, 2, h);
sprintf(query, INSERT_DATA, t,h);
my_conn.cmd_query(query);
}
Sarà necessario inserire/modificare i dati, quali IP, username e password
della propria base di dati (vedi pagine successive).
Come vengono salvati i valori registrati
Un aspetto importare in questo progetto è il salvataggio dei dati che vengono
letti dall’Arduino, sfruttando il sensore di temperatura DHT22. Infatti, se
non fosse presente un dispositivo in grado di poter salvare i dati, non
sarebbe possibile recuperare tali valori in futuro.
Per questo motivo, in questo progetto, viene utilizzata come base di dati un
server MySQL. Il motivo di utilizzare questo sistema è che esso è
relativamente facile da usare ed ad installare.
Facciamo una breve introduzione a MySQL; esso un sistema basato sull’Algebra
relazionale, che non è altro che un insieme di regole, che permettono di
mettere in relazione tra di loro dati.
Facciamo un breve esempio; per una persona è normale ipotizzare, come dati,
il suo nome, cognome, codice fiscale, città di nascita. Quindi si potrebbe
rappresentare in questa tabella i dati:
Codice Fiscale
Nome
Cognome
Città di Nascita
ABCDEFG
Paolo
Rossi
Milano
Si potrebbe approssimare, per semplicità, che è possibile creare uno schema
della propria base di dati, sfruttando questa tabella, mantenendo come
attributi, i valori in grassetto. Occorre notare che, per come è stato
realizzato il codice fiscale, esso viene definito una chiave primaria nella
relazione Persona, dal momento che non esistono due persone diverse, con lo
stesso codice fiscale.
Per una trattazione più ampia di MySQL e dell’Algebra relazione, è possibile
leggere il seguente articolo.
Come poter visualizzare i dati salvati ed effettuare richieste
Il passo successivo è quello di creare uno schema corretto per il nostro
progetto. Questa operazione, richiede di tradurre le notazioni riguardo alla
temperatura, in Algebra relazione. Per esempio, quali sono gli attributi
relativi alla misura di una temperatura ? Per esempio potrebbero essere il
valore della temperatura, dell’umidità, l’ora e la data di registrazione. Se
però avessimo più dispositivi, sparsi per esempio in varie città d’Italia,
come possiamo fare ? La soluzione più semplice è quella di usare un ID, che
identifica ogni stazione meteo.
Ricapitolando avremmo questa relazione, che ho chiamata Data, all’interno
dello schema WeatherStation:
ID
Temperature
Humidity
Date
Time
Ogni stazione meteo, ha però altre informazioni, più statiche, come ad
esempio il luogo in cui è installata. Per questo motivo è necessario creare
una seconda relazione, che contiene quelle informazioni.
Per poter creare una base di dati è necessario installare il pacchetto MySQL
server su un PC (meglio su UDOO oppure Raspberry ) e un programma client,
chiamato MySQL Workbench, poter effettuare query ed impostare lo schema della
base di dati.
idDevice
Town
Location
Installazione Tasksel
Spesso si pensa che dover installare programmi specifici su piattaforme Linux
sia difficile; in realtà non c’è cosa più semplice !!! Infatti per poter
installare il server MySQL, il server Apache server lanciare da terminare, la
seguente linea di comando:
sudo apt-get install tasksel
Ora basterà seguire l’installazione guidata, premendo invio quando richiesto.
L’installazione completa è quella del Lamp server, che consiglio di fare. Per
trovare la procedura di installazione completa, basta dare un’occhiata alla
pagina ufficiale di UDOO
http://www.udoo.org/ProjectsAndTutorials/udoo-web-server/
Una volta completa la procedura, è necessario installare il client di MySQL;
esso è disponibile nelle principali piattaforme ed è possibile scaricarle dal
seguente link http://www.mysql.it/products/workbench/
Realizzazione basi di dati
Come discusso in precedenza, per salvare i dati è necessario/conveniente
usare un DB MySQL. Nel passo precedente è stato installato il server MySQL,
sfruttando l’installazione automatica con tasksel. Durante tale installazione
è stata impostata una password di root per gestire il DB.
Per poter accedere anche da remoto al server, è necessario effettuare una
piccola modifica al file /etc/mysql/my.cnf, in particolare alla riga relativa
a bind-address:
bind-address = 0.0.0.0
In questo modo sarà possibile accedere alla base di dati anche da remoto,
effettuando il port-forwarding delle porta 3306 sul proprio router.
Per creare lo schema della stazione meteo, come indicato precedente, occorre
selezionare la voce
“Create new schema” e chiamarlo con il nome WeatherStation. Da qui sarà
necessario creare due tabelle, una con il nome Data e una chiamata Device. La
prima e la seconda dovranno avere i seguente attributi, con i relativi tipi:
Ora che abbiamo creato il nostro schema, è possibile effettuare alcune query,
che non sono altro che interrogazioni, per visualizzare certi valori, come ad
esempio il valore massimo e minimo di temperatura in un certa giornata, i
valori di temperatura in certe ore etc…
Ecco alcuni esempi utili:
Ultimo aggiornamento
Select *
From Data
WHERE Hour(Time)=HOUR(Current_TIME) && Minute(Time)=MINUTE(Current_Time)-1
Dati della giornata
Select *
From WeatherStation.Data
Where Date = CURRENT_DATE && Minute(WeatherStation.Data.Time)=00
Order by Time
Valori Max e Min per giornata
Select Max(Temperature),Min(Temperature), Max(Humidity), Min(Humidity), Date
From Data
Group by date
Caricamento file PHP sul server
Ultimo passaggio che ci rimane è quello di creare una pagina web, dalla quale
sarà possibile visualizzare i valori valori raccolti e le relative
interrogazioni che desideriamo.
Per poter interrogare facilmente un DB da una pagina WEB, è necessario
utilizzare un linguaggio lato server che si chiama PHP. Esso un linguaggio
abbastanza standard da usare e comprendere; l’unica nota utile da fare è che
tutte le variabili in PHP sono indicate con $nome_variabile = .
Ho realizzato, per semplice comodità, alcune pagine PHP utili per la stazione
meteo.
Sono già pronte all’uso, a patto di modificare il file mysql.php, che
contiene i dati d’accesso al database. I file PHP sono reperibili all’interno
della cartella PHP, che è presente nella repo di Github.
Le operazioni da fare per il progetto sono:
Installare il codice di Arduino per il client, che contiene il DHT22
Installare il codice di Arduino per il server, a cui è connessa la
scheda Ethernet
Installare su PC/Raspberry/UDOO i componenti MySQL server, Apache etc…
Creare lo schema del DB
Caricare le pagine WEB PHP nella cartella WWW del server