Dashboard in SVG

luca 22/01/2012 12

Il seguente tutorial ha l’obiettivo di mostrare come è possibile realizzare una dashboard accessibile via web per visualizzare in modo grafico dei dati… il tutto utilizzando lo standard di grafica vettoriale SVG.

Introduzione

Ero alla ricerca di un modo per visualizzare in maniera grafica i dati di un mio feed su Pachube, creando una dashboard che fosse disponibile via web e senza utilizzare tecnologie proprietarie (Flash…) quando ho trovato questo blogpost di Andrew Hazelden dove mostrava come fosse possibile modificare dinamicamente un file grafico SVG. La stessa tecnica viene utilizzata da un altro progetto opensource di raccolta dati, Nimbits.

I vantaggi principali nell’uso di SVG sono i seguenti:

  • è un formato standard, tutti i principali browser sono in grado di visualizzarlo;
  • è un formato vettoriale, le immagini possono quindi essere ridimensionate senza perdere qualità;
  • è basato su XML, quindi facilmente modificabile.

In questo tutorial vi mostrerò quindi come:

  • preparare un file template con un editor SVG (Inkscape);
  • modificare tale template in base a dati esterni utilizzando il linguaggio PHP;
  • ricevere dati da un feed Pachube sempre con PHP.

Potete scaricare tutto il materiale (template SVG, sorgenti PHP) dal repository su GitHub; inoltre è disponibile una demo online all’indirizzo: http://www.lucadentella.it/demo/pachube.php

Nella prossima pagina vedremo come creare il template della nostra dashboard

Il template in SVG

Il primo passo per realizzare la dashboard è preparare un template in SVG. Vi sono molti programmi di grafica vettoriale che supportano tale formato; il mio consiglio è quello di utilizzare Inkscape, opensource e di cui è disponibile anche una versione portable.

Molto importante è disegnare visualizzando la griglia (menu View – Grid):

Per prima cosa, disegnamo la parte “statica” della dashboard: nell’esempio che vi propongo la dashboard sarà composta da un termometro e da una indicazione testuale della temperatura. Se non conoscete ancora Inkscape, in rete potete trovare ottimi tutorial (es. 1 e 2) per imparare ad utilizzarlo.

Nel disegno del termometro è molto importante identificare il numero di unità che corrispondono all’incremento di un grado (nella scala dell’esempio, 1 grado = 5 unità):

Aggiungiamo al disegno le componenti che varieranno al variare del valore da rappresentare: un rettangolo che rappresenta l’altezza del liquido nel termometro e la scritta. Non è importante il particolare valore che utilizziamo:

Apriamo ora l’editor XML (menu Edit – XML Editor…):

Selezionando un elemento del disegno, è possibile visualizzarne le corrispondenti proprietà nel sorgente XML. Selezioniamo il rettangolo e proviamo a modificare la proprietà height (dopo aver modificato il valore, confermiamo con CTRL+INVIO):

Se il rettangolo si è allungato nella direzione sbagliata (verso il basso), utilizziamo il comando Object – Flip Vertical per ruotarlo di 180°:

Modifichiamo la proprietà id assegnando un nome più significativo all’oggetto (es. temp_level):

Selezioniamo la scritta e anche per questo oggetto modifichiamo la proprietà id (es. temp_value):

Infine ridimensioniamo la “pagina” su cui stiamo disegnando: menu File – Document properties…, espandiamo Resize page to content… e clicchiamo Resize page to drawing or selection. Eventualmente possiamo aggiungere qualche pixel di margine attorno al nostro disegno:

Nella prossima pagina vedremo come rendere dinamico il nostro file SVG usando il linguaggio PHP…

PHP e XML

Come detto, un file SVG non è altro che un file di testo in formato XML: questo rende facile la sua modifica utilizzando le funzionalità della libreria SimpleXML di PHP.

Scriveremo del codice PHP che:

  • riceverà come parametro (GET, ovvero passato come suffisso alla URL nella forma ?parametro=valore) il valore da rappresentare;
  • caricherà il template SVG;
  • modificherà la proprietà height del rettangolo e il valore della scritta;
  • cambierà il colore di entrambi in base al valore (blu se minore di 15, rosso se maggiore di 25 altrimenti verde);
  • invierà il risultato al browser.

Leggiamo il valore del parametro “value” dall’array associativo $_GET:

$value = $_GET["value"];

Carichiamo il template leggendolo dalla cartella nella quale è presente anche il file PHP: otteniamo il path di tale cartella usando la costante __DIR__:

$root = __DIR__;
$svg_template = simplexml_load_file("$root/template.svg");

Otteniamo i nodi XML del rettangolo e della scritta con una query XPath che ricerca l’id impostato con Inkscape:

