
Cada vez que recibo la factura de electricidad y agua me sorprendo: ¿acaso mi familia consume tanto? Bueno, sí, hay suelo radiante y un calentador en el baño, pero no están funcionando todo el tiempo. También parece que estamos ahorrando agua (aunque nos gusta relajarnos en la bañera). Hace unos años ya y al hogar inteligente, pero eso se quedó ahí. Solo ahora he tenido tiempo de analizar el consumo, de lo cual trata este artículo.
Recientemente cambié a Home Assistant como mi sistema de hogar inteligente. Una de las razones fue precisamente la capacidad de recopilar una gran cantidad de datos y poder generar gráficos de diferentes tipos de manera conveniente.
La información descrita en este artículo no es nueva, todas estas cosas ya se han descrito en Internet bajo diferentes enfoques. Pero cada artículo, por lo general, describe solo un enfoque o aspecto. Comparar todos estos enfoques y elegir el más adecuado fue mi tarea. El artículo aún no proporciona información exhaustiva sobre la recopilación de datos, pero es una especie de resumen de cómo lo hice yo. Por lo tanto, se agradecen críticas constructivas y sugerencias de mejora.
Planteamiento del problema
Así que el objetivo del ejercicio de hoy es obtener gráficos atractivos del consumo de agua y electricidad:
- Por hora durante 2 días
- Por día durante 2 semanas
- (opcional) semanal y mensual
En esto nos encontramos con algunas dificultades:
- Los componentes gráficos estándar suelen ser bastante limitados. En el mejor de los casos, se puede construir un gráfico lineal a partir de puntos.
Si se busca bien, se pueden encontrar componentes de terceros que amplían las posibilidades del gráfico estándar. Para Home Assistant, el componente , aunque es bastante bueno y bonito, también tiene algunas limitaciones:
- Es complicado establecer parámetros para el gráfico de barras en intervalos grandes (el ancho de la barra se define en fracciones de hora, por lo que los intervalos mayores de una hora se definirán con números fraccionarios)
- No se pueden agregar diferentes entidades a un mismo gráfico (por ejemplo, temperatura y humedad, o combinar un gráfico de barras con una línea)
- No solo el asistente de inicio utiliza por defecto la base de datos más primitiva, SQLite (y yo, con mis torpes manos, no logré instalar MySQL o Postgres), sino que los datos se almacenan de la manera menos óptima. Por ejemplo, cada vez que cambia cualquier parámetro digital, por más pequeño que sea, se escribe en la base de datos un enorme JSON de alrededor de un kilobyte.
{"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}}}Tengo muchos sensores (sensores de temperatura en cada habitación, contadores de agua y electricidad), y algunos generan bastantes datos. Por ejemplo, solo el contador de electricidad SDM220 genera alrededor de una decena de valores cada 10-15 segundos, y me gustaría instalar alrededor de 8 de esos contadores. Además, hay un montón de parámetros que se calculan en función de otros sensores. Por lo tanto, todos estos valores fácilmente pueden aumentar la base de datos en 100-200 MB diariamente. Después de una semana, el sistema apenas funcionará, y después de un mes, la memoria flash se apagará (en el caso de una instalación típica del asistente en Raspberry PI), y ni hablar de almacenar datos durante un año.
- Si tienes suerte, tu contador puede medir el consumo por sí mismo. En cualquier momento, puedes consultar al contador y preguntar cuál es el valor acumulado del consumo. Por lo general, todos los contadores eléctricos que tienen una interfaz digital (RS232/RS485/Modbus/Zigbee) ofrecen tal posibilidad.
Es peor si el dispositivo solo puede medir un parámetro instantáneo (por ejemplo, potencia instantánea o corriente), o simplemente generar pulsos cada X vatios-hora o litros. Entonces hay que pensar en cómo y con qué integrarlo y dónde acumular el valor. Existe el riesgo de pasar por alto el próximo informe por alguna razón, y la precisión del sistema en general plantea dudas. Claro que se puede delegar esto a un sistema de hogar inteligente como home assistant, pero el punto sobre la cantidad de registros en la base de datos no se ha cancelado, y no se puede preguntar a los sensores con más frecuencia que una vez por segundo (limitación de la arquitectura de home assistant).
Enfoque 1
Primero veamos lo que proporciona home assistant fuera de la caja. La medición del consumo durante un periodo es una funcionalidad muy demandada. Por supuesto, hace tiempo que se implementó en forma de un componente especializado: utility_meter.
La esencia del componente es que introduce una variable current_accumulated_value y la restablece al final del periodo designado (hora/semana/mes). El componente monitoriza la variable de entrada (el valor de algún sensor), se suscribe a los cambios de valor y usted simplemente obtiene el resultado final. Esto se describe en solo unas pocas líneas en el archivo de configuración.
utility_meter:
water_cold_hour_um:
source: sensor.water_meter_cold
cycle: hourly
water_cold_day_um:
source: sensor.water_meter_cold
cycle: daily
Aquí, sensor.water_meter_cold es el valor actual del contador en litros, que recibo a través de MQTT. La estructura crea 2 nuevos sensores water_cold_hour_um y water_cold_day_um, que acumulan las lecturas horarias y diarias, restableciéndolas al final del periodo. Aquí está el gráfico del acumulador horario durante medio día.

El código para los gráficos horarios y diarios para lovelace-UI se ve así:
- type: history-graph
title: 'Consumo de agua horario usando vars'
hours_to_show: 48
entities:
- sensor.water_hour
- type: history-graph
title: 'Consumo de agua diario usando vars'
hours_to_show: 360
entities:
- sensor.water_day
De hecho, en este algoritmo radica el problema de este enfoque. Como mencioné anteriormente, para cada valor de entrada (la lectura actual del contador para cada siguiente litro) se genera 1 kB de registro en la base de datos. Cada medidor de servicios también genera un nuevo valor, que también se almacena en la base. Si quiero recopilar lecturas horarias/dia/semana/mensuales, además de varios grupos de agua, y agregar un montón de contadores eléctricos, ¡habrá muchos datos! Bueno, en realidad no son tantos datos, pero dado que el asistente doméstico escribe un montón de información innecesaria en la base, el tamaño de la base crecerá como la espuma. Temo incluso estimar el tamaño de la base para gráficos semanales y mensuales.
Además, el medidor de servicios por sí mismo no resuelve el problema planteado. El gráfico de valores que emite el medidor de servicios es una función que crece de manera monótona y se reinicia a 0 cada hora. Necesitamos un gráfico de consumo que sea comprensible para el usuario, que muestre cuántos litros se han consumido durante un periodo. El componente estándar history-graph no puede hacer esto, pero podemos utilizar un componente externo llamado mini-graph-card.
Este es el código de la tarjeta para lovelace-UI:
- aggregate_func: max
entities:
- color: var(--primary-color)
entity: sensor.water_cold_hour_um
group_by: hour
hours_to_show: 48
name: "Consumo de agua horario agregado por medidor de servicios"
points_per_hour: 1
show:
graph: bar
type: 'custom:mini-graph-card'Además de las configuraciones estándar como el nombre del sensor, el tipo de gráfico y el color (no me gustó el naranja estándar), es importante señalar 3 configuraciones:
- group_by:hour — el gráfico se generará alineando las barras al inicio de la hora.
- points_per_hour: 1 — una barra para cada hora.
- Y lo más importante, aggregate_func: max — obtener el valor máximo dentro de cada hora. Precisamente este parámetro convierte el gráfico en barras.

No prestes atención a la serie de barras a la izquierda, es el comportamiento estándar del componente si no hay datos. Y no hubo datos, ya que solo hace un par de horas activé la recopilación de datos del medidor de servicios solo para este artículo (mi enfoque actual lo explicaré más adelante).
En esta imagen quería mostrar que a veces la visualización de datos funciona, y las barras realmente reflejan los valores correctos. Sin embargo, no todas lo hacen. La barra destacada entre las 11 y las 12 de la mañana muestra 19 litros, mientras que en el gráfico dentado arriba, durante el mismo período y desde el mismo sensor, vemos un consumo de 62 litros. O es un error, o hay algo mal hecho. Aún no he entendido por qué se rompieron los datos a la derecha — el consumo allí era normal, lo cual también se ve en el gráfico dentado.
En general, no logré hacer que este enfoque fuera creíble — el gráfico casi siempre muestra alguna tontería.
Código similar para el sensor diario.
- aggregate_func: max
entities:
- color: var(--primary-color)
entity: sensor.water_cold_day_um
group_by: interval
hours_to_show: 360
name: "Consumo diario de agua agregado por medidor de servicios"
points_per_hour: 0.0416666666
show:
graph: bar
type: 'custom:mini-graph-card'
Tenga en cuenta que el parámetro group_by se establece en interval y está controlado por el parámetro points_per_hour. Aquí radica otro problema de este componente: points_per_hour funciona bien en gráficos de una hora o menos, pero funciona muy mal en intervalos mayores. Así que para obtener una barra por un día, tuve que introducir el valor 1/24=0.04166666. Ya ni hablemos de gráficos semanales y mensuales.
Enfoque 2
Aún mientras aprendía sobre home assistant, me encontré con este video:

Un compañero recopila datos de consumo de varios tipos de enchufes de Xiaomi. Su tarea es un poco más sencilla: simplemente mostrar el valor del consumo de hoy, ayer y del mes. No se requieren gráficos.
Dejaremos de lado las consideraciones sobre la integración manual de los valores instantáneos de potencia — ya he escrito sobre la "precisión" de este enfoque anteriormente. No está claro por qué no usó los valores acumulados de consumo, que ya recoge el mismo enchufe. En mi opinión, la integración dentro del dispositivo funcionará mejor.
Tomaremos del video la idea del cálculo manual del consumo durante un período. El hombre solo cuenta los valores de hoy y ayer, pero iremos más allá e intentaremos dibujar un gráfico. La esencia del método propuesto en mi caso es la siguiente.
Crearemos una variable valor_al_inicio_de_la_hora, en la que registraremos las lecturas actuales del contador.
Al final de la hora (o al principio de la siguiente), contaremos la diferencia entre la lectura actual y la guardada al inicio de la hora. Esta diferencia será el consumo de la hora actual; almacenaremos el valor en el sensor y en el futuro construiremos un gráfico basado en este valor.
También es necesario "resetear" la variable valor_al_inicio_hora guardando allí el valor actual del contador.
Todo esto se puede hacer a través de las herramientas del propio home assistant.
Tendremos que escribir un poco más de código que en el enfoque anterior. Primero estableceremos estas "variables". No tenemos una entidad de "variable" de forma predeterminada, pero podemos recurrir a los servicios del broker mqtt. Enviaremos valores con la bandera retain=true; esto mantendrá el valor dentro del broker y podrá recuperarse en cualquier momento, incluso al reiniciar home assistant. He creado contadores horarios y diarios de inmediato.
- 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: lToda la magia ocurre en la automatización que se ejecuta cada hora y cada noche, respectivamente.
- 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: trueAmbas automatizaciones realizan 2 acciones:
- Calculan el valor del intervalo como la diferencia entre el valor inicial y el final
- Actualizan el valor base para el siguiente intervalo
La construcción de gráficos en este caso se resuelve con un history-graph normal:
- type: history-graph
title: 'Consumo de agua horario usando vars'
hours_to_show: 48
entities:
- sensor.water_hour
- type: history-graph
title: 'Consumo de agua diario usando vars'
hours_to_show: 360
entities:
- sensor.water_dayAsí es como se ve:

En principio, esto es ya lo que se necesita. La ventaja de este método es que los datos se generan una sola vez por intervalo. Es decir, en total 24 registros por día para el gráfico horario.
Lamentablemente, esto no resuelve el problema general de la creciente base de datos. Si quiero un gráfico del consumo mensual, tendré que almacenar datos durante al menos un año. Y dado que el asistente doméstico solo proporciona una configuración de duración de almacenamiento para toda la base, eso significa que TODOS los datos en el sistema tendrán que almacenarse durante un año. Por ejemplo, en un año consumo 200 metros cúbicos de agua, lo que equivale a 200000 registros en la base. Y si consideramos otros sensores, la cifra se vuelve realmente exorbitante.
Enfoque 3
Afortunadamente, personas inteligentes ya han resuelto este problema al crear la base de datos InfluxDB. Esta base está optimizada específicamente para el almacenamiento de datos basados en el tiempo y es ideal para almacenar los valores de diferentes sensores. El sistema también proporciona un lenguaje de consultas similar a SQL, que permite extraer valores de la base y luego agregarlos de diversas maneras. Finalmente, diferentes datos se pueden almacenar durante diferentes períodos. Por ejemplo, lecturas que cambian con frecuencia, como la temperatura o la humedad, se pueden almacenar solo durante un par de semanas, mientras que las lecturas diarias del consumo de agua se pueden almacenar durante todo un año.
Además de InfluxDB, las personas inteligentes también han inventado Grafana, un sistema para crear gráficos con datos de InfluxDB. Grafana puede dibujar diferentes tipos de gráficos, personalizarlos en detalle y, lo más importante, estos gráficos se pueden “incrustar” en la interfaz Lovelace del asistente doméstico.
Inspirarse y . Los artículos describen en detalle el proceso de instalación y conexión de InfluxDB y Grafana al asistente doméstico. Yo me centraré en resolver mi tarea específica.
Así que, lo primero que haremos es comenzar a almacenar el valor del medidor en InfluxDB. Un fragmento de configuración del asistente doméstico (en este ejemplo me entretendré no solo con agua fría, sino también con agua caliente):
influxdb:
host: localhost
max_retries: 3
default_measurement: state
database: homeassistant
include:
entities:
- sensor.water_meter_hot
- sensor.water_meter_coldDesactivaremos el almacenamiento de estos mismos datos en la base de datos interna del asistente doméstico, para no inflarla innecesariamente:
recorder:
purge_keep_days: 10
purge_interval: 1
exclude:
entities:
- sensor.water_meter_hot
- sensor.water_meter_coldAhora pasemos a la consola de InfluxDB y configuremos nuestra base de datos. En particular, necesitamos ajustar cuánto tiempo se almacenarán ciertos datos. Esto se regula mediante la llamada política de retención, que se asemeja a bases de datos dentro de la base de datos principal, y cada base interna tiene su propia configuración. Por defecto, todos los datos se almacenan en una política de retención llamada autogen, y estos datos se almacenarán durante una semana. Me gustaría que los datos horarios se guardaran un mes, los semanales un año, y los mensuales nunca se eliminaran. Crearemos las políticas de retención correspondientes.
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 1Ahora, el truco principal: la agregación de datos mediante consulta continua. Este es un mecanismo que ejecuta automáticamente una consulta a intervalos de tiempo establecidos, agrega datos según esa consulta, y almacena el resultado en un nuevo valor. Vamos a verlo con un ejemplo (escribo en columnas para facilitar la lectura, pero en realidad tuve que introducir este comando en una sola línea).
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)
ENDEste comando:
- Crea una consulta continua llamada cq_water_cold_hourly en la base homeassistant.
- La consulta se ejecutará cada hora (time(1h)).
- La consulta recogerá todos los datos de la medición homeassistant.autogen.l (litros), incluyendo las lecturas de agua fría y caliente.
- Los datos agregados se agruparán por entity_id, lo que nos dará valores separados para el agua fría y caliente.
- Dado que el contador de litros es una secuencia monotonamente creciente, dentro de cada hora se tomará el valor máximo; por lo tanto, la agregación se realizará mediante la función max(value).
- El nuevo valor se registrará en homeassistant.month.water_meter_hour, donde month es el nombre de la política de retención con un período de almacenamiento de un mes. Además, los datos de agua fría y caliente se distribuirán en entradas separadas con el correspondiente entity_id y valor en el campo value.
Durante la noche o cuando no hay nadie en casa, no hay consumo de agua y, por lo tanto, tampoco hay nuevos registros en homeassistant.autogen.l. Para evitar que haya omisiones de valores en consultas normales, se puede usar fill(previous). Esto hará que InfluxDB utilice el valor de la hora anterior.
Lamentablemente, la consulta continua tiene una característica: el truco fill(previous) no funciona y los registros simplemente no se crean. Además, es un problema insuperable que . Abordaremos este problema más adelante, y el fill(previous) en la consulta continua puede permanecer, ya que no interfiere.
Verificaremos qué hemos obtenido (por supuesto, hay que esperar un par de horas):
> 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
Tenga en cuenta que los valores en la base de datos se guardan en UTC, por lo que en esta lista difieren por 3 horas: los valores de las 7 de la mañana en la salida de InfluxDB corresponden a los valores de las 10 de la mañana en los gráficos anteriores. También tenga en cuenta que entre las 2 y las 5 de la mañana simplemente no hay registros: esa es la característica de la consulta continua.
Como puede ver, el valor agregado también es una secuencia monótonamente creciente, solo que los registros son menos frecuentes: una vez por hora. Pero no es un problema: podemos escribir otra consulta que extraiga los datos correctos para el gráfico.
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)Dejaré claro:
- Extraeremos datos de la base de datos homeassistant.month.water_meter_hour para entity_id='water_meter_cold' durante las últimas 24 horas (time >= now() -24h).
- Como mencioné anteriormente, en la secuencia homeassistant.month.water_meter_hour pueden faltar algunos registros. Estos datos los generaremos de nuevo, ejecutando la consulta con GROUP BY time(1h). Esta vez fill(previous) funcionará como se espera, generando los datos faltantes (la función tomará el valor anterior)
- Lo más importante en esta consulta es la función difference, que calculará la diferencia entre las marcas horarias. Por sí sola no funciona y requiere una función de agregación. Que sea max() como se usó antes.
El resultado de la ejecución se ve así
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 a 5 de la mañana (UTC) no hubo consumo. Sin embargo, la consulta devolverá el mismo valor de consumo gracias a fill(previous), y la función difference restará este valor de sí mismo y obtendremos 0, que es lo que se requiere.
Solo falta lo más sencillo: construir el gráfico. Para ello, abrimos Grafana, abrimos algún panel existente (o creamos uno nuevo), y creamos un nuevo panel. La configuración de los gráficos será la siguiente.

Voy a mostrar los datos de agua fría y caliente en un mismo gráfico. La consulta es exactamente la misma que describí anteriormente.
Los parámetros de visualización se definen así. En mi caso, será un gráfico de líneas (lines) que avanza en escalones (stairs). El parámetro Stack lo explicaré un poco más abajo. A continuación, hay otros parámetros de visualización, pero no son tan interesantes.

Para añadir el gráfico obtenido a home assistant, se necesita:
- salir del modo de edición del gráfico. Por alguna razón, la configuración correcta de compartir gráficos solo se ofrece desde la página del dashboard.
- Hacer clic en el triángulo junto al nombre del gráfico, en el menú seleccionar compartir.
- En la ventana que se abre, ir a la pestaña de insertar.
- Desmarcar la casilla de rango de tiempo actual: el rango de tiempo lo estableceremos a través de la URL.
- Seleccionar el tema necesario. En mi caso, es claro.
- Copiar la URL resultante en la tarjeta de configuración de 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"
Tenga en cuenta que el rango de tiempo (últimos 2 días) se define aquí, y no en la configuración del dashboard.
Así es como se ve el gráfico. No utilicé agua caliente en los últimos 2 días, por lo que solo se muestra el gráfico del agua fría.

Así que aún no he decidido cuál gráfico me gusta más, el de línea escalonada o las verdaderas barras. Por eso, simplemente daré un ejemplo de gráfico diario de consumo, pero esta vez con barras. Las consultas se construyen de manera similar a las descritas anteriormente. Los parámetros de visualización son los siguientes:

Este gráfico se ve así:

Así que sobre el parámetro Stack. En este gráfico, la barra de agua fría se dibuja sobre la barra de agua caliente. La altura total corresponde al consumo total de agua fría y caliente durante el período.
Todos los gráficos mostrados son dinámicos. Se puede pasar el ratón sobre un punto de interés y ver los detalles y el valor en un punto específico.
Desafortunadamente, no se pudo evitar un par de cucharadas de alquitrán. En el gráfico de columnas (a diferencia del gráfico de líneas escalonadas), el medio de la columna no se encuentra a la mitad del día, sino a las 00:00. Es decir, la mitad izquierda de la columna se dibuja en el lugar del día anterior. Así que los gráficos del sábado y domingo están dibujados un poco más a la izquierda que la zona azulada. Aún no he encontrado la manera de solucionar esto.
Otro problema radica en la imposibilidad de trabajar correctamente con intervalos mensuales. La cuestión es que la duración de la hora/día/semana es fija, mientras que la duración del mes varía cada vez. InfluxDB solo puede trabajar con intervalos iguales. Por ahora, solo he podido establecer un intervalo fijo de 30 días. Sí, el gráfico se desviará un poco a lo largo del año y las columnas no corresponderán exactamente a los meses. Pero como esta cosa me interesa simplemente como medidor, estoy bien con eso.
Veo al menos dos soluciones:
- Ignorar los gráficos mensuales y limitarnos a los semanales. 52 columnas semanales al año se ven bastante bien.
- Calcular el consumo mensual como método nº 2, usando Grafana solo para gráficos bonitos. Se obtendrá una solución bastante precisa. Incluso se pueden superponer los gráficos del año pasado para comparación — Grafana puede hacer eso.
Conclusión
No sé por qué, pero me encanta este tipo de gráficos. Muestran que la vida está en constante movimiento y todo cambia. Ayer había mucho, hoy poco, mañana será algo diferente. Solo queda trabajar con los miembros de la familia sobre el tema del consumo. Pero incluso con los apetitos actuales, simplemente un número grande y confuso en la factura ya se transforma en una imagen de consumo bastante clara.
A pesar de tener casi 20 años de carrera como programador, apenas he tenido contacto con bases de datos. Por eso, la instalación de una base de datos externa me parecía algo tan abstracto e incomprensible. Todo cambió resultó ser que conectar la herramienta adecuada se hace en un par de clics, y con una herramienta especializada, la tarea de crear gráficos se vuelve un poco más fácil.
En el título mencioné el consumo de electricidad. Lamentablemente, en este momento no puedo proporcionar ningún gráfico. Un contador SDM120 se ha roto, y el otro falla al comunicarse a través de Modbus. Sin embargo, esto no afecta el tema del artículo: los gráficos se construirán de la misma manera que los de agua.
En este artículo he presentado los enfoques que he probado yo mismo. Seguramente hay otros métodos para organizar la recolección y visualización de datos que desconozco. Cuéntame sobre ellos en los comentarios, me interesará mucho. Apreciaré las críticas constructivas y nuevas ideas. Espero que el material expuesto también ayude a alguien más.
Fuente: habr.com
