En esta entrada se está continuando el proyecto de la Raspberry. En esta ocasión se van a descargar los datos de ThingSpeak y se van a graficar usando Google Charts, html y JavaScript. Como en el caso del programa de Python, esta entrada está muy relacionada con la entrada de la sesión 05. Como el caso anterior, si no has leído la entrada podría ser conveniente echarla un ojo antes de comenzar con esta.
Como siempre, si quieres saltarte toda la explicación, al final de la entrada tienes el código para copiar. Y si no, siempre puedes acudir a GitHub.
Reconstrucción de los datos
Como se querían subir datos cada 10 segundos, se han creado dos canales y se han subido los datos de forma alterna. Por tanto, el primer paso tras descargarlos será reconstruir los datos. Para descárgalos, se hará de forma análoga a la entrada de la sesión 05, solo que esta vez se trabajará con 3 callback functions. Estas funciones se usarán para descargar los datos a graficar. Las funciones que se tendrán serán como la siguientes:
<script type="text/javascript">
var jsonData01
function myCallback01(dataWeGotViaJsonp) {
jsonData01 = dataWeGotViaJsonp['feeds'];
};
</script>
Esta se realizará tres veces, para los datos del canal 01, los del canal 02 y, finalmente, los datos juntos. El código de las descargas quedará:
<script src="https://api.thingspeak.com/channels/CHANNEL_ID/feeds.json?results=40&callback=myCallback01" type="text/javascript"></script>
<script src="https://api.thingspeak.com/channels/CHANNEL_ID/feeds.json?results=40&callback=myCallback02" type="text/javascript"></script>
<script src="https://api.thingspeak.com/channels/CHANNEL_ID/feeds.json?results=80&callback=myCallback03" type="text/javascript"></script>
La cantidad de resultados pueden variar, pero es importante que los del canal 01 y 02 descarguen la misma cantidad y que la tercera función descargue el doble. Par esta última da igual el canal elegido, lo que se busca es crear la estructura, los datos ya se pisarán.
A la hora de reconstruir los datos es importante detectar cuál ha sido el último canal actualizado. Esto se puede realizar comparando los timestamp. Si el último canal actualizado es el 01, se comenzará la reconstrucción por el 02 y viceversa.
<script type="text/javascript">
var j =0;
for(var i=0; i<jsonData.length-1; i++) {
if(jsonData01[j]['created_at']>jsonData02[j]['created_at']){
j = i/2;
jsonData[i]['created_at'] = jsonData02[j]['created_at'];
jsonData[i]['field1'] = jsonData02[j]['field1'];
jsonData[i]['field2'] = jsonData02[j]['field2'];
jsonData[i+1]['created_at'] = jsonData01[j]['created_at'];
jsonData[i+1]['field1'] = jsonData01[j]['field1'];
jsonData[i+1]['field2'] = jsonData01[j]['field2'];
i = i+1;
} else {
j = i/2;
jsonData[i]['created_at'] = jsonData01[j]['created_at'];
jsonData[i]['field1'] = jsonData01[j]['field1'];
jsonData[i]['field2'] = jsonData01[j]['field2'];
jsonData[i+1]['created_at'] = jsonData02[j]['created_at'];
jsonData[i+1]['field1'] = jsonData02[j]['field1'];
jsonData[i+1]['field2'] = jsonData02[j]['field2'];
i = i+1;
};
};
</script>
Y de esta manera se tiene todos los datos en jsonData, con los valores de humedad, temperatura y tiempo bien ordenados. Importante, si no reconstruyes teniendo en cuenta el momento de actualización, al graficar podrías acabar encontrándote con algo como esto:
Graficando
Una vez se tiene los datos bien reconstruidos, graficar es casi lo más fácil. Puedes usar las librerías que más te gusten. En este caso se ha decidido trabajar con Google charts debido a que es muy sencillo de utilizar y perfectamente funcional.
Se van a crear dos gráficas lineales, una para la humedad y otra para la temperatura, y una tabla con los datos que aparecen en las gráficas para que sea más fácil buscar algún en concreto.
El proceso de introducción de los datos es idéntico al de la sesión 05, con la diferencia que en esta ocasión se tendrán 3 ids en el body en vez de tan solo uno. Dos de ellos corresponderán a las gráficas y el tercero será de la tabla.
<body>
<div id="hum_chart"></div>
<div id="temp_chart"></div>
<div id="table_div"></div>
</body>
La visualización sería la siguiente: