
Chaque fois que je reçois ma facture d'Ă©lectricitĂ© et d'eau, je suis Ă©tonnĂ© : ma famille consomme-t-elle vraiment autant ? Certes, nous avons un chauffage au sol et un chauffe-eau dans la salle de bain, mais ils ne fonctionnent pas en continu. Nous essayons aussi d'Ă©conomiser l'eau (mĂȘme si nous aimons nous dĂ©tendre dans la baignoire). Il y a dĂ©jĂ plusieurs annĂ©es, j'ai et Ă la maison intelligente, mais je me suis arrĂȘtĂ© lĂ . Ce n'est que rĂ©cemment que j'ai vraiment commencĂ© Ă analyser mes consommations, et c'est de cela que parle cet article.
Récemment, je suis passé à Home Assistant comme systÚme de maison intelligente. L'une des raisons était justement la possibilité de collecter une grande quantité de données et de construire facilement divers types de graphiques.
Les informations décrites dans cet article ne sont pas nouvelles ; toutes ces choses ont déjà été abordées sous différentes formes sur Internet. Mais chaque article se concentre généralement sur une seule approche ou un seul aspect. J'ai dû comparer toutes ces approches et choisir celle qui me convenait le mieux. Cet article n'apporte pas d'informations exhaustives sur la collecte de données, mais constitue plutÎt un résumé de ma propre expérience. Je suis donc ouvert à toute critique constructive et à des suggestions d'amélioration.
Définition du problÚme
Ainsi, l'objectif de l'exercice d'aujourd'hui est d'obtenir de jolis graphiques de consommation d'eau et d'électricité :
- Horaire sur 2 jours
- Journalier sur 2 semaines
- (optionnel) Hebdomadaire et Mensuel
Nous rencontrons quelques difficultés ici :
- Les composants graphiques standards sont généralement assez limités. Dans le meilleur des cas, on peut créer un graphique linéaire à partir de points.
Si l'on cherche bien, on peut trouver des composants tiers qui élargissent les capacités des graphiques standards. Pour Home Assistant, il y a un composant qui est à la fois joli et fonctionnel : , mais il est aussi un peu limité :
- Il est difficile de dĂ©finir les paramĂštres d'un histogramme sur de grands intervalles (largeur de la barre dĂ©finie en fractions d'heure, donc les intervalles de plus d'une heure doivent ĂȘtre spĂ©cifiĂ©s par des nombres dĂ©cimaux)
- On ne peut pas ajouter diffĂ©rentes entitĂ©s sur un mĂȘme graphique (par exemple, combiner la tempĂ©rature et l'humiditĂ©, ou mĂ©langer un histogramme avec une ligne)
- Non seulement Home Assistant utilise par dĂ©faut une base de donnĂ©es SQLite assez rudimentaire (et moi, avec mes compĂ©tences limitĂ©es, je n'ai pas rĂ©ussi Ă installer MySQL ou Postgres), mais les donnĂ©es sont Ă©galement stockĂ©es de maniĂšre peu optimale. Par exemple, Ă chaque changement de n'importe quel paramĂštre numĂ©rique, mĂȘme le plus insignifiant, un Ă©norme JSON d'environ un kilooctet est enregistrĂ© dans la base.
{"entity_id": "sensor.water_cold_hourly", "old_state": {"entity_id": "sensor.water_cold_hourly", "state": "3", "attributes": {"source": "sensor.water_meter_cold", "status": "collecting", "last_period": "29", "last_reset": "2020-02-23T21:00:00.022246+02:00", "meter_period": "hourly", "unit_of_measurement": "l", "friendly_name": "water_cold_hourly", "icon": "mdi:counter"}, "last_changed": "2020-02-23T19:05:06.897604+00:00", "last_updated": "2020-02-23T19:05:06.897604+00:00", "context": {"id": "aafc8ca305ba4e49ad4c97f0eddd8893", "parent_id": null, "user_id": null}}, "new_state": {"entity_id": "sensor.water_cold_hourly", "state": "4", "attributes": {"source": "sensor.water_meter_cold", "status": "collecting", "last_period": "29", "last_reset": "2020-02-23T21:00:00.022246+02:00", "meter_period": "hourly", "unit_of_measurement": "l", "friendly_name": "water_cold_hourly", "icon": "mdi:counter"}, "last_changed": "2020-02-23T19:11:11.251545+00:00", "last_updated": "2020-02-23T19:11:11.251545+00:00", "context": {"id": "0de64b8af6f14bb9a419dcf3b200ef56", "parent_id": null, "user_id": null}}}J'ai un nombre assez élevé de capteurs (des capteurs de température dans chaque piÚce, des compteurs d'eau et d'électricité), et certains génÚrent également une quantité importante de données. Par exemple, le compteur électrique SDM220 génÚre environ une dizaine de valeurs toutes les 10 à 15 secondes, et j'aimerais installer environ 8 de ces compteurs. De plus, il y a toute une série de paramÚtres calculés sur la base d'autres capteurs. Ainsi, toutes ces valeurs peuvent facilement gonfler la base de données de 100 à 200 Mo par jour. AprÚs une semaine, le systÚme aura du mal à fonctionner, et aprÚs un mois, la clé USB risque de rendre l'ùme (dans le cas d'une installation typique de Home Assistant sur un Raspberry Pi), et il est hors de question de stocker les données pendant un an.
- Si vous avez de la chance, votre compteur est capable de calculer la consommation par lui-mĂȘme. Vous pouvez Ă tout moment interroger le compteur pour connaĂźtre la valeur accumulĂ©e de la consommation. En gĂ©nĂ©ral, tous les compteurs Ă©lectriques disposant d'une interface numĂ©rique (RS232/RS485/Modbus/Zigbee) offrent cette possibilitĂ©.
Il est pire si l'appareil peut simplement mesurer un certain paramĂštre instantanĂ© (par exemple, la puissance instantanĂ©e ou le courant), ou gĂ©nĂ©rer des impulsions toutes les X watts-heure ou litres. Dans ce cas, il faut rĂ©flĂ©chir Ă comment et avec quoi l'intĂ©grer et oĂč stocker la valeur. Il existe un risque de manquer un rapport pour une raison quelconque, et la prĂ©cision du systĂšme en gĂ©nĂ©ral soulĂšve des questions. Bien sĂ»r, on peut tout confier Ă un systĂšme de maison intelligente comme Home Assistant, mais le point concernant le nombre d'enregistrements dans la base n'est pas Ă ignorer, et il n'est pas possible de sonder les capteurs plus d'une fois par seconde (restriction de l'architecture de Home Assistant).
Approche 1
Commençons par voir ce que Home Assistant propose par dĂ©faut. La mesure de la consommation sur une pĂ©riode est une fonctionnalitĂ© trĂšs demandĂ©e. Ăvidemment, cela a Ă©tĂ© rĂ©alisĂ© depuis longtemps sous la forme d'un composant spĂ©cialisĂ© : utility_meter.
Le principe du composant est qu'il crĂ©e en interne une variable current_accumulated_value, et la rĂ©initialise Ă l'expiration de la pĂ©riode dĂ©finie (heure/semaine/mois). Le composant surveille lui-mĂȘme la variable d'entrĂ©e (la valeur d'un capteur quelconque), s'abonne aux changements de valeur - vous obtenez simplement le rĂ©sultat final. C'est dĂ©crit en quelques lignes dans le fichier de configuration.
utility_meter:
water_cold_hour_um:
source: sensor.water_meter_cold
cycle: hourly
water_cold_day_um:
source: sensor.water_meter_cold
cycle: daily
Ici, sensor.water_meter_cold est la valeur actuelle du compteur en litres, que je reçois via MQTT. La structure crée 2 nouveaux capteurs water_cold_hour_um et water_cold_day_um, qui accumulent les lectures horaires et journaliÚres, les réinitialisant à l'expiration de la période. Voici le graphique de l'accumulateur horaire pour une demi-journée.

Le code des graphiques horaire et journalier pour l'interface Lovelace ressemble Ă ceci :
- type: history-graph
title: 'Consommation d'eau horaire utilisant des variables'
hours_to_show: 48
entities:
- sensor.water_hour
- type: history-graph
title: 'Consommation d'eau quotidienne utilisant des variables'
hours_to_show: 360
entities:
- sensor.water_day
En rĂ©alitĂ©, c'est dans cet algorithme que rĂ©side le problĂšme de cette approche. Comme je l'ai dĂ©jĂ mentionnĂ©, pour chaque valeur d'entrĂ©e (la lecture actuelle du compteur pour chaque litre suivant), 1 Ko d'enregistrement est gĂ©nĂ©rĂ© dans la base. Chaque compteur utilitaire gĂ©nĂšre Ă©galement une nouvelle valeur qui s'ajoute Ă la base. Si je veux collecter des relevĂ©s horaires/journaliers/hebdomadaires/mensuels, et ce pour plusieurs colonnes d'eau, tout en ajoutant une pile de compteurs Ă©lectriques â cela va gĂ©nĂ©rer une quantitĂ© Ă©norme de donnĂ©es. En rĂ©alitĂ©, les donnĂ©es ne sont pas trĂšs nombreuses, mais puisque l'assistant domestique Ă©crit une quantitĂ© d'informations superflues dans la base, la taille de celle-ci va croĂźtre de maniĂšre exponentielle. J'ose mĂȘme pas estimer la taille de la base pour des graphiques hebdomadaires et mensuels.
De plus, le compteur utilitaire ne résout pas le problÚme posé. Le graphique des valeurs fournies par le compteur utilitaire est une fonction constamment croissante qui est réinitialisée à 0 chaque heure. Nous avons besoin d'un graphique de consommation compréhensible pour l'utilisateur, montrant combien de litres ont été consommés sur une période donnée. Le composant standard history-graph n'est pas capable de cela, mais un composant externe comme mini-graph-card pourrait nous aider.
Voici le code de la carte pour lovelace-UI :
- aggregate_func: max
entities:
- color: var(--primary-color)
entity: sensor.water_cold_hour_um
group_by: hour
hours_to_show: 48
name: "Consommation d'eau horaire agrégée par compteur utilitaire"
points_per_hour: 1
show:
graph: bar
type: 'custom:mini-graph-card'En plus des paramÚtres standard comme le nom du capteur, le type de graphique, la couleur (je n'ai pas aimé l'orange standard), il est important de noter 3 réglages :
- group_by:hour â le graphique sera gĂ©nĂ©rĂ© en alignant les barres au dĂ©but de l'heure
- points_per_hour: 1 â une barre pour chaque heure
- Et le plus important, aggregate_func: max â prendre la valeur maximale dans chaque heure. C'est ce paramĂštre qui transforme le graphique en dents de scie en barres.

Ne vous inquiĂ©tez pas pour les barres sur la gauche â c'est le comportement standard du composant s'il n'y a pas de donnĂ©es. Et il n'y avait pas de donnĂ©es â je n'ai commencĂ© Ă collecter les donnĂ©es via le compteur utilitaire que quelques heures avant cet article (je vous parlerai de mon approche actuelle un peu plus bas).
Sur cette image, je voulais montrer que parfois l'affichage des donnĂ©es fonctionne, et que les barres reflĂštent rĂ©ellement les bonnes valeurs. Cependant, ce n'est pas le cas pour tout. La barre sur la pĂ©riode de 11h Ă 12h affiche inexplicablement 19 litres, alors que sur le graphique dentelĂ© juste au-dessus pour la mĂȘme pĂ©riode provenant du mĂȘme capteur, nous voyons une consommation de 62 litres. Soit c'est un bug, soit la manipulation est dĂ©fectueuse. Je ne comprends pas encore pourquoi les donnĂ©es de droite ont Ă©tĂ© perdues â la consommation y Ă©tait normale, comme le montre Ă©galement le graphique dentelĂ©.
Globalement, je n'ai pas rĂ©ussi Ă obtenir la crĂ©dibilitĂ© de cette approche â le graphique montre presque toujours des absurditĂ©s.
Code similaire pour le capteur quotidien.
- aggregate_func: max
entities:
- color: var(--primary-color)
entity: sensor.water_cold_day_um
group_by: interval
hours_to_show: 360
name: "Consommation d'eau quotidienne agrégée par compteur de service"
points_per_hour: 0.0416666666
show:
graph: bar
type: 'custom:mini-graph-card'
Notez que le paramĂštre group_by est dĂ©fini sur interval, et c'est le paramĂštre points_per_hour qui en dĂ©pend. Et c'est lĂ qu'est un autre problĂšme de ce composant â points_per_hour fonctionne bien sur les graphiques d'une heure ou moins, mais est horrible sur des intervalles plus longs. Pour obtenir une barre pour une journĂ©e, il a fallu entrer la valeur 1/24=0.04166666. Je ne parle mĂȘme pas des graphiques hebdomadaires et mensuels.
Approche 2
Alors que je commençais à comprendre l'assistant domestique, je suis tombé sur cette vidéo :

Un camarade collecte des donnĂ©es de consommation de plusieurs types de prises Xiaomi. Sa tĂąche est un peu plus simple â il s'agit simplement d'afficher la valeur de consommation pour aujourd'hui, hier et pour le mois. Aucun graphique n'est requis.
Mettons de cĂŽtĂ© les rĂ©flexions sur l'intĂ©gration manuelle des valeurs instantanĂ©es de puissance â j'ai dĂ©jĂ Ă©crit ci-dessus sur la 'prĂ©cision' de cette approche. Il n'est pas clair pourquoi il n'a pas utilisĂ© les valeurs accumulĂ©es de consommation, qui sont dĂ©jĂ collectĂ©es par la mĂȘme prise. Ă mon avis, l'intĂ©gration Ă l'intĂ©rieur du matĂ©riel fonctionnera mieux.
Nous allons prendre de la vidéo l'idée du calcul manuel de la consommation sur une période. L'homme ne compte que les valeurs d'aujourd'hui et d'hier, mais nous irons plus loin et essayerons de dessiner un graphique. L'essence de la méthode proposée dans mon cas est la suivante.
Nous allons créer une variable valeur_au_début_de_l_heure, dans laquelle nous enregistrerons les relevés actuels du compteur.
Ă la fin de chaque heure (ou au dĂ©but de la suivante), nous allons calculer la diffĂ©rence entre la lecture actuelle et celle mĂ©morisĂ©e au dĂ©but de l'heure. Cette diffĂ©rence correspondra Ă la consommation pour l'heure en cours â nous allons enregistrer cette valeur dans le capteur et dans le futur, nous allons construire un graphique basĂ© sur cette valeur.
Il est également nécessaire de "réinitialiser" la variable valeur_au_début_de_l'heure en y écrivant la valeur actuelle du compteur.
Tout cela peut ĂȘtre rĂ©alisĂ© grĂące aux moyens fournis par home assistant.
Nous devrons Ă©crire un peu plus de code que dans l'approche prĂ©cĂ©dente. Pour commencer, crĂ©ons ces "variables". Par dĂ©faut, nous n'avons pas d'entitĂ© "variable", mais nous pouvons utiliser les services du broker mqtt. Nous allons y envoyer des valeurs avec le drapeau retain=true â cela conservera la valeur Ă l'intĂ©rieur du broker, et il sera possible de l'extraire Ă tout moment, mĂȘme aprĂšs un redĂ©marrage de home assistant. J'ai immĂ©diatement créé des compteurs horaires et journaliers.
- platform: mqtt
state_topic: "test/water/hour"
name: water_hour
unit_of_measurement: l
- platform: mqtt
state_topic: "test/water/hour_begin"
name: water_hour_begin
unit_of_measurement: l
- platform: mqtt
state_topic: "test/water/day"
name: water_day
unit_of_measurement: l
- platform: mqtt
state_topic: "test/water/day_begin"
name: water_day_begin
unit_of_measurement: lToute la magie se produit dans l'automatisation, qui s'active chaque heure et chaque nuit respectivement.
- id: water_new_hour
alias: water_new_hour
initial_state: true
trigger:
- platform: time_pattern
minutes: 0
action:
- service: mqtt.publish
data:
topic: "test/water/hour"
payload_template: >
{{ (states.sensor.water_meter_cold.state|int) - (states.sensor.water_hour_begin.state|int) }}
retain: true
- service: mqtt.publish
data:
topic: "test/water/hour_begin"
payload_template: >
{{ states.sensor.water_meter_cold.state }}
retain: true
- id: water_new_day
alias: water_new_day
initial_state: true
trigger:
- platform: time
at: "00:00:00"
action:
- service: mqtt.publish
data:
topic: "test/water/day"
payload_template: >
{{ (states.sensor.water_meter_cold.state|int) - (states.sensor.water_day_begin.state|int) }}
retain: true
- service: mqtt.publish
data:
topic: "test/water/day_begin"
payload_template: >
{{ states.sensor.water_meter_cold.state }}
retain: trueLes deux automatisations effectuent 2 actions :
- Elles calculent la valeur pour l'intervalle en prenant la différence entre la valeur de départ et celle de fin.
- Elles mettent Ă jour la valeur de base pour le prochain intervalle.
La construction de graphiques se fait ici avec un history-graph ordinaire :
- type: history-graph
title: 'Consommation d'eau horaire utilisant des variables'
hours_to_show: 48
entities:
- sensor.water_hour
- type: history-graph
title: 'Consommation d'eau quotidienne utilisant des variables'
hours_to_show: 360
entities:
- sensor.water_dayCela ressemble Ă ceci :

En principe, c'est déjà ce dont nous avons besoin. L'avantage de cette méthode est que les données sont générées une seule fois par intervalle. C'est-à -dire au maximum 24 enregistrements par jour pour le graphique horaire.
Malheureusement, cela ne rĂ©sout toujours pas le problĂšme gĂ©nĂ©ral de la base de donnĂ©es croissante. Si je veux un graphique de la consommation mensuelle, je vais devoir stocker des donnĂ©es pendant au moins un an. Ătant donnĂ© que Home Assistant ne propose qu'un seul paramĂštre de durĂ©e de conservation pour toute la base, cela signifie que TOUTES les donnĂ©es du systĂšme devront ĂȘtre conservĂ©es pendant une annĂ©e entiĂšre. Par exemple, au cours de l'annĂ©e, je consomme 200 mĂštres cubes d'eau, ce qui Ă©quivaut Ă 200000 enregistrements dans la base. Et si l'on considĂšre d'autres capteurs, ce chiffre devient vraiment indĂ©cent.
Approche 3
Heureusement, des personnes intelligentes ont dĂ©jĂ rĂ©solu ce problĂšme en Ă©crivant la base de donnĂ©es InfluxDB. Cette base est spĂ©cialement optimisĂ©e pour le stockage de donnĂ©es temporelles et convient parfaitement Ă la conservation des valeurs de diffĂ©rents capteurs. Le systĂšme propose Ă©galement un langage de requĂȘte similaire Ă SQL, qui permet d'extraire des valeurs de la base, puis de les agrĂ©ger de diffĂ©rentes maniĂšres. Enfin, on peut conserver diffĂ©rentes donnĂ©es pendant des pĂ©riodes diffĂ©rentes. Par exemple, des mesures qui changent frĂ©quemment, comme la tempĂ©rature ou l'humiditĂ©, peuvent ĂȘtre stockĂ©es pendant seulement quelques semaines, alors que les relevĂ©s quotidiens de consommation d'eau peuvent ĂȘtre conservĂ©s pendant un an entier.
En plus d'InfluxDB, des personnes intelligentes ont Ă©galement inventĂ© Grafana â un systĂšme de crĂ©ation de graphiques Ă partir des donnĂ©es d'InfluxDB. Grafana peut crĂ©er diffĂ©rents types de graphiques, les personnaliser en dĂ©tail, et, surtout, ces graphiques peuvent ĂȘtre 'intĂ©grĂ©s' dans l'interface Lovelace de Home Assistant.
S'inspirer de et . Les articles décrivent en détail le processus d'installation et de connexion d'InfluxDB et de Grafana à Home Assistant. Quant à moi, je vais me concentrer sur la résolution de mon problÚme spécifique.
Alors, tout d'abord, nous allons commencer par enregistrer la valeur du compteur dans InfluxDB. Voici un extrait de la configuration de Home Assistant (dans cet exemple, je vais m'amuser avec de l'eau froide et chaude) :
influxdb:
hĂŽte: localhost
max_retries: 3
default_measurement: state
database: homeassistant
include:
entities:
- sensor.water_meter_hot
- sensor.water_meter_coldNous allons dĂ©sactiver la sauvegarde de ces mĂȘmes donnĂ©es dans la base interne de Home Assistant, afin de ne pas l'encombrer inutilement :
recorder:
purge_keep_days: 10
purge_interval: 1
exclude:
entities:
- sensor.water_meter_hot
- sensor.water_meter_coldPassons maintenant à la console InfluxDB et configurons notre base de données. En particulier, il est nécessaire de définir combien de temps certaines données seront conservées. Cela est régulé par la politique de conservation, qui est similaire à des bases de données à l'intérieur de la base de données principale, chaque base interne ayant ses propres paramÚtres. Par défaut, toutes les données sont stockées dans la politique de conservation appelée autogen, ces données seront conservées pendant une semaine. Je voudrais que les données horaires soient conservées un mois, hebdomadaires - un an, et que les mensuelles ne soient jamais supprimées. Créons les politiques de conservation correspondantes.
CREATE RETENTION POLICY "month" ON "homeassistant" DURATION 30d REPLICATION 1
CREATE RETENTION POLICY "year" ON "homeassistant" DURATION 52w REPLICATION 1
CREATE RETENTION POLICY "infinite" ON "homeassistant" DURATION INF REPLICATION 1Maintenant, le principal tour de magie - l'agrĂ©gation des donnĂ©es Ă l'aide d'une requĂȘte continue. C'est un mĂ©canisme qui exĂ©cute automatiquement une requĂȘte Ă intervalles rĂ©guliers, agrĂšge les donnĂ©es selon cette requĂȘte et stocke le rĂ©sultat dans une nouvelle valeur. DĂ©montrons-le avec un exemple (j'Ă©cris en colonne pour la lisibilitĂ©, mais en rĂ©alitĂ©, j'ai dĂ» entrer cette commande sur une seule ligne).
CREATE CONTINUOUS QUERY cq_water_hourly ON homeassistant
BEGIN
SELECT max(value) AS value
INTO homeassistant.month.water_meter_hour
FROM homeassistant.autogen.l
GROUP BY time(1h), entity_id fill(previous)
ENDCette commande :
- CrĂ©e une requĂȘte continue nommĂ©e cq_water_cold_hourly dans la base homeassistant.
- La requĂȘte sera exĂ©cutĂ©e chaque heure (time(1h)).
- La requĂȘte rĂ©cupĂ©rera toutes les donnĂ©es de la mesure homeassistant.autogen.l (litres), y compris les relevĂ©s d'eau froide et chaude.
- Les données agrégées seront regroupées par entity_id, ce qui nous donnera des valeurs distinctes pour l'eau froide et l'eau chaude.
- Ătant donnĂ© que le compteur de litres est une sĂ©quence monotone croissante, dans le cadre de chaque heure, il faudra prendre la valeur maximale, donc l'agrĂ©gation se fera avec la fonction max(value).
- La nouvelle valeur sera enregistrĂ©e dans homeassistant.month.water_meter_hour, oĂč month est le nom de la politique de conservation avec une pĂ©riode de stockage d'un mois. Les donnĂ©es d'eau froide et chaude seront rĂ©parties dans des enregistrements distincts avec les entity_id correspondants et les valeurs dans le champ value.
La nuit ou lorsque personne n'est Ă la maison, il n'y a pas de consommation d'eau, et donc pas de nouvelles entrĂ©es dans homeassistant.autogen.l non plus. Pour Ă©viter des valeurs manquantes dans les requĂȘtes normales, vous pouvez utiliser fill(previous). Cela forcera InfluxDB Ă utiliser la valeur de l'heure prĂ©cĂ©dente.
Malheureusement, la requĂȘte continue a une particularitĂ© : le truc fill(previous) ne fonctionne pas et les enregistrements ne sont tout simplement pas créés. Il s'agit d'un problĂšme apparemment insurmontable, qui . Nous aborderons ce problĂšme plus tard, et pour le moment, la fonction fill(previous) dans la requĂȘte continue pourra rester â elle ne gĂȘne pas.
Vérifions ce que nous avons obtenu (bien sûr, il faut attendre quelques heures) :
> select * from homeassistant.month.water_meter_hour group by entity_id
...
name: water_meter_hour
tags: entity_id=water_meter_cold
time value
---- -----
...
2020-03-08T01:00:00Z 370511
2020-03-08T02:00:00Z 370513
2020-03-08T05:00:00Z 370527
2020-03-08T06:00:00Z 370605
2020-03-08T07:00:00Z 370635
2020-03-08T08:00:00Z 370699
2020-03-08T09:00:00Z 370761
2020-03-08T10:00:00Z 370767
2020-03-08T11:00:00Z 370810
2020-03-08T12:00:00Z 370818
2020-03-08T13:00:00Z 370827
2020-03-08T14:00:00Z 370849
2020-03-08T15:00:00Z 370921
Notez que les valeurs dans la base sont enregistrĂ©es en UTC, donc dans cette liste, elles diffĂšrent de 3 heures â les valeurs Ă 7 heures du matin dans le rendu InfluxDB correspondent aux valeurs Ă 10 heures du matin sur les graphiques ci-dessus. Notez Ă©galement qu'il n'y a tout simplement pas d'enregistrements entre 2 et 5 heures â c'est cette mĂȘme particularitĂ© de la requĂȘte continue.
Comme vous pouvez le voir, la valeur agrĂ©gĂ©e est Ă©galement une sĂ©quence croissante monotone, les enregistrements Ă©tant seulement moins frĂ©quents â une fois par heure. Mais ce n'est pas un problĂšme â nous pouvons Ă©crire une autre requĂȘte qui extraira les bonnes donnĂ©es pour le graphique.
SELECT difference(max(value))
FROM homeassistant.month.water_meter_hour
WHERE entity_id='water_meter_cold' and time >= now() -24h
GROUP BY time(1h), entity_id
fill(previous)Je vais clarifier :
- Nous allons extraire les données de la base homeassistant.month.water_meter_hour pour entity_id='water_meter_cold' au cours des derniÚres 24 heures (time >= now() -24h).
- Comme je l'ai dĂ©jĂ mentionnĂ©, il peut manquer certains enregistrements dans la sĂ©quence homeassistant.month.water_meter_hour. Nous allons rĂ©gĂ©nĂ©rer ces donnĂ©es en lançant une requĂȘte avec GROUP BY time(1h). Cette fois, fill(previous) fonctionnera comme il se doit, en gĂ©nĂ©rant les donnĂ©es manquantes (la fonction prendra la valeur prĂ©cĂ©dente).
- L'Ă©lĂ©ment le plus important dans cette requĂȘte est la fonction difference, qui calculera la diffĂ©rence entre les horodatages horaires. Elle ne fonctionne pas seule et nĂ©cessite une fonction d'agrĂ©gation. Cela sera max() utilisĂ©e auparavant.
Le résultat d'exécution est le suivant :
name: water_meter_hour
tags: entity_id=water_meter_cold
time difference
---- ----------
...
2020-03-08T02:00:00Z 2
2020-03-08T03:00:00Z 0
2020-03-08T04:00:00Z 0
2020-03-08T05:00:00Z 14
2020-03-08T06:00:00Z 78
2020-03-08T07:00:00Z 30
2020-03-08T08:00:00Z 64
2020-03-08T09:00:00Z 62
2020-03-08T10:00:00Z 6
2020-03-08T11:00:00Z 43
2020-03-08T12:00:00Z 8
2020-03-08T13:00:00Z 9
2020-03-08T14:00:00Z 22
2020-03-08T15:00:00Z 72De 2 Ă 5 heures du matin (UTC), il n'y a eu aucune consommation. Cependant, la requĂȘte renverra la mĂȘme valeur de consommation grĂące Ă fill(previous), et la fonction difference soustraira cette valeur d'elle-mĂȘme, ce qui nous donnera 0, ce qui est justement ce qui est requis.
Il ne reste plus qu'à construire le graphique. Pour cela, ouvrons Grafana, prenons un tableau de bord existant (ou créons-en un nouveau), puis créons un nouveau panneau. Les paramÚtres des graphiques seront les suivants.

Je vais afficher les donnĂ©es sur l'eau froide et chaude sur un seul graphique. La requĂȘte est exactement celle que j'ai dĂ©crite ci-dessus.
Les paramÚtres d'affichage sont définis comme suit. Pour moi, ce sera un graphique à lignes (lines), qui sera en escalier (stairs). Je vais expliquer le paramÚtre Stack un peu plus bas. Il y a encore quelques paramÚtres d'affichage en dessous, mais ils ne sont pas aussi intéressants.

Pour ajouter le graphique obtenu Ă l'assistant maison, il faut :
- sortir du mode d'Ă©dition du graphique. Ătrangement, les paramĂštres corrects de partage des graphiques ne sont proposĂ©s que depuis la page du tableau de bord.
- Cliquer sur le triangle à cÎté du nom du graphique, puis dans le menu, choisir partager.
- Dans la fenĂȘtre qui s'ouvre, aller Ă l'onglet embarquer.
- DĂ©sĂ©lectionner la case current time range â la plage horaire sera dĂ©finie via l'URL.
- Choisir le thÚme nécessaire. Dans mon cas, c'est clair.
- Copier l'URL obtenue dans la carte de paramĂštres lovelace-UI.
- type: iframe
id: graf_water_hourly
url: "http://192.168.10.200:3000/d-solo/rZARemQWk/water?orgId=1&panelId=2&from=now-2d&to=now&theme=light"
Notez que la plage horaire (les 2 derniers jours) est définie ici, et non dans les paramÚtres du tableau de bord.
Le graphique ressemble à ça. Je n'ai pas utilisé d'eau chaude au cours des 2 derniers jours, donc seul le graphique de l'eau froide est affiché.

Je n'ai pas encore dĂ©cidĂ© quel graphique je prĂ©fĂšre, celui en escalier ou les vrais barres. Par consĂ©quent, je vais juste donner un exemple d'un graphique de consommation quotidienne, mais cette fois avec des barres. Les requĂȘtes sont construites de maniĂšre similaire Ă celles dĂ©crites ci-dessus. Les paramĂštres d'affichage sont les suivants :

Ce graphique ressemble à ça :

à propos du paramÚtre Stack. Dans ce graphique, la barre d'eau froide est dessinée au-dessus de celle d'eau chaude. La hauteur totale correspond à la consommation totale d'eau froide et chaude pour la période.
Tous les graphiques affichĂ©s sont dynamiques. Vous pouvez passer la souris sur un point d'intĂ©rĂȘt et voir les dĂ©tails et la valeur Ă un point prĂ©cis.
Malheureusement, il y a eu quelques points négatifs. Dans le graphique à barres (contrairement au graphique à lignes en escalier), le milieu de la barre ne se situe pas au milieu de la journée, mais à 00h00. Autrement dit, la moitié gauche de la barre est dessinée à la place du jour précédent. Les graphiques pour samedi et dimanche sont donc légÚrement décalés vers la gauche par rapport à la zone bleutée. Je n'ai pas encore trouvé comment y remédier.
Un autre problÚme réside dans l'impossibilité de travailler correctement avec des intervalles mensuels. En fait, la durée de l'heure / du jour / de la semaine est fixe, tandis que la durée du mois varie à chaque fois. InfluxDB ne peut travailler qu'avec des intervalles identiques. Pour l'instant, j'ai trouvé le moyen de définir un intervalle fixe de 30 jours. Oui, le graphique va un peu dériver au cours de l'année et les barres ne correspondra pas tout à fait aux mois. Mais comme cette fonctionnalité m'intéresse juste à titre d'indicateur, cela me convient.
Je vois au moins deux solutions :
- Abandonner les graphiques mensuels et se limiter aux hebdomadaires. 52 barres hebdomadaires par an se présentent plutÎt bien.
- ConsidĂ©rer la consommation mensuelle comme mĂ©thode n°2, et utiliser Grafana uniquement pour de beaux graphiques. Cela donnera une solution assez prĂ©cise. On peut mĂȘme superposer les graphiques de l'annĂ©e prĂ©cĂ©dente pour comparaison â Grafana sait le faire.
Conclusion
Je ne sais pas pourquoi, mais j'adore ce genre de graphiques. Ils montrent que la vie bouillonne et que tout change. Hier il y avait beaucoup, aujourd'hui peu, et demain sera encore diffĂ©rent. Il reste Ă travailler avec les membres du mĂ©nage sur le sujet de la consommation. Mais mĂȘme avec les appĂ©tits actuels, un chiffre simplement grand et incomprĂ©hensible sur la facture devient dĂ©jĂ un tableau de consommation assez clair.
MalgrĂ© presque 20 ans de carriĂšre en tant que programmeur, je n'ai pratiquement pas eu de contacts avec les bases de donnĂ©es. C'est pourquoi l'installation d'une base de donnĂ©es externe me semblait quelque chose de follement complexe et inconnu. Tout a changĂ© â il s'est avĂ©rĂ© que la connexion d'un outil appropriĂ© se fait en quelques clics, et avec un outil spĂ©cialisĂ©, la tĂąche de construction de graphiques devient un peu plus simple.
Dans le titre, j'ai mentionnĂ© la consommation d'Ă©lectricitĂ©. Malheureusement, je ne peux pas fournir de graphiques pour le moment. Un compteur SDM120 est tombĂ© en panne, et l'autre fonctionne mal lors de l'accĂšs via Modbus. Cela dit, cela n'a aucune incidence sur le sujet de cet article : les graphiques seront construits de la mĂȘme maniĂšre que pour l'eau.
Dans cet article, j'ai prĂ©sentĂ© les approches que j'ai expĂ©rimentĂ©es moi-mĂȘme. Il existe sĂ»rement d'autres mĂ©thodes pour organiser la collecte et la visualisation des donnĂ©es dont je ne suis pas au courant. N'hĂ©sitez pas Ă m'en parler dans les commentaires, cela m'intĂ©ressera beaucoup. Je serai ravi des critiques constructives et des nouvelles idĂ©es. J'espĂšre que le matĂ©riel exposĂ© pourra Ă©galement aider quelqu'un.
Source : habr.com
