Gestion des tarifs Tempo et cout recharge véhicule électrique

Petit tuto décrivant ma méthode pour suivre les couts de recharge de mon véhicule hybride rechargeable en fonctions des tarifs tempo.

Matériel:
Pour la lecture des tarifs:

  • un linky
  • une interface PiTinfo (ou autre fait maison)
  • un esp32 avec ESPHome
    On peux aussi faire ça avec l’intégration RTE Tempo si linky trop loin, a voir si les heures de bascules sont strictement identique, dans tous les cas seul le compteur fait fois…

Pour la mesure de la puissance de charge du VE:
Les systèmes ne manque pas libre à chacun de choisir celui adapté à son besoin. Pour mes tests j’utilise une prise tplink tapo sur un absorbeur d’humidité (qui consomme moins de 200W). Sur la papier elle suffit pour la voiture (qui charge à 8A), mais je pense prévoir quelque chose de plus solide.

Lecture du tarif sur le linky et automatisation du changement de cout
Pour le paramétrage de l’esp sous esphome avec lecture du linky voir les multiples articles à ce sujet en fonction du mode du linky (je ne sais plus où j’ai récupéré mon fichier de config)
On a donc maintenant qui s’affiche: l’energie soutirée (depuis le début de vie du compteur), les 6 index (on ne s’en servira pas), et la période tarifaire en cours (et plein d’autres choses dont on ne parleras pas ici)
J’ai lu des méthodes avec utility meter que je n’ai toujours pas compris. J’ai fait simple:

  • Création de 6 entrées numériques correspondant aux 6 tarifs (qui seront à mettre à jour à chaque variations de tarifs).
  • Création d’une entrée numérique tarif actuel
  • Création d’une automatisation qui lance un script qui permet de faire varier le tarif actuel à chaque changement détecté sur le tarif en cours de l’esphome. Oui j’aurais pu tout mettre dans l’automatisation plutôt que créer 2 trucs. Au moins maintenant je sais faire les 2…
code configuration esphome pour un linky en mode standard
substitutions:
  name: esphome-web-313a64
  friendly_name: ESPHome linky

esphome:
  name: ${name}
  friendly_name: ${friendly_name}
  min_version: 2024.6.0
  name_add_mac_suffix: false
  project:
    name: esphome.web
    version: dev

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:

# Allow Over-The-Air updates
ota:
- platform: esphome

# Allow provisioning Wi-Fi via serial
improv_serial:

wifi:
  # Set up a wifi access point
  ap: {}

# In combination with the `ap` this allows the user
# to provision wifi credentials to the device via WiFi AP.
captive_portal:

dashboard_import:
  package_import_url: github://esphome/example-configs/esphome-web/esp32.yaml@main
  import_full_config: true

# Sets up Bluetooth LE (Only on ESP32) to allow the user
# to provision wifi credentials to the device.
esp32_improv:
  authorizer: none

# To have a "next url" for improv serial
web_server:


    # Time: https://esphome.io/components/time.html
time:
  - platform: homeassistant
    timezone: "Europe/Paris"
    id: homeassistant_time

# Status Binary Sensor: https://esphome.io/components/binary_sensor/status.html
binary_sensor:
  - platform: status
    name: "Linky Status"

# Restart Button: https://esphome.io/components/button/restart.html
button:
  - platform: restart
    name: "Linky Restart"

# https://esphome.io/custom/uart.html
uart:
  id: uart_bus
  rx_pin: GPIO3
  baud_rate: 9600 # 9600 == mode standard, 1200 == mode historique
  parity: EVEN
  data_bits: 7
  stop_bits: 1

# https://esphome.io/components/sensor/teleinfo.html
teleinfo:
  update_interval: 5s
  historical_mode: false # false == mode standard, true == mode historique

# https://esphome.io/components/sensor/index.html
sensor:
  # WiFi
  - platform: wifi_signal
    name: "Linky WiFi Signal"
    unit_of_measurement: dB
    device_class: signal_strength
    accuracy_decimals: 0
    update_interval: 600s
  # Uptime
  - platform: uptime
    name: "Linky Uptime"
    unit_of_measurement: s
    device_class: duration
    accuracy_decimals: 0
    update_interval: 60s
  #--------------
  # MODE STANDARD
  #--------------
  # Énergie active soutirée totale
  - platform: teleinfo
    tag_name: "EAST"
    name: "Linky Energie Soutirée"
    unit_of_measurement: kWh
    device_class: energy
    state_class: total_increasing
    accuracy_decimals: 3
    filters:
      - multiply: 0.001
  # Energie active soutirée Fournisseur, index 01
  - platform: teleinfo
    tag_name: "EASF01"
    name: "Linky Energie Soutirée Tempo Bleu HC"
    unit_of_measurement: kWh
    device_class: energy
    state_class: total_increasing
    accuracy_decimals: 3
    filters:
      - multiply: 0.001
  # Energie active soutirée Fournisseur, index 02
  - platform: teleinfo
    tag_name: "EASF02"
    name: "Linky Energie Soutirée Tempo Bleu HP"
    unit_of_measurement: kWh
    device_class: energy
    state_class: total_increasing
    accuracy_decimals: 3
    filters:
      - multiply: 0.001
  # Energie active soutirée Fournisseur, index 03
  - platform: teleinfo
    tag_name: "EASF03"
    name: "Linky Energie Soutirée Tempo Blanc HC"
    unit_of_measurement: kWh
    device_class: energy
    state_class: total_increasing
    accuracy_decimals: 3
    filters:
      - multiply: 0.001
  # Energie active soutirée Fournisseur, index 04
  - platform: teleinfo
    tag_name: "EASF04"
    name: "Linky Energie Soutirée Tempo Blanc HP"
    unit_of_measurement: kWh
    device_class: energy
    state_class: total_increasing
    accuracy_decimals: 3
    filters:
      - multiply: 0.001
  # Energie active soutirée Fournisseur, index 05
  - platform: teleinfo
    tag_name: "EASF05"
    name: "Linky Energie Soutirée Tempo Rouge HC"
    unit_of_measurement: kWh
    device_class: energy
    state_class: total_increasing
    accuracy_decimals: 3
    filters:
      - multiply: 0.001
  # Energie active soutirée Fournisseur, index 06
  - platform: teleinfo
    tag_name: "EASF06"
    name: "Linky Energie Soutirée Tempo Rouge HP"
    unit_of_measurement: kWh
    device_class: energy
    state_class: total_increasing
    accuracy_decimals: 3
    filters:
      - multiply: 0.001
  - platform: teleinfo
    tag_name: "IRMS1"
    name: "Linky Courant Efficace"
    unit_of_measurement: A
    device_class: current
    state_class: measurement
  # Tension Efficace, phase 1
  - platform: teleinfo
    tag_name: "URMS1"
    name: "Linky Tension Efficace"
    unit_of_measurement: V
    device_class: voltage
    state_class: measurement
  # Puissance app. Instantanée Soutirée
  - platform: teleinfo
    tag_name: "SINSTS"
    name: "Linky Puissance Apparente Instantanée Soutirée"
    unit_of_measurement: VA
    state_class: measurement
    device_class: apparent_power
  #----------------------------
  
    
# https://esphome.io/components/text_sensor/index.html
text_sensor:
  - platform: wifi_info
    ip_address:
      name: Linky IP Address
    mac_address:
      name: Linky Wifi Mac Address
    ssid:
      name: Linky Wifi SSID
    bssid:
      name: Linky Wifi BSSID
  # Libellé tarif fournisseur en cours
  - platform: teleinfo
    tag_name: "LTARF"
    name: "Linky Tarif Actuel"
    icon: mdi:information
code création des 7 entrées numériques
input_number:
  tarifhpbleu:
    name: tarif HP Bleu
    min: 0
    max: 1
    step: 0.0001
    unit_of_measurement: EUR/kWh
    mode: box
  tarifhcbleu:
    name: tarif HC Bleu
    min: 0
    max: 1
    step: 0.0001
    unit_of_measurement: EUR/kWh
    mode: box
  tarifhpblanc:
    name: tarif HP Blanc
    min: 0
    max: 1
    step: 0.0001
    unit_of_measurement: EUR/kWh
    mode: box
  tarifhcblanc:
    name: tarif HC Blanc
    min: 0
    max: 1
    step: 0.0001
    unit_of_measurement: EUR/kWh
    mode: box
  tarifhprouge:
    name: tarif HP Rouge
    min: 0
    max: 1
    step: 0.0001
    unit_of_measurement: EUR/kWh
    mode: box
  tarifhcrouge:
    name: tarif HC Rouge
    min: 0
    max: 1
    step: 0.0001
    unit_of_measurement: EUR/kWh
    mode: box
  tarifactuel:
    name: tarif Actuel
    min: 0
    max: 1
    step: 0.0001
    unit_of_measurement: EUR/kWh
    mode: box
code automatisation pour lancer le script
alias: tarif tempo
description: ""
mode: single
triggers:
  - entity_id:
      - sensor.esphome_web_313a64_linky_tarif_actuel
    to: null
    trigger: state
conditions: []
actions:
  - action: script.turn_on
    metadata: {}
    data: {}
    target:
      entity_id: script.tarif_tempo
Script pour mettre à jour le tarif actuel
alias: tarif tempo
sequence:
  - choose:
      - conditions:
          - condition: state
            entity_id: sensor.esphome_web_313a64_linky_tarif_actuel
            state: "    HC  BLEU    "
            for:
              hours: 0
              minutes: 0
              seconds: 0
        sequence:
          - action: input_number.set_value
            target:
              entity_id: input_number.tarifactuel
            data:
              value: " {{states('input_number.tarifhcbleu') }} "
      - conditions:
          - condition: state
            entity_id: sensor.esphome_web_313a64_linky_tarif_actuel
            state: "    HP  BLEU    "
            for:
              hours: 0
              minutes: 0
              seconds: 0
        sequence:
          - action: input_number.set_value
            target:
              entity_id: input_number.tarifactuel
            data:
              value: " {{states('input_number.tarifhpbleu') }} "
      - conditions:
          - condition: state
            entity_id: sensor.esphome_web_313a64_linky_tarif_actuel
            state: "    HC  BLANC    "
            for:
              hours: 0
              minutes: 0
              seconds: 0
        sequence:
          - action: input_number.set_value
            target:
              entity_id: input_number.tarifactuel
            data:
              value: " {{states('input_number.tarifhcblanc') }} "
      - conditions:
          - condition: state
            entity_id: sensor.esphome_web_313a64_linky_tarif_actuel
            state: "    HP  BLANC    "
            for:
              hours: 0
              minutes: 0
              seconds: 0
        sequence:
          - action: input_number.set_value
            target:
              entity_id: input_number.tarifactuel
            data:
              value: " {{states('input_number.tarifhpblanc') }} "
      - conditions:
          - condition: state
            entity_id: sensor.esphome_web_313a64_linky_tarif_actuel
            state: "    HC  ROUGE    "
            for:
              hours: 0
              minutes: 0
              seconds: 0
        sequence:
          - action: input_number.set_value
            target:
              entity_id: input_number.tarifactuel
            data:
              value: " {{states('input_number.tarifhcrouge') }} "
      - conditions:
          - condition: state
            entity_id: sensor.esphome_web_313a64_linky_tarif_actuel
            state: "    HP  ROUGE    "
            for:
              hours: 0
              minutes: 0
              seconds: 0
        sequence:
          - action: input_number.set_value
            target:
              entity_id: input_number.tarifactuel
            data:
              value: " {{states('input_number.tarifhprougerouge') }} "
description: ""
icon: mdi:currency-eur
mode: single

Voilà il ne reste plus qu’à ajouter l’index « énergie soutirée » et choisir « tarif actuel » dans le module énergie pour avoir un suivi de conso et du prix (vérifié avec hellowatt ça correspond à l’abonnement prêt)

A suivre: comment suivre les couts d’énergie de ma voiture et les réinitialiser quand je le veux (ou de façon automatique)

Hello, je réponds vite fait car pas eu le temps de tout lire, mais déjà merci !
Je suis exactement dans le même cas (Tempo + véhicule hybride que je charge la nuit), et j’était jusqu’à il y a quelques jours en tarif de base (même pas HP/HC).
Pour l’instant j’étais resté avec un calcul du cout de la charge « à l’arrache » avec un seul tarif (HC Bleu), mais ton tuto va grandement m’aider parce qu 'on ne va pas tarder à avoir des jours blanc voire rouge !!!
Je regarderai donc en détail ultérieurement, et je posterai ici mes propres expédiences si tu m’en donne l’autorisation bien sûr !

1 « J'aime »

Suite du tuto (toujours sur mon absorbeur d’humidité en guise de test)

Lectures des données de l’enregistreur de puissance et calcul des kw.h totaux (ici prise connectée)
Ma prise connectée donne la puissance en W, la consommation mensuelle ou journalière. On utilisera ici la puissance en W.
Méthode expliquée de multiples fois. On crée un entrée « capteur d’intégrale » sur la mesure de puissance. Pour ma part j’ai choisi la méthode des trapèzes qui me semble la plus précise (débat ouvert)
EDIT: j’ai modifié car la méthode des trapèzes me fait des « sauts », une rapide recherche m’aurais amené à tester la méthode « rectangle à gauche » qui ne pose plus se problème, la puissance de recharge de la voiture variant peu l’erreur devrais être faible.
Au passage on peux ajouter cette intégrale au module energie qui permettra d’avoir une vue graphique des consommations de l’objet surveillé par rapport au reste de la maison.


Cependant l’intégrale ne peux pas être remise à zero, il va falloir trouver une astuce que l’on verra dans la 3e partie
Dommage que le module energie ne donne pas les coûts des appareils individuels… Il va aussi falloir aussi se le faire à la main.

Calcul des coûts
On va repartir des W du capteur directement (multiplier les kw.h par le coût ne marcherais pas car le prix du tempo est variable).
On a des W, qui sont des W.h/h.
Que l’on peux en divisant par 1000 convertir en kW.h/h
Cette valeur si elle est multiplié par le tarif qui est en Eur/kW.h on obtient des Eur/h.
C’est donc un cout horaire instantané.
Facile…
On fait un template que voici:

template:
  - sensor:
      - name: "cout horaire absorbeur sous sol"
        unit_of_measurement: EUR/h
        state: "{{ states('input_number.tarifactuel')|float(0) * states('sensor.prise_absorbeur_consommation_actuelle')|float(0) / 1000 }}"

Voila ce que cela donne:


On remarque bien l’augmentation du cout horaire à 6h de mat’
Comme pour l’énergie on fait une intégrale de ce template pour obtenir le cout en Euro.

Désolé trop de chiffres significatifs :slight_smile:
Comme pour l’énergie, on ne peux remettre à zero, on verra cela dans la dernière partie.

A suivre…

1 « J'aime »

Suite et fin de ce tuto:
Comment créer un compteur (energie et €) ré-initialisable?

Il y a peut-être plus simple, mais pour moi cette méthode est la plus logique.
On crée un bouton, lorsque l’on clique dessus, on enregistre les cout cumulés et l’énergie cumulée dans 2 valeurs, on crée ensuite 2 nouveaux sensors des cout cumulés - cout reset.
Voici le détail:

Création du bouton de reset (facultatif utile uniquement si reset manuel)
Dans mon cas je souhaite faire le reset manuellement, donc création d’un bouton.
Paramètres → Appareil et services → entrées → Créer une entrée → bouton
Plus qu’a lui donner un petit nom de votre choix.
Moi il s’appelle: input_button.reset_conso_absorbeur_sous_sol

Création des valeurs « reset »
Création de 2 valeurs directement dans le configuration.yaml

code
input_number:
  resetenergieabsorbeursoussol:
    name: reset energie absorbeur sous sol
    min: 0
    max: 10000
    step: 0.001
    unit_of_measurement: kWh
    mode: box
  resetcoutabsorbeursoussol:
    name: reset cout absorbeur sous sol
    min: 0
    max: 10000
    step: 0.01
    unit_of_measurement: EUR
    mode: box

Création des compteurs « journaliers »
Création des 2 templates pour les couts et l’énergie.

code
template:
  - sensor:
      - name: "cout horaire absorbeur sous sol"
        unit_of_measurement: EUR/h
        state: "{{ states('input_number.tarifactuel')|float(0) * states('sensor.prise_absorbeur_consommation_actuelle')|float(0) / 1000 }}"
  - sensor:
      - name: "cout journalier absorbeur sous sol"
        unit_of_measurement: EUR
        state: "{{ states('sensor.cout_absorbeur_sous_sol')|float(0) - states('input_number.resetcoutabsorbeursoussol')|float(0) }}"
  - sensor:
      - name: "energie journalier absorbeur sous sol"
        unit_of_measurement: kWh
        state: "{{ states('sensor.energie_aborbeur_sous_sol')|float(0) - states('input_number.resetenergieabsorbeursoussol')|float(0) }}"

Création d’une automatisation pour écrire les valeurs « reset »
On se crée ensuite une automatisation qui permet d’écrire les valeurs actuelles dans les resets, ce qui aura pour effet d’amener les compteurs journaliers à zero.

Voici le code de l'automatisation
alias: Nouvelle automatisation
description: ""
triggers:
  - trigger: state
    entity_id:
      - input_button.reset_conso_absorbeur_sous_sol
conditions: []
actions:
  - action: input_number.set_value
    metadata: {}
    data:
      value: " {{ states('sensor.cout_absorbeur_sous_sol') }} "
    target:
      entity_id: input_number.resetcoutabsorbeursoussol
  - action: input_number.set_value
    metadata: {}
    data:
      value: " {{ states('sensor.energie_aborbeur_sous_sol') }} "
    target:
      entity_id: input_number.resetenergieabsorbeursoussol
mode: single

Chacun complétera/modifiera l’automatisation pour s’il souhaite un déclanchement automatique et quoi faire des données.

Dans l’idéal j’aurais souhaité qu’à chaque fin de charge:

  • le kilométrage de mon véhicule soit lu grâce à l’intégration ford pass (malheureusement elle ne semble pas fonctionner en ce moment)
  • Les cout journalier, l’énergie journalières et le kilométrage soit inscrit sur mon compte spritmonitor mais il ne semble pas exister d’intégration
  • Ensuite reset pour être prêt à la prochaine charge
    Voila pourquoi pour le moment je reste en manuel avec un enregistrement dans spritmonitor à la main toutes les semaine voir 2…

A vos questions et à vous de jouer!!!
Il y a aussi un bon tri à faire sur les affichages pour ne laisser que l’essentiel

Salut,

Dans ta config ESPhome pour le Linky, en standard tu peux ajouter l’étiquette « NTARF » qui te remonte un nombre de 1 à 6 correspondant au tarif actuel :
1 : bleu HC
2 : bleu HP
3 : blanc HC
4 : blanc HP
5 : rouge HC
6 : rouge HP
perso je trouve que c’est plus facile à gérer dans les automatisations qu’avec l’étiquette LTARF