Home Assistant, Shelly & Energy

Il y a quelques avantages à choisir des modules Shelly plutôt que des chinoiseries. D'abord ces modules sont aux normes européennes, et ce n'est pas juste un adhésif CE posé par un mineur au fond d'une usine chinoise (pensez surtout aux assurances qui peuvent se montrer tatillonnes en cas de sinistre), le tarif est accessible et si vous avez une question (technique ou autre) le CEO de la boite vous répondra dans le fil Facebook de la marque ou par mail.

Une chose intéressante est également que beaucoup de ces modules remontent la consommation instantanée et cumulée. Je pensais naïvement que tous conservaient la consommation cumulée en cas de coupure secteur, mais, même si dixit le CEO c'était vaguement en projet en 2019, ce n'est toujours pas le cas et cette information sera perdue localement (sauf EM), bien qu'elle reste accessible sur le cloud Shelly via l'application idoine, mais impossible à récupérer via l'API.

Pour conserver cette information je me suis un peu torturé l'esprit depuis quelques jours en cherchant différentes solutions pour stocker et conserver ce chiffre, alors qu'en fait la solution était sous mes yeux et que je l'avait déjà utilisée quand j'avais déployé mon module de calcul des couts électrique globaux. La solution passe par l'intégration utility_meter: proposée de base par Home Assistant.

Utility Meter est une intégration qui va permettre de stocker le cumul d'une valeur sur une période donnée (hourlydailyweeklymonthlybimonthlyquarterly and yearly), ainsi que la même valeur sur la période n-1. Par exemple, si vous configurez en journalier,  à 13:45 vous pourrez afficher (ou utiliser) la valeur de consommation d'un compteur depuis minuit ainsi que celle à la même heure pour le jour précédent. Imaginez juste le code et les template qu'il aurait fallut imaginer sans cette intégration...

En ce qui me concerne, en prenant par exemple un Shelly 1PM qui pilote un convecteur, ce qui va m'intéresser est de connaitre la consommation cumulée en cours et celle pour le même jour l'an dernier.

Bien sur il est possible, avec un peu d'imagination et quelques lignes de code YAML, de stocker les années précédentes dans un input_number: ou même l'évolution dans une base de données et pour les plus maniaques d'utiliser Grafana pour afficher de beaux histogrammes. Même si ça ne changera probablement rien à la facture EdF, en partant du principe que si la domotique apporte un indéniable confort, de part le surcoût induit elle permet au final rarement réaliser de vraies économies.

En pratique

Dans cet exemple j'utilise l'intégration Shelly for Hass, mais il est toute à fait possible de faire la même chose avec d'autres types de modules, voire en intégrant les modules Shelly (ou autres) avec MQTT...

On crée nos entrées utility_meter: dans notre fichier de configuration : 

utility_meter:
  energy_total_yearly_ch_bureau:
    source: sensor.shelly_shplg_s_f8ccf83_total_consumption
    cycle: yearly
    
  energy_total_yearly_ch_cheminee:
    source: sensor.shelly_shsw_pm_68c63afaf521_total_consumption
    cycle: yearly
    
  energy_total_yearly_ch_salon:
    source: sensor.shelly_shsw_pm_68c63afaf658_total_consumption
    cycle: yearly
    
  energy_total_yearly_ch_cuisine:
    source: sensor.shelly_shsw_pm_68c63afaf1ca_total_consumption
    cycle: yearly

Ensuite on va pouvoir les utiliser directement pour les afficher, ici dans une carte ou j'ai utilisé le composant multiple-entity-row pour les besoins de l'affichage. Vous remarquerez l'utilisation de l'attribut last_period pour afficher l'année précédente.

entities:
  - entities:
      - attribute: last_period
        name: Année passée
        unit: kWh
    entity: sensor.energy_total_yearly_ch_cheminee
    name: Convecteur Cheminée
    secondary_info: last-changed
    show_state: true
    state_header: Année en cours
    type: 'custom:multiple-entity-row'
title: Consomation cumulée
type: entities

Bonus

Etant donné que j'avais dans un séjour ouvert trois convecteurs qui fonctionnent en même temps, j'ai créé deux sensor: pour regrouper ces informations afin de pouvoir afficher une seule ligne pour le séjour, un pour l'année en cours et un pour l'année précédente, qui de fait sera à zéro pour un moment. Attention, utility_meter: commence à compter au moment ou les entrées sont crées.

- platform: template
  sensors:
    energy_total_yearly_ch_sejour:
        friendly_name: "Total Séjour"
        unit_of_measurement: 'kWh'
        value_template: "{{ 
            (states('sensor.energy_total_yearly_ch_cheminee') | float) +
            (states('sensor.energy_total_yearly_ch_cuisinee') | float) +
            (states('sensor.energy_total_yearly_ch_salon') | float) }}"

- platform: template
  sensors:
    energy_total_yearly_ch_sejour_last_period:
        friendly_name: "Total Séjour (N-1)"
        unit_of_measurement: 'kWh'
        value_template: "{{ 
            (states('sensor.energy_total_yearly_ch_cheminee.attributes.last_period') | float) +
            (states('sensor.energy_total_yearly_ch_cuisinee.attributes.last_period') | float) +
            (states('sensor.energy_total_yearly_ch_salon.attributes.last_period') | float) }}"

 

 

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