Domótica

Añadiendo un adaptador Z-Wave (o un coordinador Zigbee, para el caso)

Añadiendo un adaptador Z-Wave (o un coordinador Zigbee, para el caso)

Si queremos habilitar nuestro controlador domótico para gestionar una red Z-Wave necesitaremos incorporar un dispositivo que actúe como puerta de enlace entre la red y nuestro software de control Openhab. Estos dispositivos suelen venir en forma de «dongle» USB y sea cual sea la manera en que nuestro software se comunique con él, siempre deberemos especificar el puerto serie virtual al que se encuentra conectado. Sabiendo que son muchos los puertos serie virtuales que un sistema linux es capaz de crear, necesitaremos identificar correctamente cuál corresponde al dispositivo que queremos manejar.

Nota: Si bien nuestro propósito es conectar un «dongle» que nos permita gestionar una red domótica inalámbrica, todo el procedimiento aquí descrito es igualmente válido para cualquier dispositivo USB que enchufemos a nuestra máquina.

La manera clásica de hacer esto consiste en listar los dispositivos de este tipo antes y después de enchufar el adaptador y ver qué nueva línea es la que aparece en el listado.

ls -l /dev/tty*

En nuestro caso, acabamos de conectar un dongle Z-Wave Gen5 de la marca Aeotec, y lo que obtenemos es el puerto serie virtual se llama: /dev/ttyACM0

Si ahora, por ejemplo, hacemos lo mismo con el adaptador Zigbee Sonoff mientras está enchufado el anterior, veremos que aparece un segundo puerto: /dev/ttyUSB0

En principio, con estos datos ya tendríamos suficiente. Sin embargo, el problema de que la asignación de puerto se realice dinámicamente es que el puerto serie asignado al adaptador puede variar cada vez que el sistema se reinicie o, incluso, cada vez que el dispositivo se desenchufe, dependiendo de los puertos disponibles, con lo cual la configuración que hayamos ajustado para nuestro software dejará de tener sentido. De hecho, la asignación anterior de puertos podría depender, simplemente, de los puertos USB utilizados o, incluso, del orden en el que se enchufan. Para evitarlo es preciso crear una regla de persistencia.

Lo primero es obtener la información que identifica unívocamente a nuestro adaptador, concretamente dos números hexadecimales llamados «idVendor» e «idProduct». Esto se consigue listando los dispositivos USB reconocidos por el sistema. Y, para evitar confusiones, como antes, mejor hacerlo antes y después de enchufarlo.

Por ejemplo, antes de enchufar ningún adaptador obtenemos esto:

lsusb
Bus 001 Device 003: ID 058f:6254 Alcor Micro Corp. USB Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

Todos estos dispositivos corresponden, simplemente, al Hub USB. Sin embargo, si enchufamos el adaptador Z-Wave vemos esto:

lsusb
Bus 001 Device 003: ID 058f:6254 Alcor Micro Corp. USB Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 004: ID 0658:0200 Sigma Designs, Inc. Aeotec Z-Stick Gen5 (ZW090) - UZB
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

Y después de enchufar los dos, esto otro:

lsusb
Bus 001 Device 003: ID 058f:6254 Alcor Micro Corp. USB Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 005: ID 10c4:ea60 Silicon Labs CP210x UART Bridge
Bus 004 Device 004: ID 0658:0200 Sigma Designs, Inc. Aeotec Z-Stick Gen5 (ZW090) - UZB
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

En este formato, lo que nos interesa son los dos números hexadecimales que aparecen después de ID, de esta forma <idVendor>:<idProduct>

Ahora creamos el siguiente archivo en el que añadimos una línea por cada dispositivo, especificando los ID’s obtenidos en el paso anterior y un nombre facilmente reconocible:

sudo nano /etc/udev/rules.d/usb-serial.rules
ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="0658", ATTRS{idProduct}=="0200", SYMLINK+="ttyUSB-AEON-ZWAVE"
ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="10C4", ATTRS{idProduct}=="EA60", SYMLINK+="ttyUSB-SONOFF-ZIGBEE"

Esto creará un enlace simbólico entre el nombre que nosotros especifiquemos para cada dispositivo y el puerto al que se asigne cada vez, independientemente de cuál se trate.

Ahora, si comprobamos el listado de los dispositivos de tipo puerto serie:

ls -l /dev/tty*

crw-rw-rw- 1 root tty       5,  0 May 16 19:15 /dev/tty
crw--w---- 1 root tty       4,  0 May 15 22:38 /dev/tty0
crw--w---- 1 root tty       4,  1 May 15 22:39 /dev/tty1
crw--w---- 1 root tty       4,  2 May 15 22:38 /dev/tty2
crw--w---- 1 root tty       4,  3 May 15 22:38 /dev/tty3
crw--w---- 1 root tty       4,  4 May 15 22:38 /dev/tty4
crw--w---- 1 root tty       4,  5 May 15 22:38 /dev/tty5
crw--w---- 1 root tty       4,  6 May 15 22:38 /dev/tty6
crw--w---- 1 root tty       4, 60 May 15 22:38 /dev/tty60
crw--w---- 1 root tty       4, 61 May 15 22:38 /dev/tty61
crw--w---- 1 root tty       4, 62 May 15 22:38 /dev/tty62
crw--w---- 1 root tty       4, 63 May 15 22:38 /dev/tty63
crw--w---- 1 root tty       4,  7 May 15 22:38 /dev/tty7
crw--w---- 1 root tty       4,  8 May 15 22:38 /dev/tty8
crw--w---- 1 root tty       4,  9 May 15 22:38 /dev/tty9
crw-rw---- 1 root dialout 166,  0 May 16 19:25 /dev/ttyACM0
lrwxrwxrwx 1 root root          7 May 15 22:38 /dev/ttyUSB-AEON-ZWAVE -> ttyACM0
lrwxrwxrwx 1 root root          7 May 15 22:38 /dev/ttyUSB-SONOFF-ZIGBEE -> ttyUSB0
crw-rw---- 1 root dialout 188,  0 May 16 18:17 /dev/ttyUSB0
crw------- 1 root root      5,  3 May 15 22:38 /dev/ttyprintk

Podemos comprobar los nombres elegidos por nosotros y los puertos a los que hacen referencia en este momento. Por cierto, también observamos que para acceder a estos puertos es necesario ser root o pertenecer al grupo dialout

Si vamos a manejar los dispositivos desde openhab

Ahora ya podemos indicar al software que vaya a utilizar el dispositivo el puerto serie en cuestión. En el caso de que dicho software sea openhab, necesitaremos que su entorno de configuración reconozca estos nombres para hacerlos disponibles en el contexto del programa. Para ello modificamos el archivo de configuración de entorno en /etc/default/openhab añadiendo la siguiente opción en la sección correspondiente:

sudo nano /etc/default/openhab

EXTRA_JAVA_OPTS="-Dgnu.io.rxtx.SerialPorts=/dev/ttyUSB-AEON-ZWAVE:/dev/ttyUSB-SONOFF-ZIGBEE"

Y ya sólo necesitaríamos configurar los puertos correctos en la interfaz de OpenHab que corresponda al servicio en cuestión. En nuestro ejemplo, los Addons correspondientes a las redes Z-Wave y Zigbee.

Publicado por David en Domótica, Linux, 0 comentarios
Entrándole a Zigbee por la puerta de atrás (…ejem, MQTT)

Entrándole a Zigbee por la puerta de atrás (…ejem, MQTT)

¿Por qué?

Hasta la fecha de empezar a escribir estas notas, los dispositivos inalámbricos que componían mi sistema doméstico eran de dos tipos: Wifi, con protocolo MQTT y Z-Wave. Como en algún momento dejaré documentado, los dispositivos Wifi tenían la ventaja de ser muy económicos, y el inconveniente de que todos funcionaban con una aplicación propietaria, por lo que si queríamos conectarlos con un protocolo abierto resultaba necesario un pequeño hackeo. Por su parte, los dispositivos Z-Wave tenían la ventaja de funcionar «out of the box» pero el grave problema de ser más caros que el jamón. Respecto a Zigbee, lo cierto es que ha estado siendo durante todos estos años el niño perdido de la domótica. Diseñado como un protocolo con bajos requerimientos de hardware y, por ende, de elección para la fabricación de dispositivos potencialmente baratos, había sido tan pobremente adoptado que los pocos dispositivos que había eran raros y con precios no precisamente competitivos… En fin!

Sin embargo, ahora las cosas están cambiando. Raros engendros como Alexa o Google Assistant están consiguiendo que la domótica, relanzada ahora con el nombre de «hogar digital», este pasando de ser una chaladura de cuatro frikis asociada a pelis japos futuristas a convertirse casi, casi en un deporte nacional. Como consecuencia, estoy empezando a ver aparecer dispositivos Zigbee de diversas marcas más o menos reconocidas y a precios similares a los productos Wifi chinos. Por cierto, que entre ellos está una línea de productos de Ikea. Así que decidí que era momento de dedicarles un poco de atención y empezar a aprovechar el tirón.

¿Por dónde?

Lo primero para empezar a funcionar con Zigbee será adquirir y configurar un coordinador universal. Por supuesto, cada marca ofrece su propio coordinador con su app, pero por mal camino iríamos si para aprovechar un protocolo estándar nos liáramos con hardware particular de cada fabricante. Estos coordinadores universales suelen venir con la forma de un dongle USB, y lo que nos interesa es que pueda ser manejado por nuestro controlador domótico. A día de hoy, Openhab dispone de un Addon para Zigbee, pero desgraciadamente se encuentra todavía un poco en pañales y no son muchos los coordinadores con los que puede funcionar sin problemas. En concreto, le había echado el ojo a un coordinador universal que acaba de sacar Sonoff con bastante buena pinta y a un precio bastante interesante, pero que el Addon de Openhab aún no puede reconocer. Existen coordinadores más caros, más antiguos y menos disponibles que sí son compatibles pero, la verdad, no me parece una buena idea tener que morir a este palo.

Afortunadamente ya hace tiempo que existe una solución, bastante más madura, que tiene pinta de provisional pero que bien pudiera quedarse de manera definitiva en función de como evolucionen las cosas. Y se llama Zigbee2MQTT

Como su nombre indica, se trata de un puente entre ambos protocolos. En la práctica consiste en un software independiente que se ejecuta al margen de Openhab, de manera similar al broker MQTT. Zigbe2MQTT puede manejar un buen puñado de coordinadores, entre ellos el que acabo de mencionar de Sonoff, así que decidí probarlo y darle tiempo al equipo que está trabajando en el Addon para ver qué pasa. Y a la vez ir probando el puente y comprobar su versatilidad.

El funcionamiento es bastante sencillo. Por un lado, Zigbe2MQTT se conecta al coordinador para gestionar la red Zigbee, comunicándose directamente con un montón de dispositivos compatibles. Y, por otro, se enlaza al broker MQTT que uno tenga previamente instalado en su controlador domótico permitiendo así la monitorización y control de todos los dispositivos Zigbee mediante mensajes MQTT enviados y recibidos por el broker. Así, para manejar estos dispositivos desde Openhab lo único que tenemos que hacer es añadirlos como cosas genéricas MQTT. Parece sencillo, ¿no?

¿Cómo?

La instalación de Zigbee2MQTT viene bastante bien explicada en su página web. Dejo aquí unas notas de las vueltas que tuve que dar para hacer funcionar el tema.

1.- El software se descarga de Github y se compila en la propia máquina. Una vez hecho, lo instalamos como un servicio. Hasta aquí, ningún misterio.

2.- Si seguimos el proceso de instalación sugerido, el archivo de configuración se guarda en

nano /opt/zigbee2mqtt/data/configuration.yaml

3.- En este fichero conviene hacer algunos cambios. Unos claramente sugeridos en las intrucciones, otros no tanto. Por ejemplo, para manejar el software desde la interfaz web incluida en el paquete es preciso añadir las siguientes líneas al fichero de configuración:

frontend:
   port: 8081

Ojo, que el puerto por defecto es el 8080 que coincide con el de Openhab. De ahí que haya decidido cambiarlo al 8081.

También conviene modificar, por seguridad, el parámetro que permite que cualquier dispositivo Zigbee detectado pueda conectarse sin más (y habilitar esta característica a mano desde la interfaz cada vez que la necesitemos)

permit_join: false

El resto de cambios, como la especificación del puerto serie o la generación de una clave de red personalizada son claramente explicados en las indicaciones. Respecto del puerto serie, dos indicaciones:

  • Si bien podemos especificar directamente el dispositivo creado al enchufar el dongle, no es una buena idea hacerlo así, porque nada garantiza que este puerto no pueda cambiar en un futuro. Es preferible crear un enlace simbólico basado en el ID del dispositivo.
  • También tener en cuenta que el usuario que ejecuta el programa deberá pertenecer al grupo dialout o el programa no podrá acceder al puerto.

Ambas indicaciones vienen explicadas aquí.

¿Con qué?

Ya he mencionado qué coordinador elegí para comenzar mis pruebas. Ahora presentaré el primer dispositivo Zigbee en incorporarse a mis filas: Una bombilla regulable de la marca Osram que encontré en Amazon por menos de 10€

Como hemos indicado, una vez instalado el software la interfaz Web nos permite añadir dispositivos y controlarlos directamente desde la propia interfaz. Ahora bien, si queremos controlar los dispositivos a través del broker MQTT necesitamos conocer la estructura de los mensajes, lo que puede variar un poco de un dispositivo a otro. Para ello, nada como la aplicación MQTT Explorer, directamente disponible desde los repositorios de SNAP,

Operando sobre el dispositivo y fisgando con el explorer podemos ver los mensajes que alcanzan al broker. El «topic» para todos ellos es de la forma zigbee2mqtt/nombre-dispositivo/ y el «payload» del mensaje es una cadena de tipo JSON con los valores de las variables relevantes. Concretamente, para mi bombilla:

{»brightness»:124,»linkquality»:90,»state»:»ON»,»update»:{«state»:»available»}}

El prefijo del «topic» es por defecto zigbee2mqtt, pero puede ser modificado en el archivo de configuración. Y el nombre del dispositivo también puede ser personalizado desde la interfaz web una vez nos conectamos a él.

Sin embargo, si desde el explorer enviamos a dicho «topic» una cadena con la misma estructura y los valores que nosotros queremos, resulta que no pasa nada!!!

Tras mucho darle vueltas y ponerme a trazar diagramas encuentro lo evidente. La pista me la dio la variable «linkquality». Obviamente, esta variable se genera tras la recepción del mensaje, ya que no tiene ningún sentido establecer la calidad del enlace antes de que éste tenga lugar, más que nada porque aún no se conoce. Como estamos operando el dispositivo directamente a través de la red Zigbee, estos mensajes que puedo leer en el explorador son solamente aquellos que van de Zigbee2MQTT hacia el broker MQTT. Es decir, son  mensajes que informan del estado del dispositivo después de que éste haya cambiado su estado. Así que, si queremos modificar el estado del dispositivo enviando mensajes al broker desde otro programa, tal como el MQTT Explorer u Openhab, ¿cómo lo hacemos? Rebuscando un poco por ahí, ya no recuerdo dónde, di con la solución, bastante simple pero un poco puñetera si, como yo, no sabemos bien lo que estamos estamos buscando:

Los mensajes que queremos que alcancen el dispositivo han de ir dirigidos a este topic: zigbee2mqtt/nombre-dispositivo/set, y la carga útil del mensaje es, simplemente, la variable que queremos modificar en formato JSON. Por ejemplo:

zigbee2mqtt/nombre-dispositivo/set {«brightness»:124}

o bien:

zigbee2mqtt/nombre-dispositivo/set {«state»:»ON»}

Y… voilà!

 

Publicado por David en Domótica, 0 comentarios
Logitech Media Server en Ubuntu 22.04

Logitech Media Server en Ubuntu 22.04

Pues eso, una entrada rápida para dejar registro del calvario que supone, en ocasiones, actualizar a una versión nueva y radiante de Ubuntu. El asunto: un servidor con LMS deja de funcionar al actualizar a Ubuntu 22.04, así, sin más.

Algún día daré cuenta de cómo es eso de instalar un sistema de audio distribuido por toda la casa con software libre y hardware casero. Algo a la altura de los carísimos sistemas propietarios de varias marcas de prestigio pero al alcance de cualquier bolsillo modesto. Una auténtica gozada. Y prácticamente gratis. Envidia, ¿¿eh??

Pero ahora vamos al lío. Lo primero es recabar un poco de información.

1.- Lo primero, ojear el estado del servicio logitechmediaserver. Al parecer no se está ejecutando y cada vez que lo arranco muere inmediatamente:

$sudo systemctl status logitechmediaserver
○ logitechmediaserver.service - Logitech Media Server
     Loaded: loaded (/lib/systemd/system/logitechmediaserver.service; enabled; vendor preset: enabled)
     Active: inactive (dead) since Wed 2022-05-11 00:47:56 CEST; 1s ago
    Process: 113300 ExecStart=/usr/sbin/squeezeboxserver --prefsdir $PREFSDIR --logdir $LOGDIR --cachedir $CACHEDIR --charset $CHARS>
   Main PID: 113300 (code=exited, status=0/SUCCESS)
        CPU: 450ms

May 11 00:47:56 blackstone squeezeboxserver[113300]: If you're running some unsupported Linux/Unix platform, please use the buildme.>
May 11 00:47:56 blackstone squeezeboxserver[113300]: script located here:
May 11 00:47:56 blackstone squeezeboxserver[113300]: https://github.com/Logitech/slimserver-vendor/tree/public/8.2/CPAN
May 11 00:47:56 blackstone squeezeboxserver[113300]: If 8.2 is outdated by the time you read this, Replace "8.2" with the major vers>
May 11 00:47:56 blackstone squeezeboxserver[113300]: You should never need to do this if you're on Windows or Mac OSX. If the instal>
May 11 00:47:56 blackstone squeezeboxserver[113300]: don't work for you, ask for help and/or report a bug.
May 11 00:47:56 blackstone squeezeboxserver[113300]: *******
May 11 00:47:56 blackstone squeezeboxserver[113300]:                         
May 11 00:47:56 blackstone squeezeboxserver[113300]: Exiting..
May 11 00:47:56 blackstone systemd[1]: logitechmediaserver.service: Deactivated successfully.

2.- Para tener una idea de por qué se aborta puedo correr el servidor directamente desde el ejecutable:

$squeezeboxserver
The following modules failed to load: DBI EV XML::Parser::Expat HTML::Parser JSON::XS Digest::SHA1 YAML::XS Sub::Name

Lo que ya me está indicando un problema con la carga de los módulos de Perl el cual, por cierto, está instalado en su última versión.

3.- Veamos un poco más información sobre la versión de Perl actualmente instalada:

$perl -v

This is perl 5, version 34, subversion 0 (v5.34.0) built for x86_64-linux-gnu-thread-multi
(with 50 registered patches, see perl -V for more detail)

Copyright 1987-2021, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

Es decir, que tenemos la versión v5.34. ¿Y por qué no cargan los módulos? Pues vaya usted a saber. O mejor aún, búsquelo usted en DuckDuckGo (je, je…)

