Après deux hivers à régler mes thermostats un par un selon l’heure et le jour, j’ai fini par tout déléguer à Home Assistant : plannings automatiques, pause à distance et notifications Telegram. Voici le setup complet, bugs inclus.
Avant l’automatisation, mon rituel du matin ressemblait à ça : allumer le salon avant le café, penser à couper le bureau si je n’étais pas en télétravail, et découvrir le soir que la chambre était restée en éco toute la journée pour rien. Rien de dramatique, mais assez d’énergie mentale gaspillée pour que je décide d’y passer un weekend de configuration YAML plutôt que d’y penser pendant six mois d’hiver.
Le contexte
Cinq pièces, cinq thermostats Watts Vision (une marque de vannes connectées assez répandue, pas franchement conçue pour l’automatisation poussée : tout passe par une API cloud, pas de contrôle local direct). Le matériel est resté le même depuis le début, ce qui a limité mes choix : impossible de récupérer des données fines comme la puissance instantanée par vanne, tout doit transiter par l’intégration custom installée via HACS.
La contrainte principale n’était donc pas le budget mais le rythme de vie : télétravail deux à trois jours par semaine, un weekend qui commence dès le vendredi soir dans les faits, et des pièces qui n’ont clairement pas la même vocation (le salon vit toute la journée, le bureau seulement en télétravail, les chambres surtout le soir). Un planning fixe façon thermostat programmable classique n’aurait jamais collé à ça.
L’implémentation
Un planning par type de journée
Le cœur du système repose sur un helper input_select à trois états (Semaine, Weekend, Télétravail), déterminé automatiquement chaque nuit à minuit et une, et sur des schedule Home Assistant natifs, un par pièce et par type de jour. Un script central applique ensuite la bonne consigne selon la combinaison type de jour + état du planning :
script:
appliquer_plannings_chauffage:
sequence:
- choose:
- conditions:
- condition: state
entity_id: input_select.chauffage_type_jour
state: "Semaine"
sequence:
- service: climate.set_hvac_mode
target:
entity_id: climate.thermostat_salon
data:
hvac_mode: >
{{ 'heat' if is_state('schedule.chauffage_salon_semaine','on')
else 'off' }}
- conditions:
- condition: state
entity_id: input_select.chauffage_type_jour
state: "Télétravail"
sequence:
- service: climate.set_hvac_mode
target:
entity_id: climate.thermostat_bureau
data:
hvac_mode: >
{{ 'heat' if is_state('schedule.chauffage_bureau_teletravail','on')
else 'off' }}
Ce script est appelé à chaque changement de schedule et à chaque changement de type de jour. Simple sur le papier, mais avec cinq pièces et trois types de jours, le choose complet fait rapidement une centaine de lignes. C’est verbeux, mais lisible, et surtout facile à déboguer quand une pièce ne réagit pas comme prévu : on sait toujours quelle branche a été prise. Ce découpage par pièce suit la même logique de packages que je détaille dans l’article dédié à mon architecture YAML.
Le suivi cascade : profiter de la chaleur gratuite
C’est la partie qui m’a pris le plus de temps à concevoir, et celle qui rapporte le plus. Le principe : quand une pièce chauffe activement, la pompe à chaleur tourne déjà pour toute la maison. Les pièces voisines peuvent donc profiter de cette énergie « gratuite » en passant en confort, sans allumer réellement leur propre cycle.
J’ai mis en place trois suivis en cascade avec une priorité stricte (salon, puis chambre d’un des enfants, puis bureau) pour éviter les boucles où une pièce en réactive une autre indéfiniment :
automation:
- alias: "Chauffage - Suivi cascade Salon ON"
trigger:
- platform: state
entity_id: climate.thermostat_salon
attribute: hvac_action
to: "heating"
condition:
- condition: state
entity_id: input_boolean.chauffage_pause_active
state: "off"
- condition: state
entity_id: input_boolean.chauffage_mode_off
state: "off"
action:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.chauffage_suivi_salon
- service: climate.set_preset_mode
target:
entity_id:
- climate.thermostat_bureau
- climate.thermostat_chambre_enfant
- climate.thermostat_chambre_1
- climate.thermostat_chambre_amis
data:
preset_mode: comfort
Quatre capteurs history_stats mesurent ensuite la durée de chauffage « gratuite » gagnée par pièce, ce qui permet de vérifier que le mécanisme sert vraiment à quelque chose et pas juste à complexifier le YAML pour le plaisir.
Ne restaure jamais un état sauvegardé après une cascade ou une pause : réapplique directement le planning. Les cycles rapides de la pompe à chaleur (quelques minutes ON/OFF) polluent les sauvegardes, et tu te retrouves à restaurer un état qui n’a jamais été le « vrai » état voulu.
Les pièges rencontrés
HomeKit proposait un mode « clim » qui n’existait pas. Mes thermostats déclarent dans leurs attributs les modes chauffage, climatisation et arrêt, alors qu’il s’agit de vannes de chauffage uniquement. HomeKit affichait donc un bouton « Refroidir » fonctionnel en apparence : en réalité, la commande partait bien vers le cloud du fabricant, qui la rejetait silencieusement environ 20 secondes plus tard. Home Assistant ne recevait aucune erreur, l’appareil revenait juste tout seul en arrêt. Le correctif tient en une surcharge customize qui masque le mode inutile côté Home Assistant :
homeassistant:
customize:
climate.thermostat_salon:
hvac_modes:
- heat
- "off"
Une commande « allumer » perdue par une race condition dans l’intégration. Plus vicieux : certains soirs, allumer une pièce depuis HomeKit ou une carte thermostat ne faisait strictement rien, sans erreur visible. En creusant le code de l’intégration custom, le problème venait d’un enchaînement changement de mode puis réglage de température en une seule action : la seconde commande recalculait le mode à envoyer au cloud à partir d’un attribut local pas encore rafraîchi, et écrasait donc la première commande avec l’ancien mode « arrêt ». L’interface affichait un état optimiste pendant deux minutes avant de revenir en arrière au prochain rafraîchissement. Le correctif consiste à lire le mode depuis le cache local du device (déjà mis à jour par l’appel précédent) plutôt que depuis l’attribut d’entité périmé. Une intégration installée via un gestionnaire de paquets tiers, ça veut aussi dire qu’une mise à jour future peut faire revenir ce bug : je garde le correctif documenté pour pouvoir le réappliquer.
Le « réveil » involontaire d’une pièce après une pause. Le script qui annule une pause avait été pensé pour l’hiver : il restaure le préréglage sauvegardé avant la pause. En mode climatisation, restaurer un préréglage « éco » sur un appareil actuellement à l’arrêt le rallume carrément, cette fois en refroidissement. Résultat : une pièce qui tourne toute seule jusqu’à ce que quelqu’un s’en aperçoive. La correction ajoute une condition explicite sur la saison en cours : si on est en mode climatisation, on force l’arrêt au lieu de restaurer quoi que ce soit.
Depuis la 2026.7 : ce qui ne demande plus de YAML
Si tu pars de zéro aujourd’hui, tu n’as pas besoin de tout ce qui précède pour commencer. La mise à jour 2026.7 de Home Assistant a fait passer les triggers « orientés intention » en comportement par défaut de l’éditeur d’automatisation : un déclencheur du type « la température passe sous un seuil » existe tout fait dans l’interface, sans avoir à écrire un numeric_state à la main ni à réfléchir à l’attribut exact remonté par ton thermostat. Une automatisation simple (« si la chambre passe sous 18°C, allume le chauffage ») se construit maintenant entièrement dans l’éditeur graphique.
Ce que l’UI ne remplace pas encore aussi bien, c’est la logique à plusieurs pièces qui s’enchaînent conditionnellement, comme le suivi cascade décrit plus haut : plusieurs cibles, une priorité stricte entre elles, une condition sur la pause et sur le mode absent en même temps. C’est typiquement le genre d’enchaînement où le YAML reste plus rapide à lire et à maintenir qu’une suite de blocs graphiques. Mon conseil concret : démarre avec l’éditeur UI pour un planning par pièce basique, et ne descends en YAML que le jour où tu veux vraiment faire causer plusieurs thermostats entre eux.
Bilan et pour aller plus loin
Le système tient la route depuis plus d’un an, mais il n’est pas figé. Le planning climatisation reste volontairement désactivé cet été pour stabiliser les automations pendant que je fiabilise le reste : les thermostats gardent leurs dernières consignes manuelles, et un script « vide » a remplacé celui qui poussait les commandes automatiquement. Ce que je changerais si c’était à refaire : versionner les consignes de confort/éco par pièce dans un fichier plutôt que de les pousser à la main sur chaque appareil, ce qui m’aurait évité une bonne partie du travail de remise à plat de cet été. Si le sujet automatisations Home Assistant t’intéresse plus largement, j’ai détaillé mes préférées (lumières, volets, scènes) dans cet article.
Le prochain chantier, c’est un vrai suivi de fiabilité des changements d’état : un redémarrage de Home Assistant réinitialise l’horodatage « dernier changement » de mes thermostats, ce qui fausse tous mes rapports de suivi si je ne fais pas attention à comparer avec un historique persistant plutôt qu’avec l’état brut de l’entité.
Pourquoi ne pas utiliser un thermostat programmable classique ?
Parce que mes journées ne suivent pas un planning fixe : télétravail, weekend qui démarre le vendredi, invités ponctuels. Un planning YAML piloté par un helper s’adapte, un thermostat physique programmé non.
Le suivi cascade fait-il vraiment une différence sur la facture ?
Oui, mesurable via des capteurs dédiés : les pièces secondaires cumulent plusieurs dizaines d’heures de chauffage « gratuit » sur la saison grâce à la chaleur déjà produite pour la pièce principale.
Que se passe-t-il si je pars sans couper le chauffage ?
Un mode « vacances » coupe tous les thermostats et bloque l’application des plannings tant qu’il est actif, avec une notification quotidienne de rappel pour confirmer que c’est bien volontaire.
Faut-il coder en Python pour ce genre de setup ?
Non, tout est fait en YAML natif Home Assistant (automations, scripts, schedules, helpers). Seul le correctif d’un bug d’intégration tierce a nécessité de toucher à du Python.
Stack utilisée
- Home Assistant (automations, scripts, schedules, helpers input_boolean/input_select/input_text/input_datetime)
- Thermostats connectés Watts Vision (intégration custom installée via HACS)
- Intégration météo (prévisions à J+1 pour les suggestions de pause)
- Bot Telegram en mode sondage (notifications + boutons interactifs)
- HomeKit Bridge (exposition des thermostats, correctif de mode)
- Capteurs
history_statsettemplatepour le suivi de consommation et le gain « cascade »








