Home Assistant: Usando Infrarrojos, Motores y Relés

Monitor Home Assistant Hero

En este artículo, vamos a combinar el ODROID con algo de hardware y Home Assistant, para empezar a convertir dispositivos no inteligentes en dispositivos "inteligentes". Trabajaremos con cables, soldaremos un poco, conectaremos relés y en algunos casos, llegaremos a trabajar con voltaje, ¡así que ten cuidado!

Convirtiendo una unidad de aire acondicionado e un IoT AC

Si tienes una vieja unidad de aire acondicionado (AC), o si estás pensando en comprar un nuevo modelo, es posible que quieras controlarlo desde cualquier lugar. Por ejemplo, puedes encender el AC desde tu teléfono cuando estés saliendo del trabajo o cuando regreses de unas largas vacaciones. Puedes comprar una unidad AC Wi-Fi, pero éstas son aproximadamente 200$ más caras que una unidad normal sin WiFi. En su lugar vamos a convertir una unidad AC sin WiFi, LG P12RL.NSB, en una unidad inteligente. Esto lo llevaremos a cabo controlando la unidad AC a través de un ODROID-XU4, un blaster infrarrojos (IR) y Home Assistant. El blaster IR se puede usar para controlar cualquier dispositivo que disponga de un mando a distancia, no solo una unidad de Aire Acondicionado.

Figure 1 - Original AC remote (model AKB73456113) Figura 1 – Mando a distancia original del AC (model AKB73456113)

Lo primero que debe tener en cuenta es cómo se comunica el mando a distancia con la unidad AC. Hay dos métodos: el primero es cuando se presiona un botón en el mando a distancia, el estado completo se envía a través del IR (temperatura, velocidad del ventilador, potencia, etc.). La otra opción es que cuando se presiona un botón, únicamente se envía la acción en cuestión (aumentar la temperatura, encender el ventilador, etc.). Puede verificar esto, por ejemplo, enviando la correspondiente orden para encender el ventilador a toda velocidad, luego apaga el ventilador, pero con el mando a distancia fuera del alcance del dispositivo, después envía una orden para cambiar a una temperatura diferente. Si el ventilador continúa funcionando a toda velocidad, entonces es que el mando a distancia no está enviando el estado completo. En el caso de que envíe el estado completo, el proyecto http://bit.ly/2AcpKAW puede ayudarte a decodificar la información de estado que se envía. En mi caso, el mando a distancia IR solo envía la información del botón que se esté presionando en ese momento, con la excepción del botón de encendido, que también envía la temperatura y el estado del ventilador.

El hardware

Diseñar y montar un blaster IR para una placa ODROID es un proceso relativamente sencillo y se encuentra documentado en la wiki http://bit.ly/2A6HHmR. Quería que mi implementación funcionase en un ODROID-XU4 o un ODROID-C2, así que necesitaba alimentarlo desde la línea de 5V y accionar un transistor desde el GPIO. El circuito y el montaje final lo puedes ver en la Figura 2.

Figure 2 - Breadboard view of IR blaster Figura 2 - Vista de la placa de pruebas blaster IRFigure 3 - Circuit diagram of IR blaster Figura 3 - Diagrama del circuito del blaster IR

He utilizado un extensor IR de mi TV Samsung para los leds IR. Después de abrirlo, descubrí que tenía 5 LED conectados en paralelo, pero la cuestión es que no tenía las especificaciones de los LED. Hice la estimación de que cada diodo podría pasar una corriente máxima de unos 30 - 50mA (basándome en unas especificaciones técnicas generales http://bit.ly/1trG4ZM), así que 5 podrían pasar entre 150 - 250mA. Es por ello que necesitaría una resistencia de aproximadamente unos 82Ω para limitar la corriente desde el ODROID. Si utilizas menos LEDs IR, necesitarás una resistencia más grande. Lamentablemente, estas resistencias tan bajas son difíciles de encontrar, así que conecté 4 resistencias de 330 Ω, desde el kit de pequeños ajustes C, en paralelo (R1 / R4). El transistor se controla con el pin 24 en el XU4, y es utilizado para modular la señal. Cuando se encienda el GPIO, la corriente fluirá y los LED IR se encenderán, y cuando el GPIO se apage, el transistor detendrá el circuito. La resistencia R5 está ahí para proteger el GPIO.

Una vez que consigas montar esto, puedes probar el hardware alternando manualmente el GPIO 24 a través de sysfs y usar la cámara de teléfono para filmar los leds. La luz IR debe ser visible con la cámara y tiene un tono azulado. Puedes montarlo sin una placa de prueba e incluso puedes colocar el transistor y las resistencias dentro de la carcasa del XU4, pero resulta bastante más complicado. Rompí los puntos de soldadura dos veces mientras intentaba colocarlo dentro de la carcasa. El siguiente fragmento de código permite activar y desactivar manualmente el pin 24 GPIO:

$ sudo su -
# cd /sys/class/gpio/
# echo 24 > export
# cd gpio24
# echo out > direction
# echo 1 > value
# echo 0 > value

Integración LIRC

Ahora tenemos que decirle a LIRC que puede usar el Blaster IR para enviar datos. Para hacer esto, seguí las instrucciones de la wiki: http://bit.ly/2A6HHmR

$ sudo apt-get install lirc
$ sudo vi /etc/lirc/hardware.conf
#Chosen IR Transmitter
TRANSMITTER="ODROID blaster"
TRANSMITTER_MODULES="lirc_odroid lirc_dev"
TRANSMITTER_DRIVER=""
TRANSMITTER_DEVICE="/dev/lirc0"
TRANSMITTER_SOCKET=""
TRANSMITTER_LIRCD_CONF=""
TRANSMITTER_LIRCD_ARGS=""
Antes de reiniciar LIRC, debemos pasar los parámetros correctos al módulo lirc_ODROID. Podemos hacer esto creando el archivo /etc/modprobe.d/lirc.conf con el siguiente contenido:
options lirc_odroid gpio_out_pin=24 softcarrier=1 invert=0
Intenta reiniciar LIRC y monitoriza dmesg para detectar cualquier error:
$ sudo systemctl enable lirc
$ sudo service lirc restart
Si dmesg muestra errores como los que aparecen a continuación, significa que algún otro driver ha reclamado el PIN 24 de GPIO.
[   25.322482] lirc_dev: IR Remote Control driver registered, major 245
[   25.336230] lirc_odroid: module is from the staging directory, the quality is unknown, you have been warned.
[   25.346335] lirc_odroid: cant claim gpio pin 24
[   25.350461] lirc_odroid: init port fail!
[   25.353337] lirc_odroid[lirc_ODROID_exit]
En mi caso, era el módulo 1wire, que se puede desactivar añadiendo las siguientes líneas a /etc/modprobe.d/blacklist-odroid.conf y reiniciando:
# 1 wire
blacklist w1_gpio
blacklist wire

Obtener los códigos del mando a distancia

Una vez que el transmisor este listo, es hora de conseguir los códigos del mando a distancia para su control remoto. Los códigos consisten en una serie de intervalos cuando la señal está activada o desactivada medidos en microsegundos. Puedes conseguir estos códigos de varias fuentes online, o puede grabarlos con LIRC y un receptor IR. Yo usé el receptor IR en un C2 para grabar cada código en un archivo diferente, presioné CTRL + C para salir del modo2 y lo limpié eliminando la primera fila. Cuando terminé, añadí las entradas a lircd.conf:

c2$ sudo apt-get install lirc
c2$ sudo service lirc stop
c2$ sudo mode2 -m -d /dev/lirc0 | tee power-on
c2$ sudo sed -i '1d' power-on
Esto puede ser un poco tedioso, ya que tuve que registrar los códigos de encendido/apagado, desde la temperatura-18 a la temperatura-30, ventilador-bajo, ventilador-medido, ventilador-alto, balanceo-encendido/apagado, jet-encendido/apagado, ionizador encendido/apagado. No obstante, una vez hecho, los agrupé todos en un archivo de configuración, (/etc/lirc/lircd.conf) tal y como se muestra en http://bit.ly/2A9MK3r. Puedes reiniciar LIRC y probar a enviar los códigos con irsend:
$ sudo service lirc restart
$ irsend LIST lgirplus.conf ""
$ irsend SEND_ONCE lgirplus.conf power-on
$ irsend SEND_ONCE lgirplus.conf power-off
En caso de que el último comando irsend falle/agote el tiempo de espera, es posible que te hayas topado con un error de LIRC/driver. La solución es sencilla y rápida, reiniciar LIRC antes de inyectar cada comando.

Integración en Home Assistant

Si el Blaster LIRC está conectado al mismo dispositivo donde tienes instalado Home Assistant, puedes usar el componente Shell Command (http://bit.ly/2vOFnhe) para emitir comandos IR desde Home Assistant. En mi caso, LIRC se ejecuta en un sistema diferente al del Home Assistan, así que desarrollé un script Python que se comunicara con Home Assistant a través de MQTT y emitiera los comandos irsend.

El código completo para este agente MQTT está disponible en http://bit.ly/2Ax8SYz. El código obtiene datos de configuración desde /etc/ir-ac-mqtt-agent.yaml, luego se conecta con MQTT al broker. Para saber cómo configurar el bróker y Home Assistant, consulta el artículo de ODROID Magazine en http://bit.ly/2A6ql9I. También define dos funciones de retrollamada:

  • on_connect - registra una lista de temas MQTT para escuchar los comandos
  • on_message - se llama cada vez que se recibe un mensaje MQTT de los temas registrados.

El script también almacena un diccionario interno con el estado actual, como es el encendido y la temperatura. Esto le permite reaccionar mejor a los comandos entrantes. Por ejemplo, si recibe un comando de apagado, pero la alimentación ya está desconectada, ignorará el comando para evitar que la unidad AC emita un pitido.

La lógica interna intenta simular lo que hace el mando a distancia físico ignorando los comandos a menos que la alimentación esté conectada, y también ajusta la temperatura a 18 ° C y el ventilador al máximo cuando se activa el "Modo Jet". Además, se han realizado algunas simplificaciones, como cuando se envía el comando de encendido, la temperatura se ajusta a 21 ° C y el ventilador al máximo debido a que señal de encendido codifica parte del estado del mando a distancia. El script del agente escucha los comandos emitidos sobre temas tales como ha/lg_ac/ionizer/set y envía un feedback sobre ha/lg_ac/ionizer/get, de modo que la interfaz web incluye comentarios de los comandos recibidos.

Para instalar el agente MQTT, puedes usar estos comandos:

$ sudo wget -O /usr/local/bin/ir-ac-mqtt-agent.py \
https://raw.githubusercontent.com/mad-ady/home-assistant-customizations/master/external-scripts/ir-ac-mqtt-agent.py
$ sudo chmod a+x /usr/local/bin/ir-ac-mqtt-agent.py
$ sudo apt-get install python-pip python-yaml
$ sudo pip install paho-mqtt
$ sudo wget -O /etc/ir-ac-mqtt-agent.yaml \
https://github.com/mad-ady/home-assistant-customizations/blob/master/external-scripts/ir-ac-mqtt-agent.yaml
$ sudo wget -O /etc/systemd/system/ir-ac-mqtt-agent.service \
https://github.com/mad-ady/home-assistant-customizations/blob/master/external-scripts/ir-ac-mqtt-agent.service
Tómate tu tiempo para realizar los cambios necesarios en /etc/ir-ac-mqtt-agent.yaml, luego activa e inicia el servicio:
$ sudo systemctl enable ir-ac-mqtt-agent
$ sudo systemctl start ir-ac-mqtt-agent
En Home Assistant, configuraremos varios switches MQTT (http://bit.ly/2AwtDUd) para manejar la alimentación, el modo Jet, el ionizador, el balanceo, un input_select (http://bit.ly/2zEfgNA), para seleccionar la velocidad del ventilador y un input_number (http://bit.ly/2k0vfOY), para ajustar la temperatura deseada. Los switches comunican directamente su estado al script backend a través de MQTT, mientras que los demás componentes utilizan la automatización para activar los mensajes MQTT sobre los cambios. Aquí tienes la configuración del componente:
switch:
  - platform: mqtt
    command_topic: 'ha/lg_ac/power/set'
    state_topic: 'ha/lg_ac/power/get'
    payload_on: 'ON'
    payload_off: 'OFF'
    name: 'AC Power'
    retain: false
  - platform: mqtt
    command_topic: 'ha/lg_ac/ionizer/set'
    state_topic: 'ha/lg_ac/ionizer/get'
    payload_on: 'ON'
    payload_off: 'OFF'
    name: 'AC Ionizer'
    retain: false
  - platform: mqtt
    command_topic: 'ha/lg_ac/jet/set'
    state_topic: 'ha/lg_ac/jet/get'
    payload_on: 'ON'
    payload_off: 'OFF'
    name: 'AC Jet'
    retain: false
  - platform: mqtt
    command_topic: 'ha/lg_ac/swing/set'
    state_topic: 'ha/lg_ac/swing/get'
    payload_on: 'ON'
    payload_off: 'OFF'
    name: 'AC Swing'
    retain: false

input_select:
  lg_ac_fan_mode:
    name: Fan mode
    options:
      - cycle
      - low
      - med
      - high
    initial: 'low'

input_number:
  lg_ac_temperature:
    name: AC Temperature
    initial: 22
    min: 18
    max: 30
    step: 1
Podemos agrupar todos estos elementos en una vista independiente:
group:
…
 lg_ac:
    name: Air Conditioning
    view: yes
    icon: mdi:snowflake
    entities:
      - group.lg_ac_group
 lg_ac_group:
    name: LG AC
    entities:
      - switch.ac_power
      - input_number.lg_ac_temperature
      - input_select.lg_ac_fan_mode
      - switch.ac_jet
      - switch.ac_ionizer
      - switch.ac_swing
Y tras reiniciar Home Assistant, debería parecerse a la siguiente imagen.

Figure 4 - Basic support for Air ConditioningFigura 4 - Soporte básico para aire acondicionado

- action:
  - alias: LG AC MQTT Set Temperature
    data:
      payload_template: '{{ states.input_number.lg_ac_temperature.state }}'
      qos: 0
      retain: true
      topic: ha/lg_ac/temperature/set
    service: mqtt.publish
  alias: LG AC Set IR temperature
  id: '1499081218012'
  trigger:
  - entity_id: input_number.lg_ac_temperature
    platform: state
- action:
  - alias: LG AC MQTT Set Fan
    data:
      payload_template: '{{ states.input_select.lg_ac_fan_mode.state }}'
      qos: 0
      retain: true
      topic: ha/lg_ac/fan/set
    service: mqtt.publish
  alias: LG AC Set IR Fan
  id: '1499152161'
  trigger:
  - entity_id: input_select.lg_ac_fan_mode
    platform: state
- action:
  - alias: LG AC Set temperature slider
    service: input_number.set_value
    data_template:
      entity_id: input_number.lg_ac_temperature
      value: '{{trigger.payload}}'
  alias: LG AC Read temperature via MQTT
  id: '1499423002'
  trigger:
  - platform: mqtt
    topic: ha/lg_ac/temperature/get
- action:
  - alias: LG AC Set fan combo box
    service: input_select.select_option
    data_template:
      entity_id: input_select.lg_ac_fan_mode
      option: '{{trigger.payload}}'
  alias: LG AC Read temperature via MQTT
  id: '1499423003'
  trigger:
  - platform: mqtt
    topic: ha/lg_ac/fan/get
Las primeras dos automatizaciones envian los valores de los componentes de temperatura y ventilador a través de MQTT en el cambio de estado, mientras que las dos últimas automatizaciones reciben datos de temperatura y del ventilador a través de MQTT para actualizar la interfaz web. Reiniciando nuevamente debería permitirte contar con un sistema AC totalmente funcional controlado por Home Assistant. Aquí tienes un video de un prototipo en acción: https://youtu.be/zGRlhILVRCQ.

Añadir un temporizador de inicio y parada

El mando a distancia del AC tiene una opción para iniciar y detener el AC con un temporizador. También podemos configurar esto dentro de Home Assistant con unas cuantas automatizaciones y algunos componentes adicionales. Lo ideal sería usar el componente input_datetime (http://bit.ly/2A8Mmoc),para permitirle al usuario seleccionar la hora de inicio y parada, pero cuando escribí este artículo, el componente no funcionaba muy bien. En HA 0.56, usaremos input_text en su lugar (http://bit.ly/2i8lcXI), con una expresión regular que permite escribir una hora. También hay dos input_booleans (http://bit.ly/2Bnd4Yj), que parecen ser switches y que permiten al usuario activar/desactivar la funcionalidad. Aquí tienes la configuración que va dentro de configuration.yaml:

input_text:
  lg_ac_on_timer:
    name: LG AC on timer
    initial: '16:00'
    pattern: '^[0-9]{1,2}:[0-9]{1,2}$'
  lg_ac_off_timer:
    name: LG AC off timer
    initial: '18:00'
    pattern: '^[0-9]{1,2}:[0-9]{1,2}$'

input_boolean:
  ac_on_timer_active:
    name: Activate AC On timer
    initial: off
    icon: mdi:calendar
  ac_off_timer_active:
    name: Activate AC Off timer
    initial: off
    icon: mdi:calendar

group:
…
  lg_ac:
…
    entities:
…
      - group.lg_ac_timer
  lg_ac_timer:
    name: AC Timer
    entities:
      - input_boolean.ac_on_timer_active
      - input_text.lg_ac_on_timer
      - input_boolean.ac_off_timer_active
      - input_text.lg_ac_off_timer
El resultado final después de reiniciar Home Assistant debería parecerse a la siguiente imagen:

Figure 5 - AC controls with timers Figura 5 - Controles del AC con temporizadores

Para que funcione, deberás añadir las siguientes dos automatizaciones en automations.yaml. La primera automatización enciende el AC, el modo Jet y también apaga el temporizador que activa el AC, de modo que se trata de un evento de un solo disparo. Comprueba cada minuto si ac_on_timer_active está activado y si la hora actual es la misma que la cadena dentro de lg_ac_on_timer. La segunda automatización hace algo similar para el temporizador de apagado, pero con diferentes acciones.

- action:
  - service: switch.turn_on
    entity_id:
    - switch.ac_power
  - service: switch.turn_on
    entity_id:
    - switch.ac_jet
  - service: input_boolean.turn_off
    entity_id:
    - input_boolean.ac_on_timer_active
  alias: Turn On AC on timer
  id: '1502194970'
  trigger:
  - platform: time
    minutes: /1
    seconds: 0
  condition:
  - condition: state
    entity_id: input_boolean.ac_on_timer_active
    state: 'on'
  - condition: template
    value_template: '{{ now().strftime("%H:%M") == states.input_text.lg_ac_on_timer.state
      }}'
- action:
  - service: switch.turn_off
    entity_id:
    - switch.ac_power
  - service: input_boolean.turn_off
    entity_id:
    - input_boolean.ac_off_timer_active
  alias: Turn Off AC on timer
  id: '1502194971'
  trigger:
  - platform: time
    minutes: /1
    seconds: 0
  condition:
  - condition: state
    entity_id: input_boolean.ac_off_timer_active
    state: 'on'
  - condition: template
    value_template: '{{ now().strftime("%H:%M") == states.input_text.lg_ac_off_timer.state
      }}'
Tras reiniciar Home Assistant una vez más, deberías tener un completo sistema AC "inteligente" el cual puedes disfrutar durante las olas de calor. Aunque las automatizaciones anteriores son bastante básicas, puede añadir más lógica, como añadir un termostato (http://bit.ly/2Ay6kJN), y monitorizar el clima exterior con un sensor o haciendo uso del pronóstico del tiempo, para que puedas encender tu Aire Acondicionado cuando el clima exterior esté por encima de un umbral. De hecho, probaremos un termostato de este tipo en nuestro próximo proyecto.

Controlar un calentador de gas con un termóstato Home Assistant

Como para muchos lectores es invierno, puede que les interese tener un calentador inteligente. Vamos a controlar una caldera de gas natural conectada a una calefacción central, un Viessman Vitopend 100 (http://bit.ly/2Bd9X4d). El calentador, si está encendido, intentará mantener el agua a una temperatura constante, la cual fluye a través de los elementos de calefacción de la casa, pero esto puede ser un gasto innecesario si no hay nadie en casa o si la casa está muy bien aislada. En su lugar, puedes usar un termóstato para encender o apagar el calentador en función de la temperatura ambiente. Mi calentador de gas tenía un termostato, Salus 091FLRF (http://bit.ly/2AbcnkC). Mi termóstato funciona, pero tiene algunos fallos. Para empezar, se reiniciaría en mitad de la noche y pierde la configuración, dejándome helado. Un termóstato que se active por Internet tiene un coste de al menos 100$, de modo que vale la pena echar mano al bricolaje.

La ventaja de tener un termóstato externo es que tiene un relé conectado al calentador y no tienes que abrirlo. Si tiene que abrir tu calentador, asegúrate de llamar a un técnico especializado o puede que tengas problemas con tu proveedor de gas natural.

Tras analizar los esquemas del termóstato, era evidente que la comunicación con el calentador se hacía cerrando o abriendo un relé con una línea de 220V. Si añadimos un segundo relé en paralelo con el primero, puedo cerrar cualquiera de ellos para encender o apagar el calentador. ¿Por qué necesitas un relé? ¡Para que no frías tu placa ODROID! El planteamiento es usar un relé Sainsmart de 2 canales (http://bit.ly/2A5WEFF), para conectar el ODROID a la línea de 220V que va al calentador. Incluso si el relé tiene una potencia nominal de 5V, se puede usar de forma segura con un ODROID-C1 o con los GPIO de 3.3V del C2.

Figure 6 - SainSmart 2 Channel Relay Figura 6 – Relé de 2 canales SainSmart

Como vas a trabajar con voltajes, asegúrate de tener un línea electríca certificada o que cumpla con la legislación de tu país. Además, desconecta siempre todos los aparatos de la red cuando vayas a trabajar con estas líneas. El esquema que vamos a implementar es bastante simple, tal y como se muestra en la Figura 7.

Figure 7 - Implementation details Figura 7 - Detalles de implementación

Solo hay una complicación con esta configuración. En lugar de utilizar los conectores GPIO de 40 pines en el C2 (cabezal J2), usé algunos pines del cabezal I2S (J7). La razón, en mi caso, es que el encabezado J2 fue utilizado por la pantalla de 3.5" de HardKernel (http://www.hardkernel.com/main/products/prdt_info.php?g_code=G147435282441).

Para convertir los pines I2S en pines GPIO, necesitaras editar el DTB cargado con el kernel. Sigue las siguientes instrucciones para editar el DTB, y también haz los cambios permanentes cuando actualices el kernel a través de apt, tal y como se describe en http://bit.ly/2AyrWWz.

$ sudo apt-get install device-tree-compiler
$ sudo fdtput /media/boot/meson64_ODROIDc2.dtb /I2S status disabled
$ sudo fdtput /media/boot/meson64_ODROIDc2.dtb /i2s_platform status disabled
$ sudo vi /etc/kernel/postinst.d/i2s-disable
#!/bin/bash

echo "Disabling I2S support from the device tree"
/usr/bin/fdtput /media/boot/meson64_ODROIDc2.dtb /I2S status disabled
/usr/bin/fdtput /media/boot/meson64_ODROIDc2.dtb /i2s_platform status disabled
Una vez que reinicies, el cabezal J7 solo tendrá pines GPIO que podrás usar..

Controlar el relé a través de MQTT

Dado que no es el ODROID el que ejecuta Home Assistant, necesitaremos poder controlarlo a través de la red, con MQTT. El código del agente escucha mensajes ON/OFF sobre un tema específico y enciende o apaga el GPIO. Normalmente utilizaríamos wiringPI, (http://bit.ly/2zBMm0F), pero en este caso el conector J7 no está mapeado para WiringPI, así que usaremos sysfs. Los métodos pinMode y digitalWrite emulan sus equivalentes wiringPI para que el código sea más fácil de entender. El código está disponible en http://bit.ly/2jofKfN. Para instalarlo en tu sistema, sigue estos pasos:

$ sudo wget -O /usr/local/bin/heater-mqtt-agent.py \
https://raw.githubusercontent.com/mad-ady/home-assistant-customizations/master/external-scripts/heater-mqtt-agent.py
$ sudo chown a+x /usr/local/bin/heater-mqtt-agent.py
$ sudo wget -O /etc/heater-mqtt-agent.yaml \
https://github.com/mad-ady/home-assistant-customizations/blob/master/external-scripts/heater-mqtt-agent.yaml
$ sudo wget -O /etc/systemd/system/heater-mqtt-agent.service \
https://github.com/mad-ady/home-assistant-customizations/blob/master/external-scripts/heater-mqtt-agent.service
$ sudo apt-get install python-pip python-yaml
$ sudo pip install paho-mqtt
Edita el archivo de configuración /etc/heater-mqtt-agent.yaml, configura los detalles de MQTT y luego inicia el agente con:
$ sudo systemctl enable heater-mqtt-agent
$ sudo systemctl start heater-mqtt-agent
Puedes monitorizar los mensajes del agente con el siguiente comando:
$ sudo journalctl -f -u heater-mqtt-agent

Integración de Home Assistant

Para utilizar este agente dentro de Home Assistant, puedes configurar un Switch MQTT y añadirlo dentro de tu propio grupo:

switch:
…
 - platform: mqtt
    command_topic: 'ha/heater/set'
    state_topic: 'ha/heater/get'
    payload_on: 'ON'
    payload_off: 'OFF'
    name: 'Heater'
    retain: true

group:
...
  heater:
    name: Gas heater
    view: yes
    icon: mdi:fire
    entities:
      - switch.heater
Figure 8 - A switch for your heater Figura 8 - Un switch para tu calentador

Tener un switch con el que puedes activar y desactivar resulta muy útil, pero es posible que prefieras un tener un termostato. Un termostato trata de mantener una temperatura entre ciertos niveles, y Home Assistant requiere un sensor de temperatura y un switch (http://bit.ly/2Ay6kJN). El sensor de temperatura puede ser cualquier sensor, incluida la temperatura exterior, pero en nuestro caso queremos usar datos de sensores de varias habitaciones. Tengo dos sensores de temperatura DS18b20 en dos habitaciones ya integrados en Home Assistant, tal y como describí en mi anterior artículo de ODROID en http://bit.ly/2A6ql9I. No obstante, el termostato puede funcionar con un sólo sensor de temperatura. Necesitaremos combinar los dos sensores en un único sensor, que devuelva la temperatura mínima entre los dos. Esto se puede extender fácilmente a múltiples sensores, de modo que el termostato eleva la temperatura de la habitación más fría hasta la temperatura deseada. Podemos hacer esto con un sensor plantilla (http://bit.ly/2wPQLeY) dentro de configuration.yaml:

sensor:
…
  - platform: template
    sensors:
…
     house_temperature:
        friendly_name: Minimum house temperature
        unit_of_measurement: '_C'
        value_template: '{{ (states.sensor.temperature_rest_python.state, states.sensor.temperature_via_mqtt.state) | min }}'

group:
…
  weather:
…
    entities:
…
      - sensor.house_temperature
Añadir el termóstato ahora es una tarea muy sencilla (configuration.yaml):
climate:
  - platform: generic_thermostat
    name: Heater thermostat
    heater: switch.heater
    target_sensor: sensor.house_temperature
    min_temp: 15
    max_temp: 30
    target_temp: 24
    min_cycle_duration:
      minutes: 5
    tolerance: 0.3

group:
…
  heater:
…
    entities:
…
      - climate.heater_thermostat
Figure 9 - ThermostatFigura 9 - Termostato

La configuración del termostato elevará la temperatura cuando ésta esté por debajo de target_temp - tolerancia, mantendrá el calentador encendido al menos min_cycle_duration, luego lo apagará cuando la temperatura esté por encima de target_temp + tolerancia. Puede usar un termostato similar con el AC al que hemos montado anteriormente, pero debes configurarlo con ac_mode: true para que éste sea un dispositivo de enfriamiento.

Puede controlar/configurar manualmente el termostato, pero lo más divertido es que puede usar automatizaciones para controlar el termostato. Un posible uso es fijar diferentes temperaturas objetivo basadas en posibles detenciones de presencia o la hora del día. Las siguientes automatizaciones ajustan la temperatura en 23ºC durante el día y 25.5ºC durante la noche (automations.yaml):

- action:
  - alias: climate.set_temperature
    data:
      entity_id: climate.heater_thermostat
      temperature: 23
    service: climate.set_temperature
  alias: Thermostat set low
  condition: []
  id: '1506943539788'
  trigger:
  - at: 07:00
    platform: time
- action:
  - alias: climate.set_temperature
    data:
      entity_id: climate.heater_thermostat
      temperature: 25.5
    service: climate.set_temperature
  alias: Thermostat set high
  condition: []
  id: '1506943638481'
  trigger:
  - at: '19:00'
    platform: time

Controlar la persiana de la ventana con Home Assistant

Un elemento físico más que podemos integrar en Home Assistant es la persiana monotizada de una ventana. En mi caso, los motores son controlados por un interruptor físico de tres vías. Cuando está en la posición hacia arriba, la persiana sube. En la posición central, los motores están apagados, y en la posición hacia abajo, la persiana baja. Quería usar un relé y tomar el control del desplazamiento de la persiana cuando el interruptor físico estubiese en la posición central, pero que también me permitiera contralar manualmente la persiana con el interruptor normal. Tras una larga discusión en el foro (http://bit.ly/2AwFCBb), me decanté por la implementación física que se muestra en la Figura 10.

Figure 10 - Controlling a window blind motor Figura 10 – Controlando un motor de persianas

Además del ODROID-C1+ y la placa de relés de 2 módulos, también necesitamos usar un par de amortiguadores. Los amortiguadores son circuitos RC que absorven la energía reactiva que se acumula en los motores durante la conmutación, de lo contrario los picos de potencia quemaran los contactos de los relés cuando intenten liberar la enegía, dañé un relé antes de darme cuenta de esto. Utilicé los amortiguadores descritos en t http://bit.ly/2A58tf4 en mi montaje.

Ten en cuenta que, aunque mi diseño minimiza la cantidad de componentes utilizados, es más arriesgado porque funciona a 220V. El usuario del foro @Jojo propuso un diseño alternativo que cambia el voltaje del interruptor físico a 5V y utiliza circuitos digitales para controlar el relé, el cual debería ser más seguro (http://bit.ly/2Bf2txo).

Agente MQTT para el funcionamiento de la persiana

Como es de costrumbre, necesitamos un script que se ejecute en el ODROID y que escuche los comandos de las persianas, enviados a través de MQTT, luego ejecuta los comandos que activan el relé e informe del estado. La diferencia con el anterior código es que esta vez tendremos que usar hilos de ejecución, más específicamente temporizadores. El modo más simple con el que el código puede funcionar es:

Se envía un mensaje para ABRIR o CERRAR la persiana desde Home Assistant El script activa el primer relé y asume el control de los motores, luego utiliza el segundo relé para controlar la dirección en la que funciona la persiana (hacia arriba o hacia abajo) El script espera un número determinado de segundos para que la persiana pueda abrirse o cerrarse al completo, lo cual demora 17 segundos en mi caso. Cuando el tiempo expira, el relé vuelve al modo manual y se envía una actualización del estado a través de MQTT a Home Assistant

La complicación aparece cuando quieres detener las persinas a mitad de camino o en un punto arbitrario. Para hacer esto, Home Assistant puede enviar un comando STOP, o una posición deseada, pero si el script tiene un único hilo de ejecuición, éste esperará a que el motor termine antes de procesar el comando STOP. Al usar los temporizadores, después de que el motor arranque, un temporizador está programado para detener el motor en 17 segundos, y el código vuelve a escuchar mensajes MQTT. Si llega un mensaje STOP antes de que expire el temporizador, cancelará el temporizador y ejecutará inmediatamente el comando stopBlinds (). Además, la secuencia de comandos mantiene un estado interno de la posición de la persiana y la dirección del motor, así que si la persiana está a medio camino y deseas levantarla al 70%, podrás calcular el tiempo que necesita para ejecutar el motor y en qué dirección. El código está disponible en http://bit.ly/2A88Ohk y se puede instalar con:

$ sudo wget -O /usr/local/bin/blind-cover-mqtt-agent.py \
https://raw.githubusercontent.com/mad-ady/home-assistant-customizations/master/external-scripts/blind-cover-mqtt-agent.py
$ sudo chown a+x /usr/local/bin/blind-cover-mqtt-agent.py
$ sudo wget -O /etc/systemd/system/blind-cover-mqtt-agent.service \
https://raw.githubusercontent.com/mad-ady/home-assistant-customizations/master/external-scripts/blind-cover-mqtt-agent.service
$ sudo wget -O /etc/blind-cover-mqtt-agent.yaml \
https://raw.githubusercontent.com/mad-ady/home-assistant-customizations/master/external-scripts/blind-cover-mqtt-agent.yaml
$ sudo apt-get install python-pip python-yaml
$ sudo pip install paho-mqtt
Además de esto, necesitaras instalar la librería wiringPi y sus enlaces Python (http://bit.ly/2AwVQui). Tendrás que editar /etc/blind-cover-mqtt-agent.yaml e introducir tus datos MQTT, luego puedes activar e iniciar el agente:
$ sudo systemctl enable blind-cover-mqtt-agent
$ sudo systemctl start blind-cover-mqtt-agent
Podrás ver los mensajes de depuración con el siguiente comando:
$ sudo journalctl -f -u blind-cover-mqtt-agent

Configuración de Home Assistant

Home Assistant viene con un componente de Portada MQTT (http://bit.ly/2jmAIf7), que proporciona una interfaz básica para la portada. Puedes configurarlo con esta configuración dentro de configuration.yaml:

cover:
  - platform: mqtt
    name: "Blinds"
    state_topic: "ha/blind_cover/get"
    command_topic: "ha/blind_cover/set"
    set_position_topic: "ha/blind_cover/position"
    assumed_state: true
    payload_open: 'OPEN'
    payload_close: 'CLOSE'
    payload_stop: 'STOP'
    state_open: 'open'
    state_close: 'closed'
group:
…
 blinds:
    name: Blinds
    view: yes
    icon: mdi:blinds
    entities:
      - cover.blinds
Después de reiniciar Home Assistant, el control de la persiana tendrá el aspecto de la Figura 11:

Figure 11 - Standard blind controls Figura 11 - Controles de la persiana

En https://youtu.be/MIhuELv1244, puedes ver una demo de las persianas. Como he mencionado antes, ¿existe alguna forma de detener en una posición arbitraria las persinas? Hay un modo modificar el componente de la persiana para que muestre un control deslizante que te permite controlar su posición. Para hacer esto, necesitas instalar la IU personalizada de Home Assistant, descargala de http://bit.ly/2AcqDJE e introduce los siguientes comandos:

$ sudo su - homeassistant
$ cd .homeassistant/
$ curl -o update-custom-ui.sh \
"https://raw.githubusercontent.com/andrey-git/home-assistant-custom-ui/master/update.sh?raw=true"
$ chmod a+x update-custom-ui.sh
$ ./update-custom-ui.sh
Es necesario modificar la configuración para cargar el control de la persiana personalizado. En primer lugar, deberás activar los controles personalizados de la interfaz de usuario haciendo estos cambios en configuration.yaml:
customizer:
  custom_ui: local

Use the customize section to specify that all covers should use the new UI (inside configuration.yaml):

homeassistant:
  customize_glob:
    cover.*:
      custom_ui_state_card: state-card-custom-ui
Por defecto, la página tendrá el mismo aspecto que la anterior, de modo que debemos activar manualmente el control deslizante (en la sección de personalización en configuration.yaml)::
homeassistant:
  customize:
    cover.blinds:
      state_card_mode: break-slider
      stretch_slider: true
Tras reiniciar Home Assistant, la interfaz de usuario tendrá un aspecto similar a la Figura 12.

Figure 12 - Cover with slider Figura 12 – Página con control deslizante

Como puede ver, con un poco de trabajo puede convertir tu corriente casa en una casa inteligente con la ayuda de ODROID y Home Assistant. Para comentarios y discusiones, visite el hilo original en http://bit.ly/2s13GbB.

Be the first to comment

Leave a Reply