Notification anticipée d'évènement Google Calendar

Version 0.118.4
Installation Type Home Assistant Supervised
Development false
Supervisor true
Docker true
Virtual Environment false
Python Version 3.8.6
Operating System Family Linux
Operating System Version 4.4.59+
CPU Architecture x86_64
Timezone America/Mexico_City

Mon problème

Bonsoir,
Je m’arrache les cheveux pour essayer d’envoyer des notifications sur mes dispositifs AVANT l’heure de l’évènement sur le calendrier. Du style « si Visio à 14h », alors je veux émettre ma notification par exemple à 13h50.
J’ai essayé plusieurs templates dans le style de celui-ci :

value_template: "{{ ((as_timestamp(states.calendar.*MonCalendrierPerso*.attributes.**start_time**) - as_timestamp(now())) < 600) and ((as_timestamp(states.calendar.*MonCalendrierPerso*.attributes.**start_time**) - as_timestamp(now())) > 0) }}"

Le problème est que HA n’arrête pas de me dire que l’attribut start_time n’existe pas, quelque soit le calendrier que j’emploie.
Y aurait-il une ruse quelque part, dans un .yaml ou autre, pour que cet attribut soit bien reconnu ?
Car par ailleurs, j’arrive bien à récupérer par exemple l’attribut « description » pour que la notification énonce le titre du RDV. Mais le start_time semble rebelle…
Par avance, merci.

Utilise plutôt state_attr pour récupérer un attribut (documentation)

Ce qui donne :

as_timestamp(state_attr('calendar.<nom_du_calendrier>', 'start_time' ))

Et pour tout ton code :

value_template: "{{ ((as_timestamp(state_attr('calendar.<nom_du_calendrier>', 'start_time')) - as_timestamp(now())) < 600) and ((as_timestamp(state_attr('calendar.<nom_du_calendrier>', 'start_time')) - as_timestamp(now())) > 0)}}"

Bonsoir et un grand merci pour ta réponse.
Effectivement, je n’ai plus la même erreur, il me semble donc que c’est la bonne piste car en tous cas, même pour le neuneu que je suis, ça semble logique (après 5 bonnes minutes à comparer les chaîne et comprendre la différence).
Mais c’est pas encore tout rose. J’explique :

  • en tant que template dans le déclencheur d’une automatisation, pour l’instant aucun succès. Elle ne s’exécute jamais.
platform: template
value_template: >-
  value_template: "{{
  ((as_timestamp(state_attr('calendar.<nom_du_calendrier>', 'start_time')) -
  as_timestamp(now())) < 600) and
  ((as_timestamp(state_attr('calendar.<nom_du_calendrier>', 'start_time')) -
  as_timestamp(now())) > 0)}}"

Pas assez neuneu quand même pour oublier de mettre le bon <nom_du_calendrier> dans le template… N’exagérons pas.

  • dans l’éditeur de modèle (outil de développement), j’ai une erreur

TypeError: unsupported operand type(s) for -: ‹ NoneType › and ‹ float ›

Cependant, dans « Etat » de mon entité « calendar.etc », les attributs sont assez longs à s’actualiser. Donc je fait des tests avec évènement à échéance plus lointaine…
Je posterai dès que j’aurais un résultat plus convaincant.

C’est utile de poster ici !!!
En publiant mon code, je vois 2 fois value_template… Je rectifie et peut-être que ça marchera.

Tiens nous au courant, et n’hésite pas à poster le code qui fonctionne :+1:

Yes !!! Je suis enfin heureux/happy/feliz/froh !!!
Alors j’essaie d’expliquer pour les nuls comme moi :
Il faut faire attention à la façon de saisir le template selon l’endroit.

  1. directement dans le .yml par config editor
  2. dans l’automatisation en choisissant « template » comme déclencheur
  3. dans l’outil de test de template (Outil de développement → modèle)

En effet, il y a des ajouts de guillemets et backslash parasite. Le neuneu que je suis ignore pourquoi et trouve que c’est pire que la syntaxe directX testée par votre serviteur en fin des années 90. Donc, je me contente de coller ci dessous ce qui fonctionne, en précisant où je fais la saisie.
Etant donné que ça fonctionnait, j’en ai profité pour créer une entrée numérique afin de faire des tester plus facilement : le temps d’anticipation est réglable. En effet, la mise à jour depuis le calendrier de Google prend du temps, en tout cas l’actualisation de la valeur « start_time ». Ceci faisait que, malgré une syntaxe correct, j’obtenais des messages d’erreurs car les nouveaux évènements créés dans l’agenda n’avait pas encore de valeur « start_time ».
L’autre « ruse » enfin trouvé pour arriver à faire des opérations arithmétiques est de ne pas oublier le | int qui force à la conversion en valeur numérique, et non plus en chaîne (je suppose).
Assez causé. Ce qui marche :

  1. dans le fichier .yml (noter l’ajout de "\" au début puis sa fermeture en fin). Je colle depuis « trigger » pour que les identations apparaissent clairement à tous.
  trigger:
  - platform: template
    value_template: "\"{{\n  ((as_timestamp(states.calendar.<moncalendrier>.attributes.start_time)\n\
      \  - as_timestamp(now())) < 60) and\n  ((as_timestamp(states.calendar.<moncalendrier>.attributes.start_time)\n\
      \  - as_timestamp(now())) > 0) }}\""
  1. dans le template de automatisation
{{ ((as_timestamp(state_attr('calendar.<moncalendrier>', 'start_time')) - as_timestamp(now())) < (states.input_number.minavant.state | int)*60) and ((as_timestamp(state_attr('calendar.<moncalendrier>', 'start_time')) - as_timestamp(now())) > 0)}}
  1. Dans « modèle »
value_template: {{ ((as_timestamp(state_attr('calendar.<moncalendrier>', 'start_time')) - as_timestamp(now())) < (states.input_number.minavant.state | int)*60) and ((as_timestamp(state_attr('calendar.<moncalendrier>', 'start_time')) - as_timestamp(now())) > 0)}}

Evidement, la chaîne est à remplacer par la vôtre.

Aïe Aïe Aïe… :sweat_smile: Quelques petites précisions !

Pour commencer : :+1: merci d’avoir partagé ton retour d’expérience car cela permet de voir les difficultés rencontrés par les nouveaux utilisateurs :clap: .


:face_with_monocle:

Ca c’est parce que dans le champ libre de remplissage de ton modèle (template) tu as commencé et fini par le caractère ". C’est effectivement le caractère d’englobement des modèles mais l’interface graphique va te les ajouter pour toi donc les deux \" sont en faite la combinaison de \ (qui est le caractère d’évitement, signalant à l’interpréteur de code de ne pas tenir compte du caractère suivant, mais de l’afficher tout de même à l’utilisateur) et du caractère " (qui est non pris en compte grâce au caractère le précédent).

Ce fichier n’a pas pour vocation d’être édité à la main. Ce fichier est géré par l’interface graphique et est généralement pollué d’information graphique.
Par exemple :

     value_template: "\"{{\n  ((as_timestamp(states.calendar.<moncalendrier>.attributes.start_time)\n\
      \  - as_timestamp(now())) < 60) and\n  ((as_timestamp(states.calendar.<moncalendrier>.attributes.start_time)\n\
      \  - as_timestamp(now())) > 0) }}\""

équivaut à (au saut de ligne près):

     value_template: |
      {{ 
        (
          (as_timestamp(states.calendar.<moncalendrier>.attributes.start_time) - as_timestamp(now())) < 60
        ) 
        and
        (
          (as_timestamp(states.calendar.<moncalendrier>.attributes.start_time) - as_timestamp(now())) > 0
        )
      }}

Tu as des informations uniquement utilisées par l’interface graphique qui polluent la lecture.
Par contre, si tu passe par l’interface graphique pour afficher le code que tu présente, tu n’as plus de pollution avec les \n et les évitements :


Je t’ai conseillé d’utiliser state_attr pour récupérer la valeur d’un attribut.
Tu devrais relire la documentation au calme pour utiliser également states(<entité>) au lieu de states.<entité>.state comme le préconise ladite documentation, elle t’indique également que le type de donnée récupérée est une chaine de caractère (string).

Je viens de l’expliquer juste dessus que le type récupéré est une chaine de caractère donc effectivement tu dois utiliser un filtre (filter) pour le convertir en un nombre.
|int fonctionne dans ton cas, mais tu soustrait un float avec un integer. tu devrais utiliser la même base pour tout ton calcule :

{{ ((as_timestamp(state_attr('calendar.<moncalendrier>', 'start_time')) - as_timestamp(now()))|int < (states.input_number.minavant.state | int)*60) and ((as_timestamp(state_attr('calendar.<moncalendrier>', 'start_time')) - as_timestamp(now()))|int > 0)}}

J’ai fini mes remarques qui n’ont pour but que de te faire progresser !
Je salue encore une fois t’a démarche de recherche et de partage :+1: :heart:

1 J'aime

Bonjour messieurs,

Sur le même principe, à mes débuts récents de HA…je voulais récupérer TOUS les evenements d’un calendrier pour me les envoyer à la date du jour…j’ai jamais réussi :wink: J’ai abdiqué , j’avais trop de choses à appréhender en meme temps :wink:

c’est un truc que je n’ai pas le temps de faire ni les compétences…
je voudrais avoir tous les évènements du mois à venir d’un calendrier google…

ah ben je suis pas le seul à vouloir cela :wink:

Je vais jeter un oeil -) merci
Mais je prefere toujours rester en mode HA pur, moins de dependances :wink: a un tiers. Je n’ai encore jamais trop regardé du côté de appdaemon

Je n’ai jamais trop poussé non plus avec l’API voire pas du tout, mais sinon, avec un script sur google direct qui envoie les infos d’un calendrier dans un input_text ou une variable par exemple.
puis on s’envoie la valeur .

Bonsoir,
Je relierai avec beaucoup d’attention les explications de Clemalex surtout la différence entre state_attr et states.<entité>.state
J’ai fait tant d’essais que je m’y suis perdu.

Je vais chercher une solution pour pepite car j’ai besoin d’un truc similaire (juste sur la journée, pour les visio de ma fille qui est bien tête en l’air…). Mais plus tard car j’ai « encore plus urgent » avant.
For…next, c’est inconnu en Yaml, pas vrai ?

1 J'aime

https://jinja.palletsprojects.com/en/2.11.x/

The next two statements result in the same value if the state exists. The second one will result in an error if the state does not exist.

à traduire par :

Les deux instructions suivantes donnent la même valeur si l’état existe. Le second entraînera une erreur si l’état n’existe pas.

{{ states('device_tracker.paulus') }}
{{ states.device_tracker.paulus.state }}

Merci, c’est aussi sur ma ToDoList, mais pas pour maintenant :wink: Je joue avec des blueprints…:wink:

1 J'aime

Bonjour,
Pour information, je fais maintenant aussi annoncer l’heure de l’évènement. Après avoir bien galéré pour trouver comment faire afficher cette heure sous la forme HH:MM (sans la date ni les secondes), je publie la solution trouvée qui peut en aider d’autres :

{{strptime(state_attr('calendar.<nom_du_calendrier>', 'start_time'),'%Y-%m-%d %H:%M:%S').strftime('%H:%M')}}
Cette chaîne peut être précédée de texte pour être lue par alexia.media, comme par exemple :
Rendez-vous pour toto à {{strptime(state_attr('calendar.<nom_du_calendrier>', 'start_time'),'%Y-%m-%d %H:%M:%S').strftime('%H:%M')}}

Précision supplémentaire :
J’avais aussi tenté sans succès les mises en forme de type :
|timestamp_custom('%H:%M')
après la fonction strptime mais j’ignore pourquoi elles n’ont pas fonctionné.


strptime(state_attr('calendar.<nom_du_calendrier>', 'start_time'),'%Y-%m-%d %H:%M:%S')

Cette ligne convertie un TEXTE en OBJET DATETIME
La fonction strftime utilisée sur un OBJET DATETIME permet de le formatter (dans ton exemple HH:MM).

Le filtre timestamp_custom prends en entrée un TIMESTAMP, il te faut donc CONVERTIR ton OBJET DATETIME avant d’utiliser le filtre :

as_timestamp(OBJET_DATETIME) |timestamp_custom('%H:%M')

C’est pour l’explication :wink:

Pour approfondir tes connaissance, tu peux travailler avec seulement des TEXTE (je préfère de mon côté utiliser la méthode que tu décrit car elle est plus compréhensible à la lecture du code :+1: , c’est juste pour aborder la fonction SPLIT :innocent: qui amène le même résultat) :

{{(state_attr('calendar.<nom_du_calendrier>','start_time')+'s').split()[1].split(':00s')[0]}}

L’astuce consiste à ajouter un caractère en fin de texte +'s' qui servira de délimiteur pour écarter les secondes (la date est écartée avec .split() qui équivaut à split(' ')

PS:
Maintenant que tu as un OBJET DATETIME, pour ton déclencheur (trigger) tu peux l’utiliser en ajoutant un timedelta() ,toujours dans une optique de facilité de lecture de code:

strptime(state_attr('calendar.<nom_du_calendrier>', 'start_time'),'%Y-%m-%d %H:%M:%S') - timedelta(minutes: 10)

Merci @Clemalex ! Si tu savais à quel point j’apprécie tes informations à chaque fois !!! Pas toujours le temps de répondre pour le dire, mais MERCI !

Bon, là, j’ai pas encore bien compris les split car il y en a 2 successifs et impossible de trouver ce que sont les crochets. J’ai installé Python pour essayer de reproduire ça et comprendre l’influence des paramètres entre crochets mais visiblement ma syntaxe n’est pas bonne (me manque un objet et ou autres erreurs). J’ai pigé pour les délimiteurs mais pas les crochets. Tu pourrais m’aiguiller STP ?

:+1: :hacf:

Tu peux tout faire depuis Outils de développement → Onglet MODELE :+1: (ou sur https://repl.it/languages/python3 par exemple)

Les crochets sont utilisé pour récupérer un élément d’un tableau.

Lorsque tu utilise la fonction split(), cela te renvoi un tableau:

{{(state_attr('calendar.<calendrier>','start_time')+'s').split()}}

renvoi :

C’est donc un tableau qui peut s’écrire :

["2021-03-06", "10:00:00s"]

C’est un tableau contenant 2 éléments (0 et 1).

Donc si on veut extraire le 2ème élément on écrira :

{{["2021-03-06", "10:00:00s"][1]}}

ce qui donnera

Donc au final en une étape, on retombe sur la formule que je t’ai fournie (juste le premier split, il en faut un seconds pour enlever les secondes):

2 J'aime