viernes, 2 de diciembre de 2016

Programación Visual con Node-Red: Conectando el Internet de las Cosas con Facilidad


Programación Visual con Node-Red: Conectando el Internet de las Cosas con Facilidad


BY JESUS DARIO RIVERA - FREELANCE SOFTWARE ENGINEER @ TOPTAL




This article was originally written in English

A través de la programación, hacemos que las máquinas imiten un comportamiento complejo siguiendo secuencias de instrucciones simples. Utilizar lenguajes de programación textual como Asambly, C, Python y JavaScript, es una de las formas principales de hacerlo. Los diseñadores de estos lenguajes de programación han pasado horas y horas tratando de hacer que la experiencia de los programas de escritura sean lo más fácil posible a través de una sintaxis expresiva, fuertes construcciones de programación y cadenas de herramientas poderosas. Sin embargo, todos estos lenguajes de programación comparten un rasgo común: el código fuente textual.
Escribir programas en texto funciona y en la mayoría de los casos funciona bien. Sin embargo, la capacidad de expresar programas visualmente es a menudo deseable. Ser capaz de diseñar el flujo de información a través de diversos componentes de un sistema más grande es normalmente todo lo que se necesita. Las herramientas visuales de programación también son indulgentes con cualquier persona que sea nuevo en la programación y que les es difícil manejar diversos conceptos como las variables, indicadores, señales, alcances, y así sucesivamente.

Node-RED es una herramienta de programación visual. Muestra visualmente las relaciones y funciones, y permite al usuario programar sin tener que escribir una lengua. Node-RED es un editor de flujo basado en el navegador donde se puede añadir o eliminar nodos y conectarlos entre sí con el fin de hacer que se comuniquen entre ellos.
En Node-RED, cada nodo es uno de los siguientes dos tipos: un nodo de inyección o un nodo de función. Los nodos de inyección producen un mensaje sin necesidad de entrada y lanzan el mensaje al siguiente nodo conectado a éste. Los nodos de función, por el contrario, tienen una entrada y realizan algún trabajo en él. Con una gran cantidad de estos nodos para elegir, Node-Red hace que el conectar los dispositivos de hardware, APIs y servicios en línea sea más fácil que nunca.

Primeros Pasos con el Node-Red

Node-Red se basa en Node.js. Para instalar el Node-Red, necesitas tener tanto Node.js instalado como NPM. Con NPM, es muy fácil instalar Node-Red: npm install -g node-red
El editor de flujo de Node-Red es una aplicación basada en navegadores web. Para poder utilizarlo, ejecuta Node-Red:
npm install -g node-red 
Node-RED’s flow editor is a web browser based application. To be able to use it, run Node-RED:
node-red 
&hellip y vaya a http: // localhost: 1880.

¡Hola Mundo!

¿Qué tutorial de programación para principiantes está completo sin aprender a decir “Hola, mundo”? Vamos a empezar por probar exactamente eso:
1.    Arrastra y suelta un nodo de inyección en el editor de flujo. Después, haz doble clic y fija la carga útil como cadena y escribe “Hola mundo”.
2.    Arrastra y suelta un nodo de depuración, de la misma manera como lo hiciste con la inyección.
3.    Conéctalos.
4.    Haz clic en el botón “Deploy” en la esquina derecha.
5.    Haz clic en el botón azul justo a la izquierda del nodo de inyección.
Inténtalo. Verás algo como esto:



Sólo JavaScript

Con Node-Red, no te limites con simples nodos y funcionalidades. Como Node-Red está construido sobre Node.js, todo está impulsado por JavaScript. Los nodos son, de hecho, Node.js módulos. Se pueden encontrar en http://flows.nodered.org/, entonces para añadirlos a tu panel de la izquierda se pueden simplemente “instalar con NPM “. De hecho, puedes desarrollar tu propio flujo y subirlos al repositorio de flujo. Las aplicaciones pueden ser tan complejas como desees ya que puedes escribir JavaScript en los nodos de función dentro del editor de código que proporciona Node-Red.
Ya que la plataforma se basa en Node.js, ésta se aprovecha del mismo modelo orientado a eventos y sin bloqueos. Así que una aplicación construida en Node-Red puede ejecutarse en hardware de bajo costo como el Raspberry Pi, así como en la nube.

Ahora Nos Vamos a Meter en las Grandes Ligas: Es hora de Automatizar el Hogar

Para demostrar cómo Node-Red se ajusta en el ámbito del Internet de las Cosas, vamos a construir una aplicación para cambiar el color de una bombilla inteligente. No todo el mundo puede tener el mismo sistema de iluminación inteligente a su disposición, pero no hay nada de qué preocuparse, ya que se puede encontrar el módulo Node-Red apropiado desde el repositorio oficial de flujo. Sin embargo, para hacer las cosas aún más fácil vamos por algo más inteligente.
Déjmae presentarte a Netbeast. Es una plataforma de código abierto para el desarrollo de aplicaciones para los aparatos y dispositivos del Internet de las cosas sin tener que preocuparse por los detalles como los protocolos inalámbricos, compatibilidad de marca, o tener que saber cómo tratar con cada API específica que existe. ¡Nos permite utilizar los dispositivos virtuales que actúan como los de verdad! Así que incluso si no tienes una bombilla inteligente, tienes una virtual disponible.
Podemos instalar el paquete de NPM de Netbeast para Node-Red a nivel mundial así:
npm install -g node-red-contrib-netbeast 
El netbeast-red node representará el panel de control Netbeast, lo que traducirá sus primitivas API para todos los dispositivos inteligentes que tienes en casa. ¡Afortunadamente, también está disponible como un módulo!
Inicia Netbeast:
npm install -g netbeast-cli netbeast start 
Esto hará que el panel esté disponible en el puerto 8000 y SSL en 8443. A continuación, abre el navegador a http://localhost:8000 y navega a Explore. Ahí podemos encontrar muchas aplicaciones y plugins. Busca las marcas de tus bombillas inteligente (Philips Hue, LIFX, Wemo) o si no tienes una, intenta descargar el plugin de la bombilla. ¡Comprueba que los plugins del panel contienen uno de estos!



La insignia amarilla indica que los plugins se están ejecutando, pero no pueden encontrar ningún dispositivo. Haz clic en el plugin de la bombilla para crear una bombilla virtual. Cualquier otro dispositivo que se descubra debe aparecer en la red.
Con todo en su lugar, volvamos al trabajo. Haremos un flujo simple:
1.    Arrastra y suelta un nodo de inyección.
2.    Arrastra y suelta el nodo Netbeast.
3.    Arrastra y suelta un nodo de depuración.
4.    Conecta todo como se muestra a continuación:



Ahora vamos a enviar una petición HTTP al panel de control. Al usar la API Netbeast se tendrá que enviar a través del nodo de inyección un JSON que contiene los valores que queremos que se activen en nuestra bombilla.



¡Presiona el botón para inyectar el color y la energía a todas tus bombillas inteligentes!

Cada tema representa un tipo diferente de dispositivo. Así que hay temas no solo para las luces, sino también para la música, calefacción, y el vídeo; así como sensores para la humedad, la presencia, la temperatura, y la lista continúa. Puedes encontrar en tu documentación una lista de temas y su estructura recomendada para ser traducido a todo tipo de dispositivos. Este motor de la IO es novato, pero potente. Un código abierto que permite a los desarrolladores reutilizar la información para crear escenarios realmente conectados, siendo de este modo inteligente.

Ahora Adentrémonos Más

