Dans un précédent article je vous avait parlé de la partie matérielle de mes volets roulants et de leur commande via des interrupteurs et des télécommandes. Mais avec une installation domotique ouverte, on peut faire bien mieux !
L'objectif ici sera pour chaque volet (ou groupe de volets) d'automatiser leur ouverture, position intermédiaire et fermeture en fonction de :
- Le jour et la nuit
- La température extérieure et intérieure et les contraintes météo (canicule, etc.)
- La position du soleil
- Les contraintes de vie (lever tardif, soirée, etc...)
- Les contraintes de présence / absence plus ou moins longue (alarme et simulation de présence)
- Le débrayage de l'automatisme afin de laisser en paix un invité ou les enfants en vacances avec leur propres horaires et mode de vie.
Vous allez me dire tout de suite que la tache est complexe et vous aurez raison, mais pas tant que ça car je vais m'appuyer sur le travail de Fabien qui a créé un superbe moteur pour gérer tout ça, moteur que chacun pourra adapter à ses propres besoin en lui fournissant des prérequis (inputs, binary, etc..) qui permettront de gérer les différents conditions de positionnement. Vous trouverez les détails sur son blog, mais l'installation est relativement aisée, on commence par créer les entités nécessaires, ensuite on ajoute les BluePrint's de configuration et on termine avec un peu de yaml pour la configuration des conditions.
Facile, mais ça prends un peu de temps. Et surtout commencez par mettre sur le papier le résultat que vous voulez obtenir. Dans cet article je vais vous parler de ce que j'ai mis autour de son travail, plus que de son travail.
Avant de chercher à intégrer mes exemples, prenez le temps d'avoir une installation vraiment fonctionnelle avec les Blueprint's de Fabien.
De base et sans rien ajouter le moteur de Fabien va permettre d'ouvrir le volet au lever de soleil et de le fermer au coucher du soleil grâce à l'intégration sun.sun
. Bon, pour faire ça on a pas besoin d'une usine, c'est pour ça que je vais vous montrer que son moteur permet bien d'autres choses.
Température extérieure et position du soleil
Voici un exemple des plus basic de ce que j'avais fait au départ, mais je vous conseille d'adapter la version de Fabien que j'ai moi même adoptée et qui permet d'aller plus loin, avec différentes sources et notamment un capteur de luminosité.
Exemple
J'utilise les Packages et je vais commencer par créer deux sensor:
en fonction de ma localisation en m'appuyant sur sun.sun
sensor:
- platform: template
sensors:
sunelevation:
friendly_name: "Elevation du soleil"
value_template: "{{ state_attr('sun.sun', 'elevation') }}"
sunazimuth:
friendly_name: "Azimut du soleil"
value_template: "{{ state_attr('sun.sun', 'azimuth') }}"
Ensuite je vais me servir de ce site pour trouver les bonnes valeurs et je vais créer 3 binary_sensor:
avec les les valeurs basses et hautes d'azimut, ces binary passeront à ON quand le soleil tapera sur la façade concernée. Bien sur il faudra un peu tâtonner pour trouver les bonnes valeurs et les ajuster.
binary_sensor:
- platform: threshold
name: "Soleil : Ouest"
upper: 170
lower: 80
entity_id: sensor.sunazimuth
- platform: threshold
name: "Soleil : Sud"
upper: 270
lower: 100
entity_id: sensor.sunazimuth
- platform: threshold
name: "Soleil : Est"
upper: 299
lower: 260
entity_id: sensor.sunazimuth
Et pour terminer je vais créer un dernier binary_sensor:
pour déterminer les conditions météo. Il s'appuie sur les infos de l'intégration Météo France (ou avec un capteur de luminosité en s'appuyant sur l'exemple de Fabien) et dépend de seuils définis dans des input_number:
qui pourront s'afficher dans Lovelace. (je n'ai pas pris en compte la température intérieure pour l'instant).
binary_sensor:
- platform: template
sensors:
vr_sun_hot:
device_class: heat
delay_on:
seconds: 300
delay_off:
seconds: 300
value_template: "{{states('sensor.avignon_temperature')|float(0) >= states('input_number.vr_sun_hot') |float(0)
and states('sensor.avignon_cloud_cover')|float(0) <= states('input_number.vr_cloud_cover')|float(0) }}"
friendly_name: "Alerte haute température"
input_number:
vr_sun_hot:
name: Seuil haute température
min: "10"
max: "40"
step: "1"
unit_of_measurement: "°"
icon: mdi:sun-thermometer-outline
vr_cloud_cover:
name: Seuil couverture nuageuse
min: "0"
max: "100"
step: "5"
unit_of_measurement: "%"
icon: mdi:cloud-lock-outline
Et voici le travail :
Exploitation
Vous aurez remarqué que j'ai deux seuils. Il y aura donc deux conditions possibles dans le choose:
de l'automation de positionnement qui exploite les Blueprint's de Fabien. On retrouve dans l'ordre :
- La ou les conditions (and), ici la température est hot et le soleil au sud.
- La séquence de services à lancer :
- Je positionne le volet dans un
input_number:
à partir d'un input_number:
de préréglage.
- A des fin de debug je note la dernière condition utilisée et la position du volet dans un
input_text:
que je peux afficher dans Lovelace
- conditions:
- condition: state
entity_id: binary_sensor.vr_sun_hot
state: "on"
- condition: state
entity_id: binary_sensor.soleil_sud
state: "on"
sequence:
- service: input_number.set_value
target:
entity_id: input_number.vr_cuisine_planned_position
data:
value: "{{ states('input_number.vr_global_position_sun_alert') }}"
- service: input_text.set_value
target:
entity_id: input_text.vr_cuisine_condition
data:
value: "Condition : Ensoleillement excessif - {{ states('input_number.vr_global_position_sun_alert') }} %"
Attention : Dans un choose:
l'ordre de priorité des différentes conditions est important. Il y a aussi une option par défaut si aucune des conditions n'est valide mais que l'automation est tout de même déclenchée. On placera donc en premier celles qui doivent prendre le dessus, par exemple la condition issue de l'activation de l'alarme sera en premier car il est évident que l'on se moque de position du soleil si on est en voyage et que la maison est fermée.
Cela n'empêchera éventuellement pas une solution de simulation de présence qui agirait sur les volets de fonctionner. Je suis en train de tester cette intégration, attention à bien valider avant de partir en vacances...
Contraintes de vie
Réveil
Ici c'est au petit bonheur de chacun. En ce qui me concerne je n'ai pas d'horaires réguliers et je suis un lève tard. J'ai donc créé un script qui se déroule quand je dis bonjour (ou bonne nuit) à Alexa ou que j'appuis simplement sur un bouton de télécommande. Ce script va entre autres choses faire un push, si je suis présent dans la maison, sur un input_button:
que je vais utiliser ici pour entrouvrir le volet de ma chambre et de la baie du séjour (une baie vitrée coulissante s'ouvre très facilement si elle n'est pas protégée, je vais donc éviter d'ouvrir son volet quand je dors). On a donc deux input_button:
:
input_button:
lionel_up:
name: Je me lève
icon: mdi:human-greeting-variant
lionel_down:
name: Je me couche
icon: mdi:bed
La condition correspondant au réveil (la position du volet est stockée dans un input_number:
afin d'être facilement ajustée depuis l'interface)
- conditions:
- "{{ as_timestamp(states('input_button.lionel_up'))|timestamp_custom('%H:%M', true) == states('sensor.time') }}"
sequence:
- service: input_number.set_value
target:
entity_id: input_number.vr_lionel_planned_position
data:
value: "{{ states('input_number.vr_global_position_reveil') }}"
Il faut bien sur ne pas oublier de déclarer input_button:
dans le BluePrint correspondant au volet (en condition immédiate) et l'actionner dans le script ou l'interface :
- service: input_button.press
target:
entity_id: input_button.lionel_up
Et pour ce volet je vais modifier l'action par défaut d'ouverture dans l'automation afin qu'il ne se passe rien avant 13 heures... mais également rien si le volet est déjà un peu ouvert par une condition fugitive (button.press).
- conditions:
- condition: numeric_state # On ouvre le volet si le soleil est au dessus de l'horizon
entity_id: sun.sun
attribute: elevation
above: 0
- condition: time
after: "13:00:00"
- condition: state
entity_id: cover.vr_baie
state: "closed"
Soirée
En soirée, surtout en été, je n'ai pas envie que les volets soient complètement fermés car c'est l'heure ou on ouvre les fenêtres pour faire entrer un air plus frais. Je vais donc définir un binary-sensor:
correspondant à ma soirée (merci Fabien) :
binary_sensor:
- platform: template
sensors:
vr_evening:
value_template: "{{ (state_attr('sun.sun', 'azimuth') | float(0.0)) > 180 and (state_attr('sun.sun', 'elevation') | float(0.0)) < 0 and ('12:00:00' < states('sensor.time')) }}"
friendly_name: "Soirée"
J'aurais pu y ajouter un and
supplémentaire afin de valider la saison en me basant sur l'intégration Season. Sauf que les saisons tout le monde sait que ça ne veut plus dire grand chose et qu'ici depuis le début du mois de mail il fait plus ou moins 30° en journée, je testerais donc un input_boolean:
de plus pour valider cette condition (que j'aurais également pu valider dans le binary-sensor:
) :
- conditions:
- condition: state
entity_id: binary_sensor.vr_evening
state: "on"
- condition: state
entity_id: input_boolean.vr_evening
state: "on"
sequence:
- service: input_number.set_value
target:
entity_id: input_number.vr_cuisine_planned_position
data:
value: "{{ states('input_number.vr_global_position_soir') }}"
- service: input_text.set_value
target:
entity_id: input_text.vr_cuisine_condition
data:
value: "Condition : Soirée - {{ states('input_number.vr_global_position_soir') }} %"
On peut aussi faire la même chose avec d'autres conditions et sans binary_sensor:
et tout mettre dans les conditions...
- conditions:
- condition: numeric_state
entity_id: sun.sun
attribute: azimuth
above: 180
- condition: numeric_state
entity_id: sun.sun
attribute: elevation
below: 0
- condition: time
after: "18:00:00"
- condition: state
entity_id: input_boolean.vr_evening
state: "on"
Présence / Absence et Alarme
Pour ce chapitre c'est un peu plus compliqué. J'utilise en parallèle deux système. Ma centrale Visonic indépendante mais que je pilote dans Home Assistant et l'intégration Alarmo. Lors de mes test je me suis aperçu que tester uniquement l'état "armed" pouvait conduire à des surprises. Lors de l'armement et surtout le déclenchement d'une alarme (possiblement fausse) l'état de alarm_control_panel:
passe par des phases successives peu simple à gérer, et ça peu conduire à une ouverture des volets non souhaitée.
Chez moi j'ai différentes possibilités pour armer ces deux systèmes (télécommande, code, tag), je vais donc me servir d'Alarmo qui permet de lancer un script selon un état pour basculer un input_boolean:
qui me servira dans la condition immédiates du volet :
- On passe tous les volets en mode automatique (certains auraient pu êtres débrayés comme on le verra plus loin)
- On active
l'input_boolean:
qui va nous servir dans la condition de l'automatisation
- Sur le mode Vacances (absence de longue durée) je rebascule tous les volets en mode manuel. Une sécurité de plus afin d'empêcher qu'ils soient ouverts par erreur.
script:
alarmo_after_arm:
alias: Alarmo - after Arm
sequence:
- if:
then:
- service: input_select.select_option
target:
entity_id:
- input_select.vr_cuisine_immediate
- input_select.vr_marie_immediate
- input_select.vr_baie_immediate
- input_select.vr_sejour_immediate
- input_select.vr_antoine_immediate
- input_select.vr_lionel_immediate
data:
option: Automatique
- if: "{{ is_state('alarm_control_panel.alarmo', 'armed_away') }}"
then:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.alarmo_armed_away
- if: "{{ is_state('alarm_control_panel.alarmo', 'armed_vacation') }}"
then:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.alarmo_armed_vacation
- delay: "00:02:30"
- service: input_select.select_option
target:
entity_id:
- input_select.vr_cuisine_immediate
- input_select.vr_marie_immediate
- input_select.vr_baie_immediate
- input_select.vr_sejour_immediate
- input_select.vr_antoine_immediate
- input_select.vr_lionel_immediate
data:
option: Manuel
- if: "{{ is_state('alarm_control_panel.alarmo', 'armed_home') }}"
then:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.alarmo_armed_home
entity_id: input_boolean.alarmo_armed_away
Et au retour sur le disarm :
- Je repasse les
input_boolean:
à off
- Je repasse tous les volets en automatique afin que les conditions courantes prennent effet.
- Et si ma fille ou mon fils sont présents présente je vais basculer leurs volets en manuel afin qu'ils soient gérés comme bon leur semble. Mais j'attend un peu afin que l'automatisation du volet le place dans la position de la contrainte en cours.
script:
alarmo_after_to_disarm:
alias: Alarmo - after Disarm
sequence:
- if:
then:
- service: input_boolean.turn_off
target:
entity_id:
- input_boolean.alarmo_armed_away
- input_boolean.alarmo_armed_vacation
- input_boolean.alarmo_armed_home
- service: input_select.select_option
target:
entity_id:
- input_select.vr_cuisine_immediate
- input_select.vr_marie_immediate
- input_select.vr_baie_immediate
- input_select.vr_sejour_immediate
- input_select.vr_antoine_immediate
- input_select.vr_lionel_immediate
data:
option: Automatique
- if: "{{ is_state('input_boolean.presence_marie', 'on') }}"
then:
- delay: "00:01:30"
- service: input_select.select_option
target:
entity_id:
- input_select.vr_marie_immediate
data:
option: Manuel
- if: "{{ is_state('input_boolean.presence_antoine', 'on') }}"
then:
- delay: "00:01:30"
- service: input_select.select_option
target:
entity_id:
- input_select.vr_antoine_immediate
data:
option: Manuel
Ensuite il me reste qu'à configurer la contrainte dans l'automatisation, et surtout de la placer en priorité (la première).
- conditions:
- condition: state
entity_id: input_boolean.alarmo_armed_away
state: "on"
sequence:
- service: input_number.set_value
target:
entity_id: input_number.vr_cuisine_planned_position
data:
value: "{{ states('input_number.vr_global_position_alarm') }}"
- service: input_text.set_value
target:
entity_id: input_text.vr_cuisine_condition
data:
value: "Condition : Alarmo Away - {{ states('input_number.vr_global_position_alarm') }} %"
J'ai deux positions d'alarme, ARMED_AWAY et ARMED_VACATION. J'utilise la première quand que pars quelques heures, ça laisse certains volets entrouverts afin de simuler une présence avec d'autres artifices, et la seconde pour une fermeture totale.
Le débrayage
Les automatismes c'est bien, mais si mes enfants sont ici en vacances ou des amis occupent leurs chambres, je ne voudrais pas qu'un automatisme les sortent du lit à l'aube. Pour mes enfants qui disposent de l'application Home Assistant je pourrait imaginer un automatisme, mais on va oublier et leur laisser de la liberté, d'autant plus que s'agissant d'amis je ne vais pas leur imposer ma domotique.
Par contre je dispose facilement de leur date de départ et d'arrivée et une automation bascule déjà un input_boolean: qui sert au chauffage. Je vais donc m'en servir pour passer le volet de leur chambre en mode manuel :
automation:
- id: a800970c-9bf4-48ce-aedg-a67c29093eb3
description: Change vr_marie_immediate
alias: VR Global - Change mode VR Marie
mode: restart
trigger:
- platform: state
entity_id: input_boolean.presence_marie
action:
- choose:
- conditions:
- condition: state
entity_id: input_boolean.presence_marie
state: "on"
sequence:
- service: input_select.select_option
target:
entity_id:
- input_select.vr_marie_immediate
data:
option: Manuel
- conditions:
- condition: state
entity_id: input_boolean.presence_marie
state: "off"
sequence:
- service: input_select.select_option
target:
entity_id:
- input_select.vr_marie_immediate
data:
option: Automatique
Enfants et amis commanderont donc leur volets avec la petite télécommande de leur chambre.
Suspension
Si vous êtes arrivés là et que vous avez lors de la configuration des BluePrint's la durée de suspension vous vous demandez peut être de quoi il s'agit. En fait configure là le durée pendant laquelle l'automatisme sera suspendu. Imaginons que celle ci est réglée du 60 minutes, il est 13 heures, le soleil frappe fort et vous décidez de déjeuner dans le cuisine. Vous remontez le volet avec la télécommande (ou l'application), il restera levé le temps de manger (suspension de 60 minutes) et l'automatisme reprendra le dessus ensuite avec la contrainte idoine... Magique !
Conclusion
Tout cela m'a pris un peu de temps et j'ai servi de cobaye dans la phase de test d'appréhension de la solution que Fabien viens de mettre à disposition. Quand vous aurez parfaitement validé le fonctionnement souhaité sur un volet pour pourrez le dupliquer sur l'ensemble des volets.
Pour cela il faut :
- Dupliquer le fichier qui contient les informations propres à chaque volet (mes fichiers sont ici) et changer l'
ID:
de l'automation.
- Repérer les informations des 3 BluePrint's du premier volet dans le fichier
/config/automations.yaml
, les dupliquer à la suite en changeant les informations propres à chaque volet et les ID:
. Si vous ne le sentez pas configurez les BluePrint's individuellement à la main.
- Vérifier une fois de plus que tous les
ID:
ont bien été changés. J'insiste sur ce point car ça peut être la cause de bien des dysfonctionnements. Vous trouverez ici un générateur d'UUID.
- Redémarrer Home Assistant
- S'armer de patience car ce que l'on imagine parfait pour le premier volet ne le sera pas nécessairement pour les autres.
- Et surtout tester toutes les conditions car il sera désagréable de voir s'ouvrir le volet de la chambre quand on dort (vécu) voir certains volets ne pas se fermer sur l'alarme enclenchée quand on part que l'on est déjà en retard (vécu avec obligation de tous les passer en mode manuel et de les baisser à la main).
Avec plaisir pour en parler, ici ou mieux sur ce fil HACF.
Sources