$result = $svg_template->xpath("//*[@id='temp_level']");
if(count($result) == 1) $temp_level = $result[0];
else exit("Unable to find a node with temp_level ID");
 
$result = $svg_template->xpath("//*[@id='temp_value']");
if(count($result) == 1) $temp_value = $result[0];
else exit("Unable to find a node with temp_value ID");

Modifichiamo l’altezza del rettangolo e il valore della scritta (il valore viene moltiplicato per 5 perché nella scala del termometro ad un incremento di un grado corrisponde un incremento di 5 unità):

$temp_level['height'] = $value * 5;
$temp_value[0] = $value;

Modifichiamo lo stile per adattare il colore al valore attuale:

if($value < 15) {
  $temp_level['style']="fill:#0000ff;stroke:none";
  $temp_value['style'] = "font-size:72px;fill:#0000ff";
} elseif($value < 25) {
  $temp_level['style']="fill:#00ff00;stroke:none";
  $temp_value['style'] = "font-size:72px;fill:#00ff00";
} else {
  $temp_level['style']="fill:#ff0000;stroke:none";
  $temp_value['style'] = "font-size:72px;fill:#ff0000";
}

Infine indichiamo al browser il corretto MIME Type ed inviamo il file XML modificato:

header("Content-type: image/svg+xml");
echo $svg_template->asXML();

Nella prossima pagina vedremo come ricevere dati da Pachube, sempre usando il linguaggio PHP…

PHP e Pachube

Per poter ricevere dei dati da Pachube, è necessaria una api key, legata al proprio account. Dal sito web di Pachube è possibile generare keys con diversi privilegi; per leggere i dati da un feed è sufficiente assegnare READ come permitted methods:

Nel file PHP vengono definite alcune costanti per la connessione a Pachube: la api key indicata sopra, il feed id, il datastream id e la posizione del campo da utilizzare all’interno della riga (normalmente ogni riga ricevuta ha il formato <datastream_id>,<timestamp>,<value>):

define("API_KEY", "myapikey");
define("FEED_ID", 29689);
define("DATASTREAM_ID", 0);
define("ELEMENT_POSITION", 2);

Per semplicità scegliamo la modalità di ricezione dati in CSV, costruendo l’URL come indicato nella guida:

$feed_url = "http://api.pachube.com/v2/feeds/" . FEED_ID . ".csv?datastreams=" . DATASTREAM_ID;

Per il collegamento al sito web di Pachube, utilizziamo la libreria cURL: con il metodo curl_init otteniamo un handle legato all’URL del feed di Pachube. Prima di eseguire la connessione, impostiamo le proprietà RETURNTRANSFER per ottenere da cURL la risposta del server e HTTPHEADER per specificare la nostra api key:

$curl_handle = curl_init($feed_url);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_handle, CURLOPT_HTTPHEADER, array('X-PachubeApiKey: ' . API_KEY));
$out = curl_exec($curl_handle);

Una volta effettuata la connessione, controlliamo l’HTTP_CODE restituito dal server di Pachube: se tale codice è 200, significa che la connessione è andata a buon fine e che Pachube ci ha restituito il valore richiesto. Dividiamo la risposta ottenuta usando come separatore la virgola (formato CSV) e prendiamo l’elemento che ci interessa:

$http_code = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);
if($http_code == "200") {
  $elements = explode(",", $out);
  $element = $elements[ELEMENT_POSITION];
}

Infine creiamo un iframe per visualizzare il termometro passando il valore letto da Pachube:

echo "<iframe src="thermometer.php?value=$element" frameborder="0" width="320" height="240"></iframe>;

Il risultato (con attiva la modalità di debug):

12 Comments »

  1. Lucio 30/06/2012 at 16:51 - Reply

    Gentile Luca Dentella,
    ho trovato interessantissimo il suo tutorial che riguarda il dashboard svg. Le chiederei gentilmente, se possibile, di fornirmi un esempio per visualizzare in forma grafica sul browser i valore di tensione letti sugli ingressi analogici dell’arduino uno in forma vu meter lineare (tipo il suo termometro) oppure classico a lancetta.
    Ringraziando anticipatamente, Le porgo distinti saluti.
    lucio.ra@libero.it

  2. A MacLeod 06/05/2013 at 22:24 - Reply

    Thanks for taking the time to document this, I used it as a basis for my own arduino project (a web-connected heating oil level monitor.)

    Getting a nice SVG-based level indication turned out to be easier than I had feared… strangely, getting it to send warning emails was trickier!

    http://s230.photobucket.com/user/macleodaj/media/Junk/oil_level_gauge.jpg.html

    • luca 07/05/2013 at 08:19 - Reply

      Hi! Thanks for your feedback and great SVG web interface!

Leave A Response »