Estas semanas (en parte por afición y en parte por trabajo) he seguido avanzando con mis investigaciones con tecnología IoT basada en LoRaWAN. Ya había hablado anteriormente de comunicaciones básicas LoRa, uso de una red abierta LoRaWAN como es la red TTN, pero no había tocado el tema de disponer de un servidor LoRaWAN privado. Y es aquí donde entra en acción Chirpstack. Éste es un diseño basado en software libre que proporciona la capacidad de conectar dispositivos de campo LoRa y junto con los Gateway LoRaWAN permite constituir una red privada LoRaWAN. En este contexto, ChirpStack una solución que mediante una interfaz de usuario amigable permite gestionar dispositivos, usuarios, gateways, y que proporciona una interfaz de integración que permite interactuar con terceros sistemas.
ChirpStack proporciona una serie de componentes que interactúan entre sí para proporcionar la infraestructura necesaria para recibir información de dispositivos y gateways LoRa, con el objeto de proporcionar capacidades de gestión de dichos dispositivos (por un lado) y de poner la información que envían los dispositivos a disposición de terceros sistemas para que la consuman. Esto se articula en base a los siguientes componentes:
El aspecto clave de ChirpStack hace referencia al modo en el que se procesa la información. ChirpStack hace uso de los componentes anteriores para componer y almacenar información estructurada proveniente de los dispositivos de campo, en un formato similar al siguiente:
{
“applicationID”: “123″,
“applicationName”: “temperature-sensor”,
“deviceName”: “garden-sensor”,
“devEUI”: “0202020202020202″,
“rxInfo”: [
{
"gatewayID": "0303030303030303",
"name": "rooftop-gateway",
"time": "2016-11-25T16:24:37.295915988Z",
"rssi": -57,
"loRaSNR": 10,
"location": {
"latitude": 52.3740364,
"longitude": 4.9144401,
"altitude": 10.5
}
}
],
“txInfo”: {
“frequency”: 868100000,
“dr”: 5
},
“adr”: false,
“fCnt”: 10,
“fPort”: 5,
“data”: “…”,
“object”: {
“temperatureSensor”: {“1″: 25},
“humiditySensor”: {“1″: 32}
},
“tags”: {
“key”: “value”
}
}
Otro aspecto interesante es que Chirpstack se puede desplegar de muy diversas maneras, al estar estructurado en una serie de componentes bien definidos que se comunican entre ellos mediante puertos e interfaces estandarizados. Permite tanto realizar un despliegue convencional en un único servidor, a desplegarse en un modelo de microservicios en un entorno Docker o Kubernetes. Para el caso en el que estoy trabajando, he optado por hacer un despliegue basado en contenedores Docker en una máquina virtual, aunque he realizado algunas pruebas con un despliegue más monolítico, y en el ámbito laboral estoy haciendo uso de un entorno Kubernetes.
El despliegue mediante Docker es tremendamente sencillo, ya que los propios desarrolladores de Chirpstack proporcionan una configuración de ejemplo con todos los elementos necesarios. Y una vez desplegado, es bastante sencillo añadir los componentes necesarios. En mi caso, he integrado un gateway Dragino LG308. La integración es tan sencilla como apuntar el servicio LoRaWAN del gateway al puerto 1700/UDP del servidor donde se encuentre levantado el componente Network de Chirpstack. Es posible desplegar un paquete software en el gateway Dragino para convertirlo en un Gateway Bridge de Chirpstack, pero si tenemos éste desplegado en otro sitio, no es necesario realizarlo.
Y en cuanto al registro de los dispositivos, tampoco supone mayor inconveniente. Es necesario definir de manera previa unos perfiles de configuración de dispositivos y la aplicación donde registramos estos últimos, y a partir de ahí, se puede crear la propia aplicación, y registrar los dispositivos, bien por OTAA o ABP, en función de nuestras preferencias. Con todo ello, se tiene una red privada LoRaWAN perfectamente funcional.
Etiquetas: chirpstack, contenedor, docker, dragino, kubernetes, lora, lorawan, microservicio
Llevo algún tiempo trabajando con redes LoRa y LoRaWAN, tanto en temas de trabajo, como finalmente desde el punto de vista profesional. En este último ámbito voy a tener que hacer un estudio de cobertura de una red LoRaWAN para uno de nuestros clientes: la idea es registrar una serie de parámetros de los equipos que se van a instalar en una planta de producción, para lo que es necesario determinar los puntos más adecuados para instalar los gateways que encaminarán la información de los dispositivos. Todo esto implica recorrerse la planta, realizando pruebas de ubicación de los mismos y registrar estos parámetros.
Para ello voy a utilizar, dado que la red LoRaWAN del cliente aún no está constituida, la red The Things Network, que ofrece toda la información que necesito. Sin embargo, la red TTN es una red de transporte, y aunque muestra la información que necesito, no la consolida. Al fin y al cabo se trata de eso, de transportar. El tema del almacenaje ha de realizarse por otro lado. Podría apuntar estos valores a mano, pero he encontrado una manera más divertida de realizarlo: registrar los parámetros y la información de la red con Google Spreadsheet. Ojo, este mecanismo está muy bien para pruebas preliminares y análisis como el que estoy buscando, pero no debe ser usado en un entorno en producción, ya que no se establecen (es más, se eliminan) mecanismos de seguridad de las comunicaciones o de la información alguno.
El artículo que enlazo explica perfectamente cómo hacerlo, pero dejo aquí los pasos generales:
// 2017 by Daniel Eichhorn, https://blog.squix.org
// Inspired by https://gist.github.com/bmcbride/7069aebd643944c9ee8b
// Create or open an existing Sheet and click Tools > Script editor and enter the code below
// 1. Enter sheet name where data is to be written below
var SHEET_NAME = "Sheet1";
// 2. Run > setup
// 3. Publish > Deploy as web app
// - enter Project Version name and click 'Save New Version'
// - set security level and enable service (most likely execute as 'me' and access 'anyone, even anonymously)
// 4. Copy the 'Current web app URL' and post this in your form/script action
var SCRIPT_PROP = PropertiesService.getScriptProperties(); // new property service
// If you don't want to expose either GET or POST methods you can comment out the appropriate function
function doGet(e){
return handleResponse(e);
}
function doPost(e){
return handleResponse(e);
}
function handleResponse(e) {
var lock = LockService.getPublicLock();
lock.waitLock(30000); // wait 30 seconds before conceding defeat.
try {
// next set where we write the data - you could write to multiple/alternate destinations
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
// we'll assume header is in row 1 but you can override with header_row in GET/POST data
//var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var nextRow = sheet.getLastRow()+1; // get next row
var row = [];
var headerRow = [];
// loop through the header columns
var jsonData = JSON.parse(e.postData.contents);
headerRow.push("jsonData.app_id");
headerRow.push("jsonData.dev_id");
headerRow.push("jsonData.hardware_serial");
headerRow.push("jsonData.port");
headerRow.push("jsonData.counter");
headerRow.push("jsonData.payload_raw");
headerRow.push("jsonData.payload_decoded");
headerRow.push("jsonData.metadata.time");
headerRow.push("jsonData.metadata.frequency");
headerRow.push("jsonData.metadata.modulation");
headerRow.push("jsonData.metadata.data_rate");
headerRow.push("jsonData.metadata.coding_rate");
headerRow.push("jsonData.metadata.downlink_url");
for (var i = 0; i < jsonData.metadata.gateways.length; i++) {
var gateway = jsonData.metadata.gateways[i];
headerRow.push("gateway.gtw_id");
headerRow.push("gateway.timestamp");
headerRow.push("gateway.channel");
headerRow.push("gateway.rssi");
headerRow.push("gateway.snr");
headerRow.push("gateway.latitude");
headerRow.push("gateway.longitude");
headerRow.push("gateway.altitude");
}
sheet.getRange(1, 1, 1, headerRow.length).setValues([headerRow]);
row.push(jsonData.app_id);
row.push(jsonData.dev_id);
row.push(jsonData.hardware_serial);
row.push(jsonData.port);
row.push(jsonData.counter);
row.push(jsonData.payload_raw);
var raw = Utilities.base64Decode(jsonData.payload_raw);
var decoded = Utilities.newBlob(raw).getDataAsString();
row.push(decoded);
row.push(jsonData.metadata.time);
row.push(jsonData.metadata.frequency);
row.push(jsonData.metadata.modulation);
row.push(jsonData.metadata.data_rate);
row.push(jsonData.metadata.coding_rate);
row.push(jsonData.metadata.downlink_url);
for (var i = 0; i < jsonData.metadata.gateways.length; i++) {
var gateway = jsonData.metadata.gateways[i];
row.push(gateway.gtw_id);
row.push(gateway.timestamp);
row.push(gateway.channel);
row.push(gateway.rssi);
row.push(gateway.snr);
row.push(gateway.latitude);
row.push(gateway.longitude);
row.push(gateway.altitude);
}
// more efficient to set values as [][] array than individually
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
// return json success results
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "row": nextRow}))
.setMimeType(ContentService.MimeType.JSON);
} catch(e) {
// if error return this
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": e}))
.setMimeType(ContentService.MimeType.JSON);
} finally { //release lock
lock.releaseLock();
}
}
function setup() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
SCRIPT_PROP.setProperty("key", doc.getId());
}
Y con esto, la información generada por nuestros dispositivos LoRaWAN registrados en TTN pasará a almacenarse de manera automática en nuestra hoja de cálculo:
Etiquetas: google spreadsheet, lorawan, the things network
Llevo ya unos cuantos artículos hablando sobre mi sistema de domótica, y hasta ahora he omitido uno de los puntos centrales del mismo: el concentrador zigbee. Mi sistema de domótica es algo sui generis, ya que es un compendio de distintas piezas que he ido amalgamando con el paso del tiempo. El punto central del mismo es el estupendo software Home Assistant, junto con un servidor MQTT. Sobre este núcleo he ido añadiendo diversos dispositivos, empezando por hardware basado en NodeMCU programados por mí mismo. Empecé con ello en 2016, en Irlanda, pero realicé algunos proyectos preliminares aún antes, pero completamente desacoplados. Pero todo lo hecho ha tenido como hilo común el experimentar con diversas tecnologías.
Como parte de ese proceso de experimentación acabé introduciendo dispositivos Zigbee. Son unos elementos interesantes, y la tecnología en la que se basan ha tenido gran difusión en el ámbito de la domótica doméstica. Para transmitir la señal se basan el frecuencia de 2’4GHz, lo que provoca que en entornos saturados de redes WiFi y Bluetooth estemos añadiendo más elementos que pueden provocar perturbaciones. Sin embargo, no es ese su gran problema. El gran problema que tienen es que estos dispositivos necesitan de un aparato que realice las veces de concentrador de señales, actuando como pasarela entre los dispositivos en sí y el software de control que nos permite interactuar con ellos. Y si este concentrador fuera genérico, no sería demasiado malo, pero cada fabricante requiere que uses el suyo y nada más que el suyo, lo que implica que no es posible mezclar, por ejemplo, luces del sistema TRÅDFRI de Ikea con sensores de temperatura Xiaomi, o interruptores Silvercrest de Lidl, a menos que quieras tener que usar tres concentradores y tres aplicaciones distintas para cada componente. Un verdadero rollo.
Y es aquí donde entra nuestro amigo el software libre. Existe un magnífico proyecto de desarrollo de un concentrador multifabricante que permite precisamente eso: utilizar un solo concentrador abierto para gestionar dispositivos de diversos fabricantes. Ese es el proyecto zigbee2mqtt. La idea de partida es sencilla: escuchar las señales Zigbee de los diversos dispositivos, procesarlas, e inyectarlas en un servidor MQTT para poder ser utilizadas posteriormente como mejor convenga a tus intereses. Sencilla, pero brillante. Y en mi caso, dado que ya disponía de un Home Assistant configurado y mi servidor MQTT, algo que me venía como anillo al dedo.
Sin embargo, hasta ahora he hablado sólo de sofware, y para construir un concentrador que reciba señales físicas es preciso de algo de hierro. El hardware esencial es el adaptador Zigbee que recibe las señales de los dispositivos. En mi caso hago uso de un adaptador CC2531, que se conecta por USB. Es preciso programarlo con un firmware que en la propia página de zigbee2mqtt se encargan de proporcionar. Y además de eso, hace falta un dispositivo linux donde instalarlo. La respuesta más obvia es una Raspberry Pi, pero hay otras alternativas:
Una vez determinada qué opción para componer el concentrador, el resto es sencillo: ya hemos hablado del primer paso, que es cargar el firmware en el CC2531. El segundo es desplegar el software zigbee2mqtt en el concentrador. El proceso es bastante sencillo, ya que se trada de una aplicación Node.jsm y se instala tan sólo haciendo uso de un comando npm, una vez preparado el entorno para que pueda ejecutar este tipo de aplicaciones.
Por último, para tener el concentrador listo, hay que integrarlo con un servidor MQTT, que se hace mediante un fichero de configuración. Y a partir de ahí, tan sólo es cuestión de sacarle partido. Y es aquí donde entra de nuevo Home Assistant: zigbee2mqtt tiene una integración excelente con este sistema de domótica, siendo posible integrarlo con Home Assistant, y hacer que el proceso de descubrimiento en éste de los dispositivos registrados en zigbee2mqtt sea automático.
Pero he dejado lo mejor de todo para el final. Comentaba que el problema de utilizar concentradores de fabricante es que cada uno soporta solo y exclusivamente sus propios dispositivos. ¿Cuántos dispositivos soporta zigbee2mqtt? Literalmente cientos. A día de hoy, 1217 dispositivos de 189 fabricantes distintos. Y es una lista que no para de crecer. Hace algunas semanas han sido añadidos los Silvercrest de Lidl de los que escribí recientemente, solucionando el problema de que el botón físico de los interruptores no era reconocido dentro de las acciones: ahora sí lo reconoce.
¿Qué cuál es mi configuración? Bueno, a día de hoy es pelín compleja, pero tiene su gracia. Estrictamente hablando, hago uso de dos concentradores zigbee2mqtt, uno en Santiponce, y otro en Forcarey, que reportan a mi servidor MQTT, ubicado en Santiponce. Y manejo los dispositivos desde un único Home Assistant, también ubicado en Sevilla. Cada zigbee2mqtt escribe en el servidor MQTT bajo un topic diferenciado, ya que la cantidad de dispositivos es pelín larga ya. En Santiponce hago uso de:
…y en el caso de Forcarey:
No está mal, ¿no?
Etiquetas: aldi, aqara, aqara cube, arduino, asus tinker board, debian, domótica, home assistant, ikea, lidl, mqtt, nodemcu, orange pi zero, proxmox, raspberry pi, zigbee, zigbee2mqtt
Hace algunas semanas el supermercado Lidl sacó una gama de dispositivos de control domótico bajo su marca Silvercrest. . El esquema de conexión es el habitual de estos dispositivos: constan de un gateway zigbee que permite interactuar con él desde el teléfono móvil, a través de una plataforma propietaria, y controlar los distintos dispositivos desplegados en el hogar.
Lo interesante de este sistema es que, aparte de los dispositivos normales como control de enchufes y luces, dispone de algunos añadidos no tan comunes un calefactor cerámico. Así que no podía dejar de probar si podrían funcionar en mi sistema de domótica basado en zigbee2mqtt. Y, en efecto, funcionan, aunque hay que pelearse un poco con ellos. En mi caso estoy haciendo uso de ellos en el sistema de domótica delegado que tengo montado en Forcarey. Estoy utilizando mi misma plataforma Home Assistant desplegada en Santiponce, pero tengo un receptor zigbee separado, montado con una Orange Pi Zero que tenía sin usar, ubicada en Forcarey. Este receptor separado vuelca los datos en mi servidor MQTT bajo un topic distinto, y a correr.
Bueno, en realidad no ha sido tan sencillo. El primer problema es que estos dispositivos, en la fecha en que escribo esto, aún no están incorporados como dispositivos propios en la lista de dispositivos reconocidos por zigbee2mqtt. No es demasiado problemático, porque al parecer Lidl está vendiendo bajo su marca dispositivos TuYa, que sí son reconocidos. Eso sí, para que los reconozca es imprescindible tener zigbee2mqtt actualizado a su última versión. Otro punto ha sido que los dispositivos dan algo de guerra al negociar la conexión a la red, incluso ya reconocidos. En mi caso, para que terminaran la fase de interview correctamente, tuve que añadir un cable extensor USB para separar el receptor de la Orange Pi Zero. Y el tercer punto complicado es que estos dispositivos son Zigbee 3.0, y para que el sistema sea estable, es necesario utilizar el firmware del receptor zigbee con capacidades de enrutado, en vez del normal.
Con todo esto en pie, los dispositivos funcionan correctamente, tanto la luz de colores regulable como los interruptores de pared, que son con los que he experimentado. El único punto ligeramente molesto en que con estos últimos el pulsador manual no genera eventos, por lo que el uso del mismo no se registra en el sistema de domótica. Pero es algo con lo que puedo vivir.
Etiquetas: home assistant, lidl, mqtt, orange pi zero, silvercrest, zigbee, zigbee2mqtt
Hace cosa de un año escribí un artículo sobre cómo actualizar de manera manual el firmware de los Sonoff Mini, cambiándolo al firmware Tasmota. Recientemente he adquirido una nueva remesa de Sonoffs Mini, y he comprobado que el manual ya no es válido, debido a un cambio en el firmware de casa que traen los dispositivos. En la práctica, se ha simplificado el proceso, que paso a describir:
…y como siempre, mucho ojo con no cargar la versión tasmota-minimal, ya que esta versión no carga la interfaz web de administración, y puede dejar el dispositivo inservible.
Etiquetas: domótica, ota, sonoff, sonoff mini, tasmota