De Jeedom à Home Assistant : le chauffage

ARTICLE INCOMPLET EN COURS DE RÉDACTION

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

Comme je l'ai déjà expliqué dans les articles précédents (1 | 2), Jeedom, qui a remplacé la ZiBase, me sert essentiellement à gérer mes convecteurs. Jeedom est plutôt bien fait sur ce point grâce aux plugin Thermostat, Mode et Agenda. On va voir ici que l'on peut faire la même chose avec Home Assistant, on ne se contentera par contre pas de cliquer sur des boutons, il faudra un peu de codage, rien de bien méchant et surtout du copié / collé. Mais une fois que l'on a compris le concept c'est bien plus rapide et surtout extrêmement fiable. Home Assistant ne fait pas tout, mais il fait très bien ce qu'il propose.

Ici pas de plugins mais des fonctions que l'on assemble. Et donc à chaque étape, on vérifie que ça fonctionne (en exécutant ce que l'on fait), et avec le validation intégrée à HA au cas ou l'on aurait codé n'importe quoi ou simplement pas respecté les indentations. Certaines modifications apportées à configuration.yaml et ses sous ensembles nécessitent un redémarrage, par contre on peut recharger à la volée les modifications apportées aux scripts et automations.

HA dispose d'un éditeur de scripts et automations, c’est bien pour faire de petites choses et pour se familiariser, mais dès que l'on souhaite taper dans le dur je vous conseille vivement d'éditer les fichiers .yaml avec un éditeur de code (comme Notepad++, Sublime ou VSCodium (je viens de me prendre un virus avec ce dernier, surement par le biais d'une extension, du coup je suis retourné à Visual Studio Code). Attention c’est l'un ou l'autre, mais pas les deux en même temps, et ce qui sera édité à la mano ne le sera plus avec l'interface.

Alors c'est parti ! Le propre d'une solution domotique est d'obtenir un résultat final calqué à ses besoins, il faut donc les définir, ce qui doit déjà être fait si vous venez de Jeedom. Par contre il ne faudra pas chercher à reproduire exactement la même chose, mais à profiter de ce qu'offre HA.

Dans ce projet j'aurais tout pu faire en code, mais mon objectif de départ est que n'importe qui puisse ensuite changer les plages horaires de base et les températures de consigne sans aller dans le code.

Je pars du principe que vous avez déjà joué avec Home Assistant et intégré ses concepts de base, si ce n'est pas le cas commencez par là et revenez plus tard. Je vais présenter ici quelques exemple, mais ensuite je publierait toute la configuration sur Git-Hub, publication possible et intégrée à HA bien entendu.

Concepts de base

Pour gérer le chauffage on va utiliser plusieurs plusieurs composants et fonctions :

  • Climate, qui est en fait un thermostat générique que l'on adaptera à nos besoins.
  • Input_Select, Input_Boolean, Input_Number et Input_DateTime qui vont nous permettre de saisir, afficher et d'utiliser des valeurs, un peu comme des données variables, mais qui seront persistantes dans le système tant qu'on ne les change pas (donc même après un redémarrage).
  • Des automations (des scénarios) qui vont nous permettre de planifier les plages horaires.
  • Des scripts pour exécuter de rapides routines.
  • Des sources de température, les capteurs que l'on placera judicieusement dans les pièces à chauffer. J'utilise des sondes Xiaomi Aqare en Zigbee via Deconz / Phoscon et des sondes Xiaomi avec afficheur en Bluetooth. Mais n'importe quel type de sonde fera l'affaire pourvu qu'elle remonte la température quand elle change.
  • Des actionneur ON/OFF pour chaque convecteur, j'utilise une vieille carte IPX800 v2, mais ça peut être du Shelly, du Zwave, du fil pilote, bref n'importe quoi capable d'allumer un convecteur en respectant les normes en vigueur (on évite de commander un convecteur avec une chinoiserie. Et on évité également des équipements qui ne sont pas pilotables en local afin d'éviter de se retrouver sans chauffage en cas de coupure internet).

Le thermostat

La première chose à faire pour pouvoir jouer est de créer un premier Thermostat en éditant le fichier climate.yaml que l'on aura inclut dans configuration.yaml (je vous conseille de faire ainsi pour tout afin d'aérer votre code, !include_dir_merge_list permettant d'inclure tout ce qui est dans un sous répertoire pour une type donné) :

group: !include groups.yaml
#automation: !include automations.yaml
automation: !include_dir_merge_list automations/
script: !include scripts.yaml
scene: !include scenes.yaml
switch: !include switch.yaml
climate: !include climate.yaml
notify: !include notify.yaml
sensor: !include sensor.yaml
input_boolean: !include input_boolean.yaml
input_datetime: !include input_datetime.yaml
input_number: !include input_number.yaml
input_text: !include input_text.yaml
input_select: !include input_select.yaml

Et ensuite dans climate.yaml on va placer notre premier thermostat. Attention à toujours respecter l'indentation propre aux fichier .yaml (d'ou un éditeur de code).

  - platform: generic_thermostat
    name: Thermostat Cuisine
    heater: switch.study_heater
    target_sensor: sensor.mi_cuisine
    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

Je ne vais pas vous expliquer le paramétrage du thermostat, il y a des docs (paramétrage | utilisation) pour ça, et sous HA elles sont très bien faites, documentées et fournies avec des exemples.

J'ai géré des convecteurs, mais il est également possible de gérer des climatiseurs réversibles ou d'autres types d'appareils. Il faudra bien sur ajuster ces valeurs, on constate d'emblée la présence d'une valeur du mode absence qui dans certains cas constituera un seuil, le reste consistant à chauffer ou pas. C'est adapté à un poêle ou du chauffage central, mais pas à du chauffage électrique ou il faudra être plus précis et gérer des mode Eco/Confort.

A partir de la on ajoute notre thermostat dans l'interface avec une carte Thermostat et on peut commencer à jouer avec (j'ai un peu customisé le thermostat de base...).

Les Input

Ils vont nous servir de variables de base pour planifier le fonctionnement de nos thermostats avec différentes températures de consigne et différentes plages horaires.

Input_Select : c'est une sorte de combo qui me permettra de passer d'un mode à un autre pour déclencher un script qui va reparamétrage l'ensemble (planification et consignes) en fonction d'une situation. Dans mon cas j'ai un mode Normal, un mode Dîner ou j'élargit les plages horaires et je chauffe un peu plus certaines pièces quand je reçoit du monde (avec option "elle" reste dormir auquel cas je chauffe un peu plus la chambre si c'est une frileuse, ou la chambre d'amis), le mode Week-End si je reçoit des amis avec chauffage de la chambre d'amis, etc..

input_select: # ligne à supprimer quand on place ça dans un sous-fichier
  chauffage:
    name: Etats du Chauffage
    icon: mdi:home-minus
    options:
     - Normal
     - Diner
     - Week-End
     - Abscent

Cette fonction va généralement déclencher un script de mise en situation qui activera les planifications idoines, il faudra également déclencher un script de sortie pour repasser en mode Normal.

Enfin on se servira du mode défini en tant que condition  pour l'exécution d'une planification. Par exemple je chauffe le groupe (on verra plus tard la notion de climate_group) des pièces de vie en mode Confort+ à la condition que que le mode Dîner soit activé.

Input_Boolean : c’est une sorte d’interrupteur virtuel qui va me permettre de passer à ON tous les thermostats à au début de l'hiver (ce que je pourrais également programmer à l'aide des données météo externes), ou de signaler la présence des enfants en vacances chez moi et d'activer la planification du chauffage de leurs chambres (ce que je pourrais également automatiser grâce à leur géolocalisation sur une zone élargie, genre leur TGV approche à moins de 100 km, le temps d'aller les chercher à la gare et leur chambre est chauffée.

input_boolean:
  presence_antoine:
    name: Présence Antoine
    initial: off
    icon: mdi:account-switch
  presence_marie:
    name: Présence Marie
    initial: off
    icon: mdi:account-switch
  thermostats_on_off:
    name: Chauffage On / Off
    initial: off
    icon: mdi:thermostat-box

Input_DateTime : va nous servir à définir nos plages horaires de chauffage. Mais afin de pouvoir s'en servir il faut au préalable définir le sensor Date & Time(je n'ai pas encore compris ce point, mais il est indispensable).

sensor:
    - platform: time_date
      display_options:
      - 'time'
      - 'date'
      - 'date_time'
      - 'date_time_utc'
      - 'date_time_iso'
      - 'time_date'
      - 'time_utc'
      - 'beat'

Ensuite on défini autant de plages horaires que nécessaire. Je me suis abstenu à une plage par pièce, mais il est tout à fait possible d'en ajouter, par exemple sdb_start_confort_matin, de même que j'ai fait un start/stop_confort et qu'explicitement de bascule ensuite en consigne eco, mais j'aurais également pu créer un start_eco ou start_confort_plus, etc...

input_datetime:
  sejour_start_confort:
    has_date: false
    has_time: true
  sejour_stop_confort:
    has_date: false
    has_time: true
  sdb_start_confort:
    has_date: false
    has_time: true
  sdb_stop_confort:
    has_date: false
    has_time: true

On peut également pour chaque entrée ajouter un name:, je ne l'ai pas fait car je vais me servir du plugin multiple-entity-row (à installer depuis HACS) pour afficher tous ça sur une ligne horizontale dans une carte.

Input_Number : va lui me servir à définir mes consignes de température. Je les ai définie globalement, mais comme pour le reste on pourrait affiner. De base c'est c'est affiché en tant que slider, mais il est possible de faire un affichage box et une saisie manuelle, ou comme je l'ait fait de regrouper ces valeurs sur une seule ligne avec multiple-entity-row. Et on peut en ajouter à souhait !

input_number:
  consigne_confort:
    name: Confort
    initial: 20
    min: 19
    max: 24
    step: 0.1
    unit_of_measurement: °C
  consigne_eco:
    name: Eco
    initial: 17
    min: 15
    max: 19
    step: 0.1
    unit_of_measurement: °C

On en a maintenant terminé avec les Input, sachez toutefois qu'il existe également Input_Text qui pourra servir à définir le contenu des messages de notification (SMS, Slack, Telegram ou vocaux via Google Home ou Alexa). Voici le résultat en image :

Vous remarquerez que c'est en anglais, c'est volontaire le temps du développement. En effet toutes les docs étant en langue anglaise, il est bien plus facile pour la compréhension de travailler avec une interface dans cette même langue. En un clic tout peut repasser dans une autre langue.

A ce stade on peut cliquer sur les valeurs pour changer les horaires de début et de fin ainsi que les consignes (elles seront persistantes après un redémarrage car on à pas défini de valeur par défaut dans les Input).

Planification

Si à ce stade on peut commencer à utiliser manuellement nos thermostats, l’intérêt d'une solution domotique est bien sur d'automatiser afin que la domotique nous apporte une expérience confortable adaptée à notre mode de vie.

Pour y parvenir on va planifier les horaires pour adapter le confort (températures) souhaité à notre mode de vie. On commencer par la vie courante (je me lève, je travaille, je dors) et on s'occupera ensuite des cas particuliers (je voyage, je reçoit, je prends une douche à un horaire non planifié, je regarde un film, etc...). On va également gérer les cas particuliers récurrents comme la présence durant les vacances scolaires des enfants pendant x jours, ensemble ou séparément.

Autant vous dire qu'on va rentrer dans le code et notamment se servir de la notion de Template (& Templating) afin d'utiliser les valeurs définies dans nos Imput's pour nos automatisations à base d'Automation ou de Scripts. Mais n'ayez pas peur, je parle de code car ça y ressemble et que je vous recommande un éditeur de code, mais il ne s'agit jamais que de bouts de code généralement issus de nos recherches, le copié / collé est roi, heureusement car je vous rappelle que je ne sais pas coder !

Pour planifier le chauffage d'une pièce ou d'une zone notre Automation va se décomposer en trois parties qui devront êtres parfaitement formatées et indentée, chaque partie peut être multiple (and ou or, je pense) :

  1. Trigger: c'est ce qui va déclencher la planification, dans notre cas on utilisera l'heure début, mais cela pourrait également être un interrupteur, un événement, un état, etc...
    PS : je pense que dans une v2 j’utiliserai un time_pattern permettant la re planification en fonction de conditions (par exemple, de telle heure à telle heure, uniquement le samedi et en fonction d'un mode défini...).
    PS2 : On oublie time_pattern pour cet usage, trop chargé, et surtout on ne peu plus dans ce cas changer la valeur de consigne manuelement.
  2. Condition: pour l'instant je vais me servir uniquement de l'état du Mode (voir input_select plus haut). 
  3. Action: c'est ici que l'on va dire ce que l'on fait. Dans mon cas je vais :
    1. Définir la température de consigne Confort du thermostat (ou d'un groupe de thermostats) en me servant d'une valeur définie plus haut (avec input_number), ensuite j'attendrait
    2. Attendre qu'il soit l'heure de repasser en mode Eco avec un wait_template: et mon heure de fin.
    3. Définir la température de consigne Eco du thermostat
    4. Éventuellement je peux ajouter d'autres actions, comme afficher un voyant sur la vieille ZiBase (qui ne sert plus qu'à ça...) pour indique l'état Confort de la pièce... Ou encore envoyer une notification à Slack qui me servira de journal d’événements... A vous d'imaginer !

Voici ce que ça peut donner :

- alias: 'Planification / Thermostat : Antoine'
  trigger:
  - platform: template
    value_template: '{{ states.sensor.time.state == states.input_datetime.antoine_start_confort.state[0:5] }}'
  condition:
  - condition: state
    entity_id: input_boolean.presence_antoine
    state: 'on'
  action:
  - service: climate.set_temperature
    entity_id: climate.thermostat_antoine
    data_template:
      temperature: '{{ states.input_number.consigne_confort.state }}'
  - wait_template: '{{ states.sensor.time.state == states.input_datetime.antoine_stop_confort.state[0:5] }}'
  - service: climate.set_temperature
    entity_id: climate.thermostat_antoine
    data_template:
      temperature: '{{ states.input_number.consigne_eco.state }}'

Et pour repasser en mode Eco, j'ai dans ce cas intégré un wait_template. Si ça fonctionne, ça n'a rien de fabuleux car pendant tout ce temps d'attente de plusieurs heures, il peut se passer plein de choses, et notamment le redémarrage de HA, et dans ce cas il ne saura plus qu'il doit repasser en mode Eco à telle heure. On va donc oublier cette façon de faire et créer une ou plusieurs automations de fin de séquence. Je dis une ou plusieurs car si pour l'instant je n'ai imaginé qu'une seule plage par jour, dans bien des cas il en aura plusieurs (matin, midi, soir...). Mais il est possible de créer une automation de déclenchement regroupant plusieurs input_time START ou STOP afin de réduire le nombre d'automations, les multiples triggers fonctionnant sur le mode OR. On peut également imaginer une automation de nuit qui repasse en Eco tous les thermostats...

trigger:
  - platform: template
    value_template: '{{ states.sensor.time.state == states.input_datetime.antoine_start_confort_matin.state[0:5] }}'
trigger:
  - platform: template
    value_template: '{{ states.sensor.time.state == states.input_datetime.antoine_start_confort_midi.state[0:5] }}'
trigger:
  - platform: template
    value_template: '{{ states.sensor.time.state == states.input_datetime.antoine_start_confort_soir.state[0:5] }}'

On peut également vouloir déclencher un trigger à un jour et heure spécifique liée à in input_datetime.

value_template: "{{ states('sensor.date_time') == (states.input_datetime.next_diner.attributes.timestamp | int | timestamp_custom('%Y-%m-%d, %H:%M', True)) }}"

Il nous faudra donc pour chaque thermostat ou groupe de thermostats une automation qui va gérer les  START et une automation pour les STOP.

Pour valider les templates il y a dans l’interface de HA un éditeur qui permet de voir et vérifier le résultat. Notez au passage [0:5] à la fin de la seconde Template qui va me permettre de ne considérer que les 5 premiers digit [20:15] d'une valeur qui en compte plus [20:15:56] (les : comptent).

Gestion des modes

J'ai fait le choix dans cet input_select de lancer des scripts pour ne pas encombrer, il il est tout à fait possible de lancer ici une suite d'action.

- alias: 'Mode : Etats du chauffage'
  description: ''
  trigger:
  - entity_id: input_select.chauffage
    platform: state
  condition: []
  action:
  - service: script.turn_on
    data_template:
      entity_id: >
        {% if is_state("input_select.chauffage", "Normal") %}
          script.mode
        {%-elif is_state("input_select.chauffage", "Diner") %}
          script.mode_boost_diner
        {%-elif is_state("input_select.chauffage", "Week-End") %}
          script.mode_boost_week-end
        {%-elif is_state("input_select.chauffage", "Abscent") %}
          script.mode_abscent
        {% endif %}

Par contre dans la gestion de cet input_bolean j'agit directement.

- alias: 'On / Off des Thermostats'
  description: ''
  trigger:
  - platform: state
    entity_id: input_boolean.thermostats_on_off
  action:
  - service: climate.set_hvac_mode
    entity_id: climate.climate_all
    data_template:
      hvac_mode: >
        {% if states.input_boolean.thermostats_on_off.state == "on" %}
          heat
        {% else %}
          off
        {% endif %}

Alors que dans cet exemple on va utiliser deux actions sur deux entités différentes :

- alias: Input Select Chauffage Antoine
  description: ''
  initial_state: true
  hide_entity: false
  trigger:
  - entity_id: input_select.thermostat_antoine
    platform: state
  condition: []
  action:
  - service: climate.set_preset_mode
    entity_id: climate.thermostat_antoine
    data_template:
      preset_mode: >
        {% if is_state("input_select.thermostat_antoine", "Présent") %}
          none
        {%-elif is_state("input_select.thermostat_antoine", "Absent") %}
          away
        {% endif %}
  - service: climate.set_hvac_mode
    entity_id: climate.thermostat_antoine
    data_template:
      hvac_mode: >
        {% if is_state("input_select.thermostat_antoine", "Marche") %}
          heat
        {%-elif is_state("input_select.thermostat_antoine", "Arrêt") %}
          off
        {% endif %}

Cas particuliers

Mode réception

Je ne suis pas frileux et j'essaie de réaliser quelques économies. J'ai donc une température de Confort entre 19 et 20°, par contre si je reçoit du monde à dîner je ne veut pas gâcher l'ambiance à cause du froid que pourraient ressentir mes invités. Je vais donc créer une dérogation à la planification normale et utiliser une température de consigne que j'appellerait Confort+ que j'aurais définie avec un input_number. Pour définir la date et l'heure du début de l’événement, je me servirait d'un input_datetime qui me servira à lancer l'automation idoine, qui va définir la température en Confort+, basculer l'état de mon input_select en mode Diner / Réception (cet état pourra me servir pour des scènes par exemple, ou à conditionner le thermostat de la chambre). 

- alias: 'TH : CONFORT+ Groupe Réception'
  description: 'Activation CONFORT+ des Thermostats du groupe Réception (CHBS)'
  trigger:
  - platform: template
    value_template: "{{ states('sensor.date_time') == (states.input_datetime.next_diner.attributes.timestamp | int | timestamp_custom('%Y-%m-%d, %H:%M', True)) }}"
  condition:
  - condition: state
    entity_id: input_select.chauffage
    state: Normal # Normal ? Dans l'absolu cette vérification est inutile)
  action:
  - service: input_select.set_options # On bascule le mode du chauffage en : Diner
    entity_id: input_select.chauffage
    data:
      options: Diner
  - service: climate.set_temperature
    entity_id: climate.climate_reception
    data_template:
      temperature: '{{ states.input_number.consigne_confort_plus.state }}'
  - service: notify.slack_hass_canaletto
    data:
      message: Passage en mode CONFORT+ ({{ states.input_number.consigne_confort_plus.state }}°) de la zone Réception (CHBS). La température moyenne est de {{ states('sensor.mi_bureau') }}°

J'utilise ici le groupe de thermostats Réception (CHS) qui comprends la cuisine, le hall et le séjour.  Vous remarquerez au passage la présence de messages vers Slack. Très utile en période de debug, cela permet également par la suite de suivre la chronologie des événements bien plus lisible que les logs.

Je n'utilise pas d'heure de fin d’événement car l'automation de clôture de nuit normale basculera en mode ECO le groupe CHBS et repassera l'état en Normal. Je déclenche ce mode à minuit par exemple, et je considère que si on se couche plus tard on pourra faire une dérogation exceptionnelle à la main directement sur les thermostats. C’est pourquoi cette automation de clôture aura un second trigger vers 03:00.

Le mode Week-End

Là c’est un peu plus compliqué. Il va falloir désactiver les automation courantes, chauffer le séjour que j'utilise peu en temps normal, chauffer les chambres des enfants qui pourront devenir des chambres d'amis...

Je vais me servir de deux input_datetime pour le début et la fin du week-end car un week-end n'est pas forcément un samedi et un dimanche mais peut être prolongé. Je pourrais ajouter un ou deux input_boolean pour valider l'utilisation des chambres des enfants en tant que chambre d'amis, mais faisons simple et consolideront simplement l'occupation de ces chambres avec une date d'arrivée et de départ comme s'il s'agissait des enfants (il faudra juste saisir les dates).

# A VENIR
# trigger à ajuster ultérieurement + select mode basé sur le mode réception...

Absence

Basculer un via un input_boolean (géré ou pas en Géo Localisation) le groupe de thermostat ALL en mode absent permettra de conserver une température minimale qui est définie dans la configuration du thermostat. A voir selon les cas d'usage, ça peut correspondre à notre fameux Hors-Gel. On peut également se dire qu'il s'agit d'une température de type Eco.

# CODE

Présence enfants

C'est un mode à part car il peut y avoir Réception avec ou sans l'un ou l'autre de mes enfants. J'ai utilisé ici des input_boolean ou le ON va définir la condition pour le fonctionnement de la planification de leur chambre, tandis que le OFF stoppera les thermostats associés.

La date et l'heure de début et de fin va être soit saisie dans un input_datetime, soit ajoutée à celui ci depuis un agenda externe (Google ou Outlook), une information publique (calendrier des vacances scolaires), tout dépends du mode de vie, mais la saisie me parait un bon début.

#CODE

J’envisage également d'utiliser la géo localisation des enfants afin d'activer ou désactiver ce commutateur. Comme ils habitent loin, on peut imaginer que s'ils entrent dans un rayon de plus de 100 km on considère qu'ils sont ici en vacances, et de fait on chauffe...

Fenêtre ouverte

Une fonction que je n'avais jamais mis en oeuvre sur Jeedom, faute d'avoir eut un résultat immédiat, couper le thermostat quand on ouvre une fenêtre (ou un groupe de fenêtres). Il faudra bien sur un détecteur d'ouverture sur la fenêtre, après quoi une paire d'automations fera le job (à répéter sur chaque thermostats ou groupes de thermostats) :

# On couppe le chauffage quand la fenêtre est ouverte
- alias: '716 : WINDOWS : OPEN'
  trigger:
    platform: state
    entity_id: binary_sensor.fenetre_antoine
    from: 'off'
    to: 'on'
    for:
      minutes: 5
  action:
  - service: climate.set_hvac_mode
    entity_id: climate.thermostat_antoine
    data:
      hvac_mode: 'off'

- alias: '717 : WINDOWS : CLOSED'
  trigger:
    platform: state
    entity_id: binary_sensor.fenetre_antoine
    from: 'on'
    to: 'off'
    for:
      minutes: 5
  action:
  - service: climate.set_hvac_mode
    entity_id: climate.thermostat_antoine
    data:
      hvac_mode: heat

Douche ponctuelle

Quand on a une vie rangée calquée sur des horaires fixes on peut bien sur préchauffer la salle de bain pour la douche du matin ou du soir. Sur ce point j'ai une vie un peu décousue et ce genre de programmation n’est pas envisageable. De plus mon radiateur sèche serviettes Acova est au normes, il n'est donc jamais brûlant et ne permet pas de chauffer rapidement la salle de bain. J'ai donc ajouté un radiateur soufflant pour obtenir une rapide montée en température (22/23° en 10/15" selon la température de départ). 

Je vais donc programmer une Automation qui aura pour trigger un double clic sur un bouton Xiaomi Aqara, voire un déclenchement vocal via GH ou Alexa, action conditionnée par un seuil de température qui lancera le radiateur soufflant et le sèche serviettes pendant 45 minutes. (cette valeur pourra être définie dans l'interface grâce à un input_timedate, input_number ou pourquoi pas un timer que je n'ai pas encore utilisé...).

# Douche ponctuelle
- alias: 'SW : Douche ON pour 45 mn.'
  description: '2 clics Inter Gauche, scèche servietets + radiateur souffant'
  trigger:
  - device_id: d800f7295af147dcad3a5f6ca4970f4a
    domain: deconz
    platform: device
    type: remote_button_double_press
    subtype: left
  condition: []
  action:
  - service: switch.turn_on
    entity_id: switch.osram
  - service: switch.turn_on
    entity_id: switch.x2d
  - service: notify.slack_hass_canaletto
    data:
      message: Passage en chauffe de la SDB. La température actuelle est de {{ states('sensor.bt_t_salle_de_bain') }}°
  - delay: '00:45:00'
  - service: switch.turn_off
    entity_id: switch.osram
  - service: switch.turn_off
    entity_id: switch.x2d
  - service: notify.slack_hass_canaletto
    data:
      message: Fin [automatique] de chauffe de la SDB. La température actuelle est de {{ states('sensor.bt_t_salle_de_bain') }}°

# Cas d'une douche rapide ou on souhaite mettre fin au chauffage avec un simlple clic
- alias: 'SW : Douche OFF'
  description: '1 click Inter Gauche'
  trigger:
  - device_id: d800f7295af147dcad3a5f6ca4970f4a
    domain: deconz
    platform: device
    type: remote_button_short_press
    subtype: left
  condition: []
  action:
  - service: switch.turn_off
    entity_id: switch.osram
  - service: switch.turn_off
    entity_id: switch.x2d
  - service: notify.slack_hass_canaletto
    data:
      message: Fin [manuelle] de chauffe de la SDB. La température actuelle est de {{ states('sensor.bt_t_salle_de_bain') }}°

VMC

Elle est programmée pour se mettre en route en fin de nuit si la température extérieure est supérieure à 5°. (prévoir la définition de cette valeur dans l'interface avec un input_number.).

- alias: 'Q : VMC : Lancement Quotiden' #5 minutes avant
  description: ''
  trigger:
    platform: time
    at: '08:00:00'
  condition:
  - condition: template
    value_template: "{{ states('sensor.bt_t_terrasse') | float > 5 }}"
  action:
  - service: switch.turn_on
    entity_id: switch.ipx800_7_vmc
  - service: notify.slack_hass_canaletto
    data:
      message: VMC Quotidienne ON à {{ states.sensor.time.state }}, la température extérieure est de {{ states.sensor.bt_t_terrasse.state }}°  
  - delay: 00:01:00
  - service: switch.turn_off
    entity_id: switch.ipx800_7_vmc
  - service: notify.slack_hass_canaletto
    data:
      message: VMC Quotidienne OFF à {{ states.sensor.time.state }}, la température extérieure est de {{ states.sensor.bt_t_terrasse.state }}° 

La VMC se mets également en route si un certain seuil d'humidité est détecté dans la salle de bain, pendant une douche par exemple. Cette consigne est définie dans l'interface par un input_number et comparé à l'humidité détectée (après avoir tâtonné pas mal je suis parti sur cet exemple.).

- alias: '"P : VMC ON/OFF : Sur Humidité excessive SDB'
  trigger:
    platform: state
    entity_id:
      - input_number.consigne_humidite
      - sensor.bt_h_salle_de_bain
  action:
    service_template: >-
      {% set hi = (states('input_number.consigne_humidite') | float) + 2.5 %}
      {% set lo = hi - 5 %}
      {% set humidity = states('sensor.bt_h_salle_de_bain') | float %}
      {% if humidity > hi %}
        switch.turn_on
      {% elif humidity < lo %}
        switch.turn_off
      {% else %}
        switch.turn_{{states('switch.ipx800_7_vmc') | lower}}
      {% endif %}
    entity_id: switch.ipx800_7_vmc

ECS

Programmée aux heures creuses, toutes nuits en hiver et un jours sur deux en été. (il me reste à bricoler un input_qq_chose pour définir les lancements car il n'y a pas que hiver ou été comme variables, le nombre de personnes présentes est également un paramètre, et comme le chauffe eau est vieillissant pour l'instant ça sera toutes les nuits).

- alias: 'Q : ECS ON : Lancement Quotiden'
  description: ''
  trigger:
    platform: time
    at: '01:00:00'
  condition:
    condition: and
    conditions:
    - condition: state
      entity_id: input_boolean.thermostats_away
      state: 'off'
    - condition: time
#      after: '15:00:00'
#      before: '02:00:00'
      weekday:
        - mon
        - tue
        - wed
        - thu
        - fri
        - sat
        - sun
  action:
  - service: switch.turn_on
    entity_id: switch.ipx800_7_ecs
  - service: notify.slack_hass_canaletto
    data:
      message: ECS Quotidienn ON à {{ states.sensor.time.state }}

- alias: 'Q : ECS OFF : Lancement Quotiden'
  description: ''
  trigger:
    platform: time
    at: '05:00:00'
  action:
  - service: switch.turn_off
    entity_id: switch.ipx800_7_ecs
  - service: notify.slack_hass_canaletto
    data:
      message: ECS Quotidienn OFF à {{ states.sensor.time.state }}

Groupage de thermostats

By design le thermostat générique ne permet de gérer qu'un seul actionneur. Pour palier à cet inconvénient, mais également pour pouvoir appliquer des actions ou des valeurs à plusieurs thermostats il existe l'intégration climate_group qui va nous permettre de définir des groupes de thermostats qui seront ainsi vus comme un seul. Il est même possible de créer une carte avec ce groupe qui reprendra la moyenne des températures remontées sur chaque thermostat et d'y affecter une valeur de garde unique. Si cette dernière possibilité est inutile, je vais utiliser le groupe climate_jour avec de 3 thermostats dans ma zone de vie et le groupe climate_all pour allumer ou éteindre le chauffage avec le ON/OFF d'un un input_boolean.

  climate:
  - platform: climate_group
    name: 'Climate Jour'
    entities:
    - climate.thermostat_bureau
    - climate.thermostat_cuisine
    - climate.thermostat_hall

  - platform: climate_group
    name: 'Climate All'
    entities:
    - climate.thermostat_bureau
    - climate.thermostat_cuisine
    - climate.thermostat_hall
    - climate.thermostat_salle_de_bain
    - climate.thermostat_sejour
    - climate.thermostat_lionel
    - climate.thermostat_antoine
    - climate.thermostat_marie

Attention : pour l'instant ce composant ne supporte pas set_preset_mode qui permet de passer un thermostat en mode absent. C’est en discussion sur GitHub.

Surveillance

Comme expliqué plus haut j'ai choisit de générer des messages Slack pour chaque événements, delà me permet d'avoir un journal. Pour le debug on peut également surveiller ce qui est en place sur le dashboard, notamment au niveau des températures avec ce genre de graphique (interactif en passant la souris sur les courbes) :

Consommation

En ces temps ou l'énergie est de plus en plus coûteuse il devient opportun d’installer des compteurs d'énergie. Certains modules, Shelly par exemple, présentent l'avantage de remonter cette information, instantanée et cumulée. Cela pourra permettre d'afficher la consommation, mais également, avec un peu d’huile de coude, d'en calculer le coût. On peut également utiliser un Shelly EM avec des pinces pour mesurer la consommation d'un segment, ce que j'ai fait ici pour ma baie informatique et l'arrivée EdF, alors que la troisième ligne prends en compte le comptage d'un dimmer.

L’insertion de compteurs ou de pinces n'est pas facile dans un tableau existant utilisant des peignes. Legrand a bien annoncé des modules disjoncteurs ou différentiels intégrant cette fonction, mais outre leur tarif qui sera élevé, rien ne dit que le protocole (Zigbee) sera suffisamment ouvert pour s'en servir dans Home Assistant, mais c’est à considérer pour du neuf. En rénovation on préférera des module au dos des convecteurs ou les blocs de 4 relais DIN proposés par Shelly.

Re-Planification

Pour toutes ces automatisations on part du postulat que :

  1. La machine qui héberge Home Assistant est fiable et secourue par un UPS.
  2. Les actionneurs savent retrouver leur état initial après une coupure électrique. En ce qui me concerne c’est le cas des Shelly mais également de ma carte IPX800 v2. Pour les autres (modules X2D ou DI-O en 433 Mhz. par exemple, il faudra les remplacer s'ils sont stratégiques, du reste ils sont gérés par le RFPlayer sur mon Jeedom en esclave qui lui aussi devra à terme disparaître.

Si on respecte ça, une coupure du réseau électrique n'affectera pas le chauffage au retour, pas plus qu'un redémarrage de Home Assistant puisqu'on dans tous les cas on n'a pas de WAIT mais des automations de fin de cycle.

GéoLocalisation

La géolocalisation fonctionne tellement bien sous HA, que ce soit via l'application ou via le partage de position sur Google Maps, que ça me donne envie de l'utiliser. On peut également utiliser le plugin Unifi pour gérer une présence basée sur le WI-FI vraiment locale, alors que via Google Maps on pourra gérer des approches.

Avec des convecteurs la montée en chauffe est assez longue, par contre dans le cas d'un climatiseur il est possible d'obtenir un bon rafraîchissement d'une pièce en une dizaine de minutes. On peut donc facilement imaginer d'activer un climatiseur quand un utilisateur sort de sa zone Travail pour rentrer chez à son domicile et ainsi ne pas perdre en confort s'il rentre trop tôt, ou ne pas consommer de l’énergie inutile s'il rentre trop tard.

Conclusion

J'ai longtemps été sceptique sur la possibilité de remplacer Jeedom, et j'ai longtemps repoussé. J'avais peur de ne pas pouvoir faire ce que je fais avec Jeedom pour le chauffage, ce n’est pas le cas, tout est possible avec Home Assistant, par contre il faut rentrer dans le concept, ce qui finalement m'a pris bien moins de temps que quand j'ai transité de la ZiBase à Jeedom.

Le résultat est concluant et me semble bien plus fiable, on verra à l'usage, mais surtout je ne suis plus tributaire de certaines mises à jours de plugin hasardeuses. Finalement pas sur que ça m'ai pris plus de temps qu'un passage de la v3 à la v4 de Jeedom.

Maintenant que j'ai défini le concept de ma gestion du chauffage il va me falloir finaliser, dupliquer les blocs de code, les ajuster, tester encore et basculer réellement de Jeeom à HA. Je ne serait pas aidé par la météo qui est ici très clémente cet hiver (19.5° ce midi). Une fois terminé, j'ajusterais cet article en fonction des modifications éventuelles.

N’hésitez pas à commenter.

EDIT : Basculer de Jeedom m’aura pris moins de temps que je ne l'avais imaginé : 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.

Next !

Il me reste à nettoyer tous ces codes et à les publier sur GitHub !

 

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