Asterisk IOT: ¡Mis plantas me llaman por teléfono!

A estas alturas, metidos ya de lleno en el otoño, ya podemos decir sin duda alguna que una de las cosas destacadas del verano pasado fue el calor. Algún día diremos eso de «yo viví el verano del 16. ¡Eso sí que era calor!«. Mientras tanto, no nos queda más que adaptarnos. Y es que el calor nos afecta a todos. O si no preguntádselo a mis plantas. Aunque las observo a diario, muchas veces no sé si me quedo «corto» con los riegos y cuidados, pero ¿podría conseguir que ellas mismas me dijeran lo que necesitan? Claro que sí y la respuesta está en Asterisk.

El Internet of things o Internet de las cosas (IOT) es un concepto cada vez más extendido que parte de la premisa de interconectar e interactuar con los objetos que usamos a diario. Suena bien, ¿no? Nosotros queremos conocer el estado de salud de nuestras plantas y «controlarlas» en la distancia según sus necesidades. Si conectásemos sensores de temperatura, humedad o luz a nuestras plantas podríamos conseguirlo. Ahora bien, ¿cómo nos conectamos e interactuamos con estos sensores?

Uno de los retos a los que se enfrenta la industria IOT, es la necesidad de una estandarización de los protocolos de comunicación entre «las cosas» [1].  Nosotros partimos de la premisa de que una de las fuentes del conocimiento y la estandarización son las tecnologías abiertas. ¿Y qué es Asterisk? Una completa herramienta de telecomunicaciones abierta que, junto a una Raspberry Pi y unos sensores, nos abre caminos cuyo único límite es la imaginación. Para verlo más claramente, vamos a diseñar un proyecto escalable en 3 variantes, desde su mínima expresión, con una planta y un sensor, pasando por uno con varias plantas y sensores, hasta un ejemplo en el que tendremos diferentes ubicaciones geográficas, plantas y sensores.

Escenario general

Esquema

La idea es conectar un sensor de temperatura y humedad a una planta y que la planta nos alerte cuando los valores de temperatura o humedad sean superiores o inferiores a los valores límite (máximo y mínimo) que hayamos definido previamente para esa planta. La planta nos «informará» con una llamada telefónica a nuestro móvil mediante la cual nos dirá cosas como «Me estoy achicharrando», «Riégame un poquito» o «Estoy congelada».

Materiales

1 x Raspberry PI

1  x sensor DHT11

1 x resistencia

Creación de la BBDD

En principio, vamos a controlar una planta y 2 parámetros (temperatura y humedad) por lo que con una sencilla BBDD MySQL con 3 tablas será suficiente. Plantearíamos algo así:

FXO_settings_DTMF

Conexión del sensor DHT11

FXO_settings_DTMF

 

Este sensor es muy sencillo de conectar y existen múltiples ejemplos de código fuente en diferentes lenguajes para hacerlo funcionar. Podéis buscar más información [2]. Nosotros nos descargamos la versión en C. Antes de compilar, necesitamos instalar las dependencias básicas y la librería Wiringpi que permite controlar el acceso a los puertos GPIO.

Paso 1-Instalamos git y las librerías básicas para compilar

RPi#apt-get install git-core build-essential

Paso 2-Instalamos la librería Wiringpi

RPi#git clone git://git.drogon.net/wiringPi
RPI#cd wiringPi
RPI# ./build

Paso-3-Descargamos el archivo dht11.c y lo compilamos. Previamente tenemos que considerar el número de pin GPIO donde conectamos el sensor (en nuestro caso el 7)

#define DHT11PIN 7    //Este valor es el que hay que cambiar en función del Nº de PIN

RPi#gcc -o dht11 dht11.c -L/usr/local/lib -lwiringPi -lpthr

Paso 4-Ya podemos ver las lecturas de temperatura y humedad ambiental, bien juntas o de forma individual.

RPi#./dht11
RPI#./dht11 | awk -F "," '{print $1}'
RPI#./dht11 | awk -F "," '{print $2}'

 

Instalación de Asterisk en la Raspberry PI

