Hoy vengo a hablar de domótica. Hace ya tiempo compré un sensor de temperatura Bluetooth de la marca Mijia (que no deja de estar bajo el paraguas de Xiaomi), con el fin de monitorizar la temperatura del salón de mi casa. Fue un primer, aunque modesto, paso para ir domotizando mi casa.

El problema estaba en que dicho sensor era Bluetooth, con lo que sólo podía consultar sus datos cuando estaba en casa... Algo poco útil porque para eso tenía la pantalla. Para poneros un poco más en contexto, se trata de la primera versión que sacó Xiaomi de dicho sensor, en concreto el modelo NUN4019TY, que podéis ver en esta imagen:

Sensor de temperatura y humedad NUN4019TY
Sensor de temperatura y humedad NUN4019TY

Como veis, se trata de algo muy sencillo, apenas nos muestra la temperatura y la humedad, y los iconos de estado de la batería (funciona con una pila AAA) y el enlace Bluetooth.

Sin embargo, en el momento que me hice con una Raspberry Pi 4, la cual viene con Bluetooth incorporado, empecé a pensar que, si podía conectarme al sensor desde ella y extraer los datos, podría entonces publicarlos en Mosquitto y así tenerlos accesibles desde Home Assistant o desde cualquier cliente que se conectara a dicho tópico.

Así pues, me puse a investigar y di con un pequeño script en Python que pude modificar a mi gusto. Lo tenéis disponible en mi repositorio. A continuación os cuento cómo podéis usarlo si tenéis algo similar y queréis aprovecharlo.

Requisitos previos

Obviamente, necesitamos contar con una Raspberry Pi que tenga Bluetooth o algún sistema que cuente con él, un bróker MQTT (yo lo hice con Mosquitto) y un sensor de temperatura y humedad de Mijia.

Por otro lado, deberemos tener instalado bluez y python3. Con ellos, podremos instalar las dependencias haciendo uso del comando:

pip3 install -r requirements.tx

Comando para instalar las dependencias necesarias para el script

Configuración

Lo primero que tenéis que hacer es, obviamente, descargaros el código del proyecto. Una vez lo tengáis en vuestra máquina, copiad el archivo env_file (o renombradlo) a un fichero .env. Abridlo con vuestro editor y rellenad las variables que necesitéis. Aquí os dejo lo que hace cada una:

  • MQTT_SERVER: Dirección IP donde se encuentra el servidor MQTT
  • MQTT_PORT: Puerto del servidor MQTT
  • MQTT_USER: Usuario para conectarse al servidor (en caso de ser necesario)
  • MQTT_PASSWORD: Contraseña del usuario (en caso de ser necesaria)
  • MQTT_CLIENT_ID: ClientID con el que se conectará el script al servidor
  • MQTT_SENSOR_NAME: ID con el que creará el tópico para publicar la información
  • MQTT_TOPIC_PREFIX: Prefijo del tópico a usar
  • MQTT_TELE_PREFIX: Prefijo del tópico en el que publicar el estado (online/offline)
  • MQTT_PUBLISH_DELAY: Tiempo de espera, en segundos, tras publicar la info y finalizar el script
  • MIJIA_BTLE_ADDRESS: Dirección MAC del Bluetooth del sensor
  • PING_URL: URL que se puede usar para notificar que el script se ha ejecutado correctamente

Como veis, la configuración no es muy compleja. La información sobre el bróker MQTT se utilizará para publicar en 2 tópicos: uno de estado, en el que el script publicará online mientras está trabajando, y offline cuando termina; y otro formado por el prefijo definido en MQTT_TOPIC_PREFIX más el nombre del sensor que hayamos definido. La información se publica en formato JSON.

Para obtener la dirección MAC del Bluetooth del sensor, podemos ejecutar el comando hcitool dev que nos listará los dispositivos que tenemos disponibles, y usando ese resultado, el comando sudo hcitool lescan hci0 (en el caso de la RPi el Bluetooth lo trae en el dispositivo hci0 por defecto). Esto nos dará un listado de dispositivos Bluetooth y deberemos quedarnos con el del sensor, que suele venir identificado como MJ_HT_V1 o similar.

Ejecución del script

Una vez tenemos la configuración creada, bastará con darle permisos al script y ejecutarlo mediante ./main.py directamente. Como ejemplo, tendremos en la consola una salida similar a ésta:

Starting MiJia GATT client
Connecting to AA:BB:CC:DD:EE:FF
Disconnected :(
Connecting to AA:BB:CC:DD:EE:FF
Set delegate
Battery level: 84
Temperature: 19.7
Humidity: 38.7
Done.

Ejemplo de salida de la consola al ejecutar el comando

En el ejemplo anterior, vemos que ha tenido que realizar 2 intentos para conectar con el sensor. El script lo intentará una y otra vez hasta que lo logre, momento en el cual extraerá la información y la publicará en el bróker MQTT y finalizará. Durante todo el proceso, figurará como online en el tópico de telemetría. Esto nos puede permitir poner alertas si, por ejemplo, dicho tópico no pasa de online a offline en menos de 2 minutos, que es tiempo más que suficiente para que, tras X reintentos, hubiera podido conectarse.

Si definimos el prefijo como sensores/b2m y el nombre del sensor mijia-temp, si nos conectamos al bróker veremos que, bajo el tópico sensores/b2m/mijia-temp se habrá publicado un mensaje como el siguiente:

{
  "id": "mijia-temp", 
  "battery": 84, 
  "temperature": 19.7, 
  "humidity": 38.7
}

Ejemplo de mensaje publicado en el tópico de MQTT

Como se puede ver, publica la temperatura detectada por el sensor, así como la humedad, la batería restante y el mismo ID que utiliza en el tópico. Con esta información, podemos crear una entidad en Home Assistant por ejemplo, y tener disponible ahí la información del sensor, sin necesidad de un puente específico de la marca ni estar en casa para tener que consultarlo desde el móvil.

Automatización del script

Una vez hemos conseguido extraer la información y publicarla, interesa que se haga de manera regular, ¿no? Antiguamente el script lo hacía en bucle constantemente, pero decidí simplificarlo y dejar que se encargara tan sólo de la extracción y publicación de los datos (KISS por bandera), además de que, tratándose de temperatura y humedad, tampoco necesitamos extraer los datos constantemente. Por ello, una solución fácil es hacer uso de cron y generar una entrada en el mismo (recordad: crontab -e sin necesidad de hacerlo como root) similar a:

*/20 * * * * /usr/bin/python3 ~/scripts/mijia-sensors/main.py >~/scripts/mijia-sensors/last.log 2>&1

Entrada de Cron que ejecuta el script cada 20 minutos

En ese ejemplo anterior, cada 20 minutos se lanzará el script y redirigirá las salidas (tanto stdout como stderr a un fichero para que podamos consultarlo si lo necesitamos). De esta forma, tendremos 3 mediciones por hora de nuestra estancia, que en mi caso ha sido más que suficiente para tener una idea de la temperatura de mi salón, pero lo podéis ajustar a la frecuencia que mejor os encaje a vuestro caso.

Conclusiones

De esta forma, le daremos una nueva vida a esta clase de sensores 😄. No lo he probado con versiones posteriores, si alguno lo hacéis y funciona, dejádmelo en los comentarios que le será útil a más gente seguramente.

Intento mantener el script actualizado (sobre todo por las dependencias), pero no es proyecto que requiera de mucho mantenimiento, así que si con el tiempo veis que no hay commits no significa que no lo esté manteniendo, simplemente que no ha sido necesario realizarle cambios 🙈.

Como el repositorio privado que uso está en un servidor mío, tengo el proyecto replicado en Gitlab por si acaso. Es un espejo del mío, así que podéis usar cualquiera de los 2 sin problema alguno, clonarlo incluso, hacerle propuestas, etc. ¡Estoy abierto a todo tipo de mejoras!

¡Y hasta aquí llegamos por hoy! Pronto os hablaré de los sensores vía Zigbee que estoy montando en casa, y cómo poco a poco estoy domotizando la vivienda, pero vayamos poco a poco que la vida no me da para tanto 🤣.

Si te ha gustado la entrada, o te ha sido útil y quieres ayudarme a pagar los gastos que conlleva el servidor y mantener así el blog libre completamente de anuncios, puedes hacer una donación en Bitcoin en la siguiente dirección:

Donar