AnalogDemo: plot di dati e invio a Pachube in C#

luca 08/11/2011 2

In questo articolo vi mostrerò come ricevere dati dalla porta seriale, inserirli in un grafico ed inviarli a Pachube.

Pachube si definisce “una piattaforma di dati in realtime per l’Internet delle ‘cose’; piattaforma che gestisce milioni di dati al giorno per migliaia di utenti in tutto il mondo”. Si tratta infatti di un sito che consente di inviare dati propri, ottenerne una rappresentazione grafica e ricevere dati di altri utenti; si parla di “Internet delle cose” alludendo al fatto che molto spesso i dati vengono inviati da dispositivi direttamente collegati ad Interner (ad esempio un contatore Geiger basato su piattaforma Arduino, qui il grafico dei dati raccolti).

Il programma che vi illustrerò in questo articolo ha una doppia funzionalità:

  • riceve dati via seriale (ad es. da un modulo Arduino) e li rappresenta su un grafico;
  • aggiorna, con gli stessi dati, un datastream di un feed su Pachube.

Il nome del programma (“AnalogDemo“) deriva dal fatto che inizialmente è stato pensato per ricevere come dati la lettura di una porta analogica di Arduino (valori 0-1023, direttamente proporzionali alla tensione in ingresso).

Per iniziare, vediamo come gestire un nuovo feed in Pachube: se non abbiamo già un account, iscriviamoci al sito, confermiamo l’iscrizione ed eseguiamo il login.

Scegliamo Create a feed:

Inseriamo un nome e una descrizione:

Quindi in basso creiamo un nuovo datastream e confermiamo con Save:

Clicchiamo ora su My feeds:

Selezioniamo il feed appena creato:

Prendiamo nota del feed id che compare nella barra degli indirizzi del nostro browser:

Pachube ha un meccanismo di chiavi che funzionano come password per poter accedere ai nostri feed. Ad ogni utente viene assegnata una master key principale, che dovrebbe essere tenuta segreta. Per questo andiamo a generare una nuova chiave con i soli diritti per aggiornare (PUT) i nostri feed.

Clicchiamo su My keys:

Quindi su Create a new API key:

Selezioniamo il solo metodo PUT, volendo inoltre possiamo restringere l’uso di tale chiave a determinati indirizzi IP sorgenti oppure dare una data di scadenza:

Infine prendiamo nota della nuova chiave:

Nella prossima pagina, vedremo il funzionamento del programma…
Per poter testare il funzionamento del programma senza dati reali da visualizzare, ho scritto un semplice sketch per Arduino che, ogni 5 secondi, invia sulla porta seriale un valore random nello stesso range di valori di analogRead():

void setup() {
 
  Serial.begin(9600);
  randomSeed(analogRead(0));
}
 
void loop() {
 
  int randomValue = random(0, 1023);
  Serial.println(randomValue, DEC);
  delay(5000);  
}

Programmiamo quindi lo sketch in Arduino e colleghiamolo al nostro PC.

Lanciamo il programma ed inseriamo i parametri del nostro datastream

  • API key
  • Feed ID
  • Datastream ID

Attiviamo Send data se vogliamo aggiornare il datastream con i dati in arrivo:

Selezioniamo la porta seriale a cui è collegato il nostro Arduino e premiamo Connect… dopo qualche secondo sul grafico inizieranno ad apparire i valori ricevuti:

Gli stessi dati saranno visualizzati anche nel grafico sul sito di Pachube:

Nell’ultima pagina di questo lungo articolo, analizzeremo in dettaglio il codice sorgente…

Analizziamo il sorgente del programma:

Nel costruttore della Form1 vengono istanziati ed inizializzati gli oggetti principali; in particolare viene configurata la chartArea dell’oggetto chart1, modificando le proprietà degli assi (intervalli, valori minimo/massimo, colori).
L’asse X viene configurato per visualizzare un orizzonte temporale di 300 secondi (costante CHART_SECONDS):

