Home Assistant: Personalización y Automatizaciones

Advanced Home Assistant Experimentation

En la edición de julio de 2017 de ODROID Magazine, te presenté Home Assistant (http://bit.ly/2hlOPOE), una plataforma de domótica de código abierto. Basándonos en los ejemplos que aparecen en ese artículo, trataremos en profundidad temas avanzados relacionados con Home Assistant (HA). Esto te permitirá maximizar el uso de HA, y también te ayudará con los experimentos.

Trabajando con las herramientas de desarrollo de HA

Cuando se accede, la interfaz web de HA es similar a la que se muestra en la Figura 1a. En el anterior artículo, hice alusión a las herramientas de desarrollo dentro de HA. Puede acceder a éstas herramientas mediante el panel izquierdo de la interfaz web y moviéndose entre los botones.

ODROID Magazine - Webui
Figura 1a - Interfaz Web

ODROID Magazine - Working with Developer Tools and Templates
Figura 1b - Trabajando con las herramientas de desarrollo y plantillas

Las siguientes herramientas son las que están disponibles para los desarrolladores:

Services

Te permite realizar llamadas a los diversos servicios que presentan tus componentes. Puede hacer cosas como activar una automatización, ocultar o mostrar grupos, volver a cargar la configuración de HA, controlar una acción del reproductor multimedia (reproducir/pausar/cargar la lista de reproducción), etc. Los servicios disponibles pueden variar en función de los componentes que tengan activos en tu configuración. Es un buen lugar para probar alguna acción antes de añadirla a una automatización.

States

Esto te permite anular el estado de cualquier entidad. También permite enumerar todas las entidades, con su estado y atributos actuales. Puede utilizar esta lista para encontrar una entidad concreta, ya sea para saber cómo hacer referencia a ella en la configuración (por ejemplo, las entidades visibles en una vista) o para usarla en una plantilla.

Events

Te permite generar un evento en el bus de eventos. Existen varios eventos disponibles, aunque en la práctica puede que no necesites generar algunos de estos eventos.

Templates

El sistema de plantillas de HA utiliza la sintaxis de plantillas Jinja2 (http://bit.ly/2vd497l) añadiendo algunas variables internas. La sintaxis de plantilla es más como un lenguaje de programación, así que tomate el tiempo que necesites para leer la documentación (http://bit.ly/2vOK7no). El objetivo de las plantillas es procesar los datos de entrada o salida y darles un formato especifico. La vista de Plantillas te proporciona un espacio de trabajo donde puede experimentar y probar la sintaxis antes de pasarla al archivo de configuración. Cuando cargues la página por primera vez, aparecerá un ejemplo de sintaxis que, entre otras cosas, pasará por todos tus sensores mostrando sus valores actuales. Por ejemplo, esto puede enseñarte que puedes acceder a un estado de sensor llamando a {{states.sensor.sensor_name.state}}.

Info

te muestra la versión actual, así como los errores que se han ido registrando.

Para entender mejor la relación entre un nombre de entidad y cómo usarlo en una plantilla, vamos a intentar hacer un experimento. Supongamos que necesitamos obtener el icono del pronostico del tiempo de Dark Sky (https://darksky.net). En primer lugar, necesitamos utilizar la herramienta States para obtener el nombre correcto de la entidad. Si buscamos el nombre que aparece en la interfaz web "Dark Sky Hourly Summary", encontrarás una entidad denominada "sensor.dark_sky_hourly_summary". La mayoría de las entidades HA tienen un estado y pueden tener uno o más atributos y éstos ya deberían ser visibles en la vista de Estados. Ahora podemos pasarnos a la herramienta Templates y agregar nuestra propia plantilla al final del cuadro de diálogo.

Vamos a probar las siguientes plantillas y vamos a ver cuál es el resultado:

The states object is "{{ states }}"

The states.sensor object is "{{ states.sensor }}"

The states.sensor.dark_sky_hourly_summary object is "{{ states.sensor.dark_sky_hourly_summary }}"

The states.sensor.dark_sky_hourly_summary.state value is "{{ states.sensor.dark_sky_hourly_summary.state }}"

The states.sensor.dark_sky_hourly_summary.attributes.entity_picture  value is "{{ states.sensor.dark_sky_hourly_summary.attributes.entity_picture }}"
El resultado que obtenemos puede verse en la Figura 2. Algunos de los puntos de datos de objetos Python y otros objetos (como el estado y los atributos) devuelven valores en cadena que puedes utilizar. Con esta información, ya estás preparado para empezar a escribir plantillas y automatizaciones.

ODROID Magazine - Templates in action
Figura 2 - Plantilla in actión

Interfaz de notificación y API HA

Si tienes scripts que se ejecutan en segundo plano (digamos, por ejemplo, cron) es posible que quieras que se te avise cuando las cosas salen mal y el script falla por cualquier razón. La mayoría de los tutoriales que hay online te enseñaran cómo enviar un SMS o correo electrónico de notificación, pero para problemas que no sean demasiado críticos, tal vez no quieras consultar el correo electrónico o que se te despierte a las 3 de la madrugada. Para ello, puedes enviar mensajes a Home Assistant utilizando curl y su API, para que puedas recibir notificaciones de los scripts cada vez que accedas a Home Assistant. De esta forma, tienes conocimiento de lo que ocurre si accedes con regularidad a la interfaz web. Podemos utilizar una técnica similar para cambiar los estados de las entidades de Home Assistant usando disparadores externos, o puedes usar la API para hacer consultas a las entidades desde scripts externos.

Para configurar esto, tan sólo necesitas ejecutar un comando shell desde tu script cuando quieras gestionar un error:

$ /usr/bin/curl -X POST -H "x-ha-access: api_password" -H "Content-Type: application/json" --data "{\"message\": \"Something bad happened in your script\", \"title\": "My background script\"}" http://odroid-ip:8123/api/services/persistent_notification/create
El comando anterior utiliza la acción de notificación continua (http://bit.ly/2wkVRiW) llamada a través de la API de Home Assistant. Para utilizarla, deberás proporcionar el valor "api_password" y enviar un objeto json (http://www.json.org/) que contenga el mensaje y el título. Ten en cuenta que los comandos JSON utilizan comillas (") y no apóstrofe (') para citar. Lo bueno es que la notificación aparecerá en todas las vistas/pestañas, de modo que no se pierde. El resultado lo puedes ver en la Figura 3.

ODROID Magazine - Persistent notification
Figura 3 - Notificación continua

Ejecutando scripts externos sobre el cambio de estado

Supongamos, por ejemplo, que deseamos obtener el pronóstico del tiempo desde Dark Sky en rumano para que lo puedan entender quienes no hablen inglés. Puesto que Dark Sky todavía no soporta rumano, necesitamos hacerlo nosotros, lo cual no es un problema, ya que podemos hacerlo con Home Assistant usando la técnica que describimos a continuación.

1. Instalar un programa de traducción en el sistema ODROID que permita utilizar diversos servicios de traducción online y trabaje con el idioma deseado. Yo utilicé trans (http://bit.ly/2vcLJDU):

$ sudo wget -O /usr/local/bin/trans git.io/trans
$ sudo chmod a+x /usr/local/bin/trans
Prueba el programa para asegurarte de que funciona adecuadamente:
$ trans -b :ro "My name is my password"
2. Configurar un nuevo componente de comandos shell en Home Assistant (http://bit.ly/2vOFnhe) para llamar el script de línea de comandos. El componente shell puede ejecutar un comando y coger el resultado de una plantilla como parámetro para el comando. Cuando se utiliza una plantilla como parámetro, la ejecución del comando es más estricta y no tienes permitido realizar conexiones o redireccionar al archivo. Si necesitas usar líneas de comandos más complejas con redirecciones y plantillas, puede agregarlas a un script shell y, en su lugar, llamar al script. Afortunadamente, el comando trans permite escribir el resultado directamente en un archivo. Realiza los siguientes cambios en configuration.yaml:
shell_command:
  translate_weather: '/usr/local/bin/trans -b :ro "{{ states.sensor.dark_sky_hourly_summary.state }}" -o /tmp/ha-weather-forecast.txt'
El comando coge el estado del sensor Dark Sky Hourly Summary y lo pasa a trans para su traducción. Practica obteniendo el estado correcto haciendo uso de la herramienta Template, como lo hemos hecho antes. El texto traducido se envía a /tmp/ha-weather-forecast.txt. Para ejecutar este comando manualmente, inicia sesión en la interfaz web de Home Assistant, ve a las Herramientas para desarrolladores en el panel izquierdo y haz clic en el icono Services. Puedes llamar al dominio "shell_command" con el servicio translate_weather sin ningún otro parámetro. Si revisas el archivo temporal, deberías ver el pronóstico del tiempo traducido.

3. Importar de nuevo la traducción a Home Assistant configurando un sensor de archivo (http://bit.ly/2x2nmuw). Un sensor de archivo monitoriza los cambios de un archivo e importa la última línea a Home Assistant. Realiza los siguientes cambios en tu configuration.yaml:

sensor:
…
 - platform: file
    file_path: /tmp/ha-weather-forecast.txt
    name: Dark Sky Forecast Ro
También deberías importar esta nueva entidad en las vistas donde quieras utilizarla:
group:
…
  weather:
    entities:
…
      - sensor.dark_sky_forecast_ro
Si reinicias Home Assistant, debería ver el nuevo elemento en el grupo Weather. Sin embargo, todavía existe un problema: esta entidad nunca se actualizará. Aún tenemos que añadir un disparador para que cuando el pronóstico en Inglés cambie, el pronóstico traducido también cambie. Para ello, necesitamos utilizar la automatización.

ODROID Magazine - The translated forecast next to the original one
Figura 4 - El pronóstico traducido junto al original

4. Crear una automatización recurriendo al enlace Automations del panel lateral. Ten en cuenta que actualmente necesitarás utilizar el navegador Chrome para completar este paso, ya que el resto de navegadores no son compatibles. Utiliza el botón "+" para agregar una automatización, y asígnale un nombre sugerente como "Weather forecast translation". El disparador debe ser "state" y el id de la entidad debe coincidir con la entidad "fuente" deseada, que es, en nuestro caso "sensor.dark_sky_hourly_summary". Ten en cuenta que estamos utilizando el nombre del sensor tal y como se puede localizar en la herramienta States. Puedes dejar los campos "From" y "To" en blanco, ya que queremos que se active con cualquier cambio de valor.

A continuación, necesitamos especificar una acción o una secuencia de acciones a realizar cuando se active. Necesitamos "Call Service" como un tipo de acción. El Alias es sólo un nombre descriptivo para nuestra acción y podemos llamarlo "Run translate_weather shell_command". El campo Service se compone de la llamada del servicio completa, es decir, el nombre del servicio y del dominio son los mismos que los utilizados en la herramienta Services, por lo que en nuestro caso será "shell_command.translate_weather". El campo Service Data se puede dejar en blanco en nuestro caso, ya que el componente no necesita parámetros adicionales. Ahora puede hacer clic en el icono Save y guardar la automatización.

ODROID Magazine - Create a new automation
Figura 5 - Crear una nueva automatización

Ahora, cuando el pronóstico del tiempo cambie, se activará la automatización haciendo que el pronóstico se traduzca y guarde en una entidad diferente, a excepción de que posiblemente exista aún un pequeño desajuste. Al reiniciar Home Assistant, es posible que el estado del tiempo no cambie en mucho tiempo y su traducción devuelva "unknown" hasta la primera transición. Para corregir esto, ejecutaremos una segunda automatización en el inicio de Home Assistant para actualizar la traducción. Esta vez el disparador será la plataforma homeassistant con el inicio del evento. La acción será la misma que la automatización anterior. Desafortunadamente, la interfaz de usuario web todavía no admite esta plataforma, así que tendremos que editar el archivo manualmente.

Todas las automatizaciones se guardan en ~/homeassistant/.homeassistant/automations.yaml. En este caso, necesitarás añadir lo siguiente:

- action:
  - alias: Run translate_weather shell_command
    service: shell_command.translate_weather
  alias: Update weather translation on startup
  id: '1502097058891'
  trigger:
    platform: homeassistant
    event: start
Si observas la automatización que has añadido a través de la interfaz de usuario, verá una sintaxis muy similar. Lo único nuevo es el id. Éste es simplemente la fecha de registro actual de UNIX, y debe ser único para tu sistema (puede obtener uno nuevo con fecha +% s). Una vez configurado y tras reiniciar Home Assistant, obtendrás el estado traducido al momento. A partir de Home Assistant versión 0.51, hay una forma más simple, pero menos eficiente, de hacer lo mismo. Podrías tener un sensor de línea de comandos (http://bit.ly/2uUIQw3) con un parámetro de plantilla, como este:
sensor:
…
  - platform: command_line
    command:  /usr/local/bin/trans -b :ro "{{ states.sensor.dark_sky_hourly_summary.state }}"
    friendly_name: Dark Sky Forecast Romanian
La razón por la que esta solución es menos eficiente que la primera es que el sensor se consulta constantemente y se traduce cada vez. De modo que, en este caso particular, puedes encontrarte con problemas de limitación de cuota con los proveedores de traducción.

Activar/Desactivar un servicio del sistema desde Home Assistant

Vamos a analizar un nuevo posible caso de uso. Vamos suponer que tienes un servicio del sistema ejecutándose en tu ODROID el cual deseas activar/desactivar desde Home Assistant. En mi caso, este servicio sería Mycroft (https://mycroft.ai), porque utiliza algunos recursos cuando está inactivo y puede confundirse con los sonidos ambientales cuando veo una película. Tienes más información sobre Mycroft en http://bit.ly/2tt3crC. La cuestión es que puedes utilizar comandos como service mycroft start para controlar el servicio. No estas limitado sólo a los servicios; sino que puedes encender o apagar cualquier cosa.

Para controlarlo desde Home Assistant podemos usar el componente switch de línea de comandos (http://bit.ly/2wdVGW5). Añade lo siguiente a tu configuration.yaml:

switch:
  - platform: command_line
    switches:
      mycroft:
        command_on: sudo /usr/sbin/service mycroft start
        command_off: sudo /usr/sbin/service mycroft stop
        command_state: /usr/sbin/service mycroft status >/dev/null 2>&1
        friendly_name: "Mycroft status"
Y también puedes añadirlo a una vista independiente:
group:
…
 switches:
    name: Switches
    view: yes
    entities:
    - switch.mycroft
Hay una cosa más que necesitas añadir para que esto funcione. El comando sudo te pedirá una contraseña por defecto, de modo que tenemos que decirle a sudo que el usuario homeassistant puede ejecutar el comando service como root sin una contraseña. Podemos hacer esto ejecutando sudo visudo y añadiendo la siguiente línea al final del archivo:
homeassistant ALL=NOPASSWD: /usr/sbin/service
Vamos a ampliar este ejemplo un poco. Supón que quieres ser capaz de activar o desactivar un servicio que se ejecuta en un dispositivo diferente. La forma más segura de hacerlo sería a través de ssh. Para ello, tendremos que configurar las claves para ssh, de modo que el usuario homeassistant pueda ejecutar comandos a través de ssh sin que solicite una contraseña (ten en cuenta que por seguridad necesitarás proteger tus claves). Necesitaras ejecutar los siguientes pasos con el usuario de homeassistant:

1. Crear una nueva clave ssh para homeassistant sin contraseña:

$ sudo su -s /bin/bash homeassistant
$ cd ~homeassistant
$ ssh-keygen -t rsa
Acepta los valores por defecto (clave almacenada en /home/homeassistant/.ssh/id_rsa y sin contraseña). Puede utilizar esta clave para controlar muchos dispositivos (incluso usarla para iniciar sesión en routers para la detección de presencia), así que no es necesario crear varias claves.

2. Copia la clave al sistema remoto. Asegúrate de introducir la contraseña correcta de la cuenta con la que estás conectando (yo estoy usando root en el dispositivo remoto):

$ ssh-copy-id root@other-device-ip
3. Prueba la conexión manualmente:
$ ssh root@other-device-ip hostname
Deberías recibir una línea con el nombre de host del otro dispositivo, sin que se te solicite una contraseña. Si consigues esto, significa que las cosas van bien. Si no, recurre a la excelente guía de solución de problemas en http://bit.ly/2vTQYdA.

4. Configurarlo en Home Assistant añadiendo una nueva entrada switch en configuration.yaml:

switch:
  - platform: command_line
    switches:
…
      mycroft_kitchen:
        command_on: ssh root@kitchen /usr/sbin/service mycroft start
        command_off: ssh root@kitchen /usr/sbin/service mycroft stop
        friendly_name: "Mycroft Kitchen status"
Si no quieres que se realice un sondeo constante del estado en Home Assistant, puede omitir la línea "command_state" y, en este caso, Home Assistant supondrá que está desactivado y mantendrá solo los cambios que has realizado en la interfaz de usuario. Además, la interfaz cambiará de barra deslizante a disponer de dos iconos para activar/desactivar.

ODROID Magazine - Switches for system processes
Figura 6 - Switches para los procesos del sistema

Activar/desactivar un switch basado en la reproducción multimedia o en la información de presencia

Ahora que podemos activar/desactivar manualmente Mycroft (o cualquier otro switch igualmente), hagamos las cosas interesantes. Me gustaría tener Mycroft funcionando cuando estoy en casa (mi teléfono está conectado al router y es detectado por la detección de presencia que hemos implementado en el artículo anterior) y Kodi no se está ejecutando. Sin embargo, esto puede parecer ambiguo. Por lo tanto, vamos a definir lo que realmente queremos:

  • Usuario cambia de "not_home" a "home" y Kodi está inactivo => activar Mycroft
  • Usuario cambia de "home" a "not_home" => apagar Mycroft
  • Usuario esta en "home" y Kodi cambia de cualquier cosa a reproducir => apagar Mycroft
  • Usuario esta en "home" y Kodi pasa de cualquier cosa a inactivo => encender Mycroft

Para ello, crearemos unas cuantas automatizaciones. La diferencia con respecto a las automatizaciones anteriores está en el uso de las condiciones (http://bit.ly/2x2FDYz). Los disparadores indican cuando debe suceder una acción, mientras que las condiciones se utilizan como filtros e indican si esa acción debe ocurrir.

Por lo tanto, vamos a dar el primer paso. Mi usuario es rastreado por el dispositivo llamado "nutty". Puesto que la interfaz web no admite condiciones (nota: las condiciones sólo son admitudas a partir de la versión 0.51), tendremos que hacerlo manualmente, en el archivo de configuración automations.yaml:

- action:
  - alias: Turn on Mycroft
    service: switch.turn_on
    entity_id:
      - switch.mycroft
  alias: Turn on Mycroft when Nutty arrives home and Kodi is idle
  id: '1502097058892'
  trigger:
    platform: state
    entity_id: device_tracker.nutty
    to: 'home'
  condition:
    condition: and
    conditions:
      - condition: state
        entity_id: 'media_player.kodi_livingroom'
        state: 'idle'
La automatización se activan y se evalúan cada vez que la entidad "device_tracker.nutty" cambia de estado. Cuando se activa, la condición también se evalúa y si "media_player.kodi_livingroom" está inactivo en ese momento, entonces se ejecuta la acción y se activa el switch. Podría haber probado también que Mycroft estuviese apagado, pero activar un switch ya conectado no tiene ningún tipo de efecto. .

Si esto te resulta complicado, aquí tienes el pseudo-código::

onStateChange(device_tracker.nutty):
  if states.device_tracker.nutty.state == 'home':
    if states.media_player.kodi_livingroom.state == 'idle':
      switch.turn_on(switch.mycroft)
La automatización del apagado es similar, aunque es más simple ya que no tiene condiciones adicionales:
- action:
  - alias: Turn off Mycroft
    service: switch.turn_off
    entity_id:
      - switch.mycroft
  alias: Turn off Mycroft when Nutty leaves home 
  id: '1502097058893'
  trigger:
    platform: state
    entity_id: device_tracker.nutty
    to: 'not_home'
Las dos últimas automatizaciones deberían ser activadas por los cambios de estado de Kodi y usar las condiciones para comprobar si el usuario está o no en casa.
- action:
  - alias: Turn off Mycroft
    service: switch.turn_off
    entity_id:
      - switch.mycroft
  alias: Turn off Mycroft when Kodi is playing and Nutty is home
  id: '1502097058894'
  trigger:
    platform: state
    entity_id: media_player.kodi_livingroom
    to: 'playing'
  condition:
    condition: and
    conditions:
      - condition: state
        entity_id: 'device_tracker.nutty'
        state: 'home'
Y la última debería ser:
- action:
  - alias: Turn on Mycroft
    service: switch.turn_on
    entity_id:
      - switch.mycroft
  alias: Turn on Mycroft when Kodi is idle and Nutty is home
  id: '1502097058895'
  trigger:
    platform: state
    entity_id: media_player.kodi_livingroom
    to: 'idle'
  condition:
    condition: and
    conditions:
      - condition: state
        entity_id: 'device_tracker.nutty'
        state: 'home'
Una vez que termines de editar automations.yaml, puede volver a cargar las automatizaciones directamente desde Home Assistant dirigiendote a la vista "Configuration" y seleccionando "Reload Automation".

Ahora deberías probar las automatizaciones activándolas y verificando el resultado en todos los casos para descartar cualquier error. Puede utilizar la vista Logbook para ver cuándo se han activado las automatizaciones.

ODROID Magazine - Logbook viewer
Figura 7 - Visor Logbook

Personalizar los nombres y los iconos

Vamos a hablar de una cuestión más. Por defecto, todos los switches tienen el icono de un "rayo", tal vez quieras utilizar alguno más apropiado. Además, es posible que desees cambiar el nombre de una entidad, y que cambiando su id estropearía las automatizaciones en las que se encuentre. También hay algunos grupos integrados, como todos los dispositivos gestionados por un "device_tracker" o todas las automatizaciones que te permiten activar/desactivar/iniciar manualmente una automatización, pero que están ocultas por defecto. Para realizar todos estos cambios, tendremos que añadir una sección Personalizada al principio del archivo de configuración, bajo la etiqueta homeassistant, sangrada por dos espacios (http://bit.ly/2x2q6bv).

Vamos a hacer lo siguiente: mostrar el grupo de automatización y cambiar los iconos de los switches por algo más apropiado. Puedes utilizar los iconos de Material Design (http://bit.ly/2wleenC) o tus propias imágenes. Haremos cambios en configuration.yaml:

homeassistant:
…
  customize:
    group.all_automations:
      hidden: false
      friendly_name: All automations
    switch.mycroft:
      friendly_name: Mycroft living room
      icon: mdi:assistant
    switch.mycroft_kitchen:
      icon: mdi:assistant
    sensor.living_room:
      icon: mdi:temperature-celsius
…
group:
  default_view:
    entities:
…
    - group.all_automations
ODROID Magazine - Customizations for automations and icons
Figura 8 - Personalizaciones para automatizaciones e iconos

Más Ejemplos

La comunidad de Home Assistant tiene numerosos ejemplos en su cookbook en http://bit.ly/2xfAr2V. Tambien tienes más ejemplos en sus foros en http://bit.ly/2v34WbL. Por ejemplo, tienes disponible un ejemnplo de reloj alarma en http://bit.ly/2vOCv48. Para charlar sobre el tema, consulta el hilo original http://bit.ly/2fVogVu.

Be the first to comment

Leave a Reply