De Jeedom à Home Assistant

ARTICLE INCOMPLET EN COURS DE RÉDACTION

Ce ne sont que mes notes compilées au fil de l'eau...
N'hésitez pas à revenir ou d'utiliser la touche F5, et de me signaler les erreurs :-)

Suite à cet article les choses ont bien avancées. Mon premier soucis étant le chauffage, l'objectif étant de faire au moins aussi bien avec HA qu'avec Jeedom. La philosophie des deux produit est bien différente, sur Jeedom on confie les taches à des plugins plus ou moins stables, sous HA on prend un éditeur et on code, et comme je ne sais pas trop faire, comme beaucoup je suis devenu le roi du copié collé, en essayent de comprendre ce que je fais. Mais quand une fonction est ok, elle est très stable et pas sujette à une mise à jour de plugin foireuse.

Installation 

On part du principe que vous avez installé Home Assistant, pour ma part HASS.IO dans une VM ESXi, mais cela est tout à fait envisageable sur un RPI 4 ou au pire un RPI 3. Je n'arrivais pas à convertir le VMDK proposé. Impossible à installer sans conversion, erreurs lors de la création de la VM. Il y a un très bon tuto ici et une aide . Après avoir perdu 3 heures j'ai refait la même conversion avec une autre console ssh et là j'ai un retour positif !

# /vmfs/volumes/datastore1/Home Assistant # vmkfstools -i "ha38.vmdk" "ha.vmdk"
Destination disk format: VMFS zeroedthick
Cloning disk 'ha38.vmdk'...
Clone: 100% done.

Et du coup ça s'installe bien ! Sous Windows la première console SSH était Terminus qui en principe fonctionne bien, la seconde Bitwise SSH. Je pense à un problème de mapping de caractères.

Premier démarrage

Quand HA se lance il va reconnaître tout seul ce qu'il connait et qui est disponible sur le réseau local. Sonos, des ampoules Xiaomi, mon contrôleur Unifi et surtout ma passerelle Zigbee Phoscon et ses équipements ! Et d'autres bricoles, si tant est que les bonnes clés soient branchées sur la machine... Un vrai +

Les choses à installer ensuite

  • SSL : Le plus simple est d'utiliser DuckDNS. Ca prends 5 Minutes, mais le plugin Let'sEncript fait aussi le travail sur un domaines personnalisé avec les API OVH ou CloudFlare, entre autres, mais pas avec Gandi. Comme ce n'est pas non plus l'adresse d'un site public, je conseille DuckDNS qui me semble bien plus stable. Bien sur avant ça on ouvre le port idoine sur le routeur, mais ça vous maîtrisez déjà. (voir plus bas le chapitre SSL).
  • L'addon Configurator qui vous sera très rapidement indispensable.
  • L'addon SAMBA vous permettra d’accéder aux fichiers de config depuis votre ordinateur Windows ou Mac.
  • L'addon SSH pourra être utile également.
  • L'addon Check Home Assistant Configuration sera lui utile pour faire une vérification de cohérence avant une mise à jour.

Comme je n'ai pas besoin d'une solution domotique pour allumer deux ampoules on va passer sur ce sujet, mais tout comme Jeedom, HA sait automatiser plein de choses. On  va donc passer au cœur de ma problématique, et il en découlera plein d'autres rencontrées au fil de ces jours et nuits ou je me suis plongé dans Home Assistant.

Chauffage et climatisation

Pour gérer le chauffage électrique sous Jeedom je me sert essentiellement de 3 plugins.

Thermostat

Sous HA il faudra les implémenter les thermostats à la main. Le mieux est de créer un /config/climate.yaml et de l'inclure dans /config/configuration.yaml

climate: !include climate.yaml

Dans climate.yaml on va installer et paramétrer les thermostats :

- platform: generic_thermostat
  name: Thermostat Cuisine
  heater: switch.study_heater # On indique ici le relais on/off du convecteur
  target_sensor: sensor.mi_cuisine # On indique ici le capteur de température
  min_temp: 15
  max_temp: 21
  ac_mode: false
  target_temp: 17
  cold_tolerance: 0.3
  hot_tolerance: 0
  min_cycle_duration:
    seconds: 5
  keep_alive:
    minutes: 3
  initial_hvac_mode: "off"
  away_temp: 16
  precision: 0.1

Il est important de faire très attention à l'indentation, on est dans des fichiers .yaml et les règles propres à Yaml s'appliquent ici scrupuleusement. Dans bien des cas Configurator ne vous laissera d’ailleurs pas sauvegarder si le fichier est mal formaté.

Autre chose. Etant donné que toutes la documentation, les sites, ainsi que la majorité des tutos sont en anglais, je vous recommande de passer l'interface de HA en anglais, ça sera plus simple pour suivre...

Une fois que notre thermostat est installé il faut relancer HA. C’est une des plaies de HA, pour l'instant et on passe pas mal de temps à relancer. D’où l’intérêt qu'il soit installé sur une machine un peu puissante. On peut ensuite aller sur la page d’accueil de HA pour y ajouter le thermostat, en passant en mode configuration, en haut à droite, et obtenir ce joli visuel, tant sur votre desktop que via l'application mobile, qui du reste est un pur bonheur quand on pense à l'application mobile (payante) de Jeedom. Il existe des variantes possible de présentation et de customisation.

A ce stade on a obtenu très rapidement un thermostat fonctionnel, mais manuel. Sous Jeedom j'utilisais pour le piloter les plugins MODE et AGENDA, et j'avoue que le résultat était quasi parfait. Sous HA on va pouvoir facilement (enfin j'ai tout de même un peu cherché) utiliser input.select pour remplacer le plugin MODE, par contre coté agenda c’est un peu le désert pour l'instant et il va falloir faire ses propres automatisations, mais il y a des choses qui se préparent (1 | 2 | 3). On pourrait également utiliser Schedy qui m'a parut complet mais complexe, et surtout dépourvu d'interface. Donc dans un premier temps je vais faire la programmation de mes thermostats avec ce qui est disponible de base dans le core de HA.

Les modes et les consignes

Je me sert sous Jeedom de plusieurs commutateurs de modes, par exemple pour définir différents modes de chauffage selon que je suis seul, que je reçoit du monde à dîner, que j'ai des visiteurs qui passent le week-end à la maison, ou encore que ma fille ou mon fils sont présents, elle ou lui, ou les deux. Chaque mode sous entend des plages horaires de chauffage différentes et des températures de consigne adaptées à la situation. Actuellement le passage entre les différents modes est manuel, mais il pourrait être automatisé en relation avec mon agenda Outlook ou Google.

Avec input.select je vais pouvoir définir une sorte de combo que je placerait sur ma page d'accueil. Soit dans configuration.yaml, soit dans un fichier dédié que j'aurais inclus comme expliqué plus haut.

input_select:
  office_radiator:
    name: Radiateur Bureau
    icon: mdi:radiator
    options:
     - Arrêt
     - Hors-Gel
     - Eco
     - Confort -
     - Confort
     - Confort +

  chauffage_enfants:
     name: Modes du Chauffage Enfants
     icon: mdi:account-switch
     options:
     - Présence
     - Présence Antoine
     - Présence Marie
     - Abscents

  chauffage:
     name: Mode du Chauffage
     icon: mdi:home-minus
     options:
     - Normal
     - Diner
     - Week-End
     - Abscent

Le premier servira à piloter un thermostat à la française, c’est optionnel et il faudra le dupliquer sur n thermostats. Les autres pays ne se servent pas de ces modes hérités du fil pilote.ils agissent directement sur la valeur de consigne. A vous de voir si vous souhaitez les conserver. On verra plus loin comment les associer aux thermostats.

Le second mode est dédié à la présence des enfants, tandis que le troisième sera celui utilisé au quotidien. Et voici ce que ça donne sur l'interface de HA.

Maintenant il va falloir un peu de code pour faire communiquer tout ça. On peut le générer avec Configuration/Automation, plus facile pour débuter, mais qui produit un code moins propre, ou directement en éditant automations.yaml dans Configurator. La première solution évite le redémarrage, et c’est ce que je conseille en phase de test.

Les consignes avec input.select

On va donc créer une "automation" qui aura pour Trigger (déclencheur) input_select.office_radiator (notre premier input.select) et en action le code suivant (en mode édition YAML) qui permetra d'affecter au thermostat les différents preset de température :

data_template:
  temperature: |
    {% if is_state("input_select.office_radiator", "Confort") %}
      20
    {% elif is_state("input_select.office_radiator", "Confort -") %}
      19
    {% elif is_state("input_select.office_radiator", "Confort +") %}
      21
    {% elif is_state("input_select.office_radiator", "Eco") %}
      17
    {% elif is_state("input_select.office_radiator", "Hors-Gel") %}
      5
    {% elif is_state("input_select.office_radiator", "Arret") %}
      0
    {% else %}
      0
    {% endif %}
entity_id: climate.thermostat_bureau
service: climate.set_temperature

Etant donné que je suis plus système et réseaux que développeur, je n'ai pas tout compris, mais ça fonctionne, et si j'actionne ma combo sans l'interface les températures de consignes changent sur mon thermostat. Pour programmer un thermostat sur une plage horaire on pourra ainsi le faire en indiquant directement une température de consigne, mais également une mode prédéfini.

Les modes avec input.select

Ici on va gérer les modes de vie et de présence. On les actionnera manuellement avec la combo, mais on pourrait également les programmer ou les basculer avec une application de géolocalisation ou un tag de présence. On va donc créer une "automation" qui aura pour Trigger (déclencheur) input.select.chauffage (notre troisième imput.select par exemple) et en action le code suivant (en mode édition YAML) qui permettra d'affecter au thermostat les différents preset. On voit ici que l'on peut ajouter une seconde action pour déclencher de la même façon de scripts, par exemple pour activer ou désactiver des automatisations.

La première action pour changer l'état d'un thermostat :

data_template:
  option: |
    {% if is_state("input_select.chauffage", "Normal") %}
      Confort
    {%-elif is_state("input_select.chauffage", "Diner") %}
      Confort +
    {%-elif is_state("input_select.chauffage", "Week-End") %}
      Confort -
    {%-elif is_state("input_select.chauffage", "Abscent") %}
      Hors-gel
    {% endif %}
entity_id: input_select.office_radiator
service: input_select.select_option

La seconde action pour exécuter des scripts ou des automation en fonction de l'état :

data_template:
  entity_id: |
    {% if is_state("input_select.chauffage", "Normal") %}
      script.1580948753991
    {%-elif is_state("input_select.chauffage", "Diner") %}
      script.1580948753992
    {%-elif is_state("input_select.chauffage", "Week-End") %}
      script.1580948753993
    {%-elif is_state("input_select.chauffage", "Abscent") %}
      script.1580948753994
    {% endif %}
service: script.turn_on

Voilà pour vous expliquer ce que l'on peut faire d'input.select. Mais input.select comme d'autres états peut également servir à autre chose. Et notamment on va s'en servir en tant que "condition" puisque il s'agit d'un état commuté.

Les plages horaires basées sur input.select

Chacun emménage son mode de vie dans son logement comme, et ce mode de vie est également lié aux pièces et à leur dispositions. Faute d'agenda intégré on va donc définir des des Automations de planification. Pour chaque zone qui pourra contenir plusieurs thermostats il faudra une Automatiion de mise en route dans un mode de Confort et une automation de mise en route en mode Eco (en utilisant les modes prédéfinis ou des températures (Dans Action, on n'utilisera pas la fonction Wait car faute d'un agenda qui re schedulerait la valeur de cette fonction serait perdue en cas de redémarrage de HA). Enfin ces deux Automations seront conditionnées par l'état de notre Mode, ainsi se déclencheront uniquement les événements du mode choisit.

- id: '1580935599789'
  alias: 'Thermostat : Normal / Eco (Cuisine, Hall)'
  description: 'Passage en mode...'
  trigger:
  - at: 00:30:00
    platform: time
  condition:
  - condition: state
    entity_id: input_select.chauffage
    state: Normal

  action:
  - data:
      entity_id: input_select.office_radiator_hall
      option: Eco # Ici on applique un preset
    service: input_select.select_option

  action:
  - data:
      entity_id: input_select.office_radiator_kitchen
      temperature: 19 # Ici on applique une température
    service: input_select.select_option

Alors en attendant une véritable fonctionnalité de planification, voici ce que j'ai trouvé en quelques jours.  C'est donc un peu fastidieux, mais au final pas plus qu'avec des plugin Jeedom car ici le copié collé est roi ! Pour modifier les valeurs de consigne dans l'interface, pour le coté WAF s'entend, il est possible d'utiliser la fonction input.number de de créer un Slider :

input_number:
  slider1:
    name: Confort
    initial: 20
    min: 18
    max: 24
    step: 0.1
    unit_of_measurement: °C

Le mode Absent sera quant à lui géré par un script qui passera tous les thermostats sur Hors-Gel et toutes les Automations en mode désactivé. Il me faut également intégrer la planification ECS et VMC ainsi que le déclenchement de la VMC sur un seuil d'humidité, ce qui devrait se faire facilement.

Enfin, la reprise après une redémarrage de de HA. Je pense que la position des thermostats et des états restent tel qu'ils étaient avant avant l'incident. Point à vérifier.

Voilà une façon basic de remplacer le trio de plugins Jeedom Thermostat/Mode/Agenda. J'ai fait avec ce que j'ai découvert en quelques jours et je reste persuadé qu'il existe d'autres façons de faire ou d'optimiser. Je n'ai pas testé en situation, mais ça fonctionne avec une ampoule de test. 

Sondes et actionneurs

Si mes équipement Zigbee sont nativement reconnus via ma passerelle Phoscon (mais ils le sont également nativement si la clé est sur HA), pareil pour les équipement Shelley et Tuya (en cloud pour ce dernier), j'ai un problème avec mes équipements gérés par un truc bien de chez nous, le RFPlayer. Ca concerne de X2D, du Di-O en RF433, du Visonic en RF868 ainsi que mes détecteurs de coupure électrique et ma mesure de consommation électrique. J'ai un autre problème, mon hyperviseur ESXi est dans le garage, donc pas vraiment au centre de la maison pour y coller une clé Bluetooth Sena. Bref, dilemme !

J'ai donc commencé par installer un second HA en remote sur un RPI3 déporté pour gérer le Bluetooth. Çà fonctionne très bien et HA peut gérer plusieurs HA distants. Et puis il m'est venu une idée à la hauteur de mon désaveux pour Jeedom, l'utiliser en esclave !

Esclavage de Jeedom

Si le terme est un peu exagéré, il s'agit dans mon idée de continuer à utiliser les équipements qui ne sont disponibles que sur Jeedom. J'ai d'abord testé avec les URL de Jeedom disponibles sur tous les équipements, ça fonctionne mais c'est un peu vintage à l'heure ou MMQT est sur toutes les lèvres et que je suis le seul à ne pas l'utiliser. Allez on s'y colle !

MQTT

Il s'agit d'une messagerie d'objets à objets. Il faut un Broker (serveur d'échange) qui peut se trouver n'importe ou sur le réseau, c’est mieux, mais dans l'absolu il est possible d'utiliser un Broker public sur internet.

Ensuite il faut un client sur chaque objet ou solution domotique qui intègre des objets. Coté Jeedom il y en a deux de disponibles, j'ai installé le plugin JMQTT car à la lecture des forums son développeur me parait moins lunatique que l'autre... Et coté HA il suffit d'utiliser MQTT qui est intégré nativement.

Coté Jeedom le plugin s'installe facilement si ce ne sont les dépendances qui prennent un temps de fou. Ce plugin présente l'avantage d’installer en même temps le broker Mosquitto. Pratique si on n'en a pas déjà un sur le réseau. On configure le broker et on ajoute un équipement (sonde Bluetooth ici) avec les actions que l'on souhaitera échanger avec HA via MMQT.

Pour les tests on pourra se servir du bouton tester, mais ensuite il faudra créer un ou créer une action afin qu'à chaque changement de valeur de la sonde le message idoine soit transmis via MQTT. Dans un premier temps j'avais créé un scénario pour faire bouger MQTT, mais au final je j'ai fait dans la configuration de la sonde comme expliqué ici.

Coté Home Assistant on active MQTT via les intégrations et on configure le broker qui dans ce cas se trouve sur l'IP de Jeedom et on ajoute ce code dans /config/configuration.yaml :

sensor:
    - platform: mqtt
      state_topic: 'jeedom/temp'
      name: 'BT Température'
      unit_of_measurement: '°C'
      value_template: '{{ value_json.temp }}'
      - platform: mqtt
      state_topic: 'jeedom/humidity'
      name: 'BT Humidité'
      unit_of_measurement: '%'
      value_template: '{{ value_json.humidity }}'
      - platform: mqtt
      state_topic: 'jeedom/battery'
      name: 'BT Batterie'
      unit_of_measurement: '%'
      value_template: '{{ value_json.battery }}'

Et nous voici avec notre capteur Bluetooth rattaché à Jeedom disponible en temps réél sur HA. Simple !

Bluetooth 

Le Bluetooth et notamment BLE est bien sur géré des base. Pour les capteur Xiaomi il existe un composant pour améliorer l'ordinaire qui reste perfectible. Mais pour peu que HA soit installé dans une VM sur un serveur au fond du garage, va se oser un problème de portée. Si dans un premier temps je vais utiliser l'esclavage Jeedom.

Il existe une passerelle Bluetooth / MQTT (bt2mqtt) que l'on pourra monter sur un RPI 3 ou Zero, même si pour l'instant elle ne supporte pas tous les types de capteurs, et voici comment l'installer sur une carte Rasbian : (Notes de Sébastien à tester et à corriger le cas échéant).

Installation
sudo apt update && sudo apt upgrade -y
sudo apt install git virtualenv python3 python3-virtualenv python3-pip python3-wheel bluetooth bluez libglib2.0-dev -y
pip3 install --upgrade virtualenv
git clone https://github.com/zewelor/bt-mqtt-gateway.git
cd bt-mqtt-gateway
virtualenv -p python3 .venv
source .venv/bin/activate
sudo pip3 install -r requirements.txt
Configuration
sudo hcitool lescan (va trouver tous les devices Bluetooth disponibles)
cp config.yaml.example config.yaml
nano config.yaml (Editer avec les devices trouvés précédement dont on veut remonter les infos)
pip3 install `./gateway.py -r configured`
source .venv/bin/activate
sudo ./gateway.py -d (Test de la configuration en mode debug)
Déploiement
sudo cp bt-mqtt-gateway.service /etc/systemd/system/
sudo nano /etc/systemd/system/bt-mqtt-gateway.service
sudo systemctl daemon-reload
sudo systemctl start bt-mqtt-gateway
sudo systemctl status bt-mqtt-gateway
sudo systemctl enable bt-mqtt-gateway

Attention: Il faut définir le chemin absolu du fichier service.sh dans bt-mqtt-gateway.service

Oui, Mais... Un peu compliquée ces passerelle DIY à mon gout... Il existe une autre voie qui va me permettre de désosser encore un peu Jeedom. Un HA en remote sur un RPI que je vais placer au centre de la maison. Sur ce RPI je vais y coller ma clé Bluetooth SENA, et la clé Combee II (ZWave si on en a), ensuite de quoi il suffit d’installer sur le master le composant Remote... Les performances sont au top et on peu même imaginer d'avoir plusieurs HA en remote via Internet (famille, etc...). Attention à bien filter ce que vous souhaitez importer avant le lancement, faute de quoi toutes les entitées es disponibles sur le distant seront remontées...

remote_homeassistant:
  instances:
  - host: '192.168.210.43'
    port: '8123'
    secure: false
    verify_ssl: false
#    access_token: !secret rpi_access_token
    access_token: myRemoteToken
    entity_prefix: "rpi_"
    include:
      domains:
      - sensor
#      - switch
#      - light
#      - group
#      - zwave
    subscribe_events:
    - state_changed
    - service_registered
#    - zwave.network_ready
#    - zwave.node_event
    filter:
    - entity_id: sensor.rpi_mi_*

IPX800 et autres équipements Jeedom

Je pourrais ainsi gérer ma vieille carte IPX800 v2 qui bien qu'ancienne fonctionne parfaitement, d'autant que chaque relais est équipé d'un contacteur de puissance, et qu'elle peut être configurée pour retrouver son état après une coupure électrique. Pour tester je l'ai fait en direct en mode URL, c'est simple, d'autant plus que cette carte ne propose pas de retour d'état direct, il va falloir interroger le fichier status.xml ...

IPX800 v2 (sur les versions suivantes il doit être possible de le faire en rest), on part toujours du principe que vous utilisez un fichier switch.yaml inclut depuis le ficher de configuration principal.

-  platform: command_line
   switches:
     ipx800:
       command_on: 'wget -O- "http://192.168.210.31/preset.htm?led7=1" >/dev/null'
       command_off: 'wget -O- "http://192.168.210.31/preset.htm?led7=0" >/dev/null'
       friendly_name: VMC

Pour gérer le retour d'état sur une IPX800 v2 il faut interroger le fichier status.xml. Là j'avoue qu'avec mes lacunes en matière de parse ça m'a pris du temps... (mes premières version en commentaire pour parvenir à une seule ligne car seule la valeur true nous intéresse (à noter que sur une seule ligne il faut remplacer les " de la partie recherchée par des ', un mystère pour moi...). Attention également à un autre piège, dans le fichier de status les relais, appelés led sont numérotés de 0 à 7 alors que pour les actionner il faudra le faire de 1 à 8, pas très cohérent tout ça...

    command_state: 'curl "http://192.168.210.31/status.xml"'
    value_template: '{% set status = value | regex_findall_index("<led6>(.*)</led6>") %} {% if status == "1" %} true {%- endif -%}'
#
#    value_template: >  # Variante 2
#      {% set status = value | regex_findall_index('<led6>(.*)</led6>') %} {% if status == "1" %} true {%- endif -%}
#
#    value_template: >  # Variante 1 (départ)
#      {% set status = value | regex_findall_index('<led6>(.*)</led6>') %}
#      {% if status == "1" %}
#        true
#      {%- elif status == "0" -%}
#        false
#      {%- endif -%}

Pour utiliser des équipements qui seront gérés par notre esclave Jeedom, c’est encore plus simple en utilisant les url API. Le retour d'état (souvent virtuel sur de vieux équipements) est signalé par un 0 ou un 1, simple. On part toujours du principe que vous utilisez un fichier switch.yaml inclut depuis le ficher de configuration principal.

- platform: command_line
  switches:
    dio_presence_exterieur:
      command_on: curl "https://canaletto.x:6969/core/api/jeeApi.php?apikey=xxxxxx&type=cmd&id=4106"
      command_off: curl "https://canaletto.x:6969/core/api/jeeApi.php?apikey=xxxxxx&type=cmd&id=4108"
      command_state: 'wget -O- "https://canaletto.xxx:6969/core/api/jeeApi.php?apikey=xxxxxx&type=cmd&id=4105"'
      value_template: '{{ value == "1" }}'
      friendly_name: Présence Extérieur

Home Assistant pour la sécurité

Si HA ne replacera jamais une véritable centrale de sécurité, cette fonctionnalité est intégrée et permettra en se servant de capteur de présence ou d'ouverture de déclencher une alerte ou une notification silencieuse. On ajoute ce code dans /config/configuration.yaml :

  alarm_control_panel:
  - platform: manual
    name: Home Alarm
    code: 1234
    pending_time: 30
    armed_home:
    pending_time: 0
    triggered:
    pending_time: 20
    trigger_time: 4

On place un input-text  dans ce même fichier configuration.yaml. Celà va nous aider pour les notifications détaillées.

input_text:
  trigger_source:
     name: Trigger Source # alarm notification

Ensuite on crée une Automation et le tour est joué, dans mon cas je ne fais que recevoir une notification sur Slack, mais il est tout à fait possible d'actionner une sirène, de faire clignoter des lampes...  Il restera à trouver une sirène autonome en Zigbee (ou autre, la plateforme HA est autonome et secourue, les capteurs également, il faut donc que la sirène et les notifications le soient).

Normalement le composant Alarme permet de notifier uniquement le fait qu'il y a eu un déclenchement, sauf bien sûr à créer plusieurs Automations. Pour intégrer le tout dans une seule automation et avoir en prime un message indiquant la source du déclenchement (capteur) ainsi que l'horodatage, je me suis inspiré de ce post.

- id: '1580693836436' # cet ID veut dire que j'ai fait ça avec l'interface HA : Automations
  alias: Alarm
  description: 'Détection et Notification'
  trigger:
  - entity_id: binary_sensor.motion_sensor
    platform: state
    to: 'on'
  - entity_id: binary_sensor.window_door_01
    platform: state
    to: 'on'
  condition:
  - condition: state
    entity_id: alarm_control_panel.home_alarm
    state: armed_home
  action:
  - entity_id: alarm_control_panel.home_alarm
    service: alarm_control_panel.alarm_trigger
  - data_template:
    entity_id: input_text.trigger_source
    value: '{{ trigger.to_state.attributes.friendly_name }}'
    service: input_text.set_value
  - data_template:
       message: "Alarme déclenchée par le capteur : {{ states('input_text.trigger_source')\
\ }} à {{now().strftime('%H:%M le %d/%m/%Y')}} \n"
    service: notify.slack_hass_canaletto

Les résultat est : Alarme déclenchée par l'ouverture de la porte d'entrée à 03:10 le 08/02/2020

On peut également fignoler une carte de récapitulatif des capteurs en modifiant le code afin d'obtenir l’affichage du dernier déclenchement, et il est possible de cliquer sur les icônes pour obtenir l'historique.

entities:
   - entity: binary_sensor.pir_hall 
     secondary_info: last-changed


On obtient ainsi un affichage plus explicite

Mais delà ne nous donne que la dernière communication entre le capteur et HA. On peut également créer un sensor: supplémentaire pour obtenir l'heure de la dernière ouverture de la porte, que l'on insérera à la place de l'heure de la dernière communication...

    - platform: template    
      sensors:
        last_open_porte_entree:
          friendly_name: 'Last open :'
          value_template: "{{ as_timestamp(states.binary_sensor.openclose_40.last_changed)|timestamp_custom('%H:%M - %d/%m') }}"

Pour simplifier on va créer des groupes de détecteurs (dans groups.yaml)

all_sensors: # GROUP ALL pour ALARME
  name: All Sensors
  entities:
    - binary_sensor.lumi_sensor_smoke    
    - binary_sensor.porte_entree
    - binary_sensor.porte_garage
    - binary_sensor.fenetre_cuisine
    - binary_sensor.fenetre_antoine
    - binary_sensor.motion_hall
    - binary_sensor.motion_garage
    - binary_sensor.motion_sejour
    - binary_sensor.motion_cuisine

Ce qui nous permettra de d'utiliser un seul trigger comme source de déclenchement :

- alias: Alarm
  description: ''
  trigger:
    - entity_id: group.all_sensors
      platform: state
      to: 'on'
  condition:
  - condition: state
    entity_id: alarm_control_panel.home_alarm
    state: armed_home
  action:
  - entity_id: alarm_control_panel.home_alarm
    service: alarm_control_panel.alarm_trigger
  - data_template:
      entity_id: input_text.trigger_source
      value: '{{ trigger.to_state.attributes.friendly_name }}'
    service: input_text.set_value
  - data_template:
      message: "{{now().strftime('%d/%m/%Y, %H:%M')}} > A L A R M  W A R N I N G  | Sensor : {% for state in states|selectattr('entity_id','in',state_attr('group.all_sensors','entity_id'))|selectattr('state','eq','on')|list -%}{{state.name+' '}}{%- endfor %}"
    service: notify.Free_Mobile

On notera le template de notification qui permet d'indiquer la source de déclenchement :

11/03/2020, 00:17 > A L A R M  W A R N I N G | Sensor : Fenêtre Cuisine

On peut également créer un binary_sensor: en s'appuyant sur un groupe de portes ou de fenêtres (faire des groupes à part) et ainsi afficher leur état, mais également s'en servir comme condition pour ne pas activer l'alarme si une fenêtre est ouverte, ou prévenir par un tts (message vocal) si la pluie est annoncée et qu'une fenêtre est ouverte...

- platform: template
  sensors:
    state_doors:
      friendly_name: "Etat des portes"
      device_class: door
      value_template: "{{ is_state('group.doors_status', 'on') }}"

Notifications

S'il est bien sur possible de'utiliser toutes sortes de notifications possible (sms, mail, telegram, etc..), j'ai personnellement choisit d’utiliser un canal de Slack dont je me sert par ailleurs . Il y a plusieurs façons de faire :

Slack

notify:
- name: Slack
  platform: slack
  api_key: xoxp-xxx-xxx-xxx......
  default_channel: '#hass_canaletto'

- name: slack_hass_canaletto # Alternative API
  platform: rest
  method: POST_JSON
  resource: https://hooks.slack.com/services/0/2/es...........
  verify_ssl: true
  message_param_name: 'text'

Free Mobile

Ici aussi, pas besoin du moindre plugin, c'est intégré :

  - name: Free_Mobile
    platform: free_mobile
    username: 12345678
    access_token: jlkjJLjlJLjlMkLhkh

Infos EDF Tempo et EJP

On pourra s'en servir pour faire quelques économies en baissant les consignes de températures les jours rouges. Pour obtenir les valeurs mise à jour, il suffit simplement (en vrai on a un peu galéré...) les sensor: correspondants :

# TEMPO
    - platform: command_line
      name: 'EdF : Tempo demain'
      command: curl -A "'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0' 'https://particulier.edf.fr/bin/edf_rc/servlets/ejptemponew?Date_a_remonter="{{now().strftime("%Y-%m-%d")}}"&TypeAlerte=TEMPO'"
      value_template: "{{ value_json['JourJ1'].Tempo }}"

    - platform: command_line
      name: 'EdF : Tempo'
      command: curl -A "'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0' 'https://particulier.edf.fr/bin/edf_rc/servlets/ejptemponew?Date_a_remonter="{{now().strftime("%Y-%m-%d")}}"&TypeAlerte=TEMPO'"
      value_template: "{{ value_json['JourJ'].Tempo }}"

    - platform: command_line
      name: 'EdF : EJP'
      command: curl -A "'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0' 'https://particulier.edf.fr/bin/edf_rc/servlets/ejptemponew?Date_a_remonter="{{now().strftime("%Y-%m-%d")}}"&TypeAlerte=EJP'"
      value_template: "{{ value_json.JourJ.EjpSud }}"

# EJP
    - platform: command_line
      name: 'EdF : EJP'
      command: curl -A "'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0' 'https://particulier.edf.fr/bin/edf_rc/servlets/ejptemponew?Date_a_remonter="{{now().strftime("%Y-%m-%d")}}"&TypeAlerte=EJP'"
      value_template: "{{ value_json.JourJ.EjpSud }}"

    - platform: command_line
      name: 'EdF : EJP Demain'
      command: curl -A "'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0' 'https://particulier.edf.fr/bin/edf_rc/servlets/ejptemponew?Date_a_remonter="{{now().strftime("%Y-%m-%d")}}"&TypeAlerte=EJP'"
      value_template: "{{ value_json.JourJ1.EjpSud }}"    

    - platform: rest
      name: 'EdF : EJP : Jours restants'
      resource: https://particulier.edf.fr/services/rest/referentiel/historicEJPStore?searchType=ejp
      value_template: '{{ 22 - value_json.SUD.TotalCurrentPeriod }}'
      headers:
        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
        Content-Type: application/json
        User-Agent: Wget/1.20.3 (linux-gnu)

Et si on veut fignoler l'affichage (promis bientôt en rouge cligotant)

binary_sensor:
  - platform: template
    sensors:
      ejp_on:
        friendly_name: "Edf : EJP"
        value_template: "{{ is_state('sensor.edf_ejp', 'SUD_EJP') }}"
        device_class: power   
        icon_template: >
          {% if is_state('binary_sensor.ejp_on','on') %} 
            mdi:alert
            red
          {% else %} 
            mdi:sleep
          {% endif %}
#        icon_color: >
#           if (state === 'on') return 'red';
#           return 'green';

  - platform: template
    sensors:
      ejp_on_demain:
        friendly_name: "EdF : EJP Demain"
        value_template: "{{ is_state('sensor.edf_ejp_demain', 'SUD_EJP') }}"
        device_class: power   
        icon_template: >
          {% if is_state('binary_sensor.ejp_on_demain','on') %} 
            mdi:alert
            red
          {% else %} 
            mdi:sleep
          {% endif %}

Ampoules Yeelight

https://www.home-assistant.io/integrations/yeelight/
https://www.w3.org/TR/css-color-3/#svg-color

Gestion des coupures électriques

Avant je gérait les coupures électriques avec des module ITS23. Mais comem j'ai viré tout ce qui était en 433 Mhz, ça ne va plus être possible. J'ai donc monté un plugin qui va lires les données des onduleurs et est capable de me dire si l'arrivée est down.

https://community.home-assistant.io/t/apcupsd-for-multiple-ups/98962/2

https://community.home-assistant.io/t/how-to-connect-your-apc-ups-to-rpi-and-home-assistant-using-apcupsd/10609/4

Sauvegarde

Il est de base possible de faire des snapshots complets ou partiels de la configuration. On peut améliorer en automatisant avec le plugin Auto Backup qui en outre notifiera si ça se passe mal. Ces sauvegardes étant stockées sur la machine HA ça ne me paraissait pas suffisant. J'ai finalement trouvé une solution de gestion des sauvegardes qui en conserve localement et en externalise une partie sur Google Drive, bien intégrée à HA et qui fonctionne parfaitement.

Alerte batteries faibles...

Avec tous ces capteurs qui fonctionnent sur piles il faut être prudent. Don va donc mettre en place des alertes si les piles sont trop faibles, le message pourra être reçu sur n'importe quel type de notifications, ici Slack :

On commence par créer une entité dans groups.yaml :

battery_levels:
  name: Battery Levels
  entities:
    - sensor.aqara_bouton_battery_level
    - sensor.aqara_inter_battery_level
    - sensor.motion_sensor_battery_level
    - sensor.ikea_tradfri_on_off_battery_level
    - sensor.ikea_tradfri_rc_battery_level
    - sensor.mi_antoine_battery_level
    - sensor.rpi_mi_batt_582d34104d6d
    - sensor.rpi_mi_batt_582d34103286
    - sensor.rpi_mi_batt_4c65a8d1db75
    - sensor.mi_bureau_battery_level
    - sensor.mi_congelateur_battery_level
    - sensor.mi_cuisine_battery_level
    - sensor.mi_garage_battery_level
    - sensor.mi_lionel_battery_level
    - sensor.mi_marie_battery_level
    - sensor.presence_41_battery_level
    - sensor.mi_refrigerateur_battery_level
    - sensor.mi_sejour_battery_level
    - sensor.openclose_40_battery_level
    - sensor.window_door_01_battery_level

Et ensuite une automation :

- alias: Notification- Alert That Batteries Are Low
  initial_state: 'on'
  trigger:
    - platform: time
      at: '19:50:00'
  condition:
    condition: or
    conditions:
      - condition: template
        value_template: >
          {% set min_battery_level = 10 -%}
          {% set ns = namespace(found=false) -%}
          {% for entity_id in states.group.battery_levels.attributes.entity_id -%}
            {% set parts = entity_id.split('.') -%}
            {% if (states(entity_id) | replace("%","") | int) < min_battery_level -%}
              {% set ns.found = true -%}
            {% endif -%}
          {% endfor -%}
          {{ ns.found }}
  action:
    - service: notify.slack_hass_canaletto
      data_template:
        message: >
          {%- set min_battery_level = 10 -%}
          {%- for entity_id in states.group.battery_levels.attributes.entity_id -%}
            {%- set parts = entity_id.split('.') -%}
            {%- if (states(entity_id) | replace("%","") | int) < min_battery_level -%}
              {{ states[parts[0]][parts[1]].name }} battery level is only {{ states(entity_id) }} % !{{ '\n' }}
            {%- endif -%}
          {%- endfor -%}

Utilisation des voyants de la ZiBase

La ZiBase n'est pas tout à fait morte... Certains sous Jeedom s'en servent comme d'une sorte de RFPlayer pour profiter de ses protocoles, c'est fastidieux et je n'ai jamais réussit à faire fonctionner le plugin idoine. Moi je me contente d'utiliser ses 5 leds comme un afficheur d'état en les définissant en switch: avec in curl (depuis j'ai constaté que ça passait mieux avec un wget) :

    zibase_led_1:
      command_on: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%202"
      command_off: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%203"
    zibase_led_2:
      command_on: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%205"
      command_off: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%206"
    zibase_led_3:
      command_on: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%208"
      command_off: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%209"
    zibase_led_4:
      command_on: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%2011"
      command_off: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%2012"
    zibase_led_5:
      command_on: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%2014"
      command_off: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%2015"

    zibase_led_1_flashing:
      command_on: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%204"
      command_off: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%203"
    zibase_led_2_flashing:
      command_on: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%207"
      command_off: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%206"
    zibase_led_3_flashing:
      command_on: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%2010"
      command_off: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%209"
    zibase_led_4_flashing:
      command_on: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%2013"
      command_off: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%2012"
    zibase_led_5_flashing:
      command_on: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%2016"
      command_off: curl "http://192.168.210.30/cgi-bin/domo.cgi?cmd=LM%2015"

Géolocalisation et présence

Inside et de base grâce à l'application mobile. Pour aller pus loin il sera bien sur possible de gérer des tags ou d'utiliser les API de Google afin d'obtenir la position des membres de la famille et interagir.

https://www.home-assistant.io/integrations/google_maps/

Une autre idée intéressante : 

https://www.home-assistant.io/integrations/owntracks/
https://www.juanmtech.com/owntracks-http-mode-and-home-assistant/

HassOS et mode développeur

S'il est possible de monter Home Assistant sur un Linux, il existe également une version qui intègre tout dans une image et qui sera bien plus facilement installable, que ce soit sur un RPI ou en VM. 

L'inconvénient est que l'on a pas facilement accès au shell avec l'add-on SSH de base. Mais qu'à delà ne tienne, il est possible de passer en mode développeur en ajoutant sa propre clé SSH et ainsi accéder à tout. Attention à ne pas tout casser, je ne suis pas développeur mais cela l'a été utile pour récupérer des informations, et par exemple connaitre l'adresse MAC de ma clé Bluetooth Sena (1 - 2 | 3)

# hciconfig
hci0:   Type: Primary  Bus: USB
        BD Address: 00:xx:xx:47:D6:C2  ACL MTU: 310:10  SCO MTU: 64:8
        UP RUNNING
        RX bytes:616 acl:0 sco:0 events:37 errors:0
        TX bytes:942 acl:0 sco:0 commands:36 errors:0
hci1:   Type: Primary  Bus: UART
        BD Address: B8:zz:zz:CE:AD:83  ACL MTU: 1021:8  SCO MTU: 64:1
        UP RUNNING
        RX bytes:85743 acl:2 sco:0 events:2054 errors:0

# hcitool dev
Devices:
        hci1    B8:xx:xx:CE:AD:83
        hci0    00:zz:zz:47:D6:C2

SSL

Je revient ici sur le SSL et les différentes méthodes possibles. Toute la question étant de savoir si on va faire du SSL de bout en bout, ou pas, car si on installe un certificat sur HA, celui ci ne répondra plus qu'en SSL.

  • DuckDns : C'est le plus simple. Ca prends 5 minutes. Inconvénient on n'utilise pas son propre domaine. Ce n'est pas très gênant car HA n'est pas un site public.
  • Let'Encrypt : Ça revient au même, sauf que c'est le plugin qui se charge du renouvellement des certificats. Le plugin est compatible Acme 2 en DNS API, Cloudflare et OVH OK, par contre l'API Gandi n'est pas implémentée pour l'instant.
  • Cloudflare : Il peut être tentant de profiter d'un certificat gratuit pour 15 ans. Mais il y a un hic, pour que ça fonctionne cela sous entend que les requêtes passent par leur reverse proxy. Concrètement toutes les requêtes locales transiteront chez eux, et comme on se sert beaucoup de HA en local cela peu provoquer un ralentissement (la route est plus longue avec cet aller/retour) qui peut poser problème pour ceux qui ont un faible débit. Sans parler du fait que vos données transitent par un tiers. Une solution peu consister à utiliser leur mode flexible ou l'on sera en SSL entre le client et le reverse de Cloudflare, le reste transitant en clair, mais dans ce cas on peut sécuriser en et restreindre l'IP externe de HA uniquement sur les IP Cloudflaire. A réfléchir, mais la solution Cloudflare me parait bancale pour cet usage.
  • OVH SSL Gateway : Inconvénients identiques à Cloudflare
  • Proxy Local : C'est une solution (Nginx, HA Proxy, Synology, etc...), dans ce cas c'est au niveau du proxy que se gère le certificat et HA reste en HTTP. Dans l'appli mobile n peut déclarer une adresse locale en fonction du SSID.

Je reviendrait plus tard sur cette problématique (1 | 2), mais pour l'instant DuckDNS me va très bien.

Et maintenant ?

La transition de Jeedom à Home Assistant prendra du temps, au mieux pour l'hiver prochain, le temps de tout tester. Mais ce qui est quasiment certain, après avoir longtemps hésité, c'est que l'affaire est actée. Et je ne suis pas le seul d'après ce que je lis sur les fils Telegram, Facebook ou même sur les forums officiels de Jeedom

EDIT : En fait pas si longtemps que ça, moins de 3 semaines de mon temps libre et de quelques nuits... C'est bien moins de temps que j'ai du passer sur Jeedom au début et surtout pendant ! Je ne regrette absolument pas d'avoir fait cette migration, et contrairement à Jeedom je prendrais surement la peine d'installer Home Assistant chez des proches car je sais que je peux quasiment tout faire et surtout maintenir aisément cette solution.

 

Sources