Умен дом: Създаваме графики на потреблението на вода и електричество в Home Assistant

Умен дом: Създаваме графики на потреблението на вода и електричество в Home Assistant
Всеки път, когато получа сметките за електричество и вода, се учудвам – наистина ли семейството ми консумира толкова много? Да, в банята имаме подово отопление и бойлер, но те не работят постоянно. Също така явно пестим вода (въпреки че обичаме да си поплескаме в банята). Преди няколко години вече инсталирах водомери и електричество към умния дом, но оттогава нищо не се е случило. Анализът на потреблението е дошъл на дневен ред едва сега, за което всъщност е тази статия.

Наскоро преминах на Home Assistant като система за умен дом. Една от причините беше именно възможността да организираме събиране на множество данни с удобна опция за построяване на различни графики.

Информацията, описана в тази статия, не е нова; всички тези неща вече са били обсъждани онлайн под различни формати. Но всяка статия обикновено описва само един подход или аспект. Сравняването на всички тези подходи и избора на най-подходящия се наложи да го направя сам. Статията в същото време не предоставя изчерпателна информация за събиране на данни, а представлява своего рода резюме на това, как направих аз. Така че конструктивна критика и предложения за подобрения са добре дошли.

Формулиране на задачата

И така, целта на днешното упражнение е да получим красиви графики за потреблението на вода и електричество:

  • Часови за 2 дни
  • Дневни за 2 седмици
  • (по желание) седмични и месечни