A continuación, vamos a crear un segundo flujo usando otro plugin, un detector de ruido ambiental para utilizarlo como un iniciador para cambiar el color de la bombilla como un semáforo de ruido. En este tutorial vamos a utilizar uno virtual, así que no hay necesidad de comprar un nuevo hardware. Vamos a empezar haciendo clic en el botón “más” en el editor de Node-Red.
Ve de nuevo al Panel http://localhost:8000/explore a la sección Explorar y busca Volume-Plugin. Se trata de una aplicación web muy rudimentaria que se aprovecha de getUserMedia() dentro del navegador para capturar la información multimedia desde una simple aplicación HTML. Por lo tanto, es probable que sólo funcione en los navegadores modernos.
Haz clic en él para abrir, al igual que con la bombilla virtual. En él se solicita permiso para grabar desde el micrófono. A continuación, enviará los mensajes al intermediario MQTT de Netbeast, que será compartido a través de todo el panel de control, y así podremos suscribirnos. Para lograr esto sólo necesitaremos arrastrar y soltar un nodo de netbeast-trigger en el editor node red. A continuación, vamos a insertar una función entre el trigger y el nodo Netbeast, para decidir cuando está demasiado alto y cuando no. Además, deberíamos utilizar algunos nodos de depuración para comprobar si todo está bien. El esquema ahora se verá algo como esto:




Ahora, vamos a introducir algún código en el nodo de función tooLoud. Sí, sé que prometí que podrías programar sin necesidad de codificar, ¡pero ya he demostrado que puedes! Y se puede tratar de combinar los diferentes elementos disponibles u otros nodos del registro para llevar a cabo lo siguiente.
var volume = msg.payload.volume  node.log(volume)  if (volume < 50) {     return { topic: 'lights', payload: { power: 1, color: '#00CC00'}} } else if (volume < 75) {     return { topic: 'lights', payload: { power: 1, color: '#CCCC00'}} } else {     return { topic: 'lights', payload: { power: 1, color: '#FF0000'}} } 
Este fragmento de código bastante simple está regresando una de las tres cargas útiles para el siguiente nodo con un código de color específico, dependiendo del nivel de volumen reportado por el nodo anterior.
¡Ahora estamos listos para continuar! Vamos a presionar el botón Deploy de nuevo y armemos un griterío. ¡Veamos cómo cambia la bombilla de un color a otro de inmediato!
Ya que el micrófono y el navegador web que estás utilizando podrían ser diferentes, no dudes en ajustar los valores de la función y umbrales, y también juega con los valores de color para ver cómo cambia tus bombillas.

Crea tus Propios Plugins


Esta bombilla en CSS puro se inspiró en éste cssdeck.
Como habrás notado, la bombilla virtual anterior es muy rudimentaria, por lo que es posible que desees modificarla. O mejor aún, puedes crear tus propios controladores para un hogar inteligente. Así que vamos a pasar por el proceso de crear un plugin virtual para Netbeast, lo que te permitirá crear tus propios controles para dispositivos inteligentes.
Puedes utilizar el paquete netbeast-cli para generar como por arte de magia algunos códigos. Mediante la ejecución de netbeast create myplugin --plugin tendríamos un proyecto básico como el siguiente:
myplugin ├── README.md ├── index.js ├── package.json └── test.js 

Frontend

Ahora, vamos a empezar a mimetizar la bombilla con un frontend. Los controladores de dispositivos por lo general no van a tener uno, así que el comando de andamio no incluye una carpeta pública todavía. Vamos a crear un directorio public dentro del proyecto y colocamos allí los siguientes archivos HTML, CSS y JS.

index.html


<head>   <title>Netbeast Bulb Plugin</title>   <link rel="stylesheet" href="bulb.css" media="screen" charset="utf-8"> </head>  <body>   <div class="top-decoration"></div>   <div id="plugin front-end">   </div>   <div class="bulb-container small">     <div class="bulb light">       <div id="bulb">         <div class="bulb top"></div>         <div class="bulb middle-1"></div>         <div class="bulb middle-2"></div>         <div class="bulb middle-3"></div>         <div class="bulb bottom"></div>       </div>       <div id="base">         <div class="screw-top"></div>         <div class="screw a"></div>         <div class="screw b"></div>         <div class="screw a"></div>         <div class="screw b"></div>         <div class="screw a"></div>         <div class="screw b"></div>         <div class="screw c"></div>         <div class="screw d"></div>       </div>     </div>   </div>     <div class="code-container">       <pre><i class="txt-red">beast</i>(<i class="txt-green">'lights'</i>).<i class="txt-blue">set</i>({   <i class="txt-green">color</i>: <i class="txt-green">"<input id="color" type="text" class="color" name="color" value="00fea5">"</i>,   <i class="txt-green">power</i>: <i class="txt-green">"<input id="power" type="text" class="power" name="power" value="on">"</i> })</pre>     <button id="run-btn">       RUN     </button>   </div><!-- wrapper -->    <!-- declares bulb features and methods -->   <script type="text/javascript" src="bulb.js"></script>   <!-- real time comms library -->   <script type="text/javascript" src="socketio.js"></script>   <!-- simulates hardware communication -->   <script type="text/javascript" src="hw-api.js"></script> </body> 

bulb.css


section {   float: left;   padding: 20px 50px 20px 50px; }  .bulb-light {   border: 0;   background: transparent;   margin: 0 auto !important;   padding: 0 !important;   display: block;   z-index: 1; }  #bulb { opacity: 1; z-index: 3; display: block;}  .bulb.top {   border: 0;   width: 300px;   height: 300px;   margin: 0 auto;   padding: 0;   border-radius: 999px;   background: #E7E7E7; }  .bulb.middle-1 {   margin: -75px auto 0 auto;   width: 190px;   border-left: 35px solid transparent;   border-right: 35px solid transparent;   border-top: 55px solid #E7E7E7; }  .bulb.middle-2 {   margin: -22px auto 0 auto;   width: 178px;   border-left: 19px solid transparent;   border-right: 19px solid transparent;   border-top: 50px solid #E7E7E7; }  .bulb.middle-3 {   margin: -20px auto 0 auto;   width: 182px;   border-left: 5px solid transparent;   border-right: 5px solid transparent;   border-top: 30px solid #E7E7E7; }  .bulb.bottom {   width: 184px;   height: 65px;   margin: -8px auto 0 auto;   padding: 0;   border-radius: 0 0 999px 999px;   background: #E7E7E7; }  #base { position:relative; z-index: 2; }  .screw {   transform: rotate(-3deg);   -ms-transform: rotate(-3deg);   -webkit-transform: rotate(-3deg);   padding: 0; }  .screw-top {   margin: -18px auto -4px auto;   padding: 0;   width: 132px;   height: 0;   border-left: 15px solid transparent;   border-right: 15px solid transparent;   border-top: 21px solid #D3D3D3;   border-radius: 999px; }  .screw.a {   background: #DDD;   width: 150px;   height: 15px;   border-radius: 999px;   margin: -1px auto 0px; }  .screw.b {   background: #D9D9D9;   width: 135px;   height: 15px;   margin: -1px auto 0px; }  .screw.c {   margin: -1px auto 0px;   width: 78px;   height: 0;   border-left: 30px solid transparent;   border-right: 30px solid transparent;   border-top: 20px solid #DDD;   border-radius: 8px; }  .screw.d {   margin: 0 auto;   width: 15px;   height: 0;   border-left: 30px solid transparent;   border-right: 30px solid transparent;   border-top: 15px solid #444; }  .on #light {   -moz-opacity: 1;   -khtml-opacity: 1;   opacity: 1; }  .bulb.top, .bulb.bottom {   transition: all 0.5s ease-in-out; }  .bulb.middle-1, .bulb.middle-2, .bulb.middle-3 {   transition: all 0.5s ease-in-out; } 

Con estos archivos HTML y CSS, ya se debería poder ver una forma de bombilla en tu navegador. ¡Abre el archivo HTML para ver en vivo! ¿Está funcionando? Bien, ahora vamos a darle algunas funciones.


bulb.js


Este archivo imitará el comportamiento de una bombilla con un simple clic de encendido. Al hacer click para apagarla, establecerás un par de funciones que serán utilizadas un poco después para cambiar su color a través de Netbeast.

var color = document.getElementById('color') var power = document.getElementById('power') var bulb = document.getElementById('bulb') var button = document.getElementById('run-btn') var light = document.getElementById('light')  button.onclick = function toggleBulbState () {   changeBulbParams({ color: color.value, power: power.value }) }  function setBulbParams (params) {   if (params.power === 'off') {     params = { color: 'E7E7E7' }   }   console.log('set params', params)    var bulb_parts = ['.bulb.middle-1', '.bulb.middle-2', '.bulb.middle-3']    document.querySelector('.bulb.top').style.boxShadow = '0px 0px 98px #' + params.color    document.querySelector('.bulb.top').style.backgroundColor = params.color   document.querySelector('.bulb.bottom').style.backgroundColor = params.color   bulb_parts.forEach(function (className) {     document.querySelector(className).style.borderTopColor = params.color   }) }  function changeBulbParams (params) {   console.log('change params', params)   /* Overwrite html fields if necessary */   color.value = params.color || color.value   power.value = params.power || power.value   setBulbParams({color: color.value, power: power.value}) } 

Luego, todo comenzará a tener sentido: los campos y el botón de ejecución, ¡ahora podrás comenzar a probar los diferentes colores de tu nueva bombilla virtual! Sin embargo, la razón por la que vinimos hasta aquí es para hacer otro dispositivo de nuestro ecosistema del Internet de las Cosas.

hw-api.js


El último de front-end JS realizado por nosotros mismos, simula una conexión inalámbrica con el servidor, como lo haría un WiFi o bombilla Bluetooth con su mando a distancia, tales como un teléfono, un servidor o un hub. ¡Es la interfaz que el código plugin utilizará para controlarlo!

var socket = io.connect()  socket.on('connect', function () { console.log('ws:// bulb is online') }) socket.on('disconnect', function () { console.log('ws:// connection with bulb lost') })  socket.on('set', function (params) {    changeBulbParams(params) // uses functions from bulb.js! })  socket.on('get', function () {   const params = { power: power.value, color: color.value }   socket.emit('params', params) }) 

Por último, necesitamos que la biblioteca WebSocket sea incluida en nuestro HTML para que la interfaz esté lista. Puedes copiar el código fuente de https://raw.githubusercontent.com/netbeast/bulb-plugin/master/public/socketio.js y pegarlo en un archivo llamado socketio.js. Desde un terminal con curl o wget, lo puedes hacer así de simple:

curl https://raw.githubusercontent.com/netbeast/bulb-plugin/master/public/socketio.js  > public/socketio.js 

Tendríamos ahora una estructura de archivos que se ve así:

myplugin ├── README.md ├── index.js ├── package.json ├── public    ├── bulb.css    ├── bulb.js    ├── hw-api.js    ├── index.html    └── socketio.js └── test.js 

Backend


Ahora vamos a implementar la interfaz con el dispositivo y registrarlo en el motor Netbeast. Éste escuchará los websockets para detectar si alguna bombilla se ha instalado en la red, y luego hará un POST a la API del panel de control para que los nuevos recursos estén disponibles.

Por eso, vamos a echar un vistazo a los archivos que generamos antes:

package.json


Este archivo contiene todas las dependencias y la información necesaria para ejecutar tu aplicación. Netbeast utiliza el habitual package.json también para recuperar cierta información, como el nombre o el tipo. ¡Es importante especificar que este paquete es un plugin!

{   "name": "myplugin",   "version": "0.0.0",   "description": "Netbeast plugin for... <your description>",   "main": "index.js",   "netbeast": {     "bootOnLoad": true,     "type": "plugin"   },   "dependencies": {     "bluebird": "^3.3.5",     "body-parser": "^1.15.0",     "express": "^4.13.4",     "minimist": "^1.2.0",     "mocha": "^2.3.2",     "morgan": "^1.6.1",     "netbeast": "^1.0.6",     "socket.io": "^1.4.5",     "superagent": "^1.8.3"   },   "devDependencies": {},   "scripts": {     "test": "node test.js",     "start": "node index.js"   },   "repository": {     "type": "git",     "url": "GITHUB_REPOSITORY"   },   "keywords": [     "iot",     "netbeast",     "plugin"   ],   "author": "YOUR_EMAIL",   "license": "GPL 3",   "bugs": {     "url": "ISSUES_CHANNEL"   },   "homepage": "HOMEPAGE" } 

index.js


¡Éste es el código que se trae desde el panel de control de Netbeast para lanzar el plugin! Éste tendrá que aceptar el puerto a través de argumentos de línea de comando para saber dónde aceptar peticiones entrantes. Se lanzará como si escribiéramos node myplugin.js --port <a free port number>. ¡Recuerda tomar en cuenta el hashbang al principio! #!/usr/bin/env node.

#!/usr/bin/env node  var io = require('socket.io')() var express = require('express') var bodyParser = require('body-parser')  var app = express()  // Netbeast apps need to accept the port to be launched by parameters var argv = require('minimist')(process.argv.slice(2))  app.use(express.static('public')) // will serve our app in an HTTP server app.use(bodyParser.json()) // will parse JSON API calls app.use('/api', require('./plugin')(io))   var server = app.listen(argv.port || 31416, function () {   console.log('Bulb plugin listening at http://%s:%s', server.address().address,   server.address().port) })  // we need websockets to push updates to browser view io.listen(server) 

Como se puede ver nos faltaba un archivo por iniciar, el que realmente implementa los controladores socket.io. ¡Nada sofisticado!

plugin.js


var express = require('express') var netbeast = require('netbeast')  var router = express.Router() var bulbParams // auxiliar variable, nasty way to transmit changes, but works  module.exports = function (io) {   io = io      // Create resource that works on lights topic and listens on /api route   netbeast('lights').create({ app: 'myplugin', hook: '/api' })    io.on('connection', function () {       console.log('ws:// bulb has connected to plugin')    })    io.on('disconnection', function () {      console.log('ws:// bulb has disconnected from plugin')    })    io.on('connect_failure', function (err) { console.trace(err) })    router.post('/', function (req, res) {     io.emit('set', {       power: req.body.power,       color: req.body.color,     })     res.status(200).json(req.body)   })    router.get('/', function (req, res) {     io.emit('get')     var timerReference = setTimeout(function () {       if (bulbParams) {         res.json(bulbParams)       } else {         res.status(200).json({ error: 'No bulb available' })       }     }, 3000)   })    return router } 

Inicia tu Aplicación


Ahora es el momento de probar la aplicación. Puedes empaquetarlo todo en un formato tar.gz y luego subir la aplicación a tu panel de control en la sección de arrastrar y soltar http://localhost:8000/install.

beast package # Compresses your app when ran in myplugin dir 

¡Voilà! Ahora puedes ir a tus plugins y probarlo. Ve a la sección de red (http://localhost:8000/devices) para ver su funcionamiento y cambiar su color a partir de ahí.


Si algo sale mal o piensas que podrías haber olvidado un detalle, trata de ejecutar localmente con el nodo node index.js, y tal vez será más fácil de depurar que dentro del registro netbeast start.

Publicar su trabajo


Si deseas que la aplicación aparezca en el panel de control de la sección Explore de Netbeast, debes crear un repositorio en GitHub con la aplicación o plug-in de Netbeast, ambos incluidos en la descripción y README.md.

Para encontrar las aplicaciones que hacemos, usa la API de búsqueda de GitHub. Vemos los mismos resultados que aparecen cuando se realiza una solicitud GET a:https://api.github.com/search/repositories?q=netbeast+language:javascript

¡Sabrás que se mostrará tu aplicación, si parece hay!

¿Qué sigue?


Ambos proyectos son de open source y realmente han involucrado a las comunidades. Si deseas comenzar a crear tus propios flujos o nodos al Node-Red, echa un vistazo a su documentación oficial. Sigue los pasos descritos allí y podrás publicar tu propio nodo o flujo en poco tiempo.

Por otro lado, si quieres entrar en el interior Netbeast, puedes seguir su documentación también o echar un vistazo al repositorio del panel. Al usar la API Netbeast, no tienes que centrarte en los dispositivos individuales, marcas o tecnologías, así que dale una oportunidad. Puedes aprender más sobre esto aquí o unirte a su Slack channel y discutir Node-RED, IoT o Node.js.

Si deseas instalar esto en una Raspberry Pi, Beagle Bone o servidor antiguo, lo convertirías en un Smart Hub fácil de hackear, ¡sin código! Hay instaladores ya hechos para ellos en ambos sitios.

Feliz hacking.

Artículo via Toptal