La configuración por defecto de OpenVPN permite acceder sólo al equipo servidor de VPN cuando estableces la conexión desde el cliente. Sin embargo, es posible extender el acceso al resto de equipos de la red local de dicho servidor, en caso de necesitar acceso a otras máquinas. La receta es la siguiente:
Referencias:
Estas Navidades me han regalado una estación meteorológica casera, de las que tienen capacidad para mostrar temperatura y humedad tanto en interior como en exterior, esto último mediante un módulo externo que se deja a la intemperie, y que transmite la información a la estación mediante señal de radio a 433 MHz. Aparte de por el regalo en sí, este tipo de estaciones me venía interesando desde hace bastante tiempo por el hecho de enviar la información utilizando la banda antes mencionada, de la que dispongo unos cuantos receptores. Así que en cuanto abrí el regalo supe que iba a invertir algo de tiempo en intentar integrar el sensor externo en mi sistema de domótica.
Tras investigar un poco sobre este tipo de estaciones, encontré que la mayoría de ellas hacen uso de protocolos de comunicación bien definidos y relativamente estandarizados, lo que hace que sea razonablemente sencillo encontrar información sobre las mismas, e incluso implementaciones de dichos protocolos para entornos linux o arduino. Dicho lo cual, empecé a hacer algunas pruebas de implementación de un sistema que permitiera recibir la información del emisor externo. Las primeras pruebas las hice con un receptor basado en arduino y un módulo 433 MHz, más la librería rc-switch que tan buenos resultados me había dado en el pasado. No fue este el caso, ya que al intentar capturar paquetes enviados por la estación el programa de captura de paquetes basados en esta librería producía un error de desbordamiento, siendo incapaz de recibir correctamente el datagrama. Hice algunas pruebas en bruto con otras librerías, entre las que se incluían algunas diseñadas específicamente para alguno de los protocolos de envío antes mencionados, con resultados igualmente infructuosos.
Ante ello, no me quedó más remedio que cambiar el enfoque. Tocaba acometer el problema desde una perspectiva más basica. Así que me tocó desempolvar un receptor RTL SDR que compré hace algún tiempo para un proyecto similar, e intentar hacer una captura del datagrama a nivel de onda enviada, e intentar decodificar la misma (tirando para ello de programas como Gqrx, audacity, y algo de tiempo. Sin embargo, tuve algo de suerte, y tras seguir investigando un poco más, encontré una referencia a un proyecto, rtl_433, que se dedica a decodificar el tráfico de dispositivos que envían información en esta banda.
Tras una instalación sencilla en mi equipo con Debian (apt install rtl_433), y tras conectar el receptor RTL SDR al mismo, tuve la suerte de que el programa tuviera perfectamente identificado el tipo de protocolo que mi estación estaba utilizando, en concreto el protocolo “Kedsum Temperature & Humidity Sensor, Pearl NC-7415″. Trasteando un poco con el programa, pude tener algo más de información sobre este protocolo, a saber:
Frame structure:
Byte: 0 1 2 3 4
Nibble: 1 2 3 4 5 6 7 8 9 10
Type: 00 IIIIIIII BBCC++++ ttttTTTT hhhhHHHH FFFFXXXX
- I: unique id. changes on powercycle
- B: Battery state 10 = Ok, 01 = weak, 00 = bad
- C: channel, 00 = ch1, 10=ch3
- + low temp nibble
- t: med temp nibble
- T: high temp nibble
- h: humidity low nibble
- H: humidity high nibble
- F: flags
- X: CRC-4 poly 0×3 init 0×0 xor last 4 bits_Modulation = OOK_PULSE_PPM,
-Short_width = 2000,
-Long_width = 4000,
-Gap_limit = 4400,
-Reset_limit = 9400,
Bien, ya tenía identificado claramente el protocolo, y aquí puede verse una captura de la señal recibida:
root@asustinker:/etc/systemd/system# /usr/local/bin/rtl_433 -R 57
rtl_433 version 19.08-147-g639ab8a branch master at 202001210044 inputs file rtl_tcp RTL-SDR
Use -h for usage help and see https://triq.org/ for documentation.Consider using “-M newmodel” to transition to new model keys. This will become the default someday.
A table of changes and discussion is at https://github.com/merbanan/rtl_433/pull/986.Registered 1 out of 145 device decoding protocols [ 57 ]
Found Rafael Micro R820T tuner
Exact sample rate is: 250000.000414 Hz
[R82XX] PLL not locked!
Sample rate set to 250000 S/s.
Tuner gain set to Auto.
Tuned to 433.920MHz.
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time : 2020-01-25 15:24:00
model : Kedsum Temperature & Humidity Sensor ID : 226
Channel : 1 Battery : OK Flags2 : 129 Temperature: 60.20 F Humidity : 78 % Integrity : CRC
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Bien, esto me planteaba dos problemas: el primero es que la información recibida de temperatura estaba expresada en grados Fahrenheit, por lo que necesitaba hacer una conversión a Celsius. Y por otro lado, el poder transmitir esta información a mi plataforma de domótica, preferentemente a través de MQTT. Este segundo problema quedó solucionado mediante la capacidad del programa rtl_433 de encapsular la información en un JSON, que puede ser retransmitido posteriormente. En mi caso, lo hice mediante un servicio linux que lanza el programa rtl_433 con las opciones adecuadas (formato JSON, protocolo 57 -Kedsum-, e incrustando la hora UTC), que mediante un pipe es procesado por el cliente MQTT mosquitto y enviado a mi servidor MQTT, a un topic específico:
“/usr/local/bin/rtl_433 -R 57 -F json -M utc | /usr/bin/mosquitto_pub -l -h servidor_mqtt -t topic”
…donde posteriormente es procesado gracias a Node Red, en el que se hace la conversión a Celsius, se obtiene también la sensación térmica, y se inyecta la información resultante en formato JSON en un topic específico:
var data=JSON.parse(msg.payload);
//Datagram example: {“time” : “2020-01-22 19:27:58″, “model” : “Kedsum Temperature & Humidity Sensor”, “id” : 226, “channel” : 1, “battery” : “WEAK”, “flags” : 66, “temperature_F” : 54.600, “humidity” : 79, “mic” : “CRC”}
temp_value=((data.temperature_F-32)*5/9).toFixed(2);
humidity=data.humidity;HI = 0.5*(data.temperature_F + 61.0 + ((data.temperature_F-68.0)*1.2) + (humidity*0.094))
HIc = (((HI)-32)*5/9).toFixed(2); // converting to Celsiusvar thing = {
temp: temp_value,
humidity: humidity,
heatindex: HIc
};
msg.payload=thing;return msg;
…y el resultado de todo esto fue un… ¡exito! Pasé a conectar el receptor RTL SDR a mi Asus Tinker Board donde tengo implementado el sistema de domótica, con excelentes resultados. El sistema, emplazado en la segunda planta de casa, es capaz de recibir las señales del receptor externo emplazado en el patio.
Por otro lado, quedaba la integración en el sistema de domótica Home Assistant. En este caso, se trataba de alto tan simple como crear los nuevos sensores en base a la suscripción al topic MQTT de salida definido en el flujo Node Red. El resultado, como no podía ser menos, fue perfecto:
Este artículo podría haber quedado aquí, pero no me encontraba completamente satisfecho con el resultado, ya que me daba la impresión de que utilizar el receptor RTL SDR solo para este propósito era matar moscas a cañonazos. Mi idea originaria era usar un ESP8266 junto con un módulo RF de 433 Mhz para recibir estas señales, y decodificarlas en el mismo, para inyectar la información directamente en el servidor MQTT, y no tener que dar tantos saltos (RTL SDR -> JSON -> MQTT -> Node Red -> MQTT). No tuve éxito en encontrar una codificación del protocolo bajo el nombre de Kedsum, pero sí la tuve con Pearl NC-7415. Encontré un hilo en un foro de Arduino en alemán, que hablaba precisamente de ello: Dekodieren Temperatursensor von PEARL NC7427(NC7415) 433MHz. Gracias, Google Translate.
En este hilo pude encontrar alguien que había decodificado exitosamente el protocolo, y que compartía el código. Lo descargué y lo probé y… ¡funcionaba perfectamente! Solo tuve que hacer una modificación menor para realizar la conversión de Fahrenheit a Celsius, calcular la sensación térmica, e inyectarlo en el topic MQTT (el original no hacía nada de esto, se limitaba a mostrar la información por pantalla). Y de nuevo, éxito:
Sin embargo, esta vía tiene un problema: el receptor apenas es capaz de recibir la señal cuando se encuentra a unas pocas decenas de centímetros del emisor externo. Así que en la práctica ahora mismo es inusable. He probado con varios formatos de antena acoplados al módulo (173mm de largo, en hilo recto, en espiral…) con resultados bastante pobres. Tengo encargada en aliexpress una antena específica, pero aún tardará algunas semanas en llegar. Espero poder reportar mejoras una vez la reciba.
Etiquetas: 433 mhz, arduino, asus tinker board, audacity, debian, esp8266, gqrx, home assistant, kedsum, mqtt, node-red, nodemcu, rtl sdr, rtl_433
Hace un rato he recibido en casa un receptor GPS modelo GlobalSat BU-353-S4 que he comprado para un proyecto que tengo en mente.
Este receptor está soportado perfectamente en linux (algo clave para mi proyecto). De momento, he podido comprobar que funciona perfectamente con gpsd y cgps:
En apenas unos segundos ha localizado mi ubicación actual.
En cuanto al proyecto en sí, no adelantemos acontecimientos. Pero incluye una Raspberry Pi y un emisor OBD-II por bluetooth (sí, todo es mejor con Bluetooth).
Etiquetas: debian, globalsat bu-353-s4, gpsd, odb-ii
…o en xbian, o en cualquier otro sistema operativo linux para Raspberry Pi. Uno de los problemas que estoy viendo que son más habituales a la hora de manejarse con la RPi es que las tarjetas de red inalámbricas por USB no suelen disponer de drivers adecuados para funcionar.
O al menos, las dos que yo he comprado, adolecían de este problema. ^_^ En el caso concreto de la TP-Link TL-WN725N, existen, al parecer, dos versiones: la v1 hace uso del chipset RealTek RTL8188CUS (que sí cuenta con soporte nativo en la RPi), la v2 utiliza el chipset RTL8188EUS, que no lo tiene, por lo que es preciso andar compilando, algo que en la RPi suele ser un tanto doloroso. Pero que, dado que se cuenta con fuentes adecuadas, tampoco es excesivamente complicado.
Lo que sí hay que tener en cuenta, según he podido descubrir, es que el driver, compilado directamente de las fuentes, tiene dos problemas tal y como viene de fábrica: el led de estado no funciona, y vuelca demasiada información de debug en los logs de sistema. Esto último, en el caso de la RPi, que hace uso de tarjetas microSD para albergar el sistema operativo, puede ser bastante grave, tanto por problemas de rendimiento como por desgaste del dispositivo. Por suerte, se puede modificar la fuente del código para solventar este problema antes de la instalación. Los pasos a seguir son los siguientes:
Obtener el código necesario para compilar el driver
git clone https://github.com/liwei/rpi-rtl8188eu.git
git clone –depth 1 git://github.com/raspberrypi/linux.git rpi-linux
git clone –depth 1 git://github.com/raspberrypi/firmware.git rpi-firmware
Modificar el fichero rpi-rtl8188eu/include/autoconf.h
Es preciso modificar dos aspectos: descomentar la línea #define CONFIG_LED, y comentar la línea #define CONFIG_DEBUG_RTL819X. En el siguiente diff puede verse de manera más clara:
diff -Nauw ~/src/pi_plus/linux/drivers/net/wireless/rtl8188eu/include/autoconf.h include/autoconf.h
— /home/pi/src/pi_plus/linux/drivers/net/wireless/rtl8188eu/include/autoconf.h 2013-05-02 19:39:42.177227144 +0100
+++ include/autoconf.h 2013-05-03 00:22:52.383030986 +0100
@@ -156,7 +156,7 @@#define CONFIG_SKB_COPY 1//for amsdu
-//#define CONFIG_LED
+#define CONFIG_LED
#ifdef CONFIG_LED
#define CONFIG_SW_LED
#ifdef CONFIG_SW_LED
@@ -328,7 +328,7 @@
//#define CONFIG_DEBUG_RTL871X#define DBG 1
-#define CONFIG_DEBUG_RTL819X
+//#define CONFIG_DEBUG_RTL819X#define CONFIG_PROC_DEBUG 1
Compilar e instalar el driver
Seguimos con la receta anterior:
cd rpi-linux
make mrproper
zcat /proc/config.gz > .config
make modules_prepare
cp ../rpi-firmware/extra/Module.symvers .
cd ../rpi-rtl8188eu
CONFIG_RTL8188EU=m make -C ../rpi-linux M=`pwd`
sudo rmmod 8188eu
sudo install -p -m 644 8188eu.ko /lib/modules/`uname -r`/kernel/drivers/net/wireless
sudo depmod -a
sudo modprobe 8188eu
Con todo ello, quedará correctamente instalado el driver para poder utilizar esta tarjeta.
Las fuentes de este artículo son las siguientes:
Bonus extra
En la raspbian pelada y mondada, tal y como viene de fábrica, no se disponen de los elementos necesarios para compilar drivers, ni para hacer funcionar una tarjeta wifi. Es necesario, al menos, instalar lo siguiente:
Para realizar la instalación de lo anterior, lo de siempre en sistemas de la familia Debian:
apt-get install build-essentials git wireless-tools usbutils wpa-supplicant
Etiquetas: debian, raspberry pi, raspbian, rpi, tl-wn725n, tp-link
Estas semanas, cuando el trabajo y la salud me lo han permitido, he estado realizando algunos cambios en el servidor. Como comenté anteriormente, el más importante ha sido el cambio de su ubicación: ha pasado de ser un servidor virtual VMWare ubicado en Córdoba a ser un servidor físico emplazado en Sevilla. Y ya que estaba de cambios, me decidí a probar un servidor web del que llevaba tiempo escuchando hablar: nginx.
nginx es un servidor web/proxy inverso ligero de alto rendimiento y un proxy para protocolos de correo electrónico (IMAP/POP3). Es software libre y de código abierto, licenciado bajo la Licencia BSD simplificada. Es multiplataforma, por lo que corre en sistemas tipo Unix (GNU/Linux, BSD, Solaris, Mac OS X, etc.) y Windows.
El sistema es empleado en una larga lista de sitios web conocidos, como: WordPress, Hulu, GitHub, Ohloh, SourceForge y TorrentReactor. Originalmente, nginx fue desarrollado para satisfacer las necesidades de varios sitios web de Rambler que recibían unas 500 millones de peticiones al día en septiembre de 2008.
De acuerdo con el estudio de Netcraft, Netcraft’s May 2010 Web Server Survey, nginx fue el tercer servidor web más usado en todos los dominios (6.55% de los sitios estudiados) y el cuarto servidor web más usado en los sitios activos (8.77% de los sitios estudiados).
Sus características básicas son las siguientes:
La arquitectura interna de nginx le permite servir más peticiones por segundo con menos recursos que sus principales alternativas. Ésta consiste en un proceso maestro que delega el trabajo en uno o varios procesos “worker”. Cada worker gestiona múltiples peticiones de modo basado en eventos, o bien asíncrono, haciendo uso de funcionalidades especiales del kernel Linux (epoll/select/poll). Esto permite a nginx gestionar un gran número de peticiones concurrentes de una manera rápida y con muy poca sobrecarga. Por ejemplo, un servidor Apache puede ser configurado para procesar las bien una petición por proceso (pre-fork) o bien una petición por cada hilo (worker). Aunque el modo basado en hilos de Apache tiene un rendimiento mucho mejor que el basado en procesos, sigue haciendo uso de mucha más memoria y CPU que la arquitectura basada en eventos de nginx.
En mi caso concreto, mi servidor web contiene las siguientes aplicaciones:
Mi objetivo primordial era realizar un reemplazo completo del servidor Apache, motivado por las siguientes razones: el cambio del servidor me ha dejado con menos recursos hardware (en concreto, con menos RAM y con un procesador menos potente), y sobre todo, comprobar si nginx es tan bueno como lo vende.
A la hora de realizar el cambio, pude comprobar algo que es bastante importante: nginx es un servidor web de ficheros estáticos. Esto quiere decir que si estás pensando en sacar a través de él páginas web dinámicas tienes un problema. Por suerte es un problema fácilmente abordable, ya que al estar pensado desde el principio como un servidor proxy inverso, tienes la capacidad de delegar funcionalidades no soportadas en otros servidores adicionales. En mi caso, instalé en mi servidor Debian un servidor PHP externo, spawn-fcgi, que escucha peticiones por el puerto 9000.
La migración de WordPress no supuso mayor problema, una vez solucionado el tema anterior. Sin embargo, la de Gallery2 sí me ha planteado más dificultades, debido a una serie de reescrituras un tanto especiales que necesita para mantener funcionando el sistema. Tras varios días de pruebas, y viendo que no alcanzaba a migrar completamente esta aplicación, decidí darle un cambio de perspectiva: mantener el servidor Apache como un servidor web subordinado, y emplear nginx como servidor de fachada, con caché de contenido. No hay mal que por bien no venga, ya que me ha supuesto la oportunidad de realizar pruebas de esta funcionalidad, de cara a una línea de trabajo que estoy desarrollando para mi empresa.
Como consecuencia de lo anterior, decidí mover los puertos de servicio del servidor Apache al 81 (conexión http) y 444 (conexión https), que son sólo alcanzables desde la red interna de mi casa. Mediante una serie de reescrituras, las peticiones efectuadas al sistema Gallery2 son dirigidas al servidor Apache, procesadas por éste, y reenviadas por nginx al cliente, además de ser cacheadas para ganar en tiempo de respuesta. El resto de peticiones (WordPress, otras aplicaciones…) son servidas directamente por el servidor nginx. Un diagrama básico de lo expuesto hasta el momento sería el siguiente:
El resultado desde el punto de vista funcional es bastante bueno: las aplicaciones siguen siendo servidas de manera correcta, se ha ganado algo en tiempo de respuesta (por desgracia, la poca potencia del servidor y las limitaciones de la línea de datos no permiten grandes alegrías), y ha disminuido el consumo de memoria: pese a no haber eliminado el servidor Apache, se ha pasado de consumir unos 900 MB de RAM a unos 780, y con un comportamiento mucho más estable. Cada proceso nginx consume un máximo de 3 MB, mientras que cada proceso Apache ronda los 50 MB, con una gran fluctuación de memoria consumida. A esto hay que sumar los dos procesos configurados para spawn-fcgi, que también rondan los 50 MBs. La bajada en el consumo ha venido de haber podido reducir el número de procesos Apache que se mantienen en ejecución: he podido pasar de un mínimo de 10 procesos concurrentes a tan sólo 2.
En resumen: estoy bastante contento con el cambio. Estoy aprendiendo a gestionar servidores web de alto rendimiento, y creo que voy a poder sacarle bastante partido a este servidor nginx en el ámbito laboral. Esperemos que así sea.