Тук ни подстерегат някои затруднения:

  • Стандартните компоненти на графиките обикновено са доста бедни. В най-добрия случай можем да построим линейна графика на базата на точки.

    Ако се потърси добре, може да се намерят външни компоненти, които разширяват възможностите на стандартния график. За home assistant, в принципе, добър и красив компонент е mini-graph-card, но и той е малко ограничен:

    • Трудно е да се зададат параметрите на стълбовия график при дълги интервали (ширината на стълба се задава в часови дялове, а следователно интервалите, по-дълги от един час, ще се задават с дробни числа)
    • Невъзможно е да добавяме различни ентитети на един график (например температура и влажност, или да комбинираме стълбов график с линия)
  • Освен че home assistant по подразбиране използва най-примитивната база данни SQLite (а аз, некадърникът, не умея да инсталирам MySQL или Postgres), данните се съхраняват и по не особено оптимален начин. Например, при всяка промяна на дори най-малкият цифров параметър, в базата данни се записва огромен JSON с размер около килобайт.
    {"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}}}

    Имам доста датчици (температурни датчици във всяка стая, водомери и електромери), а някои от тях генерират доста данни. Например, само електромерът SDM220 генерира около десетина стойности на всеки 10-15 секунди, а бих искал да инсталирам осем такива. Освен това има цяла поредица параметры, които се изчисляват на базата на други датчици. Така всички тези стойности лесно могат да увеличат базата с 100-200 Мб дневно. След седмица системата едва ще работи, а след месец флашката ще се повреди (в случай на типична инсталация на home assistant на Raspberry PI), а за съхранение на данни за цяла една година не може да става и дума.

  • Ако сте имали късмет, вашият счетчик сам прави сметките за потребление. Вие по всяко време можете да се обърнете към счетчика и да попитате за натрупаната стойност на потреблението. Обикновено всички електромери, които имат цифров интерфейс (RS232/RS485/Modbus/Zigbee) предоставят такава възможност.

    По-лошо е, ако устройството може просто да измерва някакъв мигновен параметър (например мигновена мощност или ток) или просто да генерира импулси на всеки X ват-часа или литра. Тогава трябва да се мисли как и с какво да се интегрира и къде да се натрупва стойността. Има риск да се пропусне пореден отчет по някаква причина, освен това точността на системата като цяло предизвиква въпроси. Може, разбира се, да се делегира всичко това на система за умен дом като home assistant, но точката за броя на записите в базата данни никой не я отменя, а и опитването да се опрашват сензори по-често от веднъж в секунда не е възможно (ограничение на архитектурата на home assistant).

Подход 1

Първо да видим какво предоставя home assistant от кутията. Измерването на потреблението за период — много търсена функционалност. Разбира се, отдавна е реализирана под формата на специализиран компонент — utility_meter.

Същността на компонента е, че той въвежда променлива current_accumulated_value и я нулира след изтичането на зададения период (час/седмица/месец). Компонентът сам следи входящата променлива (стойността на някой сензор), сам подписва за промени в стойността — вие просто получавате готовия резултат. Това нещо се описва с няколко реда в конфигурационния файл.

utility_meter:
  water_cold_hour_um:
    source: sensor.water_meter_cold
    cycle: hourly
  water_cold_day_um:
    source: sensor.water_meter_cold
    cycle: daily

Тук sensor.water_meter_cold е текущата стойност на счетчика в литри, които получавам направо от устройството по mqtt. Конструкцията създава 2 нови сензора water_cold_hour_um и water_cold_day_um, които натрупват часови и дневни показания, нулирайки ги след изтичането на периода. Ето графика на часовия акумулатор за половин ден.

Умен дом: Създаваме графики на потреблението на вода и електричество в Home Assistant

Кодът на часовите и дневните графици за lovelace-UI изглежда така:

      - type: history-graph
        title: 'Потребление на вода на час с използване на променливи'
        hours_to_show: 48
        entities:
          - sensor.water_hour

      - type: history-graph
        title: 'Дневно потребление на вода с използване на променливи'
        hours_to_show: 360
        entities:
          - sensor.water_day

Всъщност, в този алгоритъм се крие проблемът на този подход. Както вече споменах, за всяка входяща стойност (настоящото показание на брояча за всеки следващ литър) се генерира по 1Кб запис в базата. Всеки utility meter също генерира нова стойност, която също се добавя в базата. Ако искам да събирам часови/дневни/седмични/месечни показания, да добавя няколко тръби за вода и куп електрически броячи — това ще бъдат много данни. Всъщност данните не са много, но тъй като home assistant записва куп излишна информация в базата, размерът ѝ ще расте като дрожди. Страхувам се дори да преценя размерът на базата за седмични и месечни графики.

Освен това, utility meter сам по себе си не решава поставената задача. Графикът на стойностите, които дава utility meter, е монотонно нарастваща функция, която се нулира на 0 всеки час. На нас обаче ни трябва разбираем за потребителя график на потреблението, колко литра са били използвани за периода. Стандартният компонент history-graph не може да направи това, но можем да използваме външен компонент mini-graph-card.

Това е кодът на картата за lovelace-UI:

      - aggregate_func: max
        entities:
          - color: var(--primary-color)
            entity: sensor.water_cold_hour_um
        group_by: hour
        hours_to_show: 48
        name: "Часово потребление на вода, агрегиранo по utility meter"
        points_per_hour: 1
        show:
          graph: bar
        type: 'custom:mini-graph-card'

Освен стандартните настройки като име на сензора, тип график, цвят (стандартният оранжев не ми хареса), важно е да се отбележат 3 настройки:

  • group_by:hour — графикът ще се генерира с подравняване на стълбчетата по началото на часа
  • points_per_hour: 1 — едно стълбче за всеки час
  • И най-важното, aggregate_func: max — вземане на максималната стойност в рамките на всеки час. Именно този параметър преобразува зъбчатия график в стълбчета

Умен дом: Създаваме графики на потреблението на вода и електричество в Home Assistant

Не обръщайте внимание на редицата стълбчета вляво — това е стандартно поведение на компонента, когато няма данни. А данни наистина нямаше — само преди няколко часа включих събирането на данни по utility meter само за тази статия (своята настояща схема ще опиша малко по-долу).

На тази снимка исках да покажа, че понякога визуализацията на данните всъщност работи и колонките наистина отразяват правилните стойности. Само че не всички. Изолираният стълбец за интервала от 11 до 12 ч. показва 19 литра, въпреки че на зъбатия график малко по-нагоре за същия период от същия сензор виждаме потребление от 62 литра. Или е бъг, или има проблем с кода. А защо данните от дясната страна са се отрязали, все още не разбирам — потреблението там беше в нормата, което е видно и от зъбатия график.

В общи линии, не успях да постигна правдоподобност с този подход — графикът почти винаги показва някаква глупост.

Аналогичен код за дневния сензор.

      - aggregate_func: max
        entities:
          - color: var(--primary-color)
            entity: sensor.water_cold_day_um
        group_by: interval
        hours_to_show: 360
        name: "Дневно потребление на вода агрегирано по утилитен метър"
        points_per_hour: 0.0416666666
        show:
          graph: bar
        type: 'custom:mini-graph-card'

Обърнете внимание, че параметърът group_by е зададен на стойност interval и контролира всичките параметри points_per_hour. И в това се крие друг проблем на този компонент — points_per_hour работи добре на графики за час или по-малко, но ужасно на по-дълги интервали. За да получим един стълбец за един ден, трябваше да впиша стойността 1/24=0.04166666. Дори не споменавам седмичните и месечните графики.

Подход 2

Все още разглеждам home assistant и попаднах на това видео:

Възпроизведи видео

Приятелът събира данни за потреблението от няколко типа розетки Xiaomi. Неговата задача е малко по-проста — просто да показва стойността на потреблението за днес, вчера и за месеца. Никакви графики не са необходими.

Ще оставим настрана разискванията за ръчната интеграция на моментните стойности на мощността — за "точността" на такъв подход вече писах по-горе. Не е ясно защо не е използвал натрупаните стойности на потреблението, които вече се събират от същата розетка. Според мен интеграцията вътре в устройството ще работи по-добре.

От видеото ще вземем идеята за ръчното изчисление на потреблението за период. При човека се отчитат само стойностите за днес и вчера, но ние ще отидем по-далеч и ще опитаме да нарисуваме график. Същността на предложения метод в моя случай е следната.

Ще зададем променлива значение_в_начале_часа, в която ще запишем текущите показания на измервателя.
В края на часа (или в началото на следващия) ще изчислим разликата между текущото показание и запомненото в началото на часа. Тази разлика ще бъде потреблението за текущия час — ще запазим стойността в сензора и в бъдеще ще изградим график въз основа на тази стойност.
Също така трябва да "нулираме" променливата значение_в_начале_часа, записвайки текущата стойност на брояча в нея.

Всичко това може да се направи чрез ж… с помощта на самия home assistant.

Кодът ще трябва да се напише малко повече от предходния подход. Първо ще създадем тези "променливи". По подразбиране нямаме същността "променлива", но можем да се възползваме от услугите на mqtt брокера. Ще изпращаме стойности там с флаг retain=true — това ще запази стойността вътре в брокера, и в който и да е момент може да бъде извлечена, дори при повторно стартиране на home assistant. Създадох часови и дневни броячи.

- 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: l

Цялата магия се случва в автоматизацията, която се стартира всеки час и всяка нощ съответно.

- 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: true

Двете автоматизации изпълняват 2 действия:

  • Изчисляват стойността за интервала като разлика между началната и крайната стойност
  • Актуализират базовата стойност за следващия интервал

Изграждането на графици в този случай се решава с обикновен history-graph:

      - type: history-graph
        title: 'Потребление на вода на час с използване на променливи'
        hours_to_show: 48
        entities:
          - sensor.water_hour

      - type: history-graph
        title: 'Дневно потребление на вода с използване на променливи'
        hours_to_show: 360
        entities:
          - sensor.water_day

Изглежда така:

Умен дом: Създаваме графики на потреблението на вода и електричество в Home Assistant

По принцип, това вече е точно това, което е нужно. Предимството на този метод е, че данните се генерират веднъж за интервала. Т.е. само 24 записа за денонощие за часовия график.

За съжаление, общият проблем с нарастващата база данни все пак не се решава. Ако искам график на месечното потребление, ще трябва да съхранявам данните поне за една година. А тъй като home assistant предлага само една настройка за продължителността на съхранение на цялата база, това означава, че ВСИЧКИ данни в системата трябва да се съхраняват цели 12 месеца. Например, за година потребявам 200 кубика вода, което означава 200000 записа в базата. А ако вземем предвид и другите сензори, числото става просто неприлично.

Подход 3

За щастие, интелигентни хора вече решиха този проблем, написвайки базата данни InfluxDB. Тази база е специално оптимизирана за съхранение на времево обвързани данни и е идеална за съхранение на стойностите на различни сензори. Системата също така предоставя SQL-подобен език за заявки, който позволява извличане на стойности от базата и след това агрегиране по различни начини. Накрая, различните данни могат да се съхраняват различно дълго време. Например, често променящи се показания като температура или влажност могат да се съхраняват само за няколко седмици, докато дневните показания за потребление на вода могат да се съхраняват цели 12 месеца.

Освен InfluxDB, интелигентни хора също така изобретиха Grafana — система за графично представяне на данни от InfluxDB. Grafana може да рисува различни видове графици, да ги кастомизира подробно и най-важното — тези графици могат да бъдат вградени в интерфейса lovelace на home assistant.

Вдъхновение тук и тук. В статиите подробно е описан процесът на инсталиране и свързване на InfluxDB и Grafana с home assistant. Аз обаче ще се съсредоточа върху решаването на моя конкретен проблем.

И така, първо ще започнем да съхраняваме стойността на брояча в InfluxDB. Част от конфигурацията на home assistant (в този пример ще се занимавам не само с топла, но и с студена вода):

influxdb:
  host: localhost
  max_retries: 3
  default_measurement: state
  database: homeassistant
  include:
    entities:
      - sensor.water_meter_hot
      - sensor.water_meter_cold

Ще изключим съхраняването на същите тези данни в вътрешната база на home assistant, за да не я раздуваме излишно:

recorder:
  purge_keep_days: 10
  purge_interval: 1
  exclude:
    entities:
      - sensor.water_meter_hot
      - sensor.water_meter_cold

Сега да преминем към конзолата на InfluxDB и да настроим нашата база. По-конкретно, трябва да зададем колко време ще се съхраняват определени данни. Това се регулира от т.н. retention policy — подобно е на бази данни вътре в основната база данни, като всяка вътрешна база има свои настройки. По подразбиране всички данни се съхраняват в retention policy, наречена autogen, и тези данни ще се съхраняват за една седмица. Бих искал часовите данни да се съхраняват за един месец, седмичните — за една година, а месечните изобщо да не се изтриват. Нека създадем съответните retention policy.

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 1

Сега, всъщност, главният трик — агрегиране на данни с помощта на continuous query. Това е механизъм, който автоматично изпълнява заявка на зададени интервали от време, агрегира данните по тази заявка, а резултатът се записва в ново значение. Нека разгледаме примера (пиша в колона за удобочитаемост, но всъщност ми се наложи да въведа тази команда в един ред).

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) 
END

Тази команда:

  • Създава continuous query с името cq_water_cold_hourly в базата homeassistant.
  • Запитването ще се изпълнява всеки час (time(1h)).
  • Запитването ще извлича всички данни от measurement'a homeassistant.autogen.l (литри), включително показанията на студена и гореща вода.
  • Агрегираните данни ще бъдат групирани по entity_id, което ще създаде отделни стойности за студена и гореща вода.
  • Тъй като измервателят на литри представлява монотонно нарастваща последователност, в рамките на всеки час ще трябва да вземем максималното значение, затова агрегацията ще се извършва с функцията max(value).
  • Новата стойност ще бъде записана в homeassistant.month.water_meter_hour, където month е името на retention policy със срок на съхранение от един месец. Данните за студена и гореща вода ще бъдат разпределени в отделни записи с съответните entity_id и стойност в полето value.

През нощта или когато никой не е у дома, потреблението на вода е нулево, следователно нови записи в homeassistant.autogen.l също няма да бъдат. За да избегнем пропуски в стойностите при обикновените запитвания, можем да използваме fill(previous). Това ще накара InfluxDB да използва стойността от предишния час.

За съжаление, continuous query има особеност: трикът fill(previous) не работи и записите просто не се създават. Освен това, това е някакъв неустоим проблем, който се обсъжда вече не първа година.С този проблем ще се занимаем по-късно, а fill(previous) в continuous query нека остане — той не пречи.

Нека да проверим какво получихме (разбира се, трябва да изчакаме няколко часа):

> 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

Обърнете внимание, че стойностите в базата се съхраняват в UTC, затова в този списък се различават с 3 часа — стойностите за 7 сутринта в извода на InfluxDB отговарят на стойностите за 10 сутринта в графиките по-горе. Също така обърнете внимание, че между 2 и 5 сутринта записите просто ги няма — това е същата особеност на continuous query.

Както виждате, агрегираното значение също е монотонно нарастваща последователност, но записите са по-рядко — на всеки час. Но това не е проблем — можем да напишем още един поиск, който ще извлече правилните данни за графика.

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)

Ще обясня:

  • От базата homeassistant.month.water_meter_hour ще извлечем данни за entity_id=’water_meter_cold’ през последните 24 часа (time >= now() -24h).
  • Както вече споменах, в последователността homeassistant.month.water_meter_hour могат да липсват някои записи. Тези данни ще генерираме отново, като стартираме запитването с GROUP BY time(1h). Този път fill(previous) ще работи както трябва, генерирайки липсващите данни (функцията ще вземе предходната стойност).
  • Най-важното в тази заявка е функцията difference, която ще изчисли разликата между часовите маркери. Самата тя не работи и изисква агрегираща функция. Нека това бъде max(), използвана по-рано.

Резултатът от изпълнението изглежда така:

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 72

От 2 до 5 часа сутринта (UTC) не е имало потребление. Въпреки това заявката ще върне едно и също значение на потреблението благодарение на fill(previous), а функцията difference ще извади това значение сама от себе си и на изхода получаваме 0, което всъщност и е необходимо.

Остана само едно — да построим график. За това ще отворим Grafana, ще отворим някой съществуващ (или ще създадем нов) дашборд, ще създадем нов панел. Настройките на графиките ще бъдат следните.

Умен дом: Създаваме графики на потреблението на вода и електричество в Home Assistant

Ще визуализирам данните за студената и горещата вода на един график. Запитването е точно такова, каквото описах по-горе.

Параметрите на визуализацията се задават по следния начин. При мен това ще бъде график с линии (lines), който е стъпаловиден (stairs). Параметърът Stack ще обясня по-долу. Има и още няколко параметъра за визуализация, но те не са толкова интересни.

Умен дом: Създаваме графики на потреблението на вода и електричество в Home Assistant

За да добавите получения график в home assistant, трябва да:

  • да излезете от режима на редактиране на графика. Защо-то правилните настройки за споделяне на графиките се предлагат само от страницата на дашборда.
  • Да кликнете на триъгълника до името на графика, в менюто да изберете share.
  • В отворилия се прозорец да преминете на таба embed.
  • Да отмаркирате опцията current time range — времевият диапазон ще зададем чрез URL.
  • Да изберете необходимата тема. В моя случай това е light.
  • Да копирате получения URL в картата с настройки на 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"

Обърнете внимание, че времевият диапазон (последните 2 дни) се задава точно тук, а не в настройките на дашборда.

Графикът изглежда по този начин. Горещата вода не е използвана през последните 2 дни, затова се визуализира само графика на студената вода.

Умен дом: Създаваме графики на потреблението на вода и електричество в Home Assistant

Не стигнах до решение кой график ми харесва повече, стъпаловиден или истински стълбовиден. Ето защо просто ще дам пример на дневния график на потреблението, но този път с колони. Запитванията се изграждат по аналогия с описаните по-горе. Параметрите за визуализация са следните:

Умен дом: Създаваме графики на потреблението на вода и електричество в Home Assistant

Този график изглежда така:

Умен дом: Създаваме графики на потреблението на вода и електричество в Home Assistant

Така че, за параметъра Stack. В този график колоната на студената вода се визуализира над колоната на горещата. Общата височина отговаря на сумарното потребление на студената и горещата вода за периода.

Всички показани графики са динамични. Можете да наведете мишката върху интересуващата ви точка и да видите детайлите и стойността в конкретната точка.

За съжаление, без малко дьо предизвикателства не се мина. На стълбовидната графика (в противовес на графиката с линейни стъпки) средата на стълба не е в средата на денонощието, а в 00:00. Т.е. лявата половина на стълба е нарисувана на мястото на предишния ден. Така графиките за събота и неделя са нарисувани малко вляво от синеватата зона. Все още не съм измислил как да преодолея това.

Друг проблем е невъзможността да се работи правилно с месечни интервали. Факт е, че дължината на часа/дена/седмицата е фиксирана, а дължината на месеца всяка седмица е различна. InfluxDB работи само с еднакви интервали. Все още моят ум стигна дотам да зададе фиксиран интервал от 30 дни. Да, графикът през годината малко ще се наклони и стълбовете няма да съвпадат точно с месеците. Но тъй като тази система ми е интересна просто като показател, приемам го.

Виждам най-малко две решения:

  • Да се игнорират месечните графики и да се огранича само до седмичните. 52 седмични стълба за година изглеждат напълно прилично.
  • Да се счита само месечното потребление по метод №2, а графана да се използва само за красиви графики. Ще се получи доста точно решение. Може дори да се наложат графики от предишната година за сравнение — графана и това може.

Заключение

Не знам защо, но много ми харесват такива графики. Те показват, че животът кипи и всичко се променя. Вчера имаше много, днес малко, утре ще бъде някак си. Остава ми да работя с домашните на тема потребление. Но дори и при текущите апетити, просто голямата и неясна цифра в сметката вече се превръща в доста ясна картина на потреблението.

Въпреки почти 20-годишната си кариера като програмист, рядко съм се срещал с бази данни. Затова инсталирането на външна база данни изглеждаше нещо сложно и неразбираемо. Всичко се промени въпросната статия — оказа се, че добавянето на подходящ инструмент става с няколко клика, а със специализирания инструмент задачата за построяване на графики става малко по-лесна.

В заглавието споменах потреблението на електричество. За съжаление в момента не мога да предоставя нито една графика. Едно SDM120 устройство се повреди, а другото има проблеми при свързване по Modbus. Все пак, това не влияе на темата на статията — графиките ще бъдат построени по същия начин, какъвто е за водата.

В тази статия представих подходите, които сам изпробвах. Сигурно има и други начини за организиране на събиране и визуализация на данни, за които не знам. Разкажете ми за тях в коментарите, ще ми бъде много интересно. Ще се радвам на конструктивна критика и нови идеи. Надявам се материалът, който представих, също да е полезен на някого.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster