Calcul intervalle de temps en jour pour notification

Slt à tous.
Je souhaite mettre en place une notif au bout d’un certain nombre de jours si le statut d’un device n’a pas bougé.
J’ai pensé à {{states.input_boolean.calib_ph.last_changed}} mais celui ci marche t il si on re-démarre la machine entre temps ? Il faut calculer le temps entre cette valeur de le date_time en jours et la je sèche.
Le format de date est un gros fouilli pour moi.

Salut ca va pas être simple de faire quelque chose qui est robuste à un redémarrage du serveur.

C’est vraiment nécessaire ?

@oncleben31 Beh je me renseigne déjà pour savoir si c’est faisable. Dans ce cas c’est pas absolument nécessaire.
C’est pour la calibration de ma sonde pH. Je peux eut être faire la chose autrement. En définissant la programmation d’une alerte dans les 30 jours suivant la calibration pour en redemander une. Mais toujours la même histoire que ce passe t’il après une coupure de courant.

Tout va dépendre de la robustesse que tu souhaites en fait.

Mais c’est faisable comme ci-dessous par exemple.

Mon code permet de sauvegarder dans un input_text la date du dernier changement d’état du capteur surveillé, dans un autre input_text son dernier état, et dans un dernier input_text la date du dernier démarrage de HA.

La remise à zéro de la date du dernier changement d’état se fait :

  • Au démarrage, si et seulement si l’état sauvegardé est différent de l’état actuel,
  • Au changement d’état du capteur surveillé.

La remise à zéro de la date du dernier changement d’état ne se fait pas :

  • Au démarrage, si l’état du capteur surveillé n’a pas changé

En résumé, l’entité input_text.date_dernier_evenement contient la date du dernier changement d’état du capteur sensor.capteur_surveille, ceci malgré un redémarrage du serveur HA qui aura pour effet de remettre à zéro la date du dernier enregistrement du capteur sensor.capteur_surveille.

SI vous voyez des coquilles dans le code, ne pas hésiter à le dire ! :+1:

##########################
# Utilisé pour les tests #
##########################
sensor:
  - platform: template
    sensors:
      capteur_surveille: #Le capteur que l'on surveille
        friendly_name: "capteur_surveille"
        value_template: "toto"
        device_class: timestamp
########################

#########################
# Entités accueillantes #
#########################
input_text:
  date_dernier_evenement:  #Contient la date du dernier changement d'état du capteur surveillé
    name: date_dernier_evenement
  etat_dernier_evenement:  #Contient le dernier état du capteur surveillé
    name: etat_dernier_evenement
  date_dernier_demarrage:  #Contient la date du dernier démarrage de HA
    name: date_dernier_demarrage
#########################
    
#########################
#    Automatisations    #
#########################
automation:
  - id: 'automatisation_mise_a_jour_de_la_date'
    ######################################################################################################
    # Automatisation permettant de sauvegarder la date du dernier changement d'état du capteur surveillé #
    # avec conservation de la date en cas de démarrage de HA si le même état                             #
    ######################################################################################################
    alias: automatisation_mise_a_jour_de_la_date
    trigger:
    - platform: state
      entity_id: sensor.capteur_surveille    
    - platform: homeassistant
      event: start  
    condition:
    action:
    - choose:
        - conditions:
            - condition: template
              value_template: "{{ states.sensor.capteur_surveille.last_changed != states.sensor.date_dernier_demarrage.last_changed }}"
            - condition: template
              value_template: "{{ states('input_text.etat_dernier_evenement') !=  states('sensor.capteur_surveille') }}"
          sequence:
            - data:
                entity_id: input_text.date_dernier_evenement
                value: "{{ states.sensor.capteur_surveille.last_changed }}"
              service: input_text.set_value
            - data:
                entity_id: input_text.etat_dernier_evenement
                value: "{{ states('sensor.capteur_surveille') }}"
              service: input_text.set_value
    ######################################################################################################

  - id: 'automatisation_date_du_dernier_demarrage'
    ###############################################################################
    # Automatisation qui permet de sauvegarder la date du dernier démarrage de HA #
    # utilisé comme condition pour la sauvegarde de la date du capteur surveillé  #
    ###############################################################################
    alias: automatisation_date_du_dernier_demarrage
    trigger:
      platform: homeassistant
      event: start
    condition: []
    action:
    - data:
        entity_id: input_text.date_dernier_demarrage
        value: "{{ states.sensor.capteur_surveille.last_changed }}"
      service: input_text.set_value  
    ###############################################################################

@Clemalex Merci pour ce partage.
J’ai pas encore encore mis en place le action:chose que je ne connaissais pas encore.
J’ai commencé par quelque chose de simple, à savoir enregistrer la date dans le input_text.
Là ou je bloque déjà c’est pour réutiliser cet input_text dans mon calcul.

J’ai trouvé la formule suivante qui marche très bien pour donner le nombre de jours depuis dernier déclenchement avec le capteur.

#  la formule:
{{ (utcnow().day) - (states.lecapteur.last_changed).day }}

Cependant, il ne marche pas avec le texte dû au template de ce dernier.

#  le template de l'input text :
{{ states.input_input_text.date_dernier_capteur.last_changed}} 
# donne place à : 
"<template state input_text.date_dernier_calibrage_ph=2021-01-02 09:57:05.044782+00:00; editable=False, min=0, max=100, pattern=None, mode=text, friendly_name=date_dernier_evenement @ 2021-01-02T10:57:05.069943+01:00>"

Une idée ? Faut-il convertir ce input_text en un nouveau sensor ou peut ont corriger le template donné pour pouvoir faire le calcul à la manière du bout de code suivant ?

{%- set time = (as_timestamp(now()) - as_timestamp(states.capteur.last_changed)) | int  %}
        {%- set minutes = ((time % 3600) // 60) %}
        {%- set minutes = '{}minutes'.format(minutes) if minutes > 0 else '' %}
        {%- set hours = ((time % 86400) // 3600) %}
        {%- set hours = '{}hours '.format(hours) if hours > 0 else '' %}
        {%- set days = (time // 86400) %}
        {%- set days = '{}days '.format(days) if days > 0 else '' %}
        {{ 'Less than 1 minute' if time < 60 else days + hours + minutes }} ago ```

Pas le temps de regarder aujourd’hui mais ce soir :+1:

En attendant, regarde ici, on a fait des calculs de temps.

Juste pour être sûr que l’on soit sur la même longueur d’onde.

Tu as bien compris que le code que je te donnais permet d’obtenir dans un input_text la date du dernier changement qui est toujours présente après un redémarrage ?

C’est à partir de cette entité qu’il faut faire un calcul pour avoir le nombre de jours.

La formule me permet d’avoir le nombre de jours depuis le dernier changement du capteur (qui sera en fait un bouton de validation).
Cependant il ne fonctionne que avec le l’état du
Capteur changement pas avec le input_textqui lui me permet de garder un trace en cas de redémarrage. Du moins c’est ce que j’espère.
Si je dois partir du texte pour faire le calcule je dois convertir le texte en date

Mais tu DOIS partir du texte si tu veux un truc robuste…

La conversion, ce n’est pas compliqué et on l’a introduit sur le lien que je t’ai donné plus haut.

Tu me confirme mes pensées ! Je vais étudier votre post. Merci.

Ok j’ai pigé ! C’est la syntaxe de mon template qui merdait. Merci pour ton aide @Clemalex
Je reprends le problème pour que les suivants puissent comprendre ou cela merdait pour moi.

Le principe :

Pour que les données soient ‹ sauvegardées › on créé un input_text qui prendra pour valeur la date et l’heure du dernier changement d’état capteur suivit. Ce dernier sera mis à jour via une automation qui sera lancée à chaque fois que je calibre mon ph metre (pour le moment lancé avec un input_boolean).

input_text:
  date_dernier_calibrage_ph:  #Contient la date du dernier changement d'état du boolean
    name: date_dernier_calibrage_ph

automation:
    alias: automatisation_alerte_calibration
    trigger:
    - platform: state
      entity_id: input_boolean.calib_ph
      from: 'off'            #lorsque le boolean est activé (laisse apparaitre un menu dans lovelace)
      to: 'on'
    action:
      - service: input_text.set_value
        data_template:
          entity_id: input_text.date_dernier_calibrage_ph 
          value: "{{states.input_boolean.calib_ph.last_changed}}"

(le problème à la con du à la syntaxe

Si l’état de cet input_text est correct et s’affiche que la date au format texte …

… Il n’en était pas de même pour le mauvais template qui servait dans mon le calcul :

{{states.input_text.date_dernier_calibrage_ph}}

<template TemplateState(<state input_text.date_dernier_calibrage_ph=2021-01-03 08:29:37.675220+00:00; editable=False, min=0, max=100, pattern=None, mode=text, friendly_name=date_dernier_evenement @ 2021-01-03T09:29:37.692242+01:00>)>"

Il fallait utiliser le bon template

{{states('input_text.date_dernier_calibrage_ph')}}

… qui donnera le résultat string attendu, à savoir :
2021-01-03 08:29:37.675220+00:00)

La suite du principe
Pour pouvoir générer une alerte tous les X jours après calibration, il manque encore un sensor qui prendra pour valeur le nombre de jours passés et qui servira dans l’automatisation de notification.
On passe alors part un sensor de type template qui calcule le temps en jour entre la date du jour sensor.date et la date sauvegardée dans le input_text.
Pour cela j’utilise as_timestamp qui converti le format date_time en nombre pour faciliter les calculs. Je compare la valeur actuelle (as_timestamp(now()) à la valeur de mon input-text et le converti en jours en le divisant par 86400

sensor:
  - platform: template
    sensors:
      jours_depuis_calibrage_ph:
        friendly_name: "Jours passés calibration"
        unit_of_measurement: "Jour(s)"
        icon_template: mdi:timer-sand
        value_template: '{{((as_timestamp(now()) - as_timestamp(states('input_text.date_dernier_calibrage_ph')))/86400) | int}}'

Encore merci ! :pray:

Merci pour le retour :+1:

Il manque juste l’automatisation qui alerte…

Tu peux la partager ?

L’automation arrive avec le code au complet. J’ai modifier le code avec un as_timestamp car l’autre code ne me donnait pas le nombre de jours.

J’arrives un peu tard, peut être il est possible d’utiliser History Stats - Home Assistant ?

Ai je mal compris le problème ?

Je l’utilise pour m’alerter si je n’ai pas branché la batterie de mon vélo les dernières 48h

https://github.com/clempat/home-assistant-config/blob/main/entities/sensors/battery_bike_changed_last_48h.yaml

PS: la solution précédente semble plus adaptée que celle la car il faudrait garder un historique de plus de 30 jours pour que cela marche. Ce qui n’est peut-être pas le cas… Enregistrer la date semble plus approprié car peut importe redémarrage ou history court la date sera toujours la.

@clement
Si jamais je retire la base ou qu’il y a un problème cela permet une « sauvegarde »

@clement
Tu aurais pu laisser ton post. C’est une autre manière qui est envisageable sur les petites périodes de temps.

Je l’ai remis. Je l’avais supprimé parce que je n’ai pas pu prendre le temps de l’adapter aux besoins.

@Clemalex
Pour l’automatisation qui alerte :

automation:
- alias: automatisation_sauvegarde_calibration_ph
  initial_state: 'on'
  trigger:
    platform: state
    entity_id: input_boolean.sauvegarde_calib_ph
    from: 'off'
    to: 'on'
  action:
  - service: input_text.set_value
    data_template:
      entity_id: input_text.date_dernier_calibrage_ph
      value: "{{states.input_boolean.calib_ph.last_changed}}"
  - service: input_boolean.turn_off
    entity_id: input_boolean.calib_ph
  - service: input_boolean.turn_off
    entity_id: input_boolean.sauvegarde_calib_ph

- alias: notif_Calib_ph
  initial_state: 'on'
  trigger:
    platform: time_pattern
    days : "/1"
    hours: "20"
  condition:
    condition: and
    conditions:
      - condition: template
        value_template: "{{states('sensor.jours_depuis_calibrage_ph') | int > states('input_number.interval_jour_calib')| int}}"
      - condition: state
        entity_id: person.raph 
        state: home
  action:
    service: notify.iosdevice
    data_template:
      title: "Calibration à faire !"
      message: "Il faut calibrer le pH metre. La derniere calibration remonte à {{states('sensor.jours_depuis_calibrage_ph') | int }}  jours."
      data:
        push:
          thread-id: "alerte_calibration-group"  

Voici les deux automatisations. Je vais tout rajouter au projet PH mètre dès que j’aurais fini les tests.

  • La première sert à enregistrer la valeur dans l’input_text et me remets les inputs_boolean en off.
    Le premier boolean me sert à afficher une « conditional card » qui laisse apparaitre le menu de calibration.
    Le second permet le déclenchement de l’automatisation qui enregistre en texte, referme le menu et revient lui même à sa position initiale. (il me reste encore a sauvegarder les valeurs de calibration pour les différentes solution tampon, mais c’est le même topo / date du calibrage)

  • La seconde encore en test concerne l’alerte en notification iOs sur tout mes devices:
    Tout les jours la condition est testée à 20h (c’est ce trigger qui est en test).
    Si les conditions sont réunies à savoir :

    - ma présence

    - un intervalle de calibration (sensor se basant sur l’input_text sauvegardé) plus grand que celui définie par un input_number

    Une notification iOS est envoyée.

Voilà.
Comme dit, je prévois d’intégrer le tout dans le projet PH mètre.

Le code en intégral pour cette partie sous forme d’un package.yaml qu’il me faudra fuisonner avec celui du pH mètre :

#a rajouter phmetre.yaml
########################
input_boolean:
  sauvegarde_calib_ph:
    name: "Save Calib pH"
########################
input_number:   
  interval_jour_calib:
    name: Intervale entre 2 calibrations
    min: 1
    max: 100
    step: 1
    unit_of_measurement: jours
    mode: box
########################
input_text:
  date_dernier_calibrage_ph:  #Contient la date du dernier changement d'état du capteur surveillé
    name: date_dernier_calibrage_ph
#########################   
sensor:
  - platform: template
    sensors:
      jours_depuis_calibrage_ph: #nombre de jours / input_text sauvegardé
        friendly_name: "Jours passés calibration"
        unit_of_measurement: "Jour(s)"
        icon_template: mdi:timer-sand
        value_template: >- 
          {{((as_timestamp(now()) - as_timestamp(states('input_text.date_dernier_calibrage_ph')))/86400) | int}}
########################
automation:
- alias: automatisation_sauvegarde_calibration_ph
  initial_state: 'on'
  trigger: #sauvegarde input_text, réinitialisation input_boolean, fermeture du menu
    platform: state
    entity_id: input_boolean.sauvegarde_calib_ph
    from: 'off'
    to: 'on'
  action:
  - service: input_text.set_value
    data_template:
      entity_id: input_text.date_dernier_calibrage_ph
      value: "{{states.input_boolean.calib_ph.last_changed}}"
  - service: input_boolean.turn_off
    entity_id: input_boolean.calib_ph
  - service: input_boolean.turn_off
    entity_id: input_boolean.sauvegarde_calib_ph

- alias: notif_Calib_ph
  initial_state: 'on'
  trigger: #notification ts les x jours si présent et valeur dépassée
    platform: time_pattern
#    days : "/1"
    hours: "/1"
  condition:
    condition: and
    conditions:
      - condition: template
        value_template: "{{states('sensor.jours_depuis_calibrage_ph') | int > states('input_number.interval_jour_calib')| int}}"
      - condition: state
        entity_id: person.raph 
        state: home
  action:
    service: notify.iosdevice
    data_template:
      title: "Calibration à faire !"
      message: "Il faut calibrer le pH metre. La derniere calibration remonte à {{states('sensor.jours_depuis_calibrage_ph') | int }}  jours."
      data:
        push:
          thread-id: "alerte_calibration-group"