La primera idea es que la actualización a Ubuntu 22.04 haya implicado un cambio a una versión más reciente de Perl (no comprobado) y que cuando LMS se ejecuta busca los módulos correspondientes a esta versión. Pero como LMS se instaló con una versión de Perl anterior, dichos módulos, simplemente, no están. Así que lo lógico parece reinstalar LMS (y, de paso, instalar la última versión). Sin embargo, esto no parece funcionar…

Así que me fijo en los mensajes de la primera salida, que había pasado por alto, y veo que los muchachos de Logitech en realidad ya me han dejado una pista que seguir, aunque de una manera un pelín críptica. Ubuntu NO es, o al menos hasta la fecha no lo era, una plataforma no soportada para su Media Server (Por eso la primera vez ni seguí leyendo) Pero, como lo cierto es que no está funcionando, empecé a pensar que, de hecho, ahora SÍ que lo es. De modo que me puse a seguir el rastro de migas.

El enlace lleva a un repositorio de github con un software que hay que compilar para parchear la instalación del servidor. También hay un archivo de ayuda (README.md) con unas austeras indicaciones de qué hacer con este software. Así que cloné el repositorio, lo compilé con el script proporcionado (buildme.sh) y realicé la copia de las dos carpetas generadas a la ruta donde squeezeboxserver está instalado, tal como indican las instrucciones. Por cierto, que me costó un poco encontrar la dichosa ruta, así que la dejo anotada aquí:

$cd /usr/share/squeezeboxserver/CPAN/arch/

Curioseando en esta carpeta compruebo, para mi sorpresa, que hay compilaciones instaladas automáticamente con cada una de las versiones anteriores, pero ninguna para la actual versión de Perl, la 5.34. Es decir, que cada instalador ha generado su carpeta con sus módulos salvo la última ¿Y eso por qué? Efectivamente, algo aquí no está funcionando bien. Y, efectivamente, una vez compilado el software y copiado a la ruta en cuestión, mi querido Logitech Media Server vuelve a funcionar. Eso sí, queda sin explicar por qué ya no se incluyen automáticamente estos módulos durante la instalación, si es que los de Logitech han decidido dejar de dar soporte a Ubuntu, si tiene que ver con la versión de Perl o qué, por lo que no sabemos qué pasará cando haya nuevas actualizaciones. Como siempre, cruzaremos ese puente cuando lleguemos a él. Y si eso… ya lo comentaremos.

Publicado por David en Blog, Domótica, Linux, 0 comentarios
Visualización de métricas con Prometheus y Grafana

Visualización de métricas con Prometheus y Grafana

¿Prometheus, Grafana o los dos?

Grafana es una de las herramientas más extendidas y populares para visualizar datos de manera gráfica. Además, estos datos pueden ser adquiridos en tiempo real de sistemas en funcionamiento, lo que permite controlarlos y monitorizarlos con detalle.

La verdad es que a poco que nos hayamos movido por el entorno de Cardano seguro que ya nos hemos encontrado con Grafana, ya que se trata de la opción más extendida y recomendada cuando se trata de supervisar un nodo de la red. No obstante, sus aplicaciones son prácticamente ilimitadas, y en mi caso concreto también me resulta muy útil como panel de control del sistema domótico Openhab.

Grafana puede conectarse a varias fuentes de datos. Una de las más populares, por ser la utilizada por Cardano, es Prometheus. También puede conectarse a InfluxDB, lo cual es muy conveniente, al ser una de las opciones más comunes de entre las disponibles en Openhab.

Prometheus es un software que tiene algunos puntos en común con Grafana. Por sí sólo también es capaz de recolectar datos y mostrarlos en forma de gráficas, aunque sus posibilidades en este sentido son mucho más limitadas. En realidad, sólo con Prometheus ya podríamos realizar la monitorización de un sistema, incluyendo el nodo de Cardano, pero Grafana añade una capa de funcionalidad y prestaciones que resultan muy convenientes. De ahí que, a menudo, en todos los artículos referidos a la monitorización en Cardano aparezcan juntos.

A efectos prácticos utilizaremos Prometheus como un sistema para recolectar y recopilar las métricas que nos interese monitorizar y Grafana como una capa adicional para transformar y visualizar estos datos de la manera que nos resulte más conveniente.

Empecemos por Prometheus

Prometheus recolecta métricas a partir de lo que llama end-points, los cuales no son sino puntos de conexión mediante el protocolo http en los que se encuentran expuestas dichas métricas en un formato XML entendible por Prometheus.

Configuración

La configuración es sencilla, pero si no queremos desorganizar demasiado los scripts de inicio del servicio systemd conviene hechar un vistazo al contenido de éste:

sudo nano /lib/systemd/system/prometheus.service
...
EnvironmentFile=/etc/default/prometheus
ExecStart=/usr/bin/prometheus $ARGS
...

Por cierto, si quieres recordar cómo encontrar la ubicación de los scripts de servicio, echa un vistazo a esta entrada.

En este archivo vemos que el ejecutable es invocado con una variable de entorno $ARGS que contiene los argumentos que se pasan al programa. Vemos también la ubicación del archivo de entorno donde encontraremos la asignación de dicha variable. Si editamos dicho archivo:

sudo nano /etc/default/prometheus

# Set the command-line arguments to pass to the server.
ARGS=""

# Prometheus supports the following options:
#  --config.file="/etc/prometheus/prometheus.yml"
#                             Prometheus configuration file path.
#  --web.listen-address="0.0.0.0:9090"
...

Observamos que la variable de entorno está vacía, lo que nos indica que se toman los argumentos por defecto. Vemos también, comentados, todos los argumentos que pueden ser pasados al ejecutable. Una opción sería especificar dichos parámetros directamente en el archivo de servicio donde se llama al ejecutable, eliminando la variable de entorno $ARGS. Sin embargo, una opción más elegante es colocar dicho parámetro dentro de la cadena $ARGS y permitir que para el resto de parámetros no especificados se apliquen los valores por defecto. Por ejemplo, para modificar el puerto al 9095 podríamos dejar el archivo así (observar las secuencias de escape para las dobles comillas):

sudo nano /etc/default/prometheus

# Set the command-line arguments to pass to the server.
ARGS="--web.listen-address=\"0.0.0.0:9095\""

# Prometheus supports the following options:
#  --config.file="/etc/prometheus/prometheus.yml"
#                             Prometheus configuration file path.
#  --web.listen-address="0.0.0.0:9090"
...

Para configurar los endpoints a los que conectarse, editar el archivo:

sudo nano /etc/prometheus/prometheus.yml

Métricas de Cardano

El software cardano-node ofrece, de manera nativa, un end-point con las métricas de funcionamiento del nodo. En el archivo de configuración de cardano-node encontraremos un apartado donde configurar el número de puerto (por si necesitáramos cambiarlo) y las direcciones desde las cuales es posible conectarse al end-point (punto importante cuando el servidor Prometheus está en una máquina diferente). Concretamente, esta sección tiene el siguiente aspecto:

"hasPrometheus": [
    "127.0.0.1",
    12798
  ]

Ésta es la configuración por defecto. Indica que la conexión sólo es posible desde la máquina local y en el puerto 12798. Si necesitamos conectarnos desde otra máquina, deberemos especificar, o bien la dirección IP de la misma, o bien «0.0.0.0» para la conexión desde cualquier dirección IP. No olvidemos que, en este caso, además deberemos habilitar este puerto en el firewall.

Si queremos echar un vistazo a los datos en crudo ofrecidos por el end-point de nuestro nodo bastará con dirigir nuestro navegador a la dirección:

http://<ip_nodo>:12798/metrics

Obviamente, el end-point deberá ser accesible desde la máquina en la que tengamos el navegador. Como es posible que eso no coincida con la configuración que estamos planeando, y para no andar toqueteando aquí o alla, una buena alternativa al navegador es el comando curl en la misma máquina en la que se encuentre el end-point:

curl -s http://localhost:12798/metrics

Métricas del nodo

Otro conjunto de datos que suele resultar interesante para comprobar el buen desempeño de una máquina es el relacionado con el correcto funcionamiento y rendimiento del hardware y del sistema operativo: temperaturas, carga de la CPU, uso de memoria, etc. Estas métricas pueden obtenerse instalando el software prometheus-node-exporter, el cual recopila todos estos parámetros y los expone en un nuevo end-point en el puerto 9100. Como antes, para comprobar el buen funcionamiento del end-point:

curl -s http://<ip_nodo>:9100/metrics

Aunque parezca una trivialidad, no está de más no confundir el software prometheus-node-exporter, el cual sólo crea un end-point donde exponer métricas de funcionamiento de la máquina, con el servidor Prometheus, que es el que se encarga de recopilar y almacenar todos los datos obtenidos de los diferentes end-points. Aunque a menudo se instalen a la vez, son piezas de software diferentes y ni siquiera es necesario que vayan juntos.

Métricas de dispositivos de red

El protocolo SNMP (Simple Network Management Protocol) permite el intercambio de información entre dispositivos conectados a una misma red. Entre sus usos más frecuentes se encuentra la configuración automática de routers o firewalls por parte de aquellos programas que lo necesiten. Sin embargo, también es posible utilizarlo para obtener métricas de dispositivos de red y mostrarlas en Grafana. Por ejemplo, podemos monitorizar el router y comprobar el buen funcionamiento de nuestra conexión a internet.

Necesitaremos dos cosas:

  • Que nuestro router sea compatible con SNMP y que éste se encuentre habilitado
  • Tener instalado prometheus-snmp-exporter en nuestro servidor. Este software es capaz de comunicar con dispositivos que hablen SNMP y de ofrecer las métricas así obtenidas exponiendo un end-point para Prometheus. Este software se puede instalar directamente desde los repositorios de Ubuntu o bien descargándolo desde github, concretamente, aquí.

Su configuración se encuentra en el archivo:

sudo nano /etc/prometheus/snmp.yml
# Due to licensing reasons, it is not possible to ship a ready-to-use snmp.yml
# config file.
#
# See /usr/share/doc/prometheus-snmp-exporter/README.Debian for instructions
# on using prometheus-snmp-generator to create a suitable snmp.yml config.

En el que nos encontramos este curioso mensaje. La lectura del archivo README.Debian tampoco proporciona mucha más información.

La manera de proceder es sencilla. En github, que es donde se aloja el proyecto, viene un archivo snmp.yml por defecto que en la mayoría de las ocasiones nos funcionará correctamente, así que podemos, simplemente, descargarlo en el directorio arriba mencionado.

Importante: dependiendo del método escogido para instalar prometheus-snmp-exporter nos encontraremos con una versión u otra. Normalmente, las versiones disponibles en los repositorios oficiales de Ubuntu suelen estar algo desfasadas con respecto a la última versión disponible en GitHub. Esto es importante, porque si el software instalado y el archivo de configuración descargado corresponden a versiones diferentes, podría no funcionar.

Por ejemplo, en el momento de escribir esta entrada, la versión instalada a partir de los repositorios de Ubuntu es la v0.16.1, bastante anterior a la versión actual de GitHub, que es la v0.20.0. Por lo tanto necesitamos buscar el archivo de configuración de la versión adecuada, lo que conseguimos tecleando:

sudo wget https://raw.githubusercontent.com/prometheus/snmp_exporter/v0.16.1/snmp.yml

Si todo va bien, podemos observar las métricas en el endpoint correspondiente:

curl http://<server_ip>:9116/snmp?target=<router_ip>

Visualizando con Prometheus

Como decíamos, Prometheus por sí mismo puede ser utilizado como herramienta de monitorización y visualización. Para ello, sólo hay que conectarse desde un navegador a la dirección de la máquina donde se esté ejectuando el servidor:

http://<nodo_prometheus>:9010

Y veremos algo como esto:

Prometheus

En esta página disponemos de algunas opciones que nos permiten ir añadiendo gráficas y seleccionando las métricas deseadas.

Y sigamos con Grafana

Grafana suele ser instalada en la misma máquina en la que tenemos el servidor Prometheus pero, en realidad, podría estar en cualquier otro. Dispone de la posibilidad para conectar con diferentes fuentes de datos, entre ellas, como ya hemos comentado, con Prometheus y con InfluxDB.

Contrariamente a lo que pensé en un principio, Grafana no es capaz de conectar directamente con los end-points que proporcionan los datos para Prometheus, sino sólo con éste último. Es decir, que para monitorizar un nodo de Cardano, Grafana nos la podríamos ahorrar, pero Prometheus no.

Base de datos

Grafana utiliza una base de datos de tipo SQLite ubicada en /var/lib/grafana/grafana.db

  • Si en algún momento metemos la pata y deseamos deshacer el desaguisado manualmente, siempre podemos descargar el archivo y editarlo manualmente con esta excelente herramienta de código abierto: DB Browser for SQLite
  • No está de más incluir este archivo entre aquellos de los que solemos hacer copia de seguridad.
Publicado por David en Cardano, Domótica, Linux, 0 comentarios
A vueltas con Openhab

A vueltas con Openhab

Actualizando Openhab

Si hemos instalado Openhab siguiendo las recomendaciones, lo más probable es que hayamos elegido Zulu como la plataforma de Java. Sin embargo, Openhab no es compatible con versiones de Java mayores que 11 y si instalamos Zulu a partir de los repositorios, cada vez que haya una actualización inevitablemente se configurará la más reciente como versión por defecto. Por eso es necesario, antes de reiniciar Openhab, seleccionar la versión correcta de Java:

~$ sudo update-alternatives --config java
[sudo] password for drhome: 
There are 2 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                          Priority   Status
------------------------------------------------------------
  0            /usr/lib/jvm/zulu15/bin/java   2153801   auto mode
* 1            /usr/lib/jvm/zulu11/bin/java   2115401   manual mode
  2            /usr/lib/jvm/zulu15/bin/java   2153801   manual mode

Press <enter> to keep the current choice[*], or type selection number:
1 

Archivos de log

 tail -f /var/log/openhab/openhab.log

Consola Karaf

OpenHab proporciona una consola desde la que poder monitorizar y gestionar algunos aspectos del sistema. Podemos conectarnos de dos maneras:
Si estamos estamos conectados con una sesión remota de shell:

openhab-cli console

Mediante ssh, solamente si estamos conectados localmente

ssh -p 8101 openhab@localhost

Por cierto, que las credenciales por defecto son:
usuario: openhab, contraseña: habopen

Publicado por David en Domótica, Linux, 0 comentarios

