Last active
May 13, 2025 12:34
-
-
Save mbo18/6c8222d60f41a8fcf46e27410a18403a to your computer and use it in GitHub Desktop.
Gestion filtration piscine (avancé)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
blueprint: | |
name: "Gestion filtration piscine (avancé)" | |
description: "Gestion automatique de la filtration/pompe de la piscine" | |
domain: automation | |
homeassistant: | |
min_version: 2024.6.0 | |
input: | |
temperature_piscine: | |
name: "Capteur de température de la piscine" | |
description: "La température permet de calculer la durée de filtration" | |
selector: | |
entity: | |
filter: | |
domain: sensor | |
device_class: temperature | |
multiple: false | |
switch_pompe: | |
name: "Entité de contrôle de la pompe" | |
description: "Pour pouvoir allumer et éteindre la pompe selon les heures calculées de début et fin de filtration" | |
selector: | |
entity: | |
filter: | |
domain: | |
- switch | |
- light | |
- input_boolean | |
multiple: true | |
bouton_reset: | |
name: "Bouton de reset du temps de filtration" | |
description: "Permet de (re)lancer le calcul de la durée et des horaires de filtration" | |
selector: | |
entity: | |
filter: | |
domain: input_button | |
multiple: false | |
parametres_generaux: | |
name: "Paramètres généraux" | |
icon: mdi:cog | |
input: | |
mode_filtration: | |
name: "Mode de filtration de la piscine" | |
description: > | |
Courbe : Calcul de la durée selon une courbe en fonction de la température de la piscine | |
Hivernage : Fait marcher la pompe 3h par jour si la température de l'eau est inférieure ou égale 10°C, 24h si la température est en dessous de la température hors gel et le mode hors gel est activé. Au dessus de 10°C, le temps de filtration est égal à la température de l'eau divisée par 3. | |
Automatique : Combine le mode Courbe et le mode Hivernage afin de ne pas avoir à changer de mode au cours de l'année. Le mode hivernage s'active dès que l'eau passe en dessous de la température configurée | |
Forcé : Force le fonctionnement de la pompe | |
Inactif : Coupe la pompe et la gestion de la filtration | |
selector: | |
entity: | |
filter: | |
domain: input_select | |
multiple: false | |
ajustement: | |
name: "Coefficient d'ajustement du temps de filtration" | |
description: "Permet d'influer à la baisse ou à la hausse le temps de filtration pour l'adapter à vos besoins" | |
selector: | |
entity: | |
filter: | |
domain: input_number | |
multiple: false | |
parametres_mode_courbe: | |
name: "Paramètres du mode Courbe" | |
icon: mdi:refresh-auto | |
input: | |
heure_pivot: | |
name: "Heure pivot de filtration" | |
description: "Heure autour de laquelle les horaires de filtration sont calculés" | |
selector: | |
entity: | |
filter: | |
domain: sensor | |
device_class: timestamp | |
multiple: false | |
duree_coupure: | |
name: "Durée de coupure de la filtration" | |
description: "Permet de définir une pause dans la filtration autour de l'heure pivot" | |
selector: | |
entity: | |
filter: | |
domain: input_number | |
multiple: false | |
parametres_mode_hiver: | |
name: "Paramètres du mode Hivernage" | |
icon: mdi:snowflake | |
input: | |
heure_hivernage: | |
name: "Heure pivot de filtration en hivernage" | |
description: "Heure autour de laquelle les horaires de filtration sont calculés en hivernage" | |
selector: | |
entity: | |
filter: | |
domain: sensor | |
device_class: timestamp | |
multiple: false | |
duree_coupure_hiver: | |
name: "Durée de coupure de la filtration" | |
description: "Permet de définir une pause dans la filtration autour de l'heure pivot" | |
selector: | |
entity: | |
filter: | |
domain: input_number | |
multiple: false | |
activation_hors_gel: | |
name: "Mode hors gel" | |
description: "En mode hors gel, la filtration est permanente si la température de la piscine est en dessous de la température hors gel" | |
default: "Activé" | |
selector: | |
select: | |
options: | |
- "Activé" | |
- "Désactivé" | |
temperature_hors_gel: | |
name: "Température hors gel" | |
description: "En dessous de cette température la filtration est permanente" | |
default: 1 | |
selector: | |
number: | |
min: -5 | |
max: 5 | |
step: 1 | |
unit_of_measurement: °C | |
mode: slider | |
parametres_mode_automatique: | |
name: "Paramètres du mode Automatique" | |
icon: mdi:refresh-auto | |
input: | |
temp_passage_hiver: | |
name: "Température de déclenchement du mode Hivernage" | |
description: "En dessous de cette température, activation du mode Hivernage" | |
default: 15 | |
selector: | |
number: | |
min: 0 | |
max: 20 | |
step: 1 | |
unit_of_measurement: °C | |
mode: slider | |
entites_pour_calcul: | |
name: "Entités pour stocker les données du calcul" | |
icon: mdi:database | |
input: | |
duree_filtration: | |
name: "Durée de filtration de la piscine" | |
selector: | |
entity: | |
filter: | |
domain: input_number | |
multiple: false | |
heure_debut_filtration_1_piscine: | |
name: "Heure début 1ère période de filtration" | |
selector: | |
entity: | |
filter: | |
domain: input_datetime | |
multiple: false | |
heure_fin_filtration_1_piscine: | |
name: "Heure fin 1ère période de filtration" | |
selector: | |
entity: | |
filter: | |
domain: input_datetime | |
multiple: false | |
heure_debut_filtration_2_piscine: | |
name: "Heure début 2ième période de filtration" | |
selector: | |
entity: | |
filter: | |
domain: input_datetime | |
multiple: false | |
heure_fin_filtration_2_piscine: | |
name: "Heure fin 2ième période de filtration" | |
selector: | |
entity: | |
filter: | |
domain: input_datetime | |
multiple: false | |
mode: single | |
max_exceeded: silent | |
variables: | |
temp_piscine: !input temperature_piscine | |
mode_filtration: !input mode_filtration | |
coef: !input ajustement | |
activation_hors_gel: !input activation_hors_gel | |
temp_hors_gel: !input temperature_hors_gel | |
duree_coupure: !input duree_coupure | |
duree_coupure_hiver: !input duree_coupure_hiver | |
heure_p: !input heure_pivot | |
heure_pivot: "{{ states(heure_p) | as_timestamp | timestamp_custom('%H:%M:%S') }}" | |
heure_p_h: !input heure_hivernage | |
heure_pivot_hiver: "{{ states(heure_p_h) | as_timestamp | timestamp_custom('%H:%M:%S') }}" | |
temp_passage_hiver: !input temp_passage_hiver | |
duree_de_filtration_courbe: >- | |
{# Pour assurer un temps minimum de filtration la temperature de calcul est forcée a 10°C #} | |
{% set temp = max(states(temp_piscine)|float(10), 10) %} | |
{# y = (0.00335 * temperature^3) + (-0.14953 * temperature^2) + (2.43489 * temperature) -10.72859 #} | |
{% set a = 0.00335 * states(coef)|float / 100 %} | |
{% set b = -0.14953 * states(coef)|float / 100 %} | |
{% set c = 2.43489 * states(coef)|float / 100 %} | |
{% set d = -10.72859 * states(coef)|float / 100 %} | |
{% set hours = (a * temp**3) + (b * temp**2) + (c * temp) + d %} | |
{% set minutes = (hours * 60)|round(0) %} | |
{{ min(minutes, 1440) }} | |
duree_de_filtration_hivernage: >- | |
{% set temp = states(temp_piscine)|float(10) %} | |
{% set min_duree = 240 %} | |
{% set max_duree = 1440 %} | |
{% if activation_hors_gel == 'Activé' and temp <= temp_hors_gel %} | |
{{ max_duree }} | |
{% elif temp < 10 %} | |
{{ min_duree }} | |
{% else %} | |
{{ ((temp / 3) * 60)|round(0) }} | |
{% endif %} | |
duree_de_filtration_automatique: >- | |
{% set temp = states(temp_piscine)|float(10) %} | |
{% set min_duree = 240 %} | |
{% set max_duree = 1440 %} | |
{% if activation_hors_gel == 'Activé' and temp <= temp_hors_gel %} | |
{{ max_duree }} | |
{% elif temp < 10 %} | |
{{ min_duree }} | |
{% elif temp < temp_passage_hiver %} | |
{{ ((temp / 3) * 60)|round(0) }} | |
{% else %} | |
{% set a = 0.00335 * states(coef)|float / 100 %} | |
{% set b = -0.14953 * states(coef)|float / 100 %} | |
{% set c = 2.43489 * states(coef)|float / 100 %} | |
{% set d = -10.72859 * states(coef)|float / 100 %} | |
{% set hours = (a * temp**3) + (b * temp**2) + (c * temp) + d %} | |
{% set minutes = (hours * 60)|round(0) %} | |
{{ min(minutes, 1440) }} | |
{% endif %} | |
trigger: | |
- platform: time | |
at: !input heure_debut_filtration_1_piscine | |
id: "1" | |
- platform: time | |
at: !input heure_fin_filtration_1_piscine | |
id: "2" | |
- platform: time | |
at: !input heure_debut_filtration_2_piscine | |
id: "3" | |
- platform: time | |
at: !input heure_fin_filtration_2_piscine | |
id: "4" | |
- platform: state | |
entity_id: !input bouton_reset | |
id: "5" | |
- platform: state | |
entity_id: !input mode_filtration | |
id: "6" | |
action: | |
# Calcul des heures de début et fin des périodes | |
- if: | |
- or: | |
- condition: trigger # Si fin de la 2nd période | |
id: "4" | |
- condition: trigger # Si reset | |
id: "5" | |
- condition: trigger # Si changement de mode | |
id: "6" | |
then: | |
- choose: | |
# mode Courbe | |
- conditions: | |
- condition: state | |
entity_id: !input mode_filtration | |
state: "Courbe" | |
sequence: | |
- service: input_number.set_value | |
target: | |
entity_id: !input duree_filtration | |
data: | |
value: "{{ duree_de_filtration_courbe }}" | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: !input heure_debut_filtration_1_piscine | |
data: | |
datetime: >- | |
{% set time = today_at(heure_pivot) - timedelta(minutes=duree_de_filtration_courbe/2) - timedelta(minutes=states(duree_coupure)|int/2) %} | |
{% if time < today_at("00:00:00") %} | |
{{ today_at("00:01:00") }} | |
{% else %} | |
{{ time }} | |
{% endif %} | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: !input heure_fin_filtration_1_piscine | |
data: | |
datetime: "{{ today_at(heure_pivot) - timedelta(minutes=states(duree_coupure)|int/2) }}" | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: !input heure_debut_filtration_2_piscine | |
data: | |
datetime: "{{ today_at(heure_pivot) + timedelta(minutes=states(duree_coupure)|int/2) }}" | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: !input heure_fin_filtration_2_piscine | |
data: | |
datetime: >- | |
{% set time = today_at(heure_pivot) + timedelta(minutes=duree_de_filtration_courbe/2) + timedelta(minutes=states(duree_coupure)|int/2) %} | |
{% if time > today_at("23:59:00") %} | |
{{ today_at("23:59:00") }} | |
{% else %} | |
{{ time }} | |
{% endif %} | |
# mode Automatique | |
- conditions: | |
- condition: state | |
entity_id: !input mode_filtration | |
state: "Automatique" | |
sequence: | |
- service: input_number.set_value | |
target: | |
entity_id: !input duree_filtration | |
data: | |
value: "{{ duree_de_filtration_automatique }}" | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: !input heure_debut_filtration_1_piscine | |
data: | |
datetime: >- | |
{% if states(temp_piscine)|float >= temp_passage_hiver %} | |
{% set time = today_at(heure_pivot) - timedelta(minutes=duree_de_filtration_automatique/2) - timedelta(minutes=states(duree_coupure)|int/2) %} | |
{% else %} | |
{% set time = today_at(heure_pivot_hiver) - timedelta(minutes=duree_de_filtration_automatique/2) - timedelta(minutes=states(duree_coupure_hiver)|int/2) %} | |
{% endif %} | |
{% if time < today_at("00:00:00") or duree_de_filtration_automatique == 1440 %} | |
{{ today_at("00:01:00") }} | |
{% else %} | |
{{ time }} | |
{% endif %} | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: !input heure_fin_filtration_1_piscine | |
data: | |
datetime: >- | |
{% if states(temp_piscine)|float >= temp_passage_hiver %} | |
{{ today_at(heure_pivot) - timedelta(minutes=states(duree_coupure)|int/2) }} | |
{% else %} | |
{{ today_at(heure_pivot_hiver) - timedelta(minutes=states(duree_coupure_hiver)|int/2) }} | |
{% endif %} | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: !input heure_debut_filtration_2_piscine | |
data: | |
datetime: >- | |
{% if states(temp_piscine)|float >= temp_passage_hiver %} | |
{{ today_at(heure_pivot) + timedelta(minutes=states(duree_coupure)|int/2) }} | |
{% else %} | |
{{ today_at(heure_pivot_hiver) + timedelta(minutes=states(duree_coupure_hiver)|int/2) }} | |
{% endif %} | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: !input heure_fin_filtration_2_piscine | |
data: | |
datetime: >- | |
{% if states(temp_piscine)|float >= temp_passage_hiver %} | |
{% set time = today_at(heure_pivot) + timedelta(minutes=duree_de_filtration_automatique/2) + timedelta(minutes=states(duree_coupure)|int/2) %} | |
{% else %} | |
{% set time = today_at(heure_pivot_hiver) + timedelta(minutes=duree_de_filtration_automatique/2) + timedelta(minutes=states(duree_coupure_hiver)|int/2) %} | |
{% endif %} | |
{% if time > today_at("23:59:00") or duree_de_filtration_automatique == 1440 %} | |
{{ today_at("23:59:00") }} | |
{% else %} | |
{{ time }} | |
{% endif %} | |
# mode Hivernage | |
- conditions: | |
- condition: state | |
entity_id: !input mode_filtration | |
state: "Hivernage" | |
sequence: | |
- service: input_number.set_value | |
target: | |
entity_id: !input duree_filtration | |
data: | |
value: "{{ duree_de_filtration_hivernage }}" | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: !input heure_debut_filtration_1_piscine | |
data: | |
datetime: >- | |
{% set time = today_at(heure_pivot_hiver) - timedelta(minutes=duree_de_filtration_hivernage/2) - timedelta(minutes=states(duree_coupure_hiver)|int/2) %} | |
{% if time < today_at("00:00:00") or duree_de_filtration_automatique == 1440 %} | |
{{ today_at("00:01:00") }} | |
{% else %} | |
{{ time }} | |
{% endif %} | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: !input heure_fin_filtration_1_piscine | |
data: | |
datetime: "{{ today_at(heure_pivot_hiver) - timedelta(minutes=states(duree_coupure_hiver)|int/2) }}" | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: !input heure_debut_filtration_2_piscine | |
data: | |
datetime: "{{ today_at(heure_pivot_hiver) + timedelta(minutes=states(duree_coupure_hiver)|int/2) }}" | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: !input heure_fin_filtration_2_piscine | |
data: | |
datetime: >- | |
{% set time = today_at(heure_pivot_hiver) + timedelta(minutes=duree_de_filtration_hivernage/2) + timedelta(minutes=states(duree_coupure_hiver)|int/2) %} | |
{% if time > today_at("23:59:00") or duree_de_filtration_automatique == 1440 %} | |
{{ today_at("23:59:00") }} | |
{% else %} | |
{{ time }} | |
{% endif %} | |
# mode Forcé | |
- conditions: | |
- condition: state | |
entity_id: !input mode_filtration | |
state: "Forcé" | |
sequence: | |
- service: input_number.set_value | |
target: | |
entity_id: !input duree_filtration | |
data: | |
value: 1440 | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: | |
- !input heure_debut_filtration_1_piscine | |
- !input heure_fin_filtration_1_piscine | |
- !input heure_debut_filtration_2_piscine | |
- !input heure_fin_filtration_2_piscine | |
data: | |
time: "00:00:00" | |
- service: homeassistant.turn_on | |
target: | |
entity_id: !input switch_pompe | |
# mode Inactif | |
- conditions: | |
- condition: state | |
entity_id: !input mode_filtration | |
state: "Inactif" | |
sequence: | |
- service: input_number.set_value | |
target: | |
entity_id: !input duree_filtration | |
data: | |
value: 0 | |
- service: input_datetime.set_datetime | |
target: | |
entity_id: | |
- !input heure_debut_filtration_1_piscine | |
- !input heure_fin_filtration_1_piscine | |
- !input heure_debut_filtration_2_piscine | |
- !input heure_fin_filtration_2_piscine | |
data: | |
time: "00:00:00" | |
- service: homeassistant.turn_off | |
target: | |
entity_id: !input switch_pompe | |
- if: | |
- "{{ states(mode_filtration) not in ['Forcé', 'Inactif'] }}" | |
then: | |
- choose: | |
# Demarrage de la pompe en debut de periode | |
- conditions: | |
- condition: trigger | |
id: "1" | |
sequence: | |
- service: homeassistant.turn_on | |
target: | |
entity_id: !input switch_pompe | |
- conditions: | |
- condition: trigger | |
id: "3" | |
- "{{ states(duree_coupure)|int > 0 }}" | |
sequence: | |
- service: homeassistant.turn_on | |
target: | |
entity_id: !input switch_pompe | |
# Arrêt de la pompe en fin de periode | |
- conditions: | |
- condition: trigger | |
id: "2" | |
- "{{ states(duree_coupure)|int > 0 }}" | |
sequence: | |
- service: homeassistant.turn_off | |
target: | |
entity_id: !input switch_pompe | |
- conditions: | |
- condition: trigger | |
id: "4" | |
sequence: | |
- service: homeassistant.turn_off | |
target: | |
entity_id: !input switch_pompe | |
# Si changement de mode | |
- conditions: | |
- condition: trigger | |
id: "6" | |
sequence: | |
- if: | |
- or: | |
- condition: time | |
after: !input heure_debut_filtration_1_piscine | |
before: !input heure_fin_filtration_1_piscine | |
- condition: time | |
after: !input heure_debut_filtration_2_piscine | |
before: !input heure_fin_filtration_2_piscine | |
then: | |
- service: homeassistant.turn_on | |
target: | |
entity_id: !input switch_pompe | |
else: | |
- service: homeassistant.turn_off | |
target: | |
entity_id: !input switch_pompe |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Merci beaucoup pour ce blueprint très complet.
J'aurai une petite proposition supplémentaire qui serait de rajouter un trigger en cas de changement d'état du switch qui gère la pompe de piscine pour pouvoir s'assurer que son état est bien celui attendu dans la plage horaire.
Le cas d'usage que j'imagine est par exemple un utilisateur qui se trompe et change l'état du switch depuis son Dashboard par exemple.
Il serait aussi intéressant de relancer un calcul de la filtration lorsqu'il y a un changement sur les entités d'heure pivot et de durée de coupure.