Bando alle ciance e iniziamo a parlare della parte puramente software del mio progetto. Come avevo detto nella prima puntata, volevo creare un sito che permettesse di raccogliere i dati dei sensori e poterli poi visualizzare assieme a vari grafici e simili, quindi un cosiddetto sito dinamico, per far ciò dobbiamo usare un linguaggio di scripting lato server e un gestore di database, per non parlare di un WebServer che è ovviamente necessario.
Indice |
I linguaggi
In ambito WEB per la gestione dei siti dinamici ci affidiamo solitamente a delle squadre di programmi, che ormai sono diventati la norma:
- Apache – MySQL – PHP (Piattaforma LAMP)
- IIS – MSSQL – ASP
La prima è composta da programmi OpenSource, la seconda è la suite di Web Developing di Microsoft.
<premessa> Non sono una di quelle persone fissate con l’open-source che vede in ogni prodotto Microsoft il Male, ansi sono un assiduo programmatore Microsoft.</premessa>
La mia scelta è ricaduta su la prima terna di programmi, per questi motivi:
- Sono Open-Source e quindi gratuiti.
- Volendo usare come servizio di Hosting Altervista, questa piattaforma supporta solo PHP e MySQL.
- Conosco meglio il PHP che l’ASP.
Come avevo accennato in un puntata precedente, un’ ottima piattaforma per lo sviluppo di siti dinamici con questa accoppiata di programmi è EasyPHP, lo consiglio perché installandolo abbiamo subito disponibili tutti e tre i programmi correttamente configurati e quindi ci possiamo dedicare subito allo sviluppo del nostro sito.
Il PHP
Il PHP (Hypertext Preprocessor) è un linguaggio di scripting lato server che, come l’ASP, restituisce a chi fa richiesta di un pagina PHP, a seguito di una elaborazione lato server, un codice HTML. Il PHP riprende per molti versi la sintassi del C e alcuni elementi di Perl, è un linguaggio Debolmente Tipizzato, cioè le variabili presenti nel programma possono assumere varie forme, senza necessità di dichiarazione del tipo. Come abbiamo visto precedentemente, possiamo passare alle pagine PHP dei parametri tramite GET, POST, etc. Per questo sono implementati degli array Superglobali (cioè comuni non solo a tutta una pagina, ma ad un’intera sessione o comunicazione) che sono : • $_GET : viene passato tramite la stringa che compare nella barra dell'indirizzo del browser. • $_POST : viene passato in background • $_SESSION : rimane persistente durante la sessione Peculiarità degli array in PHP, è l’ammissione indice non solo di un numero, ma anche di un chiave formata da una stringa. Altra nota sul PHP che ci servirà per comprendere i vari listati, le variabili sono individuate dal carattere chiave $.
SQL
L’SQL (Structured Query Language) è un linguaggio di interrogazione per database progettato per leggere, modificare e gestire dati memorizzati in un sistema di gestione di basi di dati basato sul modello relazionale (RDBMS), per creare e modificare schemi di database, per creare e gestire strumenti di controllo ed accesso ai dati. SQL è un linguaggio per interrogare e gestire basi di dati mediante l'utilizzo di costrutti di programmazione denominati Query. Le query più utilizzate, tralasciando quelle necessarie alla creazione del database e della tabelle sono:
- SELECT (selezione dei dati dal database)
- INSERT (inserzione dei dati nel database)
- UPDATE (modifica dei dati del database)
- DELETE (eliminazione dei dati dal database)
Per la loro sintassi e una migliore comprensione rimando alla guida che ho inserito nella Sitografia.
Il MySQL
Il MySQL è un RDBMS (Relational DataBase Management System) composto da un client testuale e un server entrambi disponibili per le piattaforme Unix, Windows e GNU/Linux. Da diverso tempo riesce a interpretare il linguaggio SQL per l’interazione con i database relazionali e risulta una componente fondamentale della cosiddetta piattaforma LAMP che andrò a usare per il mio progetto. (spunti tratti da Wikipedia)
I Compiti del Sito
Come dicevamo il mio sito dovrà andare a gestire prevalentemente due cose :
- Raccolta Dati
- Visualizzazione Dati
Andiamo con ordine e vediamole entrambe.
Raccolta Dati
Analiziamo la struttura del database, il passaggio dei parametri e il codice della pagina che farà il lavoro.
Il database
I dati raccolti saranno immagazzinati in un database, quindi passiamo subito a spiegarne la struttura e le motivazioni del progetto.
Come vediamo il database è composto essenzialmente da 3 tabelle:
- Utente : Contiene i dati di ogni utente del sito che contribuisce a fornire dati dei propri sensori
- Sensore : Per ogni utente ci sono n sensori, che sono caratterizzati da un loro nome, una grandezza misurata e un range entro il quale il sensore opera (necessario per i limiti dei grafici).
- Lettura : Per ogni sensore abbiamo n letture, caratterizzate dal dato letto e dalla data e ora in cui sono state effettuate (inserita in automatico dal database).
Il linguaggio SQL permetterebbe anche di creare chiavi esterne con cui la connessione logica delle tabelle verrebbe implementata in automatico con aggiornamenti e cancellazioni in cascata, però altervista ha disabilitato il motore di database con la quale sono implementabili (InnoDB), quindi farò senza, gestendole in modo manuale. Le relazioni tra le tabelle sono di tipo 1:n ramificate, cioè allontanandoci dalla tabella utente (radice) i rami dell’albero del database aumentano.
Il codice PHP
Per passare i dati al sito dobbiamo usare quegli array superglobali di cui parlavamo prima. Per adesso e per semplicità ci affidiamo all’array $_GET, che ci permette di riempirlo aggiungendo in coda all’URL, una serie di parametri, vediamo come riempirlo. In coda all’URL inseriamo:
- il carattere ‘?’
- il nome della chiave da dare al campo dell’array
- il carattere ‘=’,
- il valore del campo dell’array (non dobbiamo specificare se si tratta di numeri o caratteri dato che PHP è debolmente tipizzato)
Per aggiungere un altro campo inseriamo il carattere ‘&’ e ricominciamo dal punto 2.
Es. www.miosito.it/raccolta_dati.php?id=1&val=3.6
Nota : attualmente ho abbandonato il passaggio dei valori con GET, spostandomi su POST, per avere una protezione migliore dei dati, dato che vengono passati “di nascosto”. In un futuro post farò un elenco delle migliorie apportate al progetto finale, ma adesso ho voluto mantenere il vecchio metodo per poterlo far funzionare con il programma dei passati post.
Adesso che abbiamo riempito l’array GET con l’id del sensore da aggiornare e il valore della lettura, non ci resta altro che scrivere la pagina PHP con la query SQL per inserire questo dato nel database. Da notare che impostando la trasmissione dei dati in questo modo, chiunque che digiti nella barra dell’indirizzo del browser un URL del genere potrebbe inserire una nuova lettura ad un sensore, quindi nella versione definitiva passerò alla pagina anche l’username e la password dell’utente a cui è associato il sensore da aggiornare per fare una verifica. Per prima cosa dobbiamo connetterci al database, per far ciò abbiamo bisogno di 4 informazioni, che ci vengono fornite da Altervista una volta attivato sul nostro dominio un servizio di database, e sono:
- Nome database
- Username
- Password
- Host
Inseriamo queste impostazioni in cima ad ogni pagina PHP assegnandole ad una variabile.
$host="localhost"; // Host name $username="my_username"; // Mysql username $password="my_password"; // Mysql password $db_name="db_name"; // Database name
Dopo di che inseriamo il codice necessario per connetterci al database con queste credenziali.
mysql_connect("$host", "$username", "$password") or die ("cannot connect"); mysql_select_db("$db_name") or die ("cannot select DB");
la clausola “or die” in PHP serve per il controllo degli errori, in quanto se la funzione non va a buon fine termina l’esecuzione di tutta la pagina e stampa la frase inserita tra parentesi. Dopo essersi connessi possiamo effettuare le query sul database, ecco come fare:
$sql="SELECT * FROM utente"; $result = mysql_query($sql);
Nella prima riga componiamo la stringa contenente la query da eseguire e la memoriziamo in $sql. Nella seconda riga eseguiamo la query inserendo in $result i dati forniti dalla sua esecuzione. Nel caso di una query di SELECT in result troverà posto una tabella che conterrà tutti i dati selezionati, che potranno essere letti oppure contati. Per leggere :
while($array = mysql_fetch_array($result)) { echo ($array[‘username’]);}
nell’array $array ad ogni ciclo del while sarà presente una riga della tabella fornita dalla query, ogni campo della riga attuale è recuperabile dall’array usando come indice il nome del campo della tabella che vogliamo. L’esempio stampa a video tutti gli username del database. Per contare:
$count=mysql_num_rows($result);
Dopo questo comando, in $count, troviamo il numero di righe della tabella restituita dalla query. Nel caso in cui la query che andiamo a fare non sia una select, ci interessa solamente se questa è andata a buon fine. Controllo esecuzione :
>$sql="INSERT INTO lettura SET idsensore = 1 , lettura = 5.2"; if(mysql_query($sql)) echo("ok"); else echo(“errore”);
A seguito di questo codice verrà stampato a schermo OK, se la query è stata eseguita, ERRORE altrimenti.
La pagina di ricezione
Nella pagina definitiva passiamo tramite URL, l’username, la password, l’id del sensore e la sua lettura.
<?php $mypassword=$_GET['password']; $myusername=$_GET['username']; $host="localhost"; // Host name $username="my_username"; // Mysql username $password="my_password"; // Mysql password $db_name="db_name"; // Database name // Connect to server and select databse. mysql_connect("$host", "$username", "$password")or die("cannot connect"); mysql_select_db("$db_name")or die("cannot select DB"); $sql="SELECT * FROM utente WHERE username = '$myusername' AND password='$mypassword'";//controllo che l’utente esista $result = mysql_query($sql); $count=mysql_num_rows($result); if($count==1) { $array=mysql_fetch_array($result); $id_utente=$array['id_utente'];//recupero l’id_utente //inserire contenuto pagina if(isset($_GET['sensore']))//se la variabile è stata impostata { $id_sensore = $_GET['sensore']; if(isset($_GET['dato']) && is_numeric($_GET['dato'])) { $valore = $_GET['dato']; $sql="SELECT * FROM sensore WHERE id_utente = '$id_utente' AND id_sensore = '$id_sensore'";//controllo che esista il sensore $result = mysql_query($sql); $count=mysql_num_rows($result); if($count==1) { $sql1="INSERT INTO lettura SET id_sensore = '$id_sensore', lettura='$valore'";//inserisco il dato if(mysql_query($sql1)) { echo("ok"); } else { echo ('errore db'); } } else echo("codice sensore errato"); } else echo("formato valore non corretto"); } else echo("codice sensore mancante"); } else { echo "<h1>Area riservata - accesso negato</h1>"; die; } mysql_close();//chiudo la connessione ob_end_flush(); ?>
Visualizzazione Dati
Adesso la parte di facciata del sito, lascio a voi creare una homepage e delle pagina carine (a me non è mai riuscito, sono per le cose pratiche), parliamo della visualizzazione dei dati. Essendo una mole considerevole di informazioni, la cosa migliore è raggrupparle in un grafico per poterle esaminare nel loro insieme. Adesso quindi vi farò vedere come impostare una pagina contenente un grafico e una tabella con i dati che compongono il grafico. Per realizzare il grafico ho utilizzato un javascript chiamato dygraphs (link nella sitografia) che contiene molte funzioni per zoomare, annotare, etc. Basta fornirgli i dati e le impostazioni e al resto pensa lui. Ovviamente dobbiamo inserire nella directory del sito il file contenente lo script.
<?php ob_start(); $host="localhost"; // Host name $username="myUsername"; // Mysql username $password="myPassword"; // Mysql password $db_name="dbName"; // Database name // Connect to server and select databse. mysql_connect("$host", "$username", "$password")or die("cannot connect"); mysql_select_db("$db_name")or die("cannot select DB"); if(isset($_GET['sensore'])) { $id_sensore = $_GET['sensore']; $sql="SELECT nome,grandezza,valoreMax,valoreMin FROM sensore WHERE id_sensore='$id_sensore'"; $result = mysql_query($sql); $count=mysql_num_rows($result); $array=mysql_fetch_array($result); $nome = $array['nome']; $grandezza = $array['grandezza']; $ValMax = $array['valoreMax']; $ValMin = $array['valoreMin']; $giorni_grafico = $_GET['giorni'];//giorni dei dati da visualizzare if($count==1) {?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>Dati + Grafico</title> <script type="text/javascript" src="dygraph-combined.js"></script> </head> <body style="font-family: Arial;border: 0 none;"> <a href="http://tempduino.altervista.org/"><h1>TempDuino</h1></a> <hr> <div id="graphdiv" style="width:1000px; height:500px;">></div> <script type="text/javascript"> g = new Dygraph( // containing div document.getElementById("graphdiv"),"Date,<?php echo($nome)?>\n" <?php $tabella = "";//conterra il codice per la tabella $sql="SELECT TRUNCATE(lettura,2) as lettura, YEAR(data) as anno, MONTH(data) as mese, DAY(data) as giorno, HOUR(data) as ora, MINUTE(data) as minuti, data FROM lettura WHERE id_sensore = '$id_sensore' ORDER BY data DESC"; $result = mysql_query($sql); while($array=mysql_fetch_array($result)) { $tabella = $tabella."<td>".$array['data']."<td>".$array['lettura']."</tr>\n"; echo(" + "); echo "\"".$array['anno']."-".$array['mese']."-".$array['giorno']." ".$array['ora'].":".$array['minuti'].",".$array['lettura']."\\n\""; } ?> ,{valueRange: [<?php echo($ValMin);?>,<?php echo($ValMax);?>], title: "<?php echo($nome." (".$grandezza.")");?>" }); </script> <hr> <p> <?php echo("letture di ".$giorni_grafico." giorni del sensore : "); echo($nome." (".$grandezza.")");?> <br> <table border="1"> <tr><td>data<td >lettura</tr> <?php echo $tabella; echo("</table>"); } else echo("codice sensore errato"); } else echo("codice sensore mancante"); mysql_close(); ob_end_flush(); ?> </body> </html>
Possiamo notare che la pagina è composta da parti in PHP e altre in semplice HTML, questa cosa è utilissima, se non consigliata quando vogliamo inserire degli elementi statici nella pagina e soprattutto quando ne vogliamo definire la struttura. Per far ciò basta inserire i tag di inizio e fine del linguaggio PHP (<?php e ?>) per racchiudere il codice che il server deve interpretare come script. La parte interessante del codice si trova circa alla metà dove facciamo un SELECT di tutti dati di un sensore (il cui id ci è stato passato tramite $_GET) estraendo singolarmente anno, mese, giorno, ora e minuti dalla data per poter scrivere i dati così come vuole lo script, cioè: YYYY-MM-DD hh:mm, assieme al dato della lettura. Successivamente nel ciclo While, vado a comporre i dati per il grafico stampandoli sulla pagina nel giusto formato e riempiendo una variabile $tabella, con il codice per comporre una tabella che useremo poche righe dopo. Per la sintassi estesa del grafico rimando al sito dello sviluppatore.
Il Sito Finale
Questo è il sito che sto sviluppando assieme a un mio amico, è in continua evoluzione, quindi se incontrate della pagine temporaneamente non funzionanti è colpa nostra, oppure se trovate dei bug segnalateceli così da risolverli. Altra richiesta, spero che non vada contro il regolamento, se visitate il sito e avete un filtro per la pubblicità, vi pregherei di disattivarlo sul mio sito perchè ho inserito UN SOLO banner nella homepage per cercare di ottenere qualche altercents (la valuta virtuale di Altervista) per mantenere un database con prestazioni leggermente migliori rispetto al minimo. Grazie!
Conclusioni
Siamo arrivati a destinazione, il progetto è completo, spero che vi sia piaciuto, ma soprattuto spero sia stata un’occasione per crescere e per imparare cose nuove, per me è stata un’esperienza magnifica che mi ha permesso di ampliare le mie conoscenze e di condividerle con gli altri.
Vogli ringraziare tutti gli utenti che mi hanno seguito e che si sono fatti sentire tramite commenti o tramite messaggi e con il quale mi sono potuto confrontare.
Il ringraziamento più grande va alla community di ElectroYou che mi ha permesso di imbarcarmi in questo progetto e che mi ha sostenuto.
Ultimo, ma non meno importante, voglio nominare gohan e angus che mi hanno dato delle dritte non da poco sul metodo POST per la comunicazione http, di cui vi parlerò in futuro.
Questo non è un addio, ci mancherebbe, è un arrivederci, perché ho intenzione di pubblicare dei brevi post sulle migliorie che ho apportato al sistema e sulla community di sensori che potrebbe nascere (ho un amico che si è da poco imbarcato nel progetto, quindi il sito è in evoluzione).
Quindi CIAO a tutti!!!
Sitografia
Link agli articoli del progetto
Web Stazione Meteo con Arduino [1] - L'idea
Web Stazione Meteo con Arduino [2] - La Rilevazione dei Dati
Web Stazione Meteo con Arduino [3] - Il Primo Circuito di Prova
Web Stazione Meteo con Arduino [4] - Il circuito definitivo e la comunicazione http
Web Stazione Meteo con Arduino [5] - Appendice 1 : Le Reti spiegate a mia Nonna