jueves, noviembre 12, 2015

El Internet de tus cosas con Edison y Sinfonier (II de III)

Ya está aquí la segunda entrega de nuestra experiencia de uso con la placa Intel Edison y, como lo prometido es deuda, en esta sección, tal y como adelantamos en la primera parte de la serie, pasamos a explicar en detalle la API REST en Python que hemos desarrollado para facilitar la integración hardware-software con la placa Intel Edison.

Figura 1: El IoT de tus cosas con Sinfonier & Intel Edison (Parte II)

Despliegue API REST en placa Intel Edison

Para desplegar esta API REST y que funcione correctamente lo primero es tener bien preparado el entorno en el que se va a ejecutar, así que comenzamos por instalar todos aquellos paquetes y librerías que serán necesarios. Es fundamental tener instalado Python, en concreto hemos utilizado la versión 2.7, que ya venía instalada en nuestra placa. Partiendo de esa base, seguimos los siguientes pasos:

1. Instalar pip para poder luego instalar todas las librerías necesarias: Como pip no está dentro de los repositorios oficiales, es necesario añadir repositorios extra:
● Comenzamos instalando gcc
#opkg install gcc

● Añadimos los repositorios al archivo base-feeds.conf utilizando vi
#vi /etc/opkg/base-feeds.conf 
● Introducimos las siguientes líneas, guardamos y cerramos el archivo
src/gz all http://repo.opkg.net/edison/repo/all
src/gz edison http://repo.opkg.net/edison/repo/edison
src/gz core2-32 http://repo.opkg.net/edison/repo/core2-32 
● Actualizamos la lista de paquetes y ya podemos instalar pip.
#opkg update
#opkg install python-pip 
● Descargamos e instalamos también setuptools para complementar el funcionamiento de pip.
#wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
#python ez_setup.py
2. Instalar las librerías de Python necesarias: Como las librerías para interactuar con los sensores (mraa y pyupm_grove) vienen preinstaladas, sólo necesitamos instalar la librería del servidor que vamos a utilizar.
#pip install tornado
3. Clonar el repositorio de GitHub: en el que se encuentra la API que hemos creado.
● https://github.com/sinfonier-project/sinfonier-api-inteledison
Figura 2: Repositorio en GitHub
● Instalar git en caso de no tenerlo previamente
#opkg install git 
● Clonar el repositorio en /opt
#cd /opt 
#git clone https://github.com/sinfonier-project/sinfonier-api-inteledison.git 
● Cambiar de nombre la carpeta si se desea
#mv sinfonier-api-inteledison/ tornado
4. Comprobación y arranque de la API:
#python /opt/tornado/devapi/tornado_web.py
Figura 3: Comprobación de arranque

5. Dejar la API corriendo como servicio: La placa Intel Edison consta de systemd, que es un administrador de servicios para Linux, así que haremos uso de él. Para crear un nuevo servicio lo primero es crear un archivo llamado tornado.service en la carpeta de systemd:
#touch /lib/systemd/system/tornado.service
A continuación añadimos las siguientes líneas al archivo:
[Unit]
Description=Start, stop or restart tornado web service
[Service]
Type=oneshot
ExecStart=/usr/bin/python2.7 /opt/tornado/devapi/tornado_web.py
[Install]
WantedBy=multi-user.target
Y para que systemd actualice los cambios realizados y pongamos nuestro servicio en marcha ejecutamos los siguientes comandos:
#systemctl daemon-reload
#systemctl enable tornado.service
#systemctl start tornado.service
Para comprobar si el servicio está activo podemos ejecutar:#systemctl status tornado.service
Y para parar el servicio tenemos:
#systemctl stop tornado.service
Con esto aunque se reinicie la placa se volvería a activar la API al encenderse de nuevo automáticamente.

Llamadas disponibles en la API REST

Como se anunció en el artículo anterior las llamadas que actualmente están implementadas se corresponden con los sensores que estaban incluidos en el Grove Starter Kit que se nos proporcionó en el hackathon que participamos.

Se tienen dos tipos de llamadas a la API que dependen también del tipo de sensor, así tendremos llamadas tipo “GET” para obtener los datos que recogen los sensores y llamadas tipo “POST” para cambiar el estado de algunos de los dispositivos, como por ejemplo en el caso de los LEDs, en los que es necesario indicar si se quieren apagar o encender.

Por supuesto, este es un desarrollo inicial al que se pueden añadir más llamadas en la API y de hecho os invitamos a que creéis vuestras propias llamadas y las subáis libremente a nuestro repositorio, ya que los sensores que se encuentran en el mercado son muchos y nosotros solo tenemos un pequeño conjunto de ellos.  A continuación se explicará cómo crear nuevas llamadas en la API, pero primero vamos a ver las que se encuentran disponibles y a qué tipo pertenece cada una de ellas:
● LEDs - POST → /api/switchled
● LCD Screen - POST → /api/screen
● Light Sensor - GET → /api/light/
● Button - GET → /api/button/
● Buzzer - POST → /api/switchbuzzer
● Rotary Angle Sensor - GET → /api/rotaryangle/
● Sound Sensor - GET → /api/sound/
● Touch Sensor - GET → /api/touchsensor/
Para probar estas llamadas y ver sus efectos se pueden usar distintas aplicaciones, por ejemplo Postman para Chrome, siempre que estemos en la misma red que la placa:

Figura 4: Postman en Google Chrome
Añadir nuevas llamadas

Como no tenemos todos los sensores del mundo, os proponemos que os animéis a añadir nuevas llamadas a esta API, y a continuación veréis lo fácil que es crear una llamada para un nuevo sensor.

En primer lugar hay que crear el plugin que servirá para interactuar con el nuevo sensor, y que se guardará en el directorio /opt/tornado/plugins/. La estructura de los plugins es la siguiente (plugin_example.py).

# Se importan las librerías necesarias:
import sys
import mraa
import pyupm_grove
sys.path.append("..")
# Se crea la clase
class PluginExample(object):
 
# Inicializacion, se pasan como parametros los elementos necesarios (puerto)
def __init__(self,port):
self.info = dict()
self.port = port
# Metodo especifico para cada sensor, definiendo sus operaciones concretas 
def getPluginExampleValue(self):
#Codigo para obtener el status
self.info["result"] = pluginStatus
return self.info
# Test de funcionamiento del plugin
def testing():
b1 = PluginExample(sys.argv[1])
print b1.getPluginExampleValue()
if __name__ == "__main__":
sys.exit(testing())

En segundo lugar se deben realizar los siguientes cambios en el archivo:

/opt/tornado/devapi/fplugins.py
● Añadir el plugin creado la lista de imports
from plugins import (plugin_example)
● Crear un método con el siguiente formato para el nuevo plugin
def f_plugin_example(port):
b1 = plugin_example.PluginExample(port)
return b1.getPluginExampleValue()
Por último crear la llamada en el API para que se pueda ejecutar el nuevo plugin, para lo cual deberemos hacer los siguientes cambios en el archivo /opt/tornado/devapi/tornado_web.py

● Añadir la clase para el nuevo plugin


class PluginStatus(web.RequestHandler)
def get(self, param):
if Authorization(self.get_argument("access_token", default=0)):
self.write(fplugins.f_plugin_example(param))
else:
self.write("
HTTP 401: Unauthorized
") ● Añadir la llamada a la API propiamente dicha
application = web.Application([
#(r'/static/(.*)',web.StaticFileHandler,{"path": "./static"},),

(r'/api/switchled', SwitchOnLed),
(r'/api/screen', ScreenControl),
(r'/api/temperature/(.*)', TemperatureValue),
(r'/api/button/(.*)', ButtonStatus),
(r'/api/light/(.*)', LightValue),
(r'/api/switchbuzzer', SwitchBuzzer),
(r'/api/sound/(.*)', SoundValue),
(r'/api/touchsensor/(.*)',TouchStatus),
(r'/api/rotaryangle/(.*)', RotaryAngleValue),
(r'/api/pluginexample/(.*)', PluginStatus)
],**settings)
Así ya tendremos las nueva llamada a la API bajo el nombre /api/pluginexample/. En este caso se ha explicado el ejemplo de creación de una llamada tipo “GET”, el caso de tipo “POST” es muy similar y se pueden consultar algunos de los ejemplos que ya se tienen.

Interactuar con IntelEdison API desde el exterior

Hasta ahora hemos visto cómo interactuar con la API y los sensores desde la propia placa o estando conectados dentro de la misma red, pero lo realmente interesante es poder hacerlo desde fuera de la red. Para ello en primer lugar es muy importante tener en consideración las medidas de seguridad de autenticación para que sólo puedan acceder las personas autorizadas.

Para la autenticación se debe crear un archivo llamado config.txt en la carpeta opt:
#touch /opt/config.txt
En este archivo iremos añadiendo en cada línea los tokens de los usuarios que nos soliciten el acceso a nuestro dispositivo. En la API haremos la comprobación de que el token es correcto y , por tanto, se puede acceder con él a las distintas llamadas de la API. En siguientes versiones de la API iremos mejorando la forma de autenticación para dotarla de más seguridad.

Figura 5: Comprobación de token

Para que alguien pueda interactuar con nuestro dispositivo tendrá que añadir a cada llamada de las que hemos mencionado anteriormente el parámetro access_token. Un ejemplo de llamada correcta sería la siguiente:
GET http://192.168.1.129:8888/api/temperature/2?access_token=tokenprueba
Para conseguir acceso remoto desde Internet, mientras sigamos utilizando IPv4 en vez de IPv6, se puede contratar una IP pública fija para nuestro dispositivo o utilizar un servicio para enmascarar nuestra ip pública dinámica a un dominio. Vamos a explicar uno de estos servicios llamado no-ip, a continuación se detallan los pasos a seguir para su activación.
1. Crear una cuenta en http://www.noip.com/ 
2. Una vez hecho el login, en la pantalla principal habrá que seleccionar la opción de “Add Host”, y se desplegará una pantalla como la siguiente, que se rellena con los datos solicitados.
Figura 6: Alta de hostname
3. Se instala el cliente del servicio no-ip en la placa Intel Edison según se especifica en la guía de linux para dicho servicio
Una vez esté correctamente configurado e inicializado será necesario abrir el puerto en el que se está ejecutando la API (por defecto está configurado el 8888) en el router de la red a la que esté conectada la placa Intel Edision. A partir de aquí ya se podrán realizar cualquiera de las llamadas a la API con normalidad utilizando el dominio especificado en el servicio no-ip, que será del tipo “hostname.ddns.net”.

Llegado este punto ya sabemos qué es y qué puede hacer una Intel Edison. Hemos dotado a nuestra tarjeta de un interfaz API para comunicarnos con ella y ahora sólo falta comenzar a jugar… por ello cerraremos nuestro ciclo de 3 posts haciendo uso de Sinfonier-Project para interactuar con nuestra placa desde otros servicios. Vamos a intentar hacer una prueba empírica de lo que se denomina como “Inteligencia Accionable".

- El Internet de tus cosas con Edison y Sinfonier (I de III)
- El Internet de tus cosas con Edison y Sinfonier (II de III)
- El Internet de tus cosas con Edison y Sinfonier (III de III)

Autores:
Eva Suárez (@EvaSuarez22)
Pedro Jesús Martínez (@pejema44)

1 comentario: