Messages : 3,513
Sujets : 45
Inscription : Mar 2013
11/01/2025, 17:34:44
(Modification du message : 11/01/2025, 18:04:24 par Ives.)
Bonjour,
Ce tuto (Low code) traite l'envoi d'une notification sur le smartphone pour rappeler le changement du filtre en amont de l'adoucisseur avec un pictogramme dans le Dashboard qui clignotera en rouge jusqu'à l'acquittement (effectué manuellement une fois le filtre remplacé).
Il pourra facilement être adapté et éventuellement complété comme indiqué ici par XeNo.
1) Utilisation du calendrier Home Assistant
- Dans HA/calendrier, créer un calendrier local "Test Filtre adoucisseur"
- dans la fenêtre à gauche, cocher le calendrier puis cliquer sur "Ajouter un évènement" (en bas à droite),
ajuster la périodicité si l'une de celles proposées convient mais, dans l'exemple, le filtre est changé 3 fois par an donc je crée un évènement unique qui sera dupliqué manuellement 3 fois pour l'année (et éventuellement plus pour les années suivantes)
2) Créer une entrée booléenne
- Dans HA/Paramètres/Appareils et Services/Entrée, cliquer sur "Créer une entrée", puis '"Interrupteur" et compléter :
3) Créer une automatisation
- Dans HA/Automatisations et Scènes/Automatisation, cliquer sur "Créer une automatisation" puis "Créez une nouvelle automatisation (vide)" ;
- sélectionner les 3 points en haut à droite puis "modifier en yaml"
- effacer le code et le remplacer par celui ci-dessous :
Code : alias: test notification changement filtre adoucisseur
description: >-
Envoie une notification lorsque calendar.test_filtre_adoucisseur passe de
désactivé à activé.
triggers:
- entity_id: calendar.test_filtre_adoucisseur
from: "off"
to: "on"
trigger: state
conditions: []
actions:
- data:
title: Changement du filtre requis
message: >-
Il est temps de changer le filtre de l'adoucisseur. Merci d'acquitter
une fois terminé.
action: notify.mobile_app_iphone_y
- action: input_boolean.turn_on
target:
entity_id: input_boolean.test_acquittement_changement_filtre_adoucisseur
data: {}
mode: single
- Enregistrer et renommer "test notification changement filtre adoucisseur"
- Cliquer sur HA/Outils de développement/onglet YAML/ AUTOMATISATIONS pour redémarrer les automatisations.
4) Dans le Dashboard
Le pictogramme clignote en rouge lorsque le filtre est à changer et une fois celui-ci remplacé, il faut cliquer sur le pictogramme pour acquitter.
- Dans une vue du Dashboard, ajouter une carte "Manuel" ; effacer la 1ère ligne puis coller le code suivant:
Code : type: custom:button-card
state:
- value: "on"
color: red
icon: mdi:air-filter
styles:
icon:
- animation:
- blink 1s linear infinite
- value: "off"
color: null
tap_action:
action: toggle
entity: input_boolean.test_acquittement_changement_filtre_adoucisseur
icon: mdi:air-filter
name: Filtre Adoucisseur
C'est une carte custum-card-button (à installer avec HACS)
Pour tester immédiatement le fonctionnement, il suffit d'ajouter un évènement dans le calendrier "Test filtre adoucisseur" dont le début est quelques minutes après l'heure de test (pour acquitter il faut attendre au moins une minute).
Pour supprimer un calendrier local :
- dans HA/Appareils et services/Intégrations, sélectionner l'intégration "Calendrier local"
- cliquer sur les 3 points situés à droite du nom du calendrier à supprimer, puis "supprimer".
Messages : 516
Sujets : 24
Inscription : Feb 2020
Merci pour le tuto c'est sympa !
En fait ici c'est le fonctionnement inverse de celui que j'ai proposé. C'est des dates fixes qui envoient une notif pour réinitialiser.
Il faudrait mixer les 2 versions, des cartes intelligentes avec détection de temps/volumes qui envoient une notif quand il faut changer le/les filtres.
Je vais tenter d'ajouter la notification à tout ça.
Messages : 3,513
Sujets : 45
Inscription : Mar 2013
Bonjour,
Modification avec une carte qui affiche la date à laquelle le filtre a été remplacé et le volume filtré depuis le dernier remplacement.
![[Image: 049j.jpg]](https://zupimages.net/up/25/07/049j.jpg)
Lorsqu'on clique sur la carte :
- un clavier s'affiche pour entrer le code afin de déverrouiller la carte ; cette étape supplémentaire permet d'éviter une RAZ non souhaitée (à installer avec HACS https://github.com/iantrich/restriction-card) ;
un second clic provoque :
- le remplacement de la date par la date du jour
- la RAZ de la consommation depuis le dernier remplacement
Code d'une des cartes :
Code : type: custom:restriction-card
restrictions:
confirm: null
pin:
text: Entrez le code
code: 1234
card:
type: custom:button-card
icon: mdi:air-filter
name: Puits 25 u + Charbon
entity: input_text.date_changement_filtres_puits
show_state: true
tap_action:
action: call-service
service: script.raz_et_maj_date
styles:
card:
- height: 120px
- background: none
icon:
- color: var(--primary-color)
- width: 40px
- margin-right: 0px
name:
- font-size: 16px
- color: white
- padding-left: 10px
state:
- font-size: 12px
- color: yellow
- padding-left: 10px
state_display: |
[[[
return "<span style='color: white;'>Changé le : </span>" + states['input_text.date_changement_filtres_puits'].state +
"<br><span style='color: white;'>Conso. depuis cette date : </span>" + states['sensor.conso_eau_totale_changement_filtres_puits'].state + " L";
]]]
Il faut un input_texte dans le fichier configuration.yaml
Code : input_text:
date_changement_filtres_puits:
name: Date Changement Filtres Puits
max: 10
Le code du sensor contenant la consommation dans knx_sensor.yaml
Code : #Conso eau TOTALE depuis changement des filtres puits
- name: conso_eau_totale_changement_filtres_puits
state_address: "7/4/2"
type: "volume_liquid_litre"
state_class: total_increasing
Et un script (dans le fichier scripts.yaml) qui envoie la RAZ au compteur (dans mon cas, un objet avec DPT 1.015 dans la GA 7/4/3) et qui écrit la date du jour dans le "input_texte"
Code : ################################################
# RAZ Conso eau + date changement filtres puits #
################################################
raz_et_maj_date:
alias: "RAZ consommation + mise à jour date"
sequence:
- service: knx.send
data:
address: "7/4/3"
payload: "RESET"
type: "DPT1.015"
- delay: "00:00:01"
- service: input_text.set_value
target:
entity_id: input_text.date_changement_filtres_puits
data:
value: "{{ now().strftime('%d-%m-%Y') }}"
mode: single
Remarque :
Pour la mise au point, notamment pour vérifier que la date change bien, on peut utiliser l'onglet ACTIONS dans les outils de développement pour entrer une date différente de la date du jour.
1) Dans le champ "Action", saisir "input_text.set_value"
2) Copier ce code suivant dans la zone en dessous d'Action
Code : action: input_text.set_value
data:
value: 01-02-2025
target:
entity_id: input_text.date_changement_filtres_puits
3) Cliquer sur "Exécuter l'action"
Messages : 516
Sujets : 24
Inscription : Feb 2020
Salut Yves,
Pas mal tout ça !
Au final c'est la même chose que mes cards ici, tu n'as juste pas la mise en forme card mod en template (c'est ce qui consomme le plus de ligne de code au final)
Par contre si je comprends bien ton code là, tu reinitialises ton compteur d'eau knx ? Le global ? Ca ne fausse pas ton comptage général ?
J'avais utilisé un compteur HA dédié dans mes scripts/cards pour ne pas toucher ce qui vient du KNX.
Messages : 516
Sujets : 24
Inscription : Feb 2020
12/02/2025, 18:48:52
(Modification du message : 12/02/2025, 19:00:24 par XeNo.)
Rappel de l'autre manière de faire
Avec gestion d'un calendrier qui garde en mémoire les changements et qui permet aussi d'avoir un choix dans le type de filtre.
Le visuel
Les Cards :
Toujours dynamiques (c'etait avant le double filtre, mais c'est pareil)
En cliquant dessus pour changer le/les filtre(s) :
Le choix du filtre :
L'entrée agenda qui est générée (qui s'adapte si on change l'un des filtres ou les 2)
Messages : 3,513
Sujets : 45
Inscription : Mar 2013
(12/02/2025, 18:46:33)XeNo a écrit : Salut Yves,
Pas mal tout ça !
Au final c'est la même chose que mes cards ici, tu n'as juste pas la mise en forme card mod en template (c'est ce qui consomme le plus de ligne de code au final)
Par contre si je comprends bien ton code là, tu reinitialises ton compteur d'eau knx ? Le global ? Ca ne fausse pas ton comptage général ?
J'avais utilisé un compteur HA dédié dans mes scripts/cards pour ne pas toucher ce qui vient du KNX.
J'ai deux compteurs KNX (réseau et puits) et j'utilise pour cette fonctionnalité des registres partiels ; les registres utilisés pour les consommations ne sont donc pas impactés.
L'avantage de le faire en KNX c'est qu'en cas de plantage de HA/NUC les index seront toujours là (de plus, j'utilise un Zennio KCI qui dispose d'une batterie pour continuer à compter les impulsions en cas de coupure secteur).
Messages : 3,513
Sujets : 45
Inscription : Mar 2013
12/02/2025, 19:00:58
(Modification du message : 12/02/2025, 19:01:24 par Ives.)
@XeNo, c'est bien d'avoir complété le tuto ; ça donne le choix entre un traitement par KNX et un par HA !
Messages : 516
Sujets : 24
Inscription : Feb 2020
12/02/2025, 19:05:00
(Modification du message : 12/02/2025, 19:38:57 par XeNo.)
Pour faire tout ça :
1re étape :
Creer un calendrier HA, soit local, soit Google, soit ce que vous voulez.
2ème étape :
Creer les entités suivantes (ici pour 2 filtres) un input_number (pour stocker une valeur), un input_datetime (pour stocker la date)
3ème étape :
Réaliser un script qui sera actionné quand on cliquera sur la tuile, il est en 3 étapes :
1/ stocker la date du jour au moment du clic dans input_datetime
2/ stocker le cubage total au moment du clic dans input_number
3/ Creer un event agenda qui a comme nom, le type de changement de filtre (moi cuve ou ville), et en description les informations précédentes (durée de vie, cubage)
Attention, il faudra autant de scripts que de bouton lovelace souhaité (que de filtre à changer en somme)
Le script est long parce que ca gère 1 filtre, l'autre, ou les 2.
Le script qui est lancé :
Code : alias: Set Change Filtres Cuve1-2
sequence:
- if:
- condition: and
conditions:
- condition: not
conditions:
- condition: state
entity_id: input_select.liste_type_filtre_eau_cuve_1_nouveau
state: Pas de changement de filtre
- condition: not
conditions:
- condition: state
entity_id: input_select.liste_type_filtre_eau_cuve_2_nouveau
state: Pas de changement de filtre
then:
- action: calendar.create_event
target:
entity_id: calendar.filtres_eau
data:
summary: Changement filtres cuve
description: >
Premiere filtration - Le {{
states('input_select.liste_type_filtre_eau_cuve_1_courant') }} a
duré {{ (now() -
states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days
}} jours/{{ (states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') | int)
}} Litres
Deuxième filtration - Le {{
states('input_select.liste_type_filtre_eau_cuve_2_courant') }} a
duré {{ (now() -
states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days
}} jours/{{ (states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') | int)
}} Litres
start_date: |
{{ now().date() }}
end_date: |
{{ now().date() + timedelta(days=1) }}
- action: input_select.select_option
metadata: {}
data:
option: "{{states('input_select.liste_type_filtre_eau_cuve_1_nouveau')}}"
target:
entity_id: input_select.liste_type_filtre_eau_cuve_1_courant
- action: input_button.press
target:
entity_id: input_button.sensor_date_filtre_eau_cuve_1
data: {}
- action: input_number.set_value
target:
entity_id: input_number.volume_changement_filtre_cuve_1_litre
data:
value: "{{ states('sensor.volume_cuve_litre') }}"
- action: input_select.select_option
metadata: {}
data:
option: "{{states('input_select.liste_type_filtre_eau_cuve_2_nouveau')}}"
target:
entity_id: input_select.liste_type_filtre_eau_cuve_2_courant
- action: input_button.press
target:
entity_id: input_button.sensor_date_filtre_eau_cuve_2
data: {}
- action: input_number.set_value
target:
entity_id: input_number.volume_changement_filtre_cuve_2_litre
data:
value: "{{ states('sensor.volume_cuve_litre') }}"
- if:
- condition: and
conditions:
- condition: not
conditions:
- condition: state
entity_id: input_select.liste_type_filtre_eau_cuve_1_nouveau
state: Pas de changement de filtre
- condition: state
entity_id: input_select.liste_type_filtre_eau_cuve_2_nouveau
state: Pas de changement de filtre
then:
- action: calendar.create_event
target:
entity_id: calendar.filtres_eau
data:
summary: Changement filtres cuve
description: >-
Premiere filtration - Le {{
states('input_select.liste_type_filtre_eau_cuve_1_courant') }} a
duré {{ (now() -
states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days
}} jours/{{ (states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') | int)
}} Litres
start_date: |
{{ now().date() }}
end_date: |
{{ now().date() + timedelta(days=1) }}
- action: input_select.select_option
metadata: {}
data:
option: "{{states('input_select.liste_type_filtre_eau_cuve_1_nouveau')}}"
target:
entity_id: input_select.liste_type_filtre_eau_cuve_1_courant
- action: input_button.press
target:
entity_id: input_button.sensor_date_filtre_eau_cuve_1
data: {}
- action: input_number.set_value
target:
entity_id: input_number.volume_changement_filtre_cuve_1_litre
data:
value: "{{ states('sensor.volume_cuve_litre') }}"
- if:
- condition: and
conditions:
- condition: not
conditions:
- condition: state
entity_id: input_select.liste_type_filtre_eau_cuve_2_nouveau
state: Pas de changement de filtre
- condition: state
entity_id: input_select.liste_type_filtre_eau_cuve_1_nouveau
state: Pas de changement de filtre
then:
- action: calendar.create_event
target:
entity_id: calendar.filtres_eau
data:
summary: Changement filtre cuve
description: >-
Deuxième filtration - Le {{
states('input_select.liste_type_filtre_eau_cuve_2_courant') }} a
duré {{ (now() -
states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days
}} jours/{{ (states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') | int)
}} Litres
start_date: |
{{ now().date() }}
end_date: |
{{ now().date() + timedelta(days=1) }}
- action: input_select.select_option
metadata: {}
data:
option: "{{states('input_select.liste_type_filtre_eau_cuve_2_nouveau')}}"
target:
entity_id: input_select.liste_type_filtre_eau_cuve_2_courant
- action: input_button.press
target:
entity_id: input_button.sensor_date_filtre_eau_cuve_2
data: {}
- action: input_number.set_value
target:
entity_id: input_number.volume_changement_filtre_cuve_2_litre
data:
value: "{{ states('sensor.volume_cuve_litre') }}"
description: Creer une entrée agenda pour le changement des filtre eau de Cuve 1 et 2
icon: mdi:calendar-check-outline
4 et 5/ Et enfin, le code de la carte associée, le code est chargé parce qu'il y a pas mal de mise en forme conditionnelle pour les statuts d'alertes. Sans mise en forme il est tout petit.
J'ai conditionné, pour l'instant et de manière arbitraire le cubage à 10m3, il sera certainement plus haut par la suite. Par contre j'ai également mis une condition de temps, j'estime qu'à 6 mois, le filtre doit être changé pour des raisons d'hygiène évidente.
Il y a une demande de validation avec le choix du filtre, pas d'erreur de manip possible
Le code de la tuile concernée (ici double étage de filtration toujours)
Code : - type: custom:mushroom-template-card
icon: mdi:air-filter
icon_color: blue
name: Filtre changé ?
layout: vertical
primary: Etat filtres eau de cuve
tap_action:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: Changement des filtres d'eau de cuve
content:
type: custom:vertical-stack-in-card
cards:
- type: horizontal-stack
cards:
- type: vertical-stack
cards:
- type: custom:mushroom-title-card
title: null
subtitle: >-
Choisir les types de filtres qui seront
utilisés pour le remplacement puis valider.
card_mod:
style: |
ha-card {
margin-left: 30px;
margin-right: 30px;
}
- type: custom:mushroom-select-card
entity: >-
input_select.liste_type_filtre_eau_cuve_1_nouveau
name: >-
Type de filtre qui sera installé en première
filtration ?
secondary_info: none
card_mod:
style: |
ha-card {
margin-left: 30px;
margin-right: 30px;
}
- type: custom:mushroom-select-card
entity: >-
input_select.liste_type_filtre_eau_cuve_2_nouveau
name: >-
Type de filtre qui sera installé en seconde
filtration ?
secondary_info: none
card_mod:
style: |
ha-card {
margin-left: 30px;
margin-right: 30px;
}
- type: horizontal-stack
cards:
- type: custom:gap-card
- type: custom:mushroom-template-card
icon: mdi:tooltip-check-outline
primary: Valider
fill_container: false
icon_color: green
tap_action:
action: call-service
confirmation:
text: >-
Valider le changement du/des filtre(s)
d'eau de cuve maintenant ?
service: script.set_change_filtres_cuve1_2
card_mod:
style:
.: |
ha-card {
margin-top: 30px;
margin-bottom: 30px;
}
- type: custom:gap-card
secondary: "{% if ((now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days > 180) and ((now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days > 180) %}\n Vie filtre 1 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int)) / 1000) }} m³\n Vie filtre 2 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int)) / 1000) }} m³\n Filtre à changer !\n{% elif ((now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days > 180) %}\n Vie filtre 1 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int)) / 1000) }} m³\n Vie filtre 2 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int)) / 1000) }} m³\n Filtre 1 à changer !\n{% elif ((now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days > 180) %}\n Vie filtre 1 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int)) / 1000) }} m³\n Vie filtre 2 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int)) / 1000) }} m³\n Filtre 2 à changer !\n{% elif ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int) > 10000 ) and ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int) > 10000 ) %}\n Vie filtre 1 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int)) / 1000) }} m³\n Vie filtre 2 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int)) / 1000) }} m³\n Filtre à changer !\n{% elif ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int) > 10000 ) %}\n Vie filtre 1 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int)) / 1000) }} m³\n Vie filtre 2 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int)) / 1000) }} m³\n Filtre 1 à changer !\n{% elif ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int) > 10000 ) %}\n Vie filtre 1 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int)) / 1000) }} m³\n Vie filtre 2 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int)) / 1000) }} m³\n Filtre 2 à changer !\n{% elif ((((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int) < 10000) and ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int) > 8000))) or ((((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int) < 10000) and ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int) > 8000))) %}\n Vie filtre 1 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int)) / 1000) }} m³\n Vie filtre 2 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int)) / 1000) }} m³\n Changement Filtres à prévoir\n{% elif (((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int) < 10000) and ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int) > 8000)) %}\n Vie filtre 1 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int)) / 1000) }} m³\n Vie filtre 2 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int)) / 1000) }} m³\n Changement Filtre 1 à prévoir\n{% elif (((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int) < 10000) and ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int) > 8000)) %}\t\t\t\t\n Vie filtre 1 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int)) / 1000) }} m³\nVie filtre 2 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int)) / 1000) }} m³ Changement Filtre 2 à prévoir {% else %}\n Vie filtre 1 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int)) / 1000) }} m³\nVie filtre 2 : {{ (now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days }} jour(s) / {{ '%0.2f' | format(((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int)) / 1000) }} m³ {% endif %}\n"
badge_icon: >
{% if ((now() -
states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days
> 180) and ((now() -
states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days
> 180) %}
mdi:alert
{% elif ((now() -
states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days
> 180) %}
mdi:alert
{% elif ((now() -
states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days
> 180) %}
mdi:alert
{% elif ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') |
int) > 10000 ) and ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') |
int) > 10000 ) %}
mdi:alert
{% elif ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') |
int) > 10000 ) %}
mdi:alert
{% elif ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') |
int) > 10000 ) %}
mdi:alert
{% elif ((((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') |
int) < 10000) and ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') |
int) > 8000))) or ((((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') |
int) < 10000) and ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') |
int) > 8000))) %}
mdi:information-symbol
{% elif (((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') |
int) < 10000) and ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') |
int) > 8000)) %}
mdi:information-symbol
{% elif (((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') |
int) < 10000) and ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') |
int) > 8000)) %}
mdi:information-symbol
{% endif %}
badge_color: >
{% if ((now() -
states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days
> 180) and ((now() -
states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days
> 180) %}
red
{% elif ((now() -
states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days
> 180) %}
red
{% elif ((now() -
states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days
> 180) %}
red
{% elif ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') |
int) > 10000 ) and ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') |
int) > 10000 ) %}
red
{% elif ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') |
int) > 10000 ) %}
red
{% elif ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') |
int) > 10000 ) %}
red
{% elif ((((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') |
int) < 10000) and ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') |
int) > 8000))) or ((((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') |
int) < 10000) and ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') |
int) > 8000))) %}
amber
{% elif (((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') |
int) < 10000) and ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre') |
int) > 8000)) %}
amber
{% elif (((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') |
int) < 10000) and ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre') |
int) > 8000)) %}
amber
{% endif %}
multiline_secondary: true
card_mod:
style:
.: >
{% if ((now() -
states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days
> 180) and ((now() -
states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days
> 180) %}
ha-card {
animation: ping 1s infinite;
}
@keyframes ping {
0% {box-shadow: 0 0 0 0 rgba(var(--rgb-red), 0.7);}
70% {box-shadow: 0 0 0 10px transparent;}
100% {box-shadow: 0 0 0 0 transparent;}
}
{% elif ((now() -
states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days
> 180) %}
ha-card {
animation: ping 1s infinite;
}
@keyframes ping {
0% {box-shadow: 0 0 0 0 rgba(var(--rgb-red), 0.7);}
70% {box-shadow: 0 0 0 10px transparent;}
100% {box-shadow: 0 0 0 0 transparent;}
}
{% elif ((now() -
states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days
> 180) %}
ha-card {
animation: ping 1s infinite;
}
@keyframes ping {
0% {box-shadow: 0 0 0 0 rgba(var(--rgb-red), 0.7);}
70% {box-shadow: 0 0 0 10px transparent;}
100% {box-shadow: 0 0 0 0 transparent;}
}
{% elif ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre')
| int) > 10000 ) and ((states('sensor.volume_cuve_litre') |
int) -
(states('input_number.volume_changement_filtre_cuve_2_litre')
| int) > 10000 ) %}
ha-card {
animation: ping 1s infinite;
}
@keyframes ping {
0% {box-shadow: 0 0 0 0 rgba(var(--rgb-red), 0.7);}
70% {box-shadow: 0 0 0 10px transparent;}
100% {box-shadow: 0 0 0 0 transparent;}
}
{% elif ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre')
| int) > 10000 ) %}
ha-card {
animation: ping 1s infinite;
}
@keyframes ping {
0% {box-shadow: 0 0 0 0 rgba(var(--rgb-red), 0.7);}
70% {box-shadow: 0 0 0 10px transparent;}
100% {box-shadow: 0 0 0 0 transparent;}
}
{% elif ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre')
| int) > 10000 ) %}
ha-card {
animation: ping 1s infinite;
}
@keyframes ping {
0% {box-shadow: 0 0 0 0 rgba(var(--rgb-red), 0.7);}
70% {box-shadow: 0 0 0 10px transparent;}
100% {box-shadow: 0 0 0 0 transparent;}
}
{% else %}
ha-card {
padding-bottom: 15px !important;
}
{% endif %}
mushroom-badge-icon$: >
{% if ((now() -
states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days
> 180) and ((now() -
states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days
> 180) %}
.badge {
animation: ping 1s infinite;
--badge-icon-size: 22px;
--badge-size: 30px;
}
@keyframes ping {
0% {box-shadow: 0 0 0 0 rgba(var(--rgb-red), 0.7);}
50% {box-shadow: 0 0 0 10px transparent;}
100% {box-shadow: 0 0 0 0 transparent;}
}
{% elif ((now() -
states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days
> 180) %}
.badge {
animation: ping 1s infinite;
--badge-icon-size: 22px;
--badge-size: 30px;
}
@keyframes ping {
0% {box-shadow: 0 0 0 0 rgba(var(--rgb-red), 0.7);}
50% {box-shadow: 0 0 0 10px transparent;}
100% {box-shadow: 0 0 0 0 transparent;}
}
{% elif ((now() -
states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days
> 180) %}
.badge {
animation: ping 1s infinite;
--badge-icon-size: 22px;
--badge-size: 30px;
}
@keyframes ping {
0% {box-shadow: 0 0 0 0 rgba(var(--rgb-red), 0.7);}
50% {box-shadow: 0 0 0 10px transparent;}
100% {box-shadow: 0 0 0 0 transparent;}
}
{% elif ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre')
| int) > 10000 ) and ((states('sensor.volume_cuve_litre') |
int) -
(states('input_number.volume_changement_filtre_cuve_2_litre')
| int) > 10000 ) %}
.badge {
animation: ping 1s infinite;
--badge-icon-size: 22px;
--badge-size: 30px;
}
@keyframes ping {
0% {box-shadow: 0 0 0 0 rgba(var(--rgb-red), 0.7);}
50% {box-shadow: 0 0 0 10px transparent;}
100% {box-shadow: 0 0 0 0 transparent;}
}
{% elif ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre')
| int) > 10000 ) %}
.badge {
animation: ping 1s infinite;
--badge-icon-size: 22px;
--badge-size: 30px;
}
@keyframes ping {
0% {box-shadow: 0 0 0 0 rgba(var(--rgb-red), 0.7);}
50% {box-shadow: 0 0 0 10px transparent;}
100% {box-shadow: 0 0 0 0 transparent;}
}
{% elif ((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre')
| int) > 10000 ) %}
.badge {
animation: ping 1s infinite;
--badge-icon-size: 22px;
--badge-size: 30px;
}
@keyframes ping {
0% {box-shadow: 0 0 0 0 rgba(var(--rgb-red), 0.7);}
50% {box-shadow: 0 0 0 10px transparent;}
100% {box-shadow: 0 0 0 0 transparent;}
}
{% elif ((((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre')
| int) < 10000) and ((states('sensor.volume_cuve_litre') |
int) -
(states('input_number.volume_changement_filtre_cuve_1_litre')
| int) > 8000))) or ((((states('sensor.volume_cuve_litre') |
int) -
(states('input_number.volume_changement_filtre_cuve_2_litre')
| int) < 10000) and ((states('sensor.volume_cuve_litre') |
int) -
(states('input_number.volume_changement_filtre_cuve_2_litre')
| int) > 8000))) %}
.badge {
--badge-icon-size: 40px;
--badge-size: 30px;
{% elif (((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_1_litre')
| int) < 10000) and ((states('sensor.volume_cuve_litre') |
int) -
(states('input_number.volume_changement_filtre_cuve_1_litre')
| int) > 8000)) %}
.badge {
--badge-icon-size: 40px;
--badge-size: 30px;
{% elif (((states('sensor.volume_cuve_litre') | int) -
(states('input_number.volume_changement_filtre_cuve_2_litre')
| int) < 10000) and ((states('sensor.volume_cuve_litre') |
int) -
(states('input_number.volume_changement_filtre_cuve_2_litre')
| int) > 8000)) %}
.badge {
--badge-icon-size: 40px;
--badge-size: 30px;
{% endif %}
mushroom-shape-icon$: |
.shape {
--icon-symbol-size: 40px;
--icon-size: 60px;
}
mushroom-state-info$: "{% if ((now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days > 180) and ((now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days > 180) %}\n.container {\n --card-secondary-color: red;\n}\n{% elif ((now() - states('input_button.sensor_date_filtre_eau_cuve_1')|as_datetime).days > 180) %}\n.container {\n --card-secondary-color: red;\n}\n{% elif ((now() - states('input_button.sensor_date_filtre_eau_cuve_2')|as_datetime).days > 180) %}\n.container {\n --card-secondary-color: red;\n}\n{% elif ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int) > 10000 ) and ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int) > 10000 ) %}\n.container {\n --card-secondary-color: red;\n}\n{% elif ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int) > 10000 ) %}\n.container {\n --card-secondary-color: red;\n}\n{% elif ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int) > 10000 ) %}\n.container {\n --card-secondary-color: red;\n}\n{% elif ((((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int) < 10000) and ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int) > 8000))) or ((((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int) < 10000) and ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int) > 8000))) %}\n.container {\n --card-secondary-color: orange;\n}\n{% elif (((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int) < 10000) and ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_1_litre') | int) > 8000)) %}\n.container {\n --card-secondary-color: orange;\n}\n{% elif (((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int) < 10000) and ((states('sensor.volume_cuve_litre') | int) - (states('input_number.volume_changement_filtre_cuve_2_litre') | int) > 8000)) %}\t\t\t\t\n.container {\n --card-secondary-color: orange;\n}\n{% endif %}\n"
Voilà !
Messages : 516
Sujets : 24
Inscription : Feb 2020
12/02/2025, 19:10:32
(Modification du message : 12/02/2025, 19:15:05 par XeNo.)
(12/02/2025, 19:00:58)Ives a écrit : @XeNo, c'est bien d'avoir complété le tuto ; ça donne le choix entre un traitement par KNX et un par HA !
Pour envoyer le reset sur le KNX en plus de HA il suffit d'ajouter ça à mon script (en modifiant la GA concernée par le reset partiel). Ca permet d'avoir l'index sur HA ET sur le KNX
Code : - service: knx.send
data:
address: "7/4/3"
payload: "RESET"
type: "DPT1.015"
C'est pas vraiment ça qui change, c'est surtout la partie Calendrier, multi filtres, choix du filtre et dynamisme de la tuile. C'est pour ça que je dis que c'est une autre manière de faire.
Messages : 3,513
Sujets : 45
Inscription : Mar 2013
(12/02/2025, 19:10:32)XeNo a écrit : C'est pas vraiment ça qui change, c'est surtout la partie Calendrier, multi filtres, choix du filtre et dynamisme de la tuile. C'est pour ça que je dis que c'est une autre manière de faire.
J'ai bien vu et compris (et l'esthétique de tes cartes est top) mais l'idée de départ du tuto était "Low Code" ; avec cette dernière version de carte j'en ai un peu mais ça reste "raisonnable".
Messages : 516
Sujets : 24
Inscription : Feb 2020
Il faudrait fusionner les 2 méthodes pour lowcoder au max.
Le template cardmod que j'utilise est trop lourd, il faut le déporter dans un script et utiliser des variables comme tu le fais avec ton calendar.
Ajouter la strate de verrouillage avant le changement peut être interessant aussi
Par contre le calendar imposé n'est pas dynamique, si tu décales ton changement (vacances ou autres) ton entrée suivante ne bougera pas dans le temps sauf à le faire manuellement.
Je vais essayer de lowcoder mes cards en ajoutant un script qui check les conditions et set des variables (0 rien, 1 à prévoir, 2 à changer) et baser le cardmod uniquement sur ces 3 valeurs, ce devrait réduire drastiquement les conditions et sera moins lourd à l'affichage si c'est un script qui le gère.
Messages : 162
Sujets : 9
Inscription : Nov 2021
j'ai fait pas mal de choses sympas* avec Gemini qui comprend assez bien le code home-assistant si jamais. Il faut faire plusieurs itération, mais ça va de toutes façons plus vite que d'écrire le code à la main, le tester, recommencer et ainsi de suite.
(* : à partir de mon antenne météo griesser, je récupère la radiance en w/m2 et via les lux par facade, je calcule la puissance en W fourni gratuitement par le soleil en temps réel dans la maison, le tout en prenant en compte le type de verre des vitres, l'ombre portée du batiment sur les vitres et la position et l'orientation des lames des BSO, valeur que je compare ensuite avec l'apport en chaleur fourni par les sèches-serviettes et aussi le plancher chauffant sur PAC (le connecteur KNX me fourni l'info en W fourni) => c'est hors sujet sur ce thread donc je n'en dirai pas plus, mais c'est pour expliquer ce que Gemini m'a permis de faire en 2h top chrono.
Messages : 516
Sujets : 24
Inscription : Feb 2020
Partage ton experience et ton code sur un autre thread dans ce cas
|