Como no es la primera vez que instalamos Asterisk en un RPI, podemos recurrir a nuestros apuntes para hacer que el proceso sea sencillo. Los pasos necesarios los podemos consultar aquí.

Script de monitorización de Asterisk

En nuestro caso, creamos un script en Bash que realiza una lectura cada X segundos de la temperatura y humedad y comprueba si están dentro del rango min y max que hemos definido en las tablas temperatura y humedad de nuestra BBDD. En el caso de que la lectura no esté en rango, realiza una llamada y reproduce una locución del tipo «Tengo calor» o «Tengo frío», «Me estoy deshidratando», «Mis hojas se resecan», etc. Podría ser algo así:

(...)

while true;
do
  max_temp=`mysql -u $user -p $password -e "SELECT max_temp FROM Asterisk_IOT.temperatura limit 1"` # Como sólo tenemos una planta no nos complicamos ;)
  temp=`./dht11 | awk -F "," '{print $1}'` # Leemos la temperatura y la almacenamos en la var "temp"
  hum= `./dht11 | awk -F "," '{print $2}'` # Leemos la humedad y la almacenamos en la var "hum"

  if [[ "$max_temp" -gt "temp" ]]; then    # Si la temperatura que nos da el sensor es superior al límite superior, la planta nos llamará protestando por el calor
       asterisk -rx "channel originate SIP/612345678 application Playback tengo_calor" 
  fi

  # Aquí podríamos realizar el mismo proceso con el valor minímo de temperatura tolerado por la planta así como con la humedad.

  sleep 60                                 # Cada 60 segundos volvemos a comprobar
done
(...)

 

Escenario con múltiples plantas y sensores

Ahora que le hemos dado «voz» y «cuidados» especiales a nuestra planta, es posible que el resto de nuestro jardín quiera gozar de las mismas atenciones. Tenemos que plantear la forma de escalar nuestra infraestructura. Aquí proponemos un esquema sencillo con 3 IVR que nos permitirían seleccionar la planta, el sensor y la acción a realizar. Así, podemos añadir más plantas y sensores según necesitemos e interactuar con ellos remotamente gracias a Asterisk. En nuestro caso, contamos con 3 plantas y 5 sensores cada una, sobre las que queremos realizar las acciones de leer los datos del sensor, ajustar la sensibilidad, los límites de tolerancia de cada planta, etc.

FXO_settings_DTMF

IVR 1 Selección de planta

Reproduce locución «Seleccione_planta» y permite seleccionar la planta en la que vamos a consultar su estado.

 

1-Planta 1
2-Planta 2
3-Planta 3

[desde-plantas]

;Iniciamos IVR
exten => ivr1,1,Read(PLANT,locucion_selecciona_planta,,3)
exten => ivr1,n,GotoIf($["${READSTATUS}" != "OK"]?1);Si no es OK, volvemos a leer
exten => ivr1,n,GotoIf($[$["${PLANT}" != "1"] & $["${PLANT}" != "2"] & $["${PLANT}" != "3"]]?1) ;Si no es 1
 

 

IVR 2 Selección de sensor

Reproduce locución «Seleccione_sensor». Contamos con los siguientes sensores:

 

1-Temperatura
2-Humedad ambiental
3-Humedad sustrato
4-Luz
5-Monóxido de carbono

[desde-plantas]
exten => ivr2,1,Read(SENSOR,locucion_selecciona_sensor,,3)
exten => ivr2,n,GotoIf($["${READSTATUS}" != "OK"]?1); Si no es OK, volvemos a leer
exten => ivr2,n,GotoIf($[$["${SENSOR}" != "1"] & $["${SENSOR}" != "2"] & $["${SENSOR}" != "3"] & $["${SENSOR}" != "4"] & $["${SENSOR}" != "5"]]?1) ;Si no es 1,2 o 3, 4 o 5 volvemos a leer

 

IVR 3 Selección de acción a realizar

Reproduce la locución «Seleccione_acción». Permite seleccionar una de las acciones que vamos a poder configurar con nuestro Asterisk.

 

1-Leer sensor
2-Actualizar límites max y min en BBDD
3-Modificar intervalo entre lecturas del sensor
4-Ajustar la sensibilidad del sensor

[desde-plantas]
exten => ivr3,1,Read(ACCION,locucion_selecciona_accion,,3)
exten => ivr3,n,GotoIf($["${READSTATUS}" != "OK"]?1); Si no es OK, volvemos a leer
exten => ivr3,n,GotoIf($[$["${ACCION}" != "1"] & $["${ACCION}" != "2"] & $["${ACCION}" != "3"] & $["${ACCION}" != "4"]]?1) ;Si no es 1,2 o 3, 4 volvemos a leer
exten => ivr3,n,AGI(sensors.sh,"${PLANT}","${SENSOR}","${ACCION}")

 

Parte Dialplan

El AGI realiza la acción elegida sobre el sensor concreto de la planta pasada y devuelve la variable ${LECTURA} en el caso de que queramos conocer la lectura de un sensor, por lo que el dialplan continuaría teniendo en cuenta las diferentes opciones pasadas.

[desde-plantas]
exten => ivr3,n,GotoIf($["${ACCION}" = "1"]?leer:sigue1)
exten => ivr3(sigue1),n,GotoIf($["${ACCION}" = "2"]?limites:sigue2)
exten => ivr3(sigue2),n,GotoIf($["${ACCION}" = "3"]?interval:sigue3)
exten => ivr3(sigue3),n,GotoIf($["${ACCION}" = "4"]?sensibilidad:sigue4)
exten => ivr3(sigue4),n,Hangup;Si no es nunguna de las opciones anteriores colgamos la llamada
exten => ivr3(leer),n,Playback(locucion_lectura_es)
exten => ivr3,n,SayDigits(${LECTURA})
exten => ivr3,n,HangUp()
exten => ivr3(limites),n
;(...)
exten => ivr3(interval),n
;(...)
exten => ivr3(sensibilidad),n
;(...)

Si contamos con varias plantas y sensores, podemos trabajar un script en Python (contamos con numerosas librerías para leer los sensores) al que le pasaremos como argumentos la planta y el sensor a leer. La forma más sencilla sería seguir el planteamiento de los IVR y pasar el número de planta y sensor. (Ej. «leer_sensor.py 1 3»  devolvería la lectura de la humedad del sustrato de la planta 1).

AGI sensors.sh

En la última línea del IVR 3 pasamos los parámetros que hemos ido recogiendo en los 3 IVR (Planta, sensor y acción) mediante el AGI  «sensors.sh».

exten => ivr3,n,AGI(sensors.sh,"${PLANT}","${SENSOR}","${ACCION}")

Mediante este AGI comunicamos Asterisk con nuestros sensores y podemos realizar las diferentes acciones que queremos programar. Para el caso de la lectura de sensores, podemos usar los scripts que hemos desarrollado en Python previamente para las lecturas de los sensores:

En AGI sensors.sh

(...)
lectura=`read_sensor.py $planta $sensor` # Leemos la temperatura y la almacenamos en la var "temp"
echo "SET VARIABLE LECTURA $lectura"     # Creamos la variable de canal con la temperatura
(...)

Una vez que nuestro AGI ha devuelto la variable «Lectura», podemos reproducirla en dialplan con la función»SayNumber».

En dialplan

SayNumber(${LECTURA},c) ;Reproducimos la lectura medida

Por su parte, para otras acciones como actualizar los valores límite máx y min que queremos programar para una planta/sensor, podemos actualizar los cambios directamente en nuestro AGI. En este caso, le pasaríamos un argumento más ya que aparte de la acción, tendríamos que pasarle el valor nuevo (Ej. temperatura mínima tolerada por la planta 1) recogido previamente mediante otro IVR:

En dialplan

exten => ivr4,1,Read(VALOR,locucion_introduce_nuevoValor,,3)
exten => ivr4,n,GotoIf($["${READSTATUS}" != "OK"]?1); Si no es OK, volvemos a leer
exten => ivr4,n,GotoIf($[$["${VALOR}" < "0"] | $["${VALOR}" > "100"] ]?1) ;El valor será entre 0 y 100
exten => ivr4,n,AGI(sensors.sh,"${PLANT}","${SENSOR}","${ACCION}","${VALOR}")

En AGI sensors.sh

(...)
planta=$1   # Recogemos la planta 
sensor=$2   # Recogemos el sensor
accion=$3   # Recogemos la acción
valor= $4   # Recogemos el valor nuevo que tendría el sensor
mysql -u $user -p$password -e "UPDATE plantas.plant_temp SET min_temp='$valor' where id='$planta'"
(...)

Podríamos dejarlo mucho más elegante si usamos el AGI para reproducir locuciones personalizadas en función del sensor leído:

 

Escenario con múltiples sitios, raspberrys, plantas y sensores

Si es que era inevitable. Mis plantas (de ciudad) venga a presumir de sus capacidades tecnológicas mientras que las plantas del pueblo se sienten agraviadas. Así que no tengo más remedio que buscar la manera de «comunicarlas».  Tal vez lo más sencillo sea añadir un nuevo IVR previo a todos para seleccionar la ubicación y a partir de ahí seguir el mismo esquema (Ubicación => Planta => Sensor => Acción). Eso sí, necesitamos escalar nuestra infraestructura. Para ello, uno de los puntos a modificar sería nuestra BBDD.

Asterisk IOT multisitio, raspberrys y sensores

Revolución abierta

Que empresas como el gigante de la electrónica Siemens se hayan fijado en el sector IOT -¡y estén participando!- no es una casualidad sino el futuro inmediato. Y para ello, nos aportan 2 datos representativos con gran contraste entre sí.  Por un lado, los 26 billones de dispositivos IOT para 2020, pero por otro, lo que define como su gran «laguna«: la falta de standards [1]. Y no es la única voz que se ha pronunciado en ese sentido [3] [4] . Empresas de diferentes sectores coinciden en la necesidad de un sistema standard de comunicación IOT, desplegando las principales tecnologías empleadas actualmente. Es comprensible esta preocupación por la definición de estándares, sobre todo considerando la magnitud de la inversión necesaria para implantar una tecnología a la escala de casos como el de Siemens, marcando el camino de una tecnología unificada que permita usar un patrón común para comunicarse e interaccionar con dispositivos de naturaleza muy variada.

Y llegamos a la Cuarta Revolución Industrial, más conocida como Industria 4.0, donde no sólo interconectamos objetos y cosas, sino que tendemos a digitalizar todos los procesos productivos independientemente del sector.  ¿Y cuál es su singularidad? En nuestra opinión, la fuente de valor. Hasta ahora, cualquier producto industrial medianamente grande nos venía «dado«, generalmente por parte de un gran grupo empresarial (tan sólo unos pocos tenían acceso a la tecnología). Sin embargo, eso ha cambiado. La nueva industria nos «ofrece» las herramientas y nosotros tenemos en nuestra mano la posibilidad de generar el valor. Y lo mejor es que ese valor es incremental, porque para hacer nuestra vida más fácil, no sólo interactuamos con objetos sino que también podemos mejorar interactuando con personas. ¿Os suena? Precisamente lo que llevan haciendo hackers y desarrolladores de Software Libre durante años. Una filosofía de trabajo revelada visionaria y hoy demandada por la industria para buscar «caminos» entre infinitos destinos.

Con este modestísimo ejemplo sólo hemos pretendido poner de relieve lo mucho que tiene que aportar una herramienta como Asterisk, tratándose de un proyecto estable, maduro y abierto que lleva funcionando durante años. Si queréis, podéis echarle un vistazo a numerosos proyectos centrados en Asterisk como motor IOT [5], u a otros enfocados a cubrir la necesidad de protocolos de comunicación para proyectos IOT como Mosquitto [6]. Proyectos, ideas y conceptos hay muchos y no sabemos cuál de ellos se acabará imponiendo. Lo que sí sabemos es que será abierto o simplemente no será. ¡Revolución!



¿Te gusta este post? Es solo un ejemplo de cómo podemos ayudar a tu empresa...
Sobre Pedro Cadavid

Algún día hablaré. De momento, sólo escribo (entre líneas). ¿Me lees?

1 Comentario

¿Por qué no comentas tú también?

Queremos tu opinión :)