DateTime minValue = DateTime.Now;
DateTime maxValue = minValue.AddSeconds(CHART_SECONDS);
chart1.ChartAreas[0].AxisX.Minimum = minValue.ToOADate();
chart1.ChartAreas[0].AxisX.Maximum = maxValue.ToOADate();

Sempre nel costruttore viene creata la serie dati che conterrà i dati ricevuti e vengono impostati alcuni parametri (nome, tipo di grafico, spessore e colore della linea, tipo di dati per l’asse X):

mySerie = new Series("AnalogInput");
mySerie.ChartType = SeriesChartType.FastLine;
mySerie.BorderWidth = 1;
mySerie.Color = Color.Red;
mySerie.XValueType = ChartValueType.DateTime;
chart1.Series.Add(mySerie);

Nei metodi legati agli eventi di load della form e di click del pulsante Connect viene gestita la comunicazione con la porta seriale, in maniera simile a quanto già visto nei tutorials presenti in questo sito:

  • elenco delle porte seriali disponibili e loro aggiunta ad una combobox
  • creazione di un oggetto SerialPort e apertura della connessione (9600 baud 8N1)
  • aggiunta di un handler per l’evento DataReceived

Il metodo serialPort_DataReceived, handler di DataReceived, chiama – tramite metodo delegate - AddData() che si occupa effettivamente di aggiornare grafico e datastream.

Tale metodo riceve il dato dalla porta seriale e lo aggiunge al grafico, impostando come valore sull’asse X il timestamp attuale:

DateTime timeStamp = DateTime.Now;
string stringValue = serialPort.ReadLine();
chart1.Series[0].Points.AddXY(timeStamp, Double.Parse(stringValue));

Quindi calcola il primo dato da visualizzare, togliendo dal timestamp attuale 300 secondi e rimuove i dati più vecchi di tale timestamp. Infine sposta l’asse X in modo da centrarlo sui dati rimasti (impostando come origine il primo di essi) e invalida il grafico in modo che venga ridisegnato:

double removeBefore = timeStamp.AddSeconds(-CHART_SECONDS).ToOADate();
while (mySerie.Points[0].XValue < removeBefore)
{
    mySerie.Points.RemoveAt(0);
}
chart1.ChartAreas[0].AxisX.Minimum = mySerie.Points[0].XValue;
chart1.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(mySerie.Points[0].XValue).AddSeconds(CHART_SECONDS).ToOADate();
chart1.Invalidate();

Se è richiesto l’aggiornamento di Pachube, verifica che tutte le informazioni siano corrette e utilizza l’oggetto WebClient per chiamare con il metodo PUT l’indirizzo di aggiornamento del datastream:

string updatePath = "http://api.pachube.com/v2/feeds/" + tbFeedId.Text + "/datastreams/" + tbDatastreamId.Text + ".csv";

inserendo negli headers della chiamata HTTP la API Key specificata e gestendo eventuali errori di connessione:

webClient.Headers.Set("X-PachubeApiKey", tbAPIKey.Text);
try
{
    webClient.UploadString(updatePath, "PUT", stringValue);
}

Per semplicità ho deciso di utilizzare la modalità di aggiornamento in formato csv come indicato nella documentazione.

Nel concludere, vi ricordo che tutto il materiale (programma già compilato e sorgenti) è disponibile nel mio repository su GitHub e che nel forum di questo sito sono disponibile per domande/richieste.

2 Comments »

  1. mario 25/01/2012 at 09:13 - Reply

    Ciao Luca, progettino interessante, ho trovato in giro questa utility per Excel, solo fino al 2003, per rappresentazione grafica di dati da seriale.
    http://www.parallax.com/ProductInfo/Microcontrollers/PLXDAQDataAcquisitiontool/tabid/393/Default.aspx
    molto interessante se non l’hai già vista.
    Ci si vede
    Ciao

Leave A Response »