domingo, 27 de mayo de 2018

Instalación de HomeAssistant mediante PyEnv

Cuando uno empieza a entrar en el mundo de la domótica “casera” (nunca mejor dicho), no a base de utilizar productos comerciales sino haciéndolo todo uno mismo, lo primero que piensa es en la Raspberry Pi.
Yo, sin embargo, en mi afán de gastar lo mínimo posible comprando productos en China, decidí en un principio utilizar la Orange Pi Zero como mi controlador principal para HomeAssistant, como vimos en un artículo anterior.

Problemática

En realidad, uno puede instalar HomeAssistant en cualquier ordenador o controlador: un equipo Mac, Windows, Linux, un core I7 de última generación o un ARM con 256 MB de RAM, siempre y cuando sea posible instalarle Python.
Sin embargo, apartarse del estándar utilizado por la mayoría tiene su penalización.
Si tienes una Raspberry PI, basta con acudir a la página de HomeAssistant y bajarte una distribución de Linux especial personalizada (hass.io o hassbian) y grabarla en tu tarjeta SD para salir andando. Ambas distribuciones están pensadas para que el usuario trabaje lo mínimo, sea fácil actualizar, esté todo optimizado, etc.
Pero ¿qué pasa cuando tu distribución, que no es la estándar, se queda anticuada y los requerimientos de versiones de HomeAssistant van subiendo y no tienes posibilidad de actualizar?. De todos es sabido que las distribuciones de Linux tienen una gran ventaja que son los repositorios de software (debian, ubuntu, rpm, etc) desde los que el usuario siempre puede instalarse el software sin tener que buscar en ningún sitio más. Esta gran ventaja sin embargo se convierte en un gran inconveniente cuando los paquetes del repositorio se quedan antiguos y no se pueden actualizar más.
Tal es el caso de la Orange Pi Zero, para la cual disponemos de varias versiones (aquí y aquí) de Linux pero todas ellas basadas en un repositorio de Debian que no es el más nuevo.
Python
Esto es un problema cuando los requerimientos de HomeAssistant subieron por ejemplo de Python 3.4 a Python 3.5.3. Este cambio que en principio puede parecer mínimo hace que por ejemplo en la versión de Ubuntu 16.04.04 LTS que es la que yo uso no pueda instalar versiones recientes de HomeAssistant puesto que la versión máxima de Python que hay en los repositorios es la 3.5.2. Lo mismo nos pasaría si tuviésemos un Debian Jessie que no podamos actualizar.
Por tanto, no podemos utilizar versiones “oficiales” de Python. ¿Qué soluciones nos quedan?
A bote pronto, se me ocurren tres:
  • Utilizar un repositorio PPA.
    He consultado varios y o bien no contienen software para procesadores ARM o bien no funcionan con mi distribución.
  • Compilar Python 3.5. desde *código fuente.
    Es una posibilidad, pero bastante engorrosa.
  • Utilizar PyEnv.
    Este entorno nos permite tener múltiples instalaciones de Python en paralelo sin interferir con los paquetes “oficiales” del sistema.
Por tanto, elegiremos la tercera opción por ser la menos “invasiva” para no liarla con el sistema.

Guía de instalación

Esta guía está pensada para instalar la última versión de HomeAssistant desde cero, en un sistema (Debian Jessie, Ubuntu 16.04, etc) que no soporte de forma nativa la última versión de Python. En caso de tener ya un sistema con HomeAssistant instalado, habría que saltarse algunos pasos.

Crear el usuario homeassistant

Lo primero que necesitaremos (si no lo tenemos ya) es crear un usuario específico para ejecutar HomeAssistant. En los ejemplos de este artículo lo denominamos homeassistant, pero el nombre es lo de menos.
Para ello, seguiremos los siguientes pasos:
  1. Entramos como root en el sistema y creamos un nuevo usuario:
    # adduser homeassistant
    
  2. Lo añadimos al grupo sudo:
    # apt-get install sudo
    # usermod -aG sudo homeassistant
    

Instalar PyEnv

PyEnv nos permite instalar (compilándola) cualquier versión de python de forma no intrusiva en el sistema,
y nos permite especificar con qué versión queremos trabajar de forma global para todo el sistema o para
una aplicación concreta.
Para instalarlo seguiremos los siguientes pasos:
  1. Iniciamos sesión con el nuevo usuario homeassistant.
  2. Descargamos pyenv desde su proyecto en GitHub, creando un directorio .pyenv en el home del usuario:
    $ git clone https://github.com/pyenv/pyenv.git .pyenv
    
  3. Lo hacemos accesible desde el login, añadiendo al fichero .bashrc las siguientes líneas:
    export PYENV_ROOT="$HOME/.pyenv"
    export PATH="$PYENV_ROOT/bin:$PATH"
    if command -v pyenv 1>/dev/null 2>&1; then
     eval "$(pyenv init -)"
    fi
    
  4. Salimos del shell (logout o exit) e iniciamos sesión de nuevo con el usuario homeassistant para que se ejecuten los cambios.
  5. Instalamos una serie dependencias necesarias. HomeAssistant requiere en principio compilar python con soporte para SQLite3:
    $ sudo apt-get install libsqlite3-dev
    
  6. Instalamos la versión requerida de Python. Lo que hace PyEnv es descargarse los fuentes de la versión requerida de Python y compilarla de forma transparente para el usuario. En este ejemplo instalaremos la versión 3.5.5:
    $ pyenv install 3.5.5
    
  7. Establecemos la versión global de python del sistema
    Para ver qué versión de python utiliza el sistema, utilizaremos este comando:
    $ pyenv global
    
    Para ver qué versiones hay instaladas, utilizaremos este otro:
    $ pyenv versions
    
    Para establecer la versión 3.5.5 como global, utilizaremos este:
    $pyenv global 3.5.5
    

Configurar entorno virtual

Una vez que tenemos nuevo python en la oficina, lo más apropiado sería crearnos un entorno virtual para la instalación y ejecución de HomeAssistant.
El entorno virtual nos permite independizar las librerías y ejecutables asociadas a un programa del resto del entorno de python del sistema. Una especie de “caja negra” en la que entraremos cada vez que queramos ejecutar la aplicación.
Para este cometido, existe un plugin para PyEnv que se denomina virtualenv:
  1. Instalamos el plugin virtualenv:
    $ git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv
    
  2. Creamos un entorno virtual de python para HomeAssistant:
    $ pyenv virtualenv 3.5.5 home-assistant
    
    El entorno virtual residirá en el directorio /home/homeassistant/.pyenv/versions/home-assistant
  3. Activamos el entorno recién creado:
    $ pyenv activate home-assistant
    
    Tras hacer esto, en el prompt se nos indica el entorno en el que estamos trabajando:
    (home-assistant) homeassistant@mi-servidor:~$
    
    Todos los comandos relativos a python que se ejecuten a partir de ahora sólo afectarán al entorno activo.

Instalar HomeAssistant

Para instalar HomeAssistant en el entorno virtual de Python activo hacemos lo siguiente:
  1. Instalar paquetes adicionales:
    Serán necesarios los siguientes paquetes antes de nada:

    $ sudo apt-get install libssl-dev openssl libmariadb-dev
    $ sudo apt-get install libncursesw5-dev libgdbm-devlibc6-dev
    $ sudo apt-get install libffi-dev zlib1g-dev bzip2 libbz2-dev libreadline-de
  2. Instalar librerías necesarias de forma manual. Estas dos librerías nos harán falta para ejecutar HomeAssistant:
    $ pip3 install mysqlclient
    $ pip3 install pyserial
    
  3. Instalar el paquete:
    $ pip3 install homeassistant
    
  4. Instalar dependencias automáticas:
    Una vez instalado el paquete, lanzaremos el ejecutable por primera vez para que se autoinstalen las dependencias de python adicionales necesarias. Este proceso puede tardar un rato y nos presenta el log por la salida estandar:
    $ hass
    
    Una vez que el proceso ha acabado, podemos probar que todo ha ido bien accediendo mediante un navegador a la siguiente URL:
    http://[DIR_SERVIDOR]:8123
  5. Instalar el servicio. Para facilitarnos la vida, vamos a crearnos un servicio para poder iniciar y detener a nuestra voluntad el HomeAssistant. Para ello:
    1. Copiamos el siguiente texto en el fichero /etc/init.d/hass:
      #!/bin/sh
      ### BEGIN INIT INFO
      # Provides:          hass
      # Required-Start:    $local_fs $network $named $time $syslog
      # Required-Stop:     $local_fs $network $named $time $syslog
      # Default-Start:     2 3 4 5
      # Default-Stop:      0 1 6
      # Description:       Home\ Assistant
      ### END INIT INFO
      
      # /etc/init.d Service Script for Home Assistant
      
      RUN_AS="homeassistant"
      export PYENV_ROOT="/home/$RUN_AS/.pyenv"
      HASS_ROOT="$PYENV_ROOT/versions/home-assistant"
      PRE_EXEC="$HASS_ROOT/bin/python3"
      HASS_BIN="$HASS_ROOT/bin/hass"
      PID_DIR="/tmp"
      PID_FILE="$PID_DIR/hass.pid"
      CONFIG_DIR="/var/lib/home-assistant"
      LOG_DIR="/var/log"
      LOG_FILE="$LOG_DIR/hass.log"
      FLAGS="-v --config $CONFIG_DIR --pid-file $PID_FILE --log-file $LOG_FILE --daemon"
      
      start() {
      if [ -f $PID_FILE ] && kill -0 $(cat $PID_FILE) 2> /dev/null; then
        echo 'Service already running' >&2
        return 1
      fi
      echo -n 'Starting service' >&2
      local CMD="$PRE_EXEC $HASS_BIN $FLAGS;"
      su -s /bin/bash --preserve-environment -c "$CMD" $RUN_AS
      if [ $? -ne 0 ]; then
        echo "Failed" >&2
      else
        echo "Done" >&2
      fi
      }
      
      stop() {
      if [ ! -f "$PID_FILE" ] || ! kill -0 $(cat "$PID_FILE") 2> /dev/null; then
        echo 'Service not running' >&2
        return 1
      fi
      echo -n 'Stopping service' >&2
      kill $(cat "$PID_FILE")
      while ps -p $(cat "$PID_FILE") > /dev/null 2>&1; do sleep 1;done;
      rm -f $PID_FILE
      echo 'Done' >&2
      }
      
      install() {
      echo "Installing Home Assistant Daemon (hass)"
      update-rc.d hass defaults
      mkdir -p $CONFIG_DIR
      chown $RUN_AS $CONFIG_DIR
      mkdir -p $LOG_DIR
      chown $RUN_AS $LOG_DIR
      }
      
      uninstall() {
      echo "Are you really sure you want to uninstall this service? The INIT script will"
      echo -n "also be deleted! That cannot be undone. [yes|No] "
      local SURE
      read SURE
      if [ "$SURE" = "yes" ]; then
        stop
        echo "Notice: The config directory has not been removed"
        echo $CONFIG_DIR
        echo "Notice: The log directory has not been removed"
        echo $LOG_DIR
        update-rc.d -f hass remove
        rm -fv "$0"
        echo "Home Assistant Daemon has been removed. Home Assistant is still installed."
      fi
      }
      
      case "$1" in
      start)
        start
        ;;
      stop)
        stop
        ;;
      install)
        install
        ;;
      uninstall)
        uninstall
        ;;
      restart)
        stop
        start
        ;;
      *)
        echo "Usage: $0 {start|stop|restart|install|uninstall}"
      esac
      
    2. Le damos permisos de ejecución:
      $ sudo chmod +x /etc/init.d/hass
      
    3. Iniciamos el servicio, inicializando previamente el fichero de log:
      $ sudo touch /var/log/hass.log
      $ sudo chown homeassistant:homeassistant /var/log/hass.log
      $ sudo service hass start
      
    4. Una vez probado que funciona correctamente (ver el log en /var/log/hass.log), activamos el arranque automático del servicio, bien mediante la herramienta rcconf o bien mediante el propio servicio:
      $ sudo service hass install
      

Configuración

La configuración y el directorio de trabajo configurados por defecto están en la ruta:
/home/homeassistant/.homeassistant
El fichero de configuración principal se denomina configuration.yaml.

Actualizaciones

Con este pequeño tutorial hemos instalado la última versión de HomeAssistant en nuestro sistema. En caso de que aparezcan nuevas versiones, siempre y cuando no aumente la versión requerida de Python, podremos actualizar nuestra instalación siempre de esta manera:
  1. Iniciamos sesión con el usuario homeassistant.
  2. Activamos el entorno virtual de python:
    $ pyenv activate home-assistant
    
  3. Actualizamos a la última versión, deteniendo previamente el servicio e iniciándolo después:
    $ sudo service hass stop
    $ pip3 install --upgrade homeassistant
    $ sudo service hass start
    
Related Posts Plugin for WordPress, Blogger...

No hay comentarios:

Publicar un comentario