Antes de comenzar a programar la estación meteorológica si no habéis visto el post anterior sobre
la configuración de la Raspberry echadle un vistazo para aseguraros de que vuestra Raspberry está debidamente configurada para poder utiliziar el sensor
BMP180.
Entonces cómo comente en la presentación del blogg el objetivo principal de esta serie de posts será la de implementar una
estación meteorológica en un Raspberry y además, subir los datos que recojamos a un canal en
ThingSpeak para poder ver los datos que recoge nuestro sensor en cualquier momento desde cualquier dispositivo con acceso a internet. Para ello, si es que todavía no tenéis una cuenta en ThingSpeak, debéis
registraros.
Una vez os halláis registrado no hace falta que hagáis nada más, ya que todo lo relacionado con la gestión de los canales lo haremos desde el programa. El programa tendrá cuatro partes principales, en la primera parte, haremos una petición al servidor de
ThingSpeak para que nos de una lista de los canales que tenemos operativos en nuestra cuenta. La segunda parte del programa, la utilizaremos para borrar todos los canales que tengamos operativos en ese momento con un nombre determinado, para no ir acumulando canales en cada ejecución del programa y no tener que perder el tiempo eliminándolos a mano desde la propia página. Es decir, cada vez que ejecutemos el programa crearemos un canal con el nombre Clima, por ejemplo, para subir los datos de la estación, por lo que con el fin de no tener varios canales con el mismo nombre lo que haremos será borrar los viejos automáticamente desde el programa antes de crear uno nuevo. La tercera parte del programa la dedicaremos a crear el canal y la última a leer la información del sensor y subir los datos.
Lo primero que haremos será crear un archivo tipo Python, para ello escribiremos en el terminal este comando sudo nano /home/pi/Documents/Programas/BMP180/estacion.py por su puesto, el directorio puede ser el que vosotros queráis. Después de haber hecho esto se nos abrirá el editor de texto donde comenzaremos a escribir el programa.
Lo primero que haremos será importar todas las librería que necesitemos a lo largo del programa, para ello utilizaremos la sentencia import.
import Adafruit_BMP.BMP085 as BMP085
import urllib
Después para facilitar el uso de las funciones del sensor haremos lo siguiente:
sensor = BMP085.BMP085()
De esta manera siempre que queramos leer una de las variables que recoge el sensor sólo tendremos que escribir
sensor.función en lugar de
BMP085.BMP85().función. Ahora bien, una vez aquí comenzaremos con la primera de las cuatro partes principales del programa, la petición para conseguir la lista de canales que tenemos en nuestra cuenta. Pero antes, explicaré como funciona ThinSpeak.
Si nos metemos en nuestro perfil y vamos al apartado
Account>>My profile veremos en la aparte de la derecha un apartado con el título
ThingSpeak Settings donde veremos otros tres apartados Time zone,
User API Key y MQTT API Key. Ahora mismo, a nosotros sólo nos interesa la
User API Key, esta contraseña se utiliza como una especie de identificador, cada vez que queramos hacer trabajar a nivel usuario dentro de
ThingSpeak, es decir, para crear un canal, borrarlo etc. necesitaremos incluir este identificador en la petición que le hagamos a la página.
Para hacer una petición sea la que sea, siempre tendremos que seguir una serie de pasos, primero estableceremos conexión con la página a la que queremos acceder, segundo especificaremos el método que vamos a utilizar que por lo general será,
GET para pedir información a la página y
POST para mandar información a la página. Después crearemos la
URI, la cual nos permitirá acceder a una sección determinada dentro de la página, para después especificar qué es lo que se quiere enviar o lo que se quiere recibir (
párametros). Una vez hecho esto, juntaremos todo (lo codificaremos), el método, la
URI y los
párametros y haremos la petición a la página. Por último, recibiremos la respuesta de la página y la decodificaremos para ver si todo ha ido bien y e el caso de que no haya sido así ver que es lo que ha fallado.
Dicho esto, veremos que es lo que debemos enviar para conseguir que
ThingSpeak nos devuelva el listado de todos los canales que tenemos en nuestra cuenta. Para ello accederemos al siguiente
enlace. Si nos fijamos se puede ver que hay un listado de diferentes funcionalidades, si hacemos click en una de ellas se nos abrirá otra página, donde aparecerá explicado cuales son el
método, URI y parámetros a enviar a la hora de hacer una petición a
ThingSpeak para esa funcionalidad en concreto. Entonces, si queremos obtener un listado de todos los canales que hay en nuestra cuenta haremos click sobre
List All You Public Channels. Cabe destacar que el formato con el que enviaremos y recibiremos los datos será
JSON ya que nos facilitará mucho las cosas a la hora de desglosar la información.
El código para la obtener la lista de los canales y la definición de las claves quedarán de la siguiente manera:
Write_API_Key = "" #Clave que necesitaremos para escribir en el canal que vamos a crear
Read_API_Key = "" #Clave que necesitaremos para leer desde el canal que vamos a crear
User_API_Key = "XXXXXXXXXXXXXXXX" #Clave de usuario mencionada antes, aquí cada uno pone la suya
print "--> Creando Conexion TCP..."
conn_TCP = httplib.HTTPConnection("api.thingspeak.com") #Expresión para crear la conexión con ThinSpeak
conn_TCP.connect() #Estableciendo conexión
print "--> Conexion TCP establecida"
print "--> Lista de canales del usuario"
print "--> Enviando peticion HTTP"
metodo = "GET"
uri = "/channels.json"
cabeceras = {'Host': 'api.thingspeak.com',
'Content-Type': 'application/x-www-form-urlencoded'}
params = {'api_key': User_API_Key,
}
params_encoded = urllib.urlencode(params) #Codificación de los parametros
print " Params: " + params_encoded
cabeceras['Content-Length'] = len(params_encoded)
conn_TCP.request(metodo, uri, headers=cabeceras, body=params_encoded) #Juntamos toda la información para hacer la petición
print "--> #Peticion HTTP enviada"
print "--> #Recibiendo respuesta HTTP"
respuesta = conn_TCP.getresponse() #Respuesta a la petición del listado de canales
estatus = respuesta.status #Código para saber si ha habido errores
print " Status: " + str(estatus)
contenido = respuesta.read() #Contenido de la respuesta
print " Contenido: " + contenido
El contenido de la respuesta tendrá la siguiente forma:
Como podemos apreciar en la imagen anterior, el contenido del mensaje es muy difícil de entender a simple vista, por lo tanto utilizaremos un
desglosador de información json para ver que como extraer la información que nos hace falta para identificar el canal que queremos borrar. Para utilizar el desglosador basta con copiar el contenido de de la respuesta y hacer click en Viewer, al hacerlo pasaremos de ver el contenido como en la imagen anterior a verlo de la siguiente manera.
Entonces, vista la forma desglosada de la información que aparece en el json que nos devuelve
ThingSpeak cuando le pedimos el listado de los canales, teniendo en cuenta que si queremos borrar canales con un nombre determinado tenemos que acceder al
atributo 'name' para obtener el nombre de dicho canal. Una vez explicado como obtener el atributo al que queremos acceder, veremos ahora cuales son
el método, URI y parámetros que debemos enviar en la petición para poder borrar un determinado canal. Para ello, al igual que antes, accederemos al siguiente
enlace. Una vez ahí, miraremos en la lista de acciones cual es la que nos interesa, en este caso
Delete a Channel. Como podemos ver, el método ahora será
DELETE, la
URI será
/channels/ la ID del canal.json y los parámetros a enviar serán la
ID del canal a borrar y la
User API Key, que como podemos apreciar en al imagen anterior, es otro de los datos que nos proporciona el json que nos devuelve
ThingSpeak cuando hacemos la petición para obtener el listado de nuestros canales.
Entonces el código para borrar el un canal con un nombre determinado quedará de la siguiente manera:
contenido_parseado = json.loads(contenido)
nChannels = len (contenido_parseado)
cont = 0
while cont
identidad="contenido_parseado[cont][id]
nombre = contenido_parseado[cont][name]
if nombre == "Clima"
print "--> Borrando canal"
print "--> Enviando peticion HTTP"
metodo = "DELETE"
uri = "/channels/" +str(identidad) + ".json"
cabeceras = {'Host': 'api.thingspeak.com',
'Content-Type': 'application/x-www-form-urlencoded'}
params = {'api_key': User_API_Key,
'id': identidad
}
params_encoded = urllib.urlencode(params)
print " Params: " + params_encoded
cabeceras['Content-Length'] = len(params_encoded)
conn_TCP.request(metodo, uri, headers=cabeceras, body=params_encoded)
print "--> Peticion HTTP enviada"
print "--> Recibiendo respuesta HTTP"
respuesta = conn_TCP.getresponse()
estatus = respuesta.status
print " Status: " + str(estatus)
contenido = respuesta.read()
print " Contenido: " + contenido
cont = cont +1
Una vez aquí pasaremos a la creación de un nuevo canal al cual subiremos los datos. Para ello como hemos hecho anteriormente primero analizaremos cuales son
el método, URI y parámetros que debemos enviar en la petición. Como ahora queremos crear un canal dicha información estará en
Create a Channel. Ahora, el método será
POST, la
URI será
/channels.json y los
parámetros serán toda la infromación relativa al canal (User API Key, los datos que se van a subir, el nombre del canal etc.) En esta aplicación en concreto subiremos
tres datos:
la temperatua, la persión atmosférica y la presión de saturación del vapor. Entonces el código para la creación del canal quedará de la siguiente forma:
print "--> Creando canal en ThingSpeak"
print "--> Enviando peticion HTTP"
metodo = "POST" #definimos el método
uri = "/channels.json" #definimos la URI
cabeceras = {'Host': 'api.thingspeak.com',
'Content-Type': 'application/x-www-form-urlencoded'}
params = {'api_key': User_API_Key, #Definimos los parámetros
'field1': "Temp (C)",
'field2': "P (Pa)",
'field3': "Psat(Pa)",
'name': "Clima",
'public_flag': 'true'}
params_encoded = urllib.urlencode(params) #codificamos la información
print " Params: " + params_encoded
cabeceras['Content-Length'] = len(params_encoded)
conn_TCP.request(metodo, uri, headers=cabeceras, body=params_encoded) #hacemos la petición
print "--> Peticion HTTP enviada"
print "--> Recibiendo respuesta HTTP"
respuesta = conn_TCP.getresponse() #obtenemos la respuesta
estatus = respuesta.status
print " Status: " + str(estatus)
contenido = respuesta.read()
print " Contenido: " + contenido #visualizamos al respuesta para ver si ha habido algún error
Después de crear el canal ya sólo nos queda ver cómo subir los datos, para ello seguiremos el mismo proceso que las anteriores veces. En primer lugar, veremos cuales son
el método, URI y parámetros necesarios para subir los datos cuya información obtendremos en
Update a Channel Feed. Como podemos ver en el enlace anterior para poder actualizar los datos será necesario obtener la
Write Apy Key del nuevo canal. Para ello, lo haremos de igual modo que lo hicimos para obtener el nombre y la ID del canal que queríamos borrar.
Entonces, la última parte del código, la relativa a la subida de los datos quedará de la siguiente manera:
contenido_parseado = json.loads(contenido) #Desglosamos la información obtenida al crear el canal
Write_API_Key = contenido_parseado['api_keys'][0]['api_key'] #Conseguimos la Write APY Key
while True: #Entramos en un bucle infinito para subir datos durante un periodo de tiempo indeterminado
Temp = sensor.read_temperature() # Obtenemos la temperatura en Celcius del sensor
Psat = 611.2*math.exp((17.62*Temp)/(243.12+Temp)) #calculamos la presión de saturación
P = sensor.read_pressure() #obtenemos la presión atmosférica
print "Temp= " + str (Temp) + "C"+ " P = " +str (P) + "Pa"+ " Ps = " + str (Psat) #visualizamos los datos que vamos a subir
print "--> Subiendo datos a ThingSpeak"
print "--> Enviando peticion HTTP"
metodo = "POST" #definimos el método
uri = "/update.json"#definimos la URI
cabeceras = {'Host' : 'api.thingspeak.com',
'Content-Type': 'application/x-www-form-urlencoded'}
params = {'api_key' : Write_API_Key, #definimos lo parámetros
'field1': Temp,
'field2': P,
'field3': Psat
}
params_encoded = urllib.urlencode(params) #codificamos la información
print " Params: " + params_encoded
cabeceras['Content-Length'] = len(params_encoded)
conn_TCP.request(metodo, uri, headers=cabeceras, body=params_encoded) #hacemos la petición
print "--> Peticion HTTP enviada"
print "--> Recibiendo respuesta HTTP"
respuesta = conn_TCP.getresponse() #obtenemos la respuesta
estatus = respuesta.status
print " Status: " + str (estatus)
contenido = respuesta.read()
print " Contenido: " + contenido #visualizamos al respuesta para ver si ha habido errores
time.sleep(15) #esperamos 15s para no saturar el canal
Con esto damos por finalizada la parte relativa al código python del proyecto. Por lo tanto, si ahora accedemos a nuestra cuenta de ThingSpeak deberíamos tener un nuevo canal denominado Clima, en donde se estarán subiendo nuevos datos de temperatura, presión atmosférica y presión de saturación cada 15s.
Comentarios
Publicar un comentario