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'ai voulu 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 l'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 nos UM entre HP et HC, un peu comme le faisait le fil signal fourni 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ûts de la journée précédente. Encore une fois ce ne sont que des exemples, 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 associer 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 choisi 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 !
Bonus
Suite à une demande : Extraction en .csv et envoie par mail.
automation:
- id: '1901208243990'
alias: 'Energy - Sensor values to file - Day'
description: ''
trigger:
- platform: time
at: '23:59:55'
condition: []
action:
- service: notify.file_csv_month
data_template:
message: '{{now().strftime("%d.%m.%Y")}};{{now().strftime("%H:%M:%S")}};{{ states.sensor.linky_3a99d205_smartenergy_metering_summation_delivered.state}};kW/h'
mode: single
- id: '1708208243990'
alias: 'Energy - Sensor values to file - Mouth'
description: ''
trigger:
- platform: time
at: '23:59:55'
condition:
- condition: state
entity_id: binary_sensor.dernier_jour_du_mois
state: 'on'
action:
- service: notify.file_csv_day
data_template:
message: '{{now().strftime("%d.%m.%Y")}};{{now().strftime("%H:%M:%S")}};{{ states.sensor.linky_3a99d205_smartenergy_metering_summation_delivered.state}};kW/h'
- service: notify.mail
# data_template:
data:
target:
- [email protected]
message: 'Linky {{ now().strftime(''%H:%M:%S'')}}'
title: Mise à jour Linky
data:
images:
- '/share/linky_month.csv'
html: >
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Intruder alert</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<style type="text/css">
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 300;
src: local('Open Sans Light'), local('OpenSans-Light'), url(http://fonts.gstatic.com/s/opensans/v13/DXI1ORHCpsQm3Vp6mXoaTZS3E-kSBmtLoNJPDtbj2Pk.ttf) format('truetype');
}
h1,h2,h3,h4,h5,h6 {
font-family:'Open Sans',Arial,sans-serif;
font-weight:400;
margin:10px 0
}
</style>
</head>
<body>
<div class="jumbotron jumbotron-fluid" style="background-color: white; color: blue;">
<div class="container py-0">
<h3>Mise à jour mensuelle : \\192.168.66.150\share
<br>
Pour plus de détails : https://ha.xx.xx:8123/energy</h3>
</div>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"></script>
</html>
mode: single
Sources