domingo, 15 de noviembre de 2020

Tratamiento de datos con Matlab

 Después de haber acumulado una cantidad aceptable de datos en la base de datos, lo siguiente que hay que plantearse es que hacer con ellos. Los datos se pueden utilizar de varias formas, pero para ello hay que empezar por leerlos de la base de datos. En el caso de ThingSpeak, el hecho de formar parte del entorno de Matlab facilita las cosas a la hora de descargarlos y trabajar con ellos. Para hacerlo, basta con emplear la función thingSpeakRead.

En este caso, para descargar los datos de los dos canales, se ejecuta la función como sigue:

[data,timestamps]=thingSpeakRead(1229899,'ReadKey','EPXZHT6725584ZBI',

'Fields',[1,2],'NumPoints',4,'OutputFormat','TimeTable')

Esta función proporciona la siguiente salida:

 

También se puede omitir la opción 'OutputFormat', y el resultado se almacenará en una matriz de 4x2.

Una vez obtenidos estos datos, se pueden, por ejemplo, obtener gráficas.

 

 

También se pueden trabajar los datos con funciones mas complejas. Por ejemplo, conociendo cual es la presión típica de las borrascas en la zona de Bilbao, se podría establecer una función que determinara si se avecina una borrasca en base a la evolución de este dato.

Cliente IoT

 Finalmente, es momento de juntar todo lo visto anteriormente en un único código para subir los datos de presión y temperatura del sensor a ThingSpeak. El hardware empleado como cliente IoT es una Raspberry Pi 4B y un sensor BMP 180, mostrados a continuación.


El funcionamiento del código es el siguiente. Al ejecutar, se crea un nuevo canal. Las claves API de lectura y escritura se almacenan, y se emplea la de escritura para enviar los datos al canal cada 15s. Se ha programado una excepción para que al presionar la combinación de teclas Ctrl+C, se detenga el programa y se borre el contenido del canal. 

Se ha optado por un tamaño de letra muy pequeño para que el código entre sin cortar, asi que pido disculpas por la inconveniencia. Aun así, el código del cuerpo del mensaje que crea el canal está dividido.

import time
import signal
import sys
import requests
import urllib.parse
import json
import Adafruit_BMP.BMP085 as BMP085


def handler(sig_num, frame):
uri = 'https://api.thingspeak.com/channels/'+str(channel_id)+'/feeds'
cabeceras = {'Host': 'api.thingspeak.com', 'Content-Type': 'application/x-www-form-urlencoded'}
cuerpo = {'api_key': 'XXXXXXXXXXXXXXXX'}
cuerpo_coded = urllib.parse.urlencode(cuerpo)
cabeceras['Content-Length'] = str(len(cuerpo_coded))

respuesta = requests.delete(uri, headers=cabeceras, data=cuerpo_coded)

descripcion = respuesta.reason


print('Borrado: ' + descripcion)
print('\nSignal handler called with signal ' + str(sig_num))
print('\nExiting gracefully')
sys.exit(0)


if __name__ == '__main__':
signal.signal(signal.SIGINT, handler)
print('Running. Press CTRL-C to exit.')

########################################################################################

metodo = 'POST'
uri = 'https://api.thingspeak.com/channels'
cabeceras = {'Host': 'api.thingspeak.com', 'Content-Type': 'application/x-www-form-urlencoded'}

cuerpo = {'api_key': 'XXXXXXXXXXXXXXXX', 'name': 'Datos_Clima', 'field1': 'Temperatura (ºC)',  
    'field2': 'Presion (Pa)'}

cuerpo_coded = urllib.parse.urlencode(cuerpo)
cabeceras['Content-Length'] = str(len(cuerpo_coded))

# print(cuerpo_coded)

respuesta = requests.post(uri, headers=cabeceras, data=cuerpo_coded)

estatus = respuesta.status_code
descripcion = respuesta.reason

print('Canal creado: ' + descripcion)

contenido_json = respuesta.content
diccionario_json = json.loads(contenido_json) # JSON2diccionario
channel_id = diccionario_json['id']

for each in diccionario_json['api_keys']:
if each['write_flag']:
write_api_key = each['api_key']

else:
read_api_key = each['api_key']


############################################################################################

while True:

sensor=BMP085.BMP085()

temp='{0:0.2f}ºC'.format(sensor.read_temperature())
print('Temp = '+temp)

pres='{0:0.2f} Pa'.format(sensor.read_pressure())
print('Pressure = '+pres)

metodo='POST'
uri='https://api.thingspeak.com/update'
cabeceras={'Host':'api.thingspeak.com', 'Content-Type':'application/x-www-form-urlencoded'}
cuerpo={'api_key':write_api_key,'field1':temp, 'field2':pres}
cuerpo_coded=urllib.parse.urlencode(cuerpo)

cabeceras['Content-Length']=str(len(cuerpo_coded))

respuesta=requests.post(uri, headers=cabeceras, data=cuerpo_coded)

estatus=respuesta.status_code
descripcion=respuesta.reason

time.sleep(15)
 
A continuación, se muestra la gráfica de presión mostrada en ThingSpeak tras la ejecución del código.