Récupération automatique du prix du kwh et de l’abonnement mensuel depuis les PDF disponibles sur EDF - PDF Scrape

Cela fonctionne pour TOUS les contrats proposés par EDF. (Offres Zen, Offres Bleu, Tempo, Offres électricité verte et Gaz naturel)

Solutions déjà données pour les contrats suivants, actuellement :

  • Tempo
  • Bleu - HP HC
  • Bleu option base
  • Zen fixe HP HC


Bonjour à tous,

Dans cet exemple, cela concerne le prix mensuel de l’abonnement EDF Zen Fixe HP/HC 9kVa, et celui des kWh, que je récupère directement sur le .PDF mis en ligne et tenu à jour sur le site d’EDF, grâce à l’intégration PDF Scrape disponible là : GitHub - iluvdata/pdf_scrape: Scrape PDF files available via http or https to create sensors in Homeassistant

En complément (optionnel - étape 6 et 7), cette méthode est basée sur le fait de mettre à jour une entrée input.number en lui changeant sa valeur en fonction de celle du capteur correspondant créé sous PDF Scrape, c’est à dire récupérée sur internet, uniquement si elle est disponible. Si indisponible, vous gardez la dernière valeur valide.

Pour cela :

ETAPE 1 : Mise en place de PDF Scrape

Après avoir installé PDF Scrape depuis HACS.
Sous Appareils&services, cliquer sur Ajouter une intégration, et recherchez « PDF Scrape», puis installez-la.


ETAPE 2 : Récupérer toutes les informations du PDF ciblé

Ici, il vous faut indiquer :

Name : Le nom de fichier PDF que HA doit lire
URL of PDF : Le lien du fichier PDF en question (doit se terminer par .pdf)
Update interval : :warning: Mettre 8760 heures, soit 1 an !

Dans mon cas, j’utilise le lien : https://particulier.edf.fr/content/dam/2-Actifs/Documents/Offres/Grille-prix-zen-fixe.pdf

Vous pourrez créer autant de Capteurs que vous le désirez à partir des informations contenues dans ce texte. C’est ainsi que l’on va pouvoir créer 3 capteurs : prix abonnement + prix kwh heures pleines + prix kwh heures creuses. Possible de récupérer la date d’application de la nouvelle tarification sous forme de capteur aussi.


ETAPE 3 : Ajouter un capteur - Add Search Target

A cette étape, vous allez créer un capteur en définissant l’endroit où se trouve la valeur désirée sur le texte en provenance du PDF.

En cliquant sur « Add Search Target ».

1°) Target Page → si le PDF a plusieurs pages, sélectionner celle contenant la valeur recherchée

2°) Regular Expression → Laisser tel quel

3°) Configure Sensor →

Name : Donner le nom du capteur voulu
Limited Template : :warning: Vous trouverez tout en bas de ce tutoriel une liste des URL + Limited Template à utiliser suivant vos contrats. Si le votre n’est pas dedans, merci d’en faire la demande, ou de partager si vous avez réussi à le faire par vous-même.
Unit of Measurement : €

Résultat pour Zen fixe HP HC, dans mon cas :



ETAPE 4 : Créer une automatisation pour tenter de mettre à jour le PDF source toutes les 12h, uniquement les 5 premiers jours de févriers et d’aout, dates auxquelles les tarifs sont mis à jour chaque année depuis 8 ans maintenant.

:warning: Attention à l’indentation, sinon erreur !! :warning:

:warning: Le device_id à mettre est celui de VOTRE configuration PDF SCRAPE

alias: Mise à jour automatique du PDF EDF
description: >-
  Va chercher la nouvelle version du PDF contenant le prix de l'abonnement et
  des kwh, entre le 1 et le 5 février et même chose en aout.
triggers:
  - trigger: time_pattern
    hours: /12
conditions:
  - condition: template
    value_template: "{{ now().month in [2, 8] and now().day in range(1, 6) }}"
actions:
  - action: homeassistant.reload_config_entry
    metadata: {}
    target:
      device_id: 184bc781f8bba3ac051606855de7bb08
    data: {}
mode: single


ETAPE 5 : Créer un capteur divisant le prix de l’abonnement mensuel par le nombre de jour du mois en cours.

Pour les abonnements uniquement, le montant étant par mois, on crée une entité Template permettant d’avoir un coût journalier.

On vient créer un capteur Template qui reprend ce cout, et l’adapte pour le diviser par le nombre de jours dans le mois en cours, avant de le multiplier par 1000, avec EUR/kWh en unité de mesure. (l’idée étant d’ajouter seulement un wh/jour via une automatisation, raison de la multiplication du prix par 1000)

{% set montant_mensuel = states('sensor.nom_du_sensor_cree_avec_pdf_scrape_pour_abonnement') | float %}
{% set now = now() %}
{% set start_of_month = now.replace(day=1) %}
{% set end_of_month = (start_of_month + timedelta(days=31)).replace(day=1) - timedelta(days=1) %}
{% set days_in_month = (end_of_month - start_of_month).days + 1 %}
{{ ((montant_mensuel / days_in_month) * 1000) | round(2) }}

Pour voir le cout journalier de l’abonnement dans la page « Energie », utiliser le tuto suivant : Ajout du cout de l'abonnement EDF/Gaz/Eau (ou autre fournisseur) au dashboard Energy - accessible à tous

:warning: Attention, sauter l’étape 1 sur celui-ci, vous venez de la faire ici. :warning:


ETAPE 6 : Optionnel → ajout d’une sécurité concernant mise à jour du capteur - Partie 1

A présent, afin de s’assurer d’avoir toujours un capteur valide, on va créer un input.number sur lequel on va transférer la valeur du capteur correspondant créé via PDF Scrape. Si 3 capteurs, alors il faudra créer 3 input_number : un pour chacun.

Pour cela, se rendre sur « Appareils&services », puis « Entrées », et cliquer sur « Créer une Entrée ».

Pour l’abonnement, par exemple, il aura pour ID : input_number.nom_du_sensor_cree_avec_pdf_scrape_pour_abonnement
Avec une valeur max de 1000, du fait que le prix de l’abonnement sera normalement toujours en dessous.


ETAPE 7 : Optionnel → ajout d’une sécurité concernant mise à jour du capteur - Partie 2

Il ne reste plus qu’à créer l’automatisation qui va prendre la valeur du capteur créé sous PDF Scrape, pour la coller sur ce nouveau capteur input.number, créé à l’étape 5, qu’on utilisera sur la page Énergie.

Et comme garde-fou, on ne fera la mise à jour que si le capteur sous PDF Scrape est valide. Dans le cas contraire, notre input_number reste lui valide.

Voici l’automatisation correspondante :

alias: "Mise à jour coût abonnement si valide dans PDF Scrape "
description: ""
triggers:
  - entity_id:
      - sensor.nom_du_sensor_cree_avec_pdf_scrape_pour_abonnement
    trigger: state
conditions:
  - condition: template
    value_template: >
      {{ not states('sensor.nom_du_sensor_cree_avec_pdf_scrape_pour_abonnement') in ['unavailable', 'unknown']
      }}
actions:
  - target:
      entity_id: input_number.nom_du_sensor_cree_avec_pdf_scrape_pour_abonnement
    data:
      value: "{{ states('sensor.nom_du_sensor_cree_avec_pdf_scrape_pour_abonnement') }}"
    action: input_number.set_value

Si vous récupérez comme moi 3 prix (abonnement + prix kwh hp et hc), il vous faudra 3 input.number, bien sûr. Et adapter l’automatisation pour qu’elle soit valide pour chacun d’eux, ou simplement faire 3 automatisations.


INFOS COMPLÉMENTAIRES :

Vous avez un capteur « propre » qui restera même si vous supprimez un jour PDF Scrape.
Enfin, tant que vous utilisez cette manière de faire, vous aurez une valeur qui ne pourra jamais être indisponible.





LISTE DES URL DES PDF et LIMITED TEMPLATE CORRESPONDANTS :

Date d’application indiquée sur le PDF :

{% set mois = {'janvier':'01','février':'02','fevrier':'02','mars':'03','avril':'04','mai':'05','juin':'06','juillet':'07','août':'08','aout':'08','septembre':'09','octobre':'10','novembre':'11','décembre':'12','decembre':'12'} %}
{% set found = namespace(date='') %}
{% for line in value.split('\n') %}
  {% if 'Applicable au' in line and found.date == '' %}
    {% set line_lower = line.lower() %}
    {% for mois_nom, mois_num in mois.items() %}
      {% if mois_nom in line_lower %}
        {% set annees = line | regex_findall('(20\d\d)') %}
        {% if annees|length > 0 %}
          {% set found.date = '01/' ~ mois_num ~ '/' ~ annees[0] %}
        {% endif %}
      {% endif %}
    {% endfor %}
  {% endif %}
{% endfor %}
{{ found.date if found.date != '' else 'Non disponible' }}

Zen Fixe HP/HC :
URL du PDF : https://particulier.edf.fr/content/dam/2-Actifs/Documents/Offres/Grille-prix-zen-fixe.pdf

  • Limited Template Abonnement mensuel 9kVa :
{% set found = namespace(val='', in_hc=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Heures Creuses' in line %}
    {% set found.in_hc = true %}
  {% endif %}
  {% if found.in_hc and found.val == '' and line.strip().startswith('9 ') %}
    {% set parts = line.strip().split() %}
    {% if parts|length >= 2 %}
      {% set found.val = parts[1] %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float) | round(2) if found.val else 0 }}

Abonnement mensuel 3, 6, 12kVa et autres :
Remplacer le 9 dans cette ligne par la puissance correspondant à votre abonnement :

{% if found.in_hc and found.val == '' and line.strip().startswith('9 ') %}
  • Limited Template kWh Heures pleines :
{% set found = namespace(val='', count=0, in_hc=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Heures Creuses' in line %}
    {% set found.in_hc = true %}
  {% endif %}
  {% if found.in_hc and found.val == '' %}
    {% set found.count = 0 %}
    {% set parts = line.strip().split() %}
    {% for part in parts %}
      {% if ',' in part %}
        {% set found.count = found.count + 1 %}
      {% endif %}
    {% endfor %}
    {% if found.count == 2 %}
      {% for part in parts %}
        {% if ',' in part and found.val == '' %}
          {% set found.val = part %}
        {% endif %}
      {% endfor %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float / 100) | round(4) if found.val else 0 }}
  • Limited Template kWh Heures creuses :
{% set found = namespace(val='', count=0, found_count=0, in_hc=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Heures Creuses' in line %}
    {% set found.in_hc = true %}
  {% endif %}
  {% if found.in_hc and found.val == '' %}
    {% set found.count = 0 %}
    {% set parts = line.strip().split() %}
    {% for part in parts %}
      {% if ',' in part %}
        {% set found.count = found.count + 1 %}
      {% endif %}
    {% endfor %}
    {% if found.count == 2 %}
      {% set found.found_count = 0 %}
      {% for part in parts %}
        {% if ',' in part %}
          {% set found.found_count = found.found_count + 1 %}
          {% if found.found_count == 2 %}
            {% set found.val = part %}
          {% endif %}
        {% endif %}
      {% endfor %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float / 100) | round(4) if found.val else 0 }}


Bleu Heures pleines heures creuses:
URL du PDF : https://particulier.edf.fr/content/dam/2-Actifs/Documents/Offres/Grille_prix_Tarif_Bleu.pdf

  • Limited Template Abonnement mensuel 9kVa :
{% set found = namespace(val='', in_hc=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Heures Creuses' in line %}
    {% set found.in_hc = true %}
  {% endif %}
  {% if found.in_hc and found.val == '' and line.strip().startswith('9 ') %}
    {% set parts = line.strip().split() %}
    {% if parts|length >= 2 %}
      {% set found.val = parts[1] %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float) | round(2) if found.val else 0 }}

Abonnement mensuel 3, 6, 12kVa et autres :
Remplacer le 9 dans cette ligne par la puissance correspondant à votre abonnement :

{% if found.in_hc and found.val == '' and line.strip().startswith('9 ') %}
  • Limited Template kWh Heures pleines :
{% set found = namespace(val='', in_hc=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Heures Creuses' in line %}
    {% set found.in_hc = true %}
  {% endif %}
  {% if found.in_hc and found.val == '' and line.strip().startswith('6 ') %}
    {% set parts = line.strip().split() %}
    {% if parts|length >= 3 %}
      {% set found.val = parts[2] %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float / 100) | round(4) if found.val else 0 }}
  • Limited Template kWh Heures creuses :
{% set found = namespace(val='', in_hc=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Heures Creuses' in line %}
    {% set found.in_hc = true %}
  {% endif %}
  {% if found.in_hc and found.val == '' and line.strip().startswith('6 ') %}
    {% set parts = line.strip().split() %}
    {% if parts|length >= 4 %}
      {% set found.val = parts[3] %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float / 100) | round(4) if found.val else 0 }}


Tempo:
URL du PDF : https://particulier.edf.fr/content/dam/2-Actifs/Documents/Offres/Grille_prix_Tarif_Bleu.pdf

  • Limited Template Abonnement mensuel 9kVa :
{% set found = namespace(val='', in_tempo=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Tempo' in line %}
    {% set found.in_tempo = true %}
  {% endif %}
  {% if found.in_tempo and found.val == '' and line.strip().startswith('9 ') %}
    {% set parts = line.strip().split() %}
    {% if parts|length >= 2 %}
      {% set found.val = parts[1] %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float) | round(2) if found.val else 0 }}

Abonnement mensuel 3, 6, 12kVa et autres :
Remplacer le 9 dans cette ligne par la puissance correspondant à votre abonnement :

{% if found.in_hc and found.val == '' and line.strip().startswith('9 ') %}
  • Limited Template kWh jour bleu HC :
{% set found = namespace(val='', in_tempo=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Tempo' in line %}
    {% set found.in_tempo = true %}
  {% endif %}
  {% if found.in_tempo and found.val == '' and line.strip().startswith('6 ') %}
    {% set parts = line.strip().split() %}
    {% if parts|length >= 3 %}
      {% set found.val = parts[2] %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float / 100) | round(4) if found.val else 0 }}
  • Limited Template kWh jour bleu HP :
{% set found = namespace(val='', in_tempo=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Tempo' in line %}
    {% set found.in_tempo = true %}
  {% endif %}
  {% if found.in_tempo and found.val == '' and line.strip().startswith('6 ') %}
    {% set parts = line.strip().split() %}
    {% if parts|length >= 4 %}
      {% set found.val = parts[3] %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float / 100) | round(4) if found.val else 0 }}
  • Limited Template kWh jour blanc HC :
{% set found = namespace(val='', in_tempo=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Tempo' in line %}
    {% set found.in_tempo = true %}
  {% endif %}
  {% if found.in_tempo and found.val == '' and line.strip().startswith('6 ') %}
    {% set parts = line.strip().split() %}
    {% if parts|length >= 5 %}
      {% set found.val = parts[4] %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float / 100) | round(4) if found.val else 0 }}
  • Limited Template kWh jour blanc HP :
{% set found = namespace(val='', in_tempo=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Tempo' in line %}
    {% set found.in_tempo = true %}
  {% endif %}
  {% if found.in_tempo and found.val == '' and line.strip().startswith('6 ') %}
    {% set parts = line.strip().split() %}
    {% if parts|length >= 6 %}
      {% set found.val = parts[5] %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float / 100) | round(4) if found.val else 0 }}
  • Limited Template kWh jour rouge HC :
{% set found = namespace(val='', in_tempo=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Tempo' in line %}
    {% set found.in_tempo = true %}
  {% endif %}
  {% if found.in_tempo and found.val == '' and line.strip().startswith('6 ') %}
    {% set parts = line.strip().split() %}
    {% if parts|length >= 7 %}
      {% set found.val = parts[6] %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float / 100) | round(4) if found.val else 0 }}
  • Limited Template kWh jour rouge HP :
{% set found = namespace(val='', in_tempo=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Tempo' in line %}
    {% set found.in_tempo = true %}
  {% endif %}
  {% if found.in_tempo and found.val == '' and line.strip().startswith('6 ') %}
    {% set parts = line.strip().split() %}
    {% if parts|length >= 8 %}
      {% set found.val = parts[7] %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float / 100) | round(4) if found.val else 0 }}

Bleu option base
URL du PDF : https://particulier.edf.fr/content/dam/2-Actifs/Documents/Offres/Grille_prix_Tarif_Bleu.pdf

  • Limited Template Abonnement mensuel 9kVa :
{% set found = namespace(val='', in_base=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Base' in line %}
    {% set found.in_base = true %}
  {% endif %}
  {% if 'Option Heures Creuses' in line %}
    {% set found.in_base = false %}
  {% endif %}
  {% if found.in_base and found.val == '' and line.strip().startswith('9 ') %}
    {% set parts = line.strip().split() %}
    {% if parts|length >= 2 %}
      {% set found.val = parts[1] %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float) | round(2) if found.val else 0 }}

  • Limited Template kWh :
{% set found = namespace(val='', in_base=false) %}
{% for line in value.split('\n') %}
  {% if 'Option Base' in line %}
    {% set found.in_base = true %}
  {% endif %}
  {% if 'Option Heures Creuses' in line or 'Option Tempo' in line %}
    {% set found.in_base = false %}
  {% endif %}
  {% if found.in_base and found.val == '' and line.strip().startswith('6 ') %}
    {% set parts = line.strip().split() %}
    {% if parts|length >= 3 %}
      {% set found.val = parts[2] %}
    {% endif %}
  {% endif %}
{% endfor %}
{{ (found.val | replace(',', '.') | float / 100) | round(4) if found.val else 0 }}


Enjoy ! :blush: :

6 « J'aime »

Salut,
merci beaucoup pour ce tuto. Plus cas le mettre en place.
Super boulot :+1:

1 « J'aime »

MAJ :

Contrats disponibles dans le tutoriel:

  • Tempo
  • Zen fixe HP HC
  • Bleu HP HC
1 « J'aime »

Bonsoir,
Merci pour le tuto, plus qu’à mettre tout ça en place.
:+1:

Actuellement, j’ai un script python qui récupère les infos de tarif « Abonnement/HP/HC » sur un fichier .csv dispo sur le web (https://www.data.gouv.fr/fr/datasets/r/f7303b3a-93c7-4242-813d-84919034c416).
Ca fonctionne bien depuis plusieurs années, mais la mise à jour des nouveaux tarifs sur ce fichier est toujours décalée de 3 à 6 jours.

1 « J'aime »

installation simple et efficace avec le tuto tout prêt.
Encore merci pour ce super tuto :wink:


1 « J'aime »

Excellent tuto !

J’ai déjà mis en place la “première” version, celle ci est plus complète car elle couvre des abonnements différents.

La plus grande différence est l’obtention des tarifs directement chez EDF et non plus Kelwatt, en l’état actuel y a t-il un intérêt à changer de “source” (et de méthode de scraping) ?

WarC0zes : j’aime beaucoup tes tableaux :wink:

2 « J'aime »

Salut,

La version Scrape Kelwatt fonctionne bien, mais ça reste une source non officielle, contrairement à ici.

L’avantage de Scrape, c’est qu’on peut aller chercher pleins d’autres informations sur le net assez facilement, alors que PDF scrape limite vraiment à la lecture des PDF uniquement.

Pour ce qui est du délai de mise à jour lors d’un changement, sur Kelwatt, c’est fait dans les 48/72h, en moyenne. Sur EDF, j’ai pas encore l’information, mais j’aurais tendance à penser que c’est fait plus rapidement, notamment par necess commerciale.

Au final, les deux possibilités marchent, faut juste choisir celle qui te semble le mieux. Sinon, tu peux garder les deux (comme j’ai fait), et créer un capteur qui dit :

  • affiche le prix depuis EDF
  • si indisponible, affiche le prix depuis kelwatt
  • si indisponible, ne pas mettre à jour le input_number qui fait tampon.

Ainsi, j’ai toujours la dernière valeur en provenance de kelwatt comme garantie, et ce uniquement si j’ai rien côté EDF.

1 « J'aime »

Salut ..

Merci

Je pense qu’il faut faire attention à cet update , pour pas se faire bannir si trop d’appel !
Raisonnable tout les mois au minimum serait bien !
En plus EDF ne modifie pas si souvent dans un mois !
Moyenne 30(jour)x24(heure)x3600(seconde) == 2592000 ss
(comme l’appli calcul en sec) mais possible de mettre 720 hh ( il le calcul et le modifie tout seul !)

PS: d’ailleurs précisé par l’auteur de l’addon
Long intervals are recommended as pdf files tend to be static and you don't want to be blocked for too frequent of requests or overburden your system with unecessary downloads or updates.
French translation :
Il est recommandé de respecter de longs intervalles, car les fichiers PDF sont généralement statiques et vous ne souhaitez pas être bloqué en raison de requêtes trop fréquentes ni surcharger votre système avec des téléchargements ou des mises à jour inutiles.

Salut,

Je comprends ton point de vue, et j’ai réfléchi à ce point également lors de ma configuration.

1 fois par jour, c’est bien.
En dessous, aucun intérêt.
Si tu veux limiter, tu peux descendre à 1 fois tous les 2-3 jours, voire 1 semaine éventuellement. Mais plus tu augmentes la période, plus tu auras une série de jour avec un tarif non à jour.

1 fois par mois, tu auras tes données mises à jour avec potentiellement beaucoup de retard. (jusqu’à 1 mois) A ce moment-là, mieux vaut le faire manuellement.

Le but principal, c’est d’avoir la nouvelle valeur à jour de manière automatique mais aussi, qu’elle le soit le plus tôt possible.

Après, libre à chacun de faire comme bon lui semble suivant ses besoins/craintes. :slightly_smiling_face:

OK..
Le problème de toute façon se pose si tu ne fais pas un template des valeurs au moment x du changement (date d’application).
Tout les calculs (avant cette date) seraient faux sinon!

C’est d’ailleurs ce qui se passe dans le dash ENERGY ( si coût) ?

Désolé, pas compris de quel problème tu parles.
Tout fonctionne parfaitement depuis déjà un moment sur mon HA et celui d’autres personnes qui utilisent/utilisaient mon 1er tuto.

Dans le Dashboard Energie, ca garde bien les valeurs utilisées au moment où elles ont été utilisées.

Exemple avec mon cout d’abonnement, qui est de 0.63€ aujourd’hui, alors qu’il remonte à 0.58€, au 17/12/2025. Les calculs ne sont pas rétro-actifs, ils sont en temps réels puis stokés.

Effectivement si tu gardes dans la bd, sans modification !

Super tuto :slightly_smiling_face: , j’ai ajouté ça à mon HA.

Par contre, je voulais ajouter une condition de vérification sur la date d’application écrite dans le PDF, avant d’envoyer les tarifs à mes input_number via l’automatisation (en la comparant à “now()”, si le PDF n’est pas à jour je ne veux pas mettre à jour mes input_number).

J’ai donc essayé de récupérer la ligne “Applicable au 1er février 2026”, mais je ne parviens pas à la transformer en date, comment faire ? J’ai tenté ce code, la variable “dt” me revoit bien “1/02/2026”, mais ensuite impossible d’en faire un timestamp (alors que dans l’outil de développement j’y arrive) :

{% set found = namespace(val='', in_applicable=false) %}

{% for line in value.split('\n') %}
  {% if 'Applicable au ' in line %}
    {% set found.in_applicable = true %}
  {% endif %}
  {% if found.in_applicable and found.val == '' and line.strip().startswith('Applicable au ') %}
      {% set found.val = line %}
  {% endif %}
{% endfor %}

{% if found.val %}
  {% set dt = found.val | replace('Applicable au ', '') | replace(' janvier ','/01/') | replace(' février ','/02/') | replace(' fevrier ','/02/') | replace(' mars ','/03/') | replace(' avril ','/04/') | replace(' mai ','/05/') | replace(' juin ','/06/') | replace(' juillet ','/07/') | replace(' août ','/08/') | replace(' aout ','/08/') | replace(' septembre ','/09/') | replace(' octobre ','/10/') | replace(' novembre ','/11/') | replace(' décembre ','/12/') | replace(' decembre ','/12/') | replace('er/','/') %}
  {{ as_timestamp(strptime(dt, "%d/%m/%Y")) | timestamp_local}}
{% else %}
  0
{% endif %}

Alors que dans l’outil de développement le code suivant me renvoie bien “2026-02-01T00:00:00+01:00”

{% set dt = "1/02/2026" %}
{{ dt }}
{{ strptime(dt, "%d/%m/%Y") }}
{{ as_timestamp(strptime(dt, "%d/%m/%Y")) | timestamp_local}}

Merci :slight_smile:

1 « J'aime »

Salut,

J’ai eu la même idée, mais je n’ai finalement pas été au bout car pour moi, après réflexion, on a pas besoin de récupérer cette ligne.

J’explique pourquoi :

L’automatisation que je propose ne met à jour la valeur du input que si elle est valide, dans le cas contraire le input reste inchangé.

De plus, peu importe la date puisqu’il faut obligatoirement télécharger à nouveau le .PDF si on veut la vérifier. Il faut donc quand même le faire régulièrement. (action identique pour les deux méthodes)

Donc, qu’il remette le input à jour que s’il renvoie une valeur (comme je le propose), ou que si la date a changé (comme tu le voudrais) , au final, tu auras le même résultat.

Certes, via ma méthode, il vient écraser la valeur du input toutes les 24h00 contrairement à ce que tu proposes qui ne le ferait que si changement sur le .pdf, mais c’est la seule différence au final. Du coup, y a-t-il un intérêt à faire en fonction de la date, d’après toi ?

Si tu désires vraiment utiliser ta méthode, je peux y jeter un oeil.
Redis moi.

@juu , Cadeau :

Format : 1er février 2026

{% set found = namespace(val='') %}
{% for line in value.split('\n') %}
  {% if 'Applicable au' in line and found.val == '' %}
    {% set parts = line.strip().replace('Applicable au ', '') %}
    {% set found.val = parts %}
  {% endif %}
{% endfor %}
{{ found.val }}

Format ISO : 01/02/2026

{% set mois = {'janvier':'01','février':'02','fevrier':'02','mars':'03','avril':'04','mai':'05','juin':'06','juillet':'07','août':'08','aout':'08','septembre':'09','octobre':'10','novembre':'11','décembre':'12','decembre':'12'} %}
{% set found = namespace(date='') %}
{% for line in value.split('\n') %}
  {% if 'Applicable au' in line and found.date == '' %}
    {% set line_lower = line.lower() %}
    {% for mois_nom, mois_num in mois.items() %}
      {% if mois_nom in line_lower %}
        {% set annees = line | regex_findall('(20\d\d)') %}
        {% if annees|length > 0 %}
          {% set found.date = '01/' ~ mois_num ~ '/' ~ annees[0] %}
        {% endif %}
      {% endif %}
    {% endfor %}
  {% endif %}
{% endfor %}
{{ found.date if found.date != '' else 'Non disponible' }}

Ça répond à ta demande ?

Je voulais rajouter des sécurités pour m’assurer que les sensors tarifs renvoyés étaient bien les bons (PDF pas à jour, format de PDF qui a changé, …)

En fait aujourd’hui j’utilisais des input_number manuellement saisis dans “input_numbers.yaml”. Souvent j’arrivais à obtenir des tarifs assez proches des vrais tarifs avant la diffusion par EDF, donc je les saisissais manuellement la veille et je lançais une automatisation qui redémarrait HA le 01/02 à 0h00 pour charger les nouveaux tarifs.

Puis je scrutais la sortie du PDF pour vraiment saisir les tarifs finaux (c’est ce que j’ai fais là au 1er février, avec 7 nombres car je suis en Tempo).

Avec ta proposition, je voulais conserver mes input_number manuels + utiliser ta récupération pour alimenter des input_numbers finaux utilisables. Dans l’ordre chronologique, vu que le PDF tarde toujours un peu à sortir, ça donnerait :

  • je saisis manuellement les tarifs calculés par tout le monde que je trouve un peu partout dans mon “input_numbers.yaml”, et le 01/02 (ou 01/08) à 0h00 je redémarre HA pour les charger
  • un peu après minuit, PDF Scrape télécharge le PDF et charge des tarifs pas encore à jour dans ses sensors
  • Dans une automatisation lancée régulièrement et/ou au changement d‘état des input_number et des sensor :
    • si mes input_number manuels et les sensor PDF et les input_number finaux sont égaux ; si pas égaux et que le PDF n’est pas à jour (date “applicable au” n’est pas au 01/02 ou au 01/08 de l’année en cours) alors j’envoie une notification pour vérification humaine
    • mise à jour des input_number finaux si tout est égal, ou si pas égal prendre ceux du PDF si la date d’application est bonne.

Pour être honnête et après avoir relu le pavé que je viens d’écrire, je me dis que je suis (encore) en train de monter une usine à gaz pour pas grand-chose…. Puisque faire ça me ferait toujours saisir manuellement mes input_number + redémarrer HA à 0h00, alors que l’intérêt de ta proposition est de me simplifier la vie et de ne plus saisir manuellement ; et en plus je ne me sers pas des calculs de coût de l’électricité ultra-finement donc s’il y a une erreur de quelques centimes pendant 24-48h (temps de mise à jour du PDF par EDF) cela ne me changera absolument rien…

Conclusion : pas vraiment d’utilité, sauf pour la figure de style :upside_down_face:

PS : dans l’automatisation, il faut peut-être rajouter une sécurité supplémentaire du type “is_number(states(‘sensor.nom_du_sensor_cree_avec_pdf_scrape_pour_abonnement’))”, car si le format du PDF change et que le sensor PDF renvoie une lettre (genre un “€”) il ne faudrait pas casser les input_number finaux ? Et une autre pour vérifier que le prix PDF du kWh ne passe pas un jour en € au lieu des centimes, donc vérifier que le sensor est >0.01 par exemple ?

Merci pour ta recherche, tu as été plus rapide que moi à écrire mon post précédent.

Le souci est que tous les ans il faut mettre à jour le capteur pour changer l’année, dans mon test je ne comprends pas pourquoi le “strptime” ne fonctionne pas dans le sensor PDF alors qu’il fonctionne dans l’outil de développement.

Mais je conserve ma conclusion précédente, il faut que je calme mon cerveau et que j’arrête de faire des usines à gaz dans mon HA :wink: surtout quand ça ne m’est pas utile :roll_eyes:

1 « J'aime »

Nop, j’ai mis à jour le code. Il se base sur le mois et non plus l’année. :grin:

Pour le format renvoyé, pas neces non plus puisque derrière, on va mettre à jour le input_number. Par définition, si c’est pas un nombre, il restera avec l’ancien coût.

Par contre, tu peux faire une automatisation pour vérifier la différence entre le capteur pdf scrape, et le input. Si pas égal, alors notification.

1 « J'aime »

A tous,

En fait, je viens de regarder plus précisément, et les dates de mise à jour des tarifs depuis 8 ans, sont toujours les 1er février et les 1er aout.

Faut voir si je peux pas faire en sorte de recharger le PDF que les 1er, 2, 3 et éventuellement 4 de ces mois, uniquement.

Je vais creuser l’idée, et vous tiendrai au courant.

1 « J'aime »