Iniciar un servicio mediante systemd

En este caso se trata de una Raspberry Pi que controla unos paneles de leds que muestran, además de la fecha y la hora, algunos mensajes de información provenientes del controlador domótico mediante el protocolo MQTT, tales como la temperatura de distintas estancias, o la música que se está reproduciendo en ese momento (Y sí, os habéis fijado bien. La fecha viene en Esperanto. Qué le vamos a hacer…). El dispositivo cuenta además con un sensor de luz, el cual le permite, además de regular la luminosidad de los leds en función de la luz ambiente, proporcionar al sistema información sobre el nivel de luminosidad real de la estancia, permitiendo un control preciso de persianas y luces regulables.

Aspecto del reloj con matriz de leds en la parte superior de la librería de mi dormitorio, junto a algunos libros y colecciones de pelis en viejos archivadores de CD’s. Todo un compendio de mis pequeñas pasiones 😉

Para que el dispositivo funcione de manera autónoma, el programa deberá arrancar automáticamente cuando se encienda la placa, lo cual se puede lograr de varias maneras. Una de ellos, seguramente la más conocida, consiste en añadir la ruta al ejecutable en el archivo /etc/rc.local, aunque también es posible iniciar tareas utilizando el servicio crontab. En ambos casos tenemos un pequeño problema, y es que si el programa se cuelga o experimenta una salida inesperada debida a cualquier excepción no convenientemente capturada, todo el dispositivo se detiene dejando de funcionar.

Para salir al paso, una solución consiste en ejecutar el programa como un servicio. En el  caso que nos ocupa vamos a utilizar el sistema systemd, el cual presenta, entre otras, la gran ventaja de que si se produce un error y el progama se detiene, él mismo se reinicia automáticamente. Algo que a los manazas que vamos dejando rastros de programas mal depurados nos viene que ni de perlas. También es un sistema bastante robusto y que nos permite ajustar las condiciones adecuadas para la ejecución del probrama.

Lo primero que necesitamos es un archivo de script que contenga las instrucciones de inicio de nuestro programa. Si fuera necesario pasar parámetros para el inicio este archivo sería un lugar adecuado para especificarlos. En nuestro caso, es una simple llamada a la ejecución de un script Python:

nano /home/pi/mqtt-matrix/start.sh

#!/bin/bash
#
python3 /home/pi/mqtt-matrix/mqtt-matrix.py

Lo siguiente será la creación del archivo de unidad de servicio. Éste contendrá el nombre con el que queremos que systemd reconozca a nuestro servicio. Aunque sería improbable, no está de más comprobar que no vamos a darle un nombre que ya se encuentra en uso. Para ello, basta con echar un vistazo al contenido de la carpeta que suele contener los archivos de unidad de servicio:

cd /etc/systemd/system/
ls

También podemos probar este comando más específico y que resulta de lo más molón:

sudo systemctl list-unit-files --type=service

En mi caso, como el programa que pretendo ejecutar está en el archivo mqtt-matrix.py, he decicido que el servicio se llame mqtt-matrix.service y listos. Así que creamos el archivo en cuestión:

sudo nano /etc/systemd/system/mqtt-matrix.service

[Unit]
Description=mqtt-matrix
Wants=network.target
After=syslog.target network-online.target

[Service]
Type=simple
ExecStart=/home/pi/mqtt-matrix/start.sh
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target

El archivo que hemos creado contiene las opciones más comunes, la mayoría de las cuales resultan bastante autoexplicativas. Además, podríamos especificar el usuario y el grupo bajo el cual se va a ejecutar nuestro servicio. Si no se especifica nada, por defecto se ejecutará con permisos de administrador, que es exactamente lo que deseamos, por ser uno de los requisitos del modo en el que accedemos a los pines de nuestra raspberry, así que lo dejamos tal cual.

Y ya está. A continuación enumeramos varios de los comandos más utilizados para manejar los servicios systemd

Recargar los archivos de servicio después de alguna modificación

sudo systemctl daemon-reload

Iniciar el servicio

sudo systemctl start mqtt-matrix.service

Detener el servicio

sudo systemctl stop mqtt-matrix.service

Reiniciar el servicio

sudo systemctl restart mqtt-matrix.service

Comprobar el estado del servicio

Además, nos proporciona información adicional, tal como:

  • Avisarnos si tenemos errores en la sintaxis del archivo, aunque el servicio no esté en ejecución
  • Indicarnos la ruta del ejecutable
  • Indicarnos la ubicación del archivo de servicio si no está donde esperábamos
sudo systemctl status mqtt-matrix.service

Y, lo más importante, teniendo en cuenta de qué va todo esto, indicarle al sistema que queremos que el servicio arranque automáticamente al inicio

sudo systemctl enable mqtt-matrix.service

O bien, deshabilitar el arranque al inicio

sudo systemctl disable mqtt-matrix.service
Publicado por David en Domótica, Linux, 0 comentarios