Home Assistant & Energie

Jadis certains justifiaient l'achat d'un ordinateur personnel par la gestion des comptes familiaux, aujourd’hui d'autres viennent à la domotique en espérant faire des économies. Soyons sérieux, la domotique ça coûte de l'argent et il faut y venir dans un objectif de confort ! Il n'en reste pas moins que l'on peut s'amuser à calculer ce que l'on consomme, c’est ce que je vais vous montrer ici.

Home assistant dispose d'une fonctionnalité de base nommée utility_meter: Il s'agit en fait de compteurs qui fonctionnent en cycles (heure, jour, mois, trimestre, année), pour l'instant il manque le mode bi-mensuel et un mode paramétrable. L'idée est de se calquer sur une facturation, ou de créer une facturation, pour une location par exemple. Ce capteur suivra les valeurs d'un capteur source, réinitialisant automatiquement le compteur en fonction du cycle configuré. Lors de la réinitialisation, on stockera la valeur précédente du compteur, fournissant les moyens d'effectuer des opérations de comparaison (par exemple, "ai-je dépensé plus ou moins ce mois-ci?"), ou d'estimation de facturation. Certains fournisseurs de services ont des tarifs différents en fonction du temps / de la disponibilité des ressources / etc. Le compteur de services publics vous permet de définir les différents tarifs pris en charge par votre fournisseur. Lorsque les tarifs sont définis, une nouvelle entité apparaîtra indiquant le tarif actuel. Pour modifier le tarif, l'utilisateur doit appeler un service, généralement via une automatisation qui peut être basée sur le temps ou sur une autre source externe (par exemple un capteur REST).

Je n'ai pas trouvé beaucoup d'informations et j'y ai passé d'autant plus de temps que j'avi voulut l'adapter à mon abonnement électrique. Le plus simple ou j'ai deux tarifs, les Heures Pleines de 05:00 à 21:30, le reste étant des Heures Creuses (HC). Il est toutefois possible d'adapter facilement tout ça à des tarifs plus complexes comme Tempo ou EJP.

La première chose à faire est de décortiquer la facture EdF afin d'obtenir les valeurs de base. Pour cela chacun fera appel à Excel car au delà des tarifs fixes du kWh il existe un certain nombre de taxes locales et régionales qui font qu'en France personne ne paie vraiment son Electricité au même prix.

La liste des courses

Pour compter il va nous falloir un sensor: qui sache nous remonter cette information. J'ai pour ma part utilisé un Shelly EM, il propose deux comptages et on va ici utiliser uniquement le premier que j'ai branché sur l'arrivée EdF de la maison. Il y a plusieurs façons d'en extraire les informations (Intégration, MQTT, ...) ici je vais créer un sensor rest, simplement car c’est le premier exemple que j'ai trouvé et que c'est resté ainsi.

    - platform: rest
      name: Shelly EM EdF # Général
      resource: http://192.168.210.111/status
      # username: !secret shelly_usr
      # password: !secret shelly_pwd
      authentication: basic
      value_template: '{{ (value_json.emeters.0.total | float /1000)|round(3) }}' # Wh to kWh
      scan_interval: 300 # no point updating faster than this. The Shelly only updates every 5 minutes
      unit_of_measurement: kWh

Ensuite on va créer nos utility_meter:, dans mon ça j'en ai créé 5, ce qui va me permettre de gérer le jour, la semaine, le mois, le trimestre et l'année en cours. Ces compteurs se remettrons à zéro en début de cycle et si l'on souhaite traiter les informations au delà il conviendra d'en sauvegarder les valeurs dans un fichier extere (.CSV par exemple) ou une BDD.

utility_meter:
  energy_total_usage_daily:
    source: sensor.shelly_em_edf
    cycle: daily
    tariffs:
      - day
      - night

  energy_total_usage_weekly:
    source: sensor.shelly_em_edf
    cycle: weekly
    tariffs:
      - day
      - night

  energy_total_usage_monthly:
    source: sensor.shelly_em_edf
    cycle: monthly
    tariffs:
      - day
      - night

  energy_total_usage_quarterly:
    source: sensor.shelly_em_edf
    cycle: quarterly
    tariffs:
      - day
      - night

  energy_total_usage_yearly:
    source: sensor.shelly_em_edf
    cycle: yearly
    tariffs:
      - day
      - night

Comme vous le voyez j'ai créé deux tarifs, ne me demandez pas pourquoi je les ai nommés Jour et Nuit, mais en fait cela correspond à HP et HC que l'on retrouvera plus loin. Mais comme j'ai créé deux tarifs il va me falloir faire l'addition des deux comptages pour obtenir la consommation de la journée en kWH si je le souhaite. Dans l'absolu c’est inutile car le but est d'avoir des valeurs finales en Euros...

Pour faire tous nos calculs on va se servir de sensors et de templates, là ou systèmes auraient utilisé des scénarios et des variable. Bref, peu importe, ce qui compte c’est le résultat et que ce résultat soit dynamique. Voici donc de quoi obtenir la conso journalière en kWH dans un sensor, une simple addition qu'il conviendra de dupliquer pour les différentes périodes :

    - platform: template # Consommation journalière HP + HC
      sensors:
        energy_total_daily:
          friendly_name: 'Energie journalière consommée'
          entity_id:
            - sensor.energy_total_usage_daily_day
            - sensor.energy_total_usage_daily_night
          value_template: "{{ (states('sensor.energy_total_usage_daily_day')|float + states('sensor.energy_total_usage_daily_night')|float)|round(3) }}"
          unit_of_measurement: "kWh"

Ensuite on va créer d'autres sensor: afin de passer aux euros... Mais avant on va définir quelques input_number: afin d'y saisir les valeurs du prix du kWh et de l'abonnement au prorata des périodes HP et HC. Valeurs que l'on saisira dans une carte Lovelace que l'on verra plus loin.

  hp_daily_cost:
    name: HP - Cout journalier
    mode: box
    min: 0
    max: 100
    unit_of_measurement: "€/day"
    icon: mdi:currency-eur

  hp_energy_cost:
    name: HP - Coût du Kwh
    mode: box
    min: 0
    max: 100
    unit_of_measurement: "€/kWh"
    icon: mdi:currency-eur

  hc_daily_cost:
    name: HC - Cout journalier
    mode: box
    min: 0
    max: 100
    unit_of_measurement: "€/day"
    icon: mdi:currency-eur

  hc_energy_cost:
    name: HC - Coût du Kwh
    mode: box
    min: 0
    max: 100
    unit_of_measurement: "€/kWh"
    icon: mdi:currency-eur

Maintenant que 'on dispose de valeurs en kWh et de coûts on va pouvoir calculer ce que l'on consomme en HP et HC et additionner le tout pour obtenir une résultat journalier. Pour cela on va créer 3 sensor / template. On reste toujours sur la journée mais il faudra le dupliquer pour les autres cycles.

    - platform: template # Coût journalier HP
      sensors:
        hp_cost_today:
          friendly_name: 'HP Cost Today'
          entity_id:
            - sensor.energy_total_usage_daily_day
            - input_number.hp_daily_cost
            - input_number.hp_energy_cost
          value_template: "{{ (states('sensor.energy_total_usage_daily_day')|float * states('input_number.hp_energy_cost')|float + states('input_number.hp_daily_cost')|float)|round(2) }}"
          unit_of_measurement: "€"

    - platform: template # Coût journalier HC
      sensors:
        hc_cost_today:
          friendly_name: 'HC Cost Today'
          entity_id:
            - sensor.energy_total_usage_daily_night
            - input_number.hc_daily_cost
            - input_number.hc_energy_cost
          value_template: "{{ (states('sensor.energy_total_usage_daily_night')|float * states('input_number.hc_energy_cost')|float + states('input_number.hc_daily_cost')|float)|round(2) }}"
          unit_of_measurement: "€"

    - platform: template # Coût journalier HP + HC
      sensors:
        cost_today:
          friendly_name: "Aujourd'hui"
          entity_id:
            - sensor.hp_cost_today
            - sensor.hc_cost_today
          value_template: "{{ (states('sensor.hp_cost_today')|float + states('sensor.hc_cost_today')|float)|round(2) }}"
          unit_of_measurement: "€"

Je la fait un peu à l'envers, mais maintenant qu'on a nos bases de calculs on va avoir besoin de quelques automations, les deux premières vont nous servir à basculer nous comptes entre HP et HC, un peu comme le faisait le fil signal fourit par EdF pour actionner le chauffe eau en heures creuses...

- id: set_night
  alias: 'Set Night'
  initial_state: true
  trigger:
    platform: time
    at: '21:30:00'
  action:
  - service: utility_meter.select_tariff ###### On passe en HC (nuit)
    data:
      entity_id:
      - utility_meter.energy_total_usage_daily
      - utility_meter.energy_total_usage_weekly
      - utility_meter.energy_total_usage_monthly
      - utility_meter.energy_total_usage_quarterly
      - utility_meter.energy_total_usage_yearly
      tariff: night

- id: set_day
  alias: 'Set Day'
  initial_state: true
  trigger:
    platform: time
    at: '05:00:00'
  action:
  - service: utility_meter.select_tariff ###### On passe en HP (jour)
    data:
      entity_id:
      - utility_meter.energy_total_usage_daily
      - utility_meter.energy_total_usage_weekly
      - utility_meter.energy_total_usage_monthly
      - utility_meter.energy_total_usage_quarterly
      - utility_meter.energy_total_usage_yearly
      tariff: day

Ensuite on va créer deux input_number: que l'on utilisera avec l'automation suivante pour conserver le coût cumulé et les coût de la journée précédente. Encore une fois ce ne sont que des exemple, le reste étant à votre imagination...

  cumulative_energy_cost:
    name: Cumulative Energy Cost
    mode: box
    min: 0
    max: 5000
    unit_of_measurement: "€"
    icon: mdi:currency-eur

  yesterday_energy_cost:
    name: Yesterday Energy Cost
    mode: box
    min: 0
    max: 5000
    unit_of_measurement: "€"
    icon: mdi:currency-eur

Et comme un input_number: c’est pas joli sur Lovelace, on va leur associé des sensor:

    - platform: template # pour lovelace display à partir de l'input_number mis à jour à 23.59
      sensors:
        cost_yesterday_display:
          friendly_name: "Hier"
          entity_id:
            - input_number.yesterday_energy_cost
          value_template: "{{ (states('input_number.yesterday_energy_cost')|float)|round(2) }}"
          unit_of_measurement: "€"

L'automation finale que vous adapterez à vos envies et que l'on déclenchera en fin de journée va nous servir à plusieurs choses :

  • Stocker le cumul de consommation
  • Stocker le coût de la journée précédente
  • Envoyer une notification anxiogène sur ce que l'on vient de consommer...
  • Enregistrer un log avec toutes les valeurs possibles et imaginables...
- id: daily_energy_use_message
  alias: '000 - Daily Energy Use Message'
  trigger:
    platform: time
    at: '23:59:50'
  action:
  - service: input_number.set_value # Stocker le cumul de consommation...
    data_template:
      entity_id: input_number.cumulative_energy_cost
      value: "{{ states('input_number.cumulative_energy_cost')|float + states('sensor.cost_today')|float }}"

  - service: input_number.set_value # Stocker le coût de la journée précédente
    data_template:
      entity_id: input_number.yesterday_energy_cost
      value: "{{ states('sensor.cost_today')|float }}"

  - service: notify.slack_hass_canaletto
    data_template:
      title: '*Information*' # Envoyer un message en fin de journée...
      message: "La consommation de la journée écoulée est de {{ states('sensor.energy_total_daily') }} kWh., soit {{ states('sensor.cost_yesterday_display') }} €"

  - service: notify.file_notify_power # Ecrire un log exploitable dans un fichier .csv
    data_template:
      message: "{{ states('sensor.date') }},{{ states('sensor.energy_total_usage_daily_day') }},{{ states('sensor.energy_total_usage_daily_night') }},{{ states('sensor.energy_total_daily') }},{{ states('sensor.cost_today') }}"

Et ainsi recevoir un message du genre...

La consommation de la journée écoulée est de 25.561 kWh., soit 4.56 €

Voila pour le code. Maintenant on dispose de plein de nouveaux sensor: que l'on va pouvoir exploiter dans d'autres automations à imaginer, mais on va commencer par afficher ces informations sur une carte Lovelace et faire quelques graphiques... Comme c'est riche en formation j'ai choisit une carte qui se déplie, Fold-Entity-Row, et Multiple-Entity-Row pour compacter un peu les informations et dont voici le code :

entities:
  - entity: utility_meter.energy_total_usage_daily
    name: Tarif actuel
  - label: 'Coûts HP / HC :'
    type: section
  - entities:
      - entity: sensor.hp_cost_today
        name: HP
      - entity: sensor.hc_cost_today
        name: HC
    entity: sensor.cost_today
    icon: 'mdi:currency-eur'
    name: Journée en cours
    secondary_info: last-changed
    show_state: false
    type: 'custom:multiple-entity-row'
  - entities:
      - entity: sensor.hp_cost_weekly
        name: HP
      - entity: sensor.hc_cost_weekly
        name: HC
    entity: sensor.cost_weekly
    icon: 'mdi:currency-eur'
    name: Semaine en cours
    secondary_info: last-changed
    show_state: false
    type: 'custom:multiple-entity-row'
  - entities:
      - entity: sensor.hp_cost_monthly
        name: HP
      - entity: sensor.hc_cost_monthly
        name: HC
    entity: sensor.cost_monthly
    icon: 'mdi:currency-eur'
    name: Mois en cours
    secondary_info: last-changed
    show_state: false
    type: 'custom:multiple-entity-row'
  - entities:
      - entity: sensor.hp_cost_quarterly
        name: HP
      - entity: sensor.hc_cost_quarterly
        name: HC
    entity: sensor.cost_quarterly
    icon: 'mdi:currency-eur'
    name: Trimestre en cours
    secondary_info: last-changed
    show_state: false
    type: 'custom:multiple-entity-row'
  - entities:
      - entity: sensor.hp_cost_yearly
        name: HP
      - entity: sensor.hc_cost_yearly
        name: HC
    entity: sensor.cost_yearly
    icon: 'mdi:currency-eur'
    name: Année en cours
    secondary_info: last-changed
    show_state: false
    toggle: true
    type: 'custom:multiple-entity-row'
  - label: 'Coût cummulé :'
    type: section
  - entities:
      - entity: sensor.cost_today
        name: Aujourd'hui
      - entity: sensor.cost_yesterday_display
        name: Hier
    entity: sensor.cost_yearly
    icon: 'mdi:currency-eur'
    name: Journées
    secondary_info: last-changed
    show_state: false
    toggle: true
    type: 'custom:multiple-entity-row'
  - label: 'Coût :'
    type: section
  - entity: sensor.cost_yearly
    icon: 'mdi:currency-eur'
  - entities:
      - entity: input_number.hp_daily_cost
      - entity: input_number.hp_energy_cost
      - entity: input_number.hc_daily_cost
      - entity: input_number.hc_energy_cost
    head:
      label: Tarifs EDF
      type: section
    padding: 0
    type: 'custom:fold-entity-row'
  - entities:
      - entity: utility_meter.energy_total_usage_daily
        name: Tarif actuel
      - label: Journée en cours
        type: section
      - entity: sensor.energy_total_usage_daily_day
        name: Tarif HP
      - entity: sensor.energy_total_usage_daily_night
        name: Tarif HC
      - entity: sensor.energy_total_daily
        name: Total
      - label: Semaine en cours
        type: section
      - entity: sensor.energy_total_usage_weekly_day
        name: Tarif HP
      - entity: sensor.energy_total_usage_weekly_night
        name: Tarif HC
      - entity: sensor.energy_total_weekly
        name: Total
      - label: Mois en cours
        type: section
      - entity: sensor.energy_total_usage_monthly_day
        name: Tarif HP
      - entity: sensor.energy_total_usage_monthly_night
        name: Tarif HC
      - entity: sensor.energy_total_monthly
        name: Total
      - label: Trimestre en cours
        type: section
      - entity: sensor.energy_total_usage_quarterly_day
        name: Tarif HP
      - entity: sensor.energy_total_usage_quarterly_night
        name: Tarif HC
      - entity: sensor.energy_total_quarterly
        name: Total
      - label: Année en cours
        type: section
      - entity: sensor.energy_total_usage_yearly_day
        name: Tarif HP
      - entity: sensor.energy_total_usage_yearly_night
        name: Tarfif HC
      - entity: sensor.energy_total_yearly
        name: Total
      - type: divider
      - entity: input_number.cumulative_energy_cost
      - entity: input_number.yesterday_energy_cost
    head:
      label: Compteurs d'énergie
      type: section
    padding: 0
    type: 'custom:fold-entity-row'
  - entities:
      - entity: sensor.shelly_shem_0560de_1_current_consumption
        name: 'Maison : Consommation instantanée'
      - entity: sensor.shelly_shem_0560de_1_total_consumption
        name: 'Maison : Consommation cummulée'
    head:
      label: Equipements surveillés
      type: section
    padding: 0
    type: 'custom:fold-entity-row'
show_header_toggle: false
style: |
  ha-card {
    border: solid 2px var(--primary-color);
  }
theme: teal
title: Consommation électrique
type: entities

Encore une fois c'est a adapter à vos besoins. Coté graphiques je n'ai rien inventé non plus, j'ai juste adapté ce que j'ai trouvé en me servant de Mini-Graph-Card. Pour les graphiques suivants je suis allé chercher les informations MQTT après avoir configuré le Shelly EM en MQTT vers mon broker. Mais c’est juste pour l'exemple car j'aurais tout aussi bien put utiliser les valeurs du sensor: créé par l'intégration Shelly...

    - platform: mqtt
      name: "Shelly EM : Arrivée EdF"
      state_topic: "shellies/shellyem-0560DE/emeter/0/power"
      value_template: '{{ value|round(1) }}'
      qos: 1
      unit_of_measurement: "W"
      icon: mdi:gauge

    - platform: mqtt
      name: "Shelly EM : Baie Informatique"
      state_topic: "shellies/shellyem-0560DE/emeter/1/power"
      value_template: '{{ value|round(1) }}'
      qos: 1
      unit_of_measurement: "W"
      icon: mdi:gauge

    - platform: mqtt
      name: "Shelly EM : Voltage"
      state_topic: "shellies/shellyem-0560DE/emeter/0/voltage"
      qos: 1
      unit_of_measurement: "V"
      icon: mdi:flash

Pour mettre en évidence les heures creuses, on se fait un petit binary_sensor: dédié (on pourrait s'en servir dans l'automation plus haut...).

- platform: tod
  name: Heures Creuses
  after: '21:30'
  before: '05:00'

Et pour terminer, le code de la carte qui va générer mes 3 graphiques. C’est un peu compliqué car je suis parti d'un exemple ou l'auteur, bien plus chevronné que moi s'est servi de la luminosité en temps réel pour générer des valeurs Jour et Nuit afin de calculer sa productivité en énergie solaire.

cards:
  - color_thresholds:
      - color: '#039BE5'
        value: 0
      - color: '#0da035'
        value: 600
      - color: '#e0b400'
        value: 1200
      - color: '#e45e65'
        value: 2400
    color_thresholds_transition: hard
    entities:
      - sensor.shelly_em_arrivee_edf
      - color: 'rgba(0,0,255,1)'
        entity: binary_sensor.dark_outside
        show_line: false
        y_axis: secondary
    group: false
    hour24: true
    hours_to_show: 24
    line_width: 4
    name: Total
    points_per_hour: 4
    show:
      extrema: true
      fill: fade
      icon: true
      labels: false
      name: true
      state: true
    state_map:
      - label: Day
        value: 'off'
      - label: Night
        value: 'on'
    style: |
      ha-card {
        border: solid 2px var(--primary-color);
      }
    type: 'custom:mini-graph-card'
  - color_thresholds:
      - color: '#039BE5'
        value: 0
      - color: '#0da035'
        value: 600
      - color: '#e0b400'
        value: 1200
      - color: '#e45e65'
        value: 2400
    color_thresholds_transition: hard
    entities:
      - sensor.shelly_em_baie_informatique
      - color: 'rgba(0,0,255,1)'
        entity: binary_sensor.dark_outside
        show_line: false
        y_axis: secondary
    group: false
    hour24: true
    hours_to_show: 24
    line_width: 4
    name: Baie Informatique
    points_per_hour: 4
    show:
      extrema: true
      fill: fade
      icon: true
      labels: false
      name: true
      state: true
    state_map:
      - label: Day
        value: 'off'
      - label: Night
        value: 'on'
    style: |
      ha-card {
        border: solid 2px var(--primary-color);
      }
    type: 'custom:mini-graph-card'
  - color_thresholds:
      - color: '#039BE5'
        value: 0
      - color: '#0da035'
        value: 600
      - color: '#e0b400'
        value: 1200
      - color: '#e45e65'
        value: 2400
    color_thresholds_transition: hard
    entities:
      - sensor.shelly_em_voltage
      - color: 'rgba(0,0,255,1)'
        entity: binary_sensor.dark_outside
        show_line: false
        y_axis: secondary
    group: false
    hour24: true
    hours_to_show: 24
    line_width: 4
    points_per_hour: 4
    show:
      extrema: true
      fill: fade
      icon: true
      labels: false
      name: true
      state: true
    state_map:
      - label: Day
        value: 'off'
      - label: Night
        value: 'on'
    style: |
      ha-card {
        border: solid 2px var(--primary-color);
      }
    type: 'custom:mini-graph-card'
type: vertical-stack

Voilà, à vous de jouer !

Sources