Inteligentny dom: Budujemy wykresy zużycia wody i prądu w Home Assistant

Inteligentny dom: Budujemy wykresy zużycia wody i prądu w Home Assistant
Za każdym razem, gdy otrzymuję płatność za prąd i wodę, dziwię się – czy moja rodzina rzeczywiście tak dużo zużywa? No tak, w łazience jest podgrzewana podłoga i bojler, ale nie palą się w nich cały czas. Wydaje się, że oszczędzamy też wodę (choć lubimy też pluskać się w łazience). Już kilka lat temu podłączonych wodomierzy и elektryczność do inteligentnego domu, ale tu coś utknęło. Dopiero teraz zajęliśmy się analizą konsumpcji, o której właściwie mowa w tym artykule.

Niedawno przerzuciłem się na Home Assistant jako mój system inteligentnego domu. Jednym z powodów była właśnie możliwość uporządkowania gromadzenia dużej ilości danych z możliwością wygodnego konstruowania różnego rodzaju wykresów.

Informacje opisane w tym artykule nie są nowe, wszystkie te rzeczy pod różnymi sosami zostały już opisane w Internecie. Jednak każdy artykuł opisuje zwykle tylko jedno podejście lub aspekt. Musiałem porównać wszystkie te podejścia i sam wybrać najbardziej odpowiedni. Artykuł nadal nie dostarcza wyczerpujących informacji na temat zbierania danych, ale stanowi swego rodzaju podsumowanie tego, jak ja to zrobiłem. Dlatego konstruktywna krytyka i sugestie dotyczące ulepszeń są mile widziane.

Stwierdzenie problemu

Zatem celem dzisiejszego ćwiczenia jest uzyskanie pięknych wykresów zużycia wody i prądu:

  • Co godzinę przez 2 dni
  • Codziennie przez 2 tygodnie
  • (opcjonalnie) co tydzień i co miesiąc

Wiążą się z tym pewne trudności:

  • Standardowe elementy wykresu są zwykle dość ubogie. W najlepszym razie możesz zbudować wykres liniowy punkt po punkcie.

    Jeśli przyjrzysz się wystarczająco uważnie, możesz znaleźć komponenty innych firm, które rozszerzają możliwości standardowego wykresu. Dla asystenta domowego jest to w zasadzie dobry i piękny element karta minigraficzna, ale jest również nieco ograniczone:

    • Trudno jest ustawić parametry wykresu słupkowego dla dużych odstępów czasu (szerokość słupka ustalana jest w ułamkach godzinnych, co oznacza, że ​​przedziały dłuższe niż godzina będą ustawiane w liczbach ułamkowych)
    • Nie można dodawać różnych elementów do jednego wykresu (na przykład temperatury i wilgotności ani łączyć wykresu słupkowego z linią)
  • Home Assistant nie tylko domyślnie korzysta z najbardziej prymitywnej bazy danych SQLite (a ja, złota rączka, nie poradziłem sobie z instalacją MySQL czy Postgres), to jeszcze dane nie są przechowywane w najbardziej optymalny sposób. Na przykład za każdym razem, gdy zmieniasz nawet najmniejszy parametr cyfrowy parametru, do bazy danych zapisywany jest ogromny plik json o rozmiarze około kilobajta
    {"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}}}

    Czujników mam całkiem sporo (czujniki temperatury w każdym pomieszczeniu, liczniki wody i prądu), a niektóre też generują całkiem sporo danych. Przykładowo sam licznik energii elektrycznej SDM220 generuje kilkanaście wartości co 10-15 sekund, a chciałbym zamontować około 8 takich liczników.Jest też cała masa parametrów, które wyliczane są na podstawie innych czujników. To. wszystkie te wartości spokojnie mogą nadmuchać bazę danych o 100-200 MB dziennie. Za tydzień system ledwo będzie się ruszał, a za miesiąc pendrive umrze (w przypadku instalacji typowego asystenta domowego na Raspberry PI), a przechowywanie danych przez cały rok nie wchodzi w grę.

  • Jeśli masz szczęście, Twój licznik sam zliczy zużycie. W każdej chwili możesz zwrócić się do licznika i zapytać, o której godzinie jest skumulowana wartość zużycia. Z reguły wszystkie liczniki energii elektrycznej posiadające interfejs cyfrowy (RS232/RS485/Modbus/Zigbee) zapewniają taką możliwość.

    Gorzej, jeśli urządzenie może po prostu zmierzyć jakiś chwilowy parametr (na przykład chwilową moc lub prąd) lub po prostu wygenerować impulsy co X watogodzin lub litrów. Następnie należy zastanowić się, jak i z czym to zintegrować oraz gdzie gromadzić wartość. Istnieje ryzyko pominięcia kolejnego raportu z jakiegokolwiek powodu, a dokładność systemu jako całości budzi wątpliwości. Można to wszystko oczywiście powierzyć systemowi inteligentnego domu jakim jest asystent domowy, ale nikt nie odwołał punktu o liczbie rekordów w bazie, nie będzie też możliwości odpytywania czujników częściej niż raz na sekundę (a ograniczenia architektury asystenta domowego).

Podejście 1

Najpierw zobaczmy, co oferuje asystent domowy od razu po wyjęciu z pudełka. Pomiar zużycia w danym okresie jest bardzo pożądaną funkcją. Oczywiście został on już dawno zaimplementowany w postaci specjalizowanego komponentu – Utilities_meter.

Istotą komponentu jest to, że wewnętrznie tworzy zmienną wartość_bieżąca_zakumulowana i resetuje ją po upływie określonego czasu (godzina/tydzień/miesiąc). Komponent sam monitoruje zmienną wejściową (wartość jakiegoś czujnika), subskrybuje zmiany wartości - po prostu otrzymujesz gotowy wynik. Jest to opisane w zaledwie kilku linijkach pliku konfiguracyjnego

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

Tutaj sensor.water_meter_cold to aktualna wartość licznika w litrach, którą otrzymuję bezpośrednio z kawałka żelaza przez mqtt. Projekt tworzy 2 nowe czujniki water_cold_hour_um i water_cold_day_um, które gromadzą odczyty godzinowe i dzienne, zerując je po upływie okresu. Oto wykres godzinowego zużycia baterii przez pół dnia.

Inteligentny dom: Budujemy wykresy zużycia wody i prądu w Home Assistant

Kod wykresów godzinowych i dziennych dla lovelace-UI wygląda następująco:

      - type: history-graph
        title: 'Hourly water consumption using vars'
        hours_to_show: 48
        entities:
          - sensor.water_hour

      - type: history-graph
        title: 'Daily water consumption using vars'
        hours_to_show: 360
        entities:
          - sensor.water_day

W rzeczywistości problem tego podejścia leży w tym algorytmie. Jak już wspomniałem, dla każdej wartości wejściowej (aktualny stan licznika dla każdego kolejnego litra) w bazie danych generowanych jest 1kb rekordów. Każdy licznik mediów generuje także nową wartość, która również jest dodawana do bazy. Jeśli chcę zbierać odczyty godzinowe/dzienne/tygodniowe/miesięczne i dla kilku pionów wodociągowych, a do tego dodać paczkę liczników energii elektrycznej, będzie to dużo danych. A dokładniej danych nie jest dużo, ale skoro asystent domowy zapisuje do bazy mnóstwo niepotrzebnych informacji, to wielkość bazy będzie rosła skokowo. Boję się nawet oszacować wielkość bazy dla wykresów tygodniowych i miesięcznych.

Ponadto sam licznik mediów nie rozwiązuje problemu. Wykres wartości wytwarzanych przez licznik mediów jest monotonicznie rosnącą funkcją, która co godzinę resetuje się do 0. Potrzebujemy zrozumiałego dla użytkownika wykresu zużycia, pokazującego ile litrów zużyto w danym okresie. Standardowy komponent wykresu historii nie może tego zrobić, ale zewnętrzny komponent mini-karty wykresu może nam pomóc.

Oto kod karty dla lovelace-UI:

      - aggregate_func: max
        entities:
          - color: var(--primary-color)
            entity: sensor.water_cold_hour_um
        group_by: hour
        hours_to_show: 48
        name: "Hourly water consumption aggregated by utility meter"
        points_per_hour: 1
        show:
          graph: bar
        type: 'custom:mini-graph-card'

Oprócz standardowych ustawień, takich jak nazwa czujnika, typ wykresu, kolor (nie podobał mi się standardowy pomarańczowy), warto zwrócić uwagę na 3 ustawienia:

  • group_by:hour — wykres zostanie wygenerowany ze słupkami ustawionymi na początek godziny
  • punkty_per_godzinę: 1 - jeden pasek na każdą godzinę
  • I co najważniejsze, agregat_func: max - przyjmuje maksymalną wartość w ciągu każdej godziny. To właśnie ten parametr zamienia wykres piłokształtny w słupki

Inteligentny dom: Budujemy wykresy zużycia wody i prądu w Home Assistant

Nie zwracaj uwagi na rząd kolumn po lewej stronie – to standardowe zachowanie komponentu w przypadku braku danych. Ale nie było danych – włączyłem zbieranie danych z liczników mediów dopiero kilka godzin temu na potrzeby tego artykułu (poniżej opiszę moje obecne podejście).

Na tym zdjęciu chciałem pokazać, że czasami wyświetlanie danych w ogóle działa i słupki rzeczywiście odzwierciedlają prawidłowe wartości. Ale to nie wszystko. Z jakiegoś powodu wybrana kolumna dla okresu od 11 do 12 pokazuje 19 litrów, chociaż na ząbkowanym wykresie nieco wyższym dla tego samego okresu z tego samego czujnika widzimy zużycie 62 litry. Albo jest błąd, albo ręce są krzywe. Ale nadal nie rozumiem, dlaczego dane po prawej stronie się zepsuły - zużycie było w normie, co widać również na zębatym wykresie.

W sumie nie udało mi się osiągnąć wiarygodności tego podejścia - wykres prawie zawsze pokazuje jakąś herezję.

Podobny kod dla czujnika dziennego.

      - aggregate_func: max
        entities:
          - color: var(--primary-color)
            entity: sensor.water_cold_day_um
        group_by: interval
        hours_to_show: 360
        name: "Daily water consumption aggregated by utility meter"
        points_per_hour: 0.0416666666
        show:
          graph: bar
        type: 'custom:mini-graph-card'

Należy pamiętać, że parametr group_by jest ustawiony na interwał, a parametr punkty_per_godzinę rządzi wszystkim. I w tym tkwi kolejny problem z tym komponentem - punkty_per_godzinę działają dobrze na wykresach godzinowych lub krótszych, ale są do bani w przypadku większych interwałów. Aby więc otrzymać jedną kolumnę w ciągu jednego dnia, musiałem wprowadzić wartość 1/24=0.04166666. O wykresach tygodniowych i miesięcznych nawet nie mówię.

Podejście 2

Wciąż rozumiejąc asystenta domowego, natknąłem się na ten film:


Znajomy zbiera dane o zużyciu z kilku typów gniazd Xiaomi. Jego zadanie jest nieco prostsze – wystarczy wyświetlić wartość zużycia na dziś, wczoraj i za miesiąc. Nie są wymagane żadne harmonogramy.

Pomińmy już dyskusje na temat ręcznego całkowania wartości mocy chwilowej – o „dokładności” takiego podejścia pisałem już powyżej. Nie jest jasne, dlaczego nie wykorzystał skumulowanych wartości zużycia, które zbiera już ten sam punkt sprzedaży. Moim zdaniem integracja wewnątrz sprzętu będzie działać lepiej.

Z filmu weźmiemy pomysł ręcznego liczenia zużycia w danym okresie. Facet liczy tylko wartości z dzisiaj i wczoraj, ale pójdziemy dalej i spróbujemy narysować wykres. Istota proponowanej metody w moim przypadku jest następująca.

Stwórzmy zmienną wartość_na_początku_godziny, do której będziemy zapisywać aktualne odczyty liczników
Za pomocą timera na koniec godziny (lub na początku następnej) obliczamy różnicę pomiędzy odczytem bieżącym a odczytem zapisanym na początku godziny. Tą różnicą będzie zużycie na obecną godzinę - zapiszemy wartość w czujniku, a w przyszłości na tej wartości zbudujemy wykres.
Należy także „zresetować” zmienną wartość_na_początku_godziny, wpisując tam aktualną wartość licznika.

Wszystko to można zrobić za pośrednictwem samego asystenta domowego.

Będziesz musiał napisać trochę więcej kodu niż w poprzednim podejściu. Najpierw utwórzmy te same „zmienne”. Po wyjęciu z pudełka nie mamy jednostki „zmiennej”, ale możemy skorzystać z usług brokera mqtt. Wyślemy tam wartości z flagą keep=true - spowoduje to zapisanie wartości wewnątrz brokera i będzie można ją stamtąd wyciągnąć w dowolnym momencie, nawet po ponownym uruchomieniu home Assistant. Zrobiłem od razu liczniki godzinowe i dzienne.

- 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

Cała magia dzieje się w automatyce, która działa odpowiednio co godzinę i każdej nocy.

- 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

Obie automatyzacje wykonują 2 akcje:

  • Oblicz wartość przedziału jako różnicę między wartością początkową i końcową
  • Zaktualizuj wartość bazową dla następnego interwału

Konstrukcję wykresów w tym przypadku rozwiązuje się za pomocą zwykłego wykresu historii:

      - type: history-graph
        title: 'Hourly water consumption using vars'
        hours_to_show: 48
        entities:
          - sensor.water_hour

      - type: history-graph
        title: 'Daily water consumption using vars'
        hours_to_show: 360
        entities:
          - sensor.water_day

To wygląda tak:

Inteligentny dom: Budujemy wykresy zużycia wody i prądu w Home Assistant

W zasadzie to już jest potrzebne. Zaletą tej metody jest to, że dane są generowane raz na interwał. Te. tylko 24 rekordy dziennie w przypadku wykresu godzinowego.

Niestety, nadal nie rozwiązuje to ogólnego problemu rosnącej bazy. Jeśli chcę mieć wykres miesięcznego zużycia, będę musiał przechowywać dane przez co najmniej rok. A ponieważ Home Assistant zapewnia tylko jedno ustawienie czasu przechowywania całej bazy danych, oznacza to, że WSZYSTKIE dane w systemie będą musiały być przechowywane przez cały rok. Przykładowo w ciągu roku zużywam 200 metrów sześciennych wody, co oznacza, że ​​w bazie danych znajduje się 200000 XNUMX wpisów. A jeśli weźmiesz pod uwagę inne czujniki, liczba stanie się ogólnie nieprzyzwoita.

Podejście 3

Na szczęście mądrzy ludzie rozwiązali już ten problem, pisząc bazę danych InfluxDB. Ta baza danych jest specjalnie zoptymalizowana do przechowywania danych opartych na czasie i idealnie nadaje się do przechowywania wartości różnych czujników. System udostępnia także język zapytań przypominający SQL, który umożliwia wyodrębnianie wartości z bazy danych, a następnie agregowanie ich na różne sposoby. Wreszcie, różne dane mogą być przechowywane przez różne czasy. Na przykład często zmieniające się odczyty, takie jak temperatura lub wilgotność, można przechowywać zaledwie przez kilka tygodni, podczas gdy odczyty dziennego zużycia wody można przechowywać przez cały rok.

Oprócz InfluxDB mądrzy ludzie wymyślili także Grafanę, system do rysowania wykresów na podstawie danych z InfluxDB. Grafana może rysować różne typy wykresów, szczegółowo je dostosowywać, a co najważniejsze, wykresy te można „podłączyć” do domowego asystenta Lovelace-UI.

Zainspirować się tutaj и tutaj. W artykułach szczegółowo opisano proces instalacji i podłączenia InfluxDB i Grafany do asystenta domowego. Skupię się na rozwiązaniu mojego konkretnego problemu.

Zacznijmy więc od dodawania wartości licznika w influxDB. Fragment konfiguracji asystenta domowego (w tym przykładzie będę się bawił nie tylko zimną, ale i ciepłą wodą):

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

Wyłączmy zapisywanie tych samych danych w wewnętrznej bazie danych asystenta domowego, aby ponownie ich nie rozdęć:

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

Przejdźmy teraz do konsoli InfluxDB i skonfigurujmy naszą bazę danych. W szczególności musisz skonfigurować czas przechowywania określonych danych. Reguluje to tzw. polityka przechowywania — jest podobna do baz danych w głównej bazie danych, przy czym każda wewnętrzna baza danych ma własne ustawienia. Domyślnie wszystkie dane są przechowywane w ramach polityki przechowywania zwanej autogenem; dane te będą przechowywane przez tydzień. Chciałbym, aby dane godzinowe były przechowywane przez miesiąc, dane tygodniowe przez rok, a dane miesięczne nigdy nie były usuwane. Stwórzmy odpowiednią politykę przechowywania

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

Tak naprawdę główną sztuczką jest agregacja danych przy użyciu ciągłego zapytania. Jest to mechanizm, który automatycznie uruchamia zapytanie w określonych odstępach czasu, agreguje dane dla tego zapytania i dodaje wynik do nowej wartości. Spójrzmy na przykład (piszę w kolumnie dla czytelności, ale w rzeczywistości musiałem wpisać to polecenie w jednym wierszu)

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

To polecenie:

  • Tworzy ciągłe zapytanie o nazwie cq_water_cold_hourly w bazie danych homeassistant
  • Żądanie będzie realizowane co godzinę (czas (1h))
  • Żądanie spowoduje usunięcie wszystkich danych z pomiaru homeassistant.autogen.l (litry), w tym odczytów zimnej i ciepłej wody
  • Zagregowane dane zostaną pogrupowane według podmiotu_id, co da nam oddzielne wartości dla zimnej i ciepłej wody
  • Ponieważ licznik litrów jest sekwencją rosnącą monotonicznie w ciągu każdej godziny, konieczne będzie przyjęcie wartości maksymalnej, dlatego agregacja zostanie przeprowadzona funkcją max(wartość)
  • Nowa wartość zostanie zapisana w parametrze homeassistant.month.water_meter_hour, gdzie miesiąc to nazwa polityki przechowywania z miesięcznym okresem przechowywania. Ponadto dane dotyczące zimnej i ciepłej wody zostaną rozproszone w oddzielnych rekordach z odpowiadającym im identyfikatorem jednostki i wartością w polu wartości

W nocy lub gdy nikogo nie ma w domu, nie ma zużycia wody, dlatego też w homeassistant.autogen.l nie pojawiają się żadne nowe wpisy. Aby uniknąć brakujących wartości w zwykłych zapytaniach, możesz użyć fill(previous). Zmusi to InfluxDB do użycia wartości z ostatniej godziny.

Niestety, ciągłe zapytania mają swoją specyfikę: sztuczka z wypełnieniem (poprzednim) nie działa i rekordy po prostu nie są tworzone. Co więcej, jest to problem nie do pokonania jest omawiany już od kilku lat. Zajmiemy się tym problemem później, ale niech fill(previous) będzie w zapytaniu ciągłym - nie przeszkadza to.

Sprawdźmy co się stało (oczywiście trzeba poczekać kilka godzin):

> 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

Należy pamiętać, że wartości w bazie danych przechowywane są w formacie UTC, zatem lista ta różni się o 3 godziny – wartości z godziny 7:10 na wyjściu InfluxDB odpowiadają wartościom z godziny 2:5 na powyższych wykresach. Należy również pamiętać, że między godziną XNUMX a XNUMX w nocy po prostu nie ma żadnych rekordów - jest to ta sama cecha ciągłego zapytania.

Jak widać zagregowana wartość również jest sekwencją rosnącą monotonicznie, tylko wpisy występują rzadziej - raz na godzinę. Nie stanowi to jednak problemu – możemy napisać kolejne zapytanie, które pobierze poprawne dane do wykresu.

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)

Rozszyfruję:

  • Z bazy homeassistant.month.water_meter_hour wyciągniemy dane dla Entity_id='water_meter_cold' za ostatni dzień (czas >= now() -24h).
  • Jak już wspomniałem, w sekwencji homeasystent.miesiąc.woda_metr_godzina może brakować niektórych wpisów. Dane te zregenerujemy uruchamiając zapytanie z czasem GROUP BY (1h). Tym razem fill(previous) będzie działać zgodnie z oczekiwaniami, generując brakujące dane (funkcja przyjmie poprzednią wartość)
  • Najważniejszą rzeczą w tym żądaniu jest funkcja różnicy, która obliczy różnicę między znakami godzinowymi. Nie działa samodzielnie i wymaga funkcji agregującej. Niech to będzie użyta wcześniej funkcja max().

Wynik wykonania wygląda następująco

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

Od 2 do 5 rano (UTC) nie było zużycia. Niemniej jednak zapytanie zwróci tę samą wartość zużycia dzięki fill(previous), a funkcja różnicy odejmie tę wartość od siebie, a wynikiem będzie 0, czyli dokładnie to, co jest wymagane.

Pozostaje tylko zbudować wykres. Aby to zrobić, otwórz Grafanę, otwórz istniejący (lub utwórz nowy) dashboard i utwórz nowy panel. Ustawienia wykresu będą takie.

Inteligentny dom: Budujemy wykresy zużycia wody i prądu w Home Assistant

Wyświetlę dane dotyczące zimnej i ciepłej wody na tym samym wykresie. Żądanie jest dokładnie takie samo, jak opisałem powyżej.

Parametry wyświetlania ustawia się w następujący sposób. Dla mnie będzie to wykres z liniami, który przebiega stopniowo (schody). Poniżej wyjaśnię parametr Stack. Poniżej znajduje się jeszcze kilka opcji wyświetlania, ale nie są one zbyt interesujące.

Inteligentny dom: Budujemy wykresy zużycia wody i prądu w Home Assistant

Aby dodać powstały wykres do Home Assistant należy:

  • wyjdź z trybu edycji wykresu. Z jakiegoś powodu prawidłowe ustawienia udostępniania wykresów są dostępne tylko na stronie panelu kontrolnego
  • Kliknij trójkąt obok nazwy wykresu i wybierz z menu opcję udostępnij
  • W oknie, które zostanie otwarte, przejdź do zakładki osadzaj
  • Odznacz aktualny zakres czasu - zakres czasu ustalimy poprzez adres URL
  • Wybierz wymagany temat. W moim przypadku jest lekki
  • Skopiuj wynikowy adres URL na kartę ustawień 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"

Należy pamiętać, że zakres czasu (ostatnie 2 dni) ustawia się tutaj, a nie w ustawieniach panelu kontrolnego.

Wykres wygląda tak. Nie korzystałem z ciepłej wody przez ostatnie 2 dni, więc narysowany jest tylko wykres zimnej wody.

Inteligentny dom: Budujemy wykresy zużycia wody i prądu w Home Assistant

Jeszcze sam nie zdecydowałem, który wykres podoba mi się bardziej, krok liniowy czy prawdziwe słupki. Dlatego podam po prostu przykładowy wykres dziennego spożycia, tylko tym razem w słupkach. Zapytania konstruowane są podobnie do tych opisanych powyżej. Opcje wyświetlania to:

Inteligentny dom: Budujemy wykresy zużycia wody i prądu w Home Assistant

Ten wykres wygląda następująco:

Inteligentny dom: Budujemy wykresy zużycia wody i prądu w Home Assistant

A więc o parametrze Stack. Na tym wykresie słup zimnej wody jest narysowany na słupie gorącej wody. Całkowita wysokość odpowiada całkowitemu zużyciu zimnej i ciepłej wody w danym okresie.

Wszystkie pokazane wykresy są dynamiczne. Możesz najechać myszką na interesujące Cię miejsce i zobaczyć szczegóły oraz wartość w konkretnym punkcie.

Niestety w maści było kilka much. Na wykresie słupkowym (w przeciwieństwie do wykresu z liniami schodkowymi) środek słupka nie znajduje się w środku dnia, ale na godzinie 00:00. Te. lewa połowa kolumny jest rysowana w miejscu poprzedniego dnia. Zatem wykresy dla soboty i niedzieli są narysowane nieco na lewo od niebieskawej strefy. Dopóki nie wymyśliłem, jak go pokonać.

Kolejnym problemem jest brak możliwości prawidłowej pracy w miesięcznych odstępach czasu. Faktem jest, że długość godziny/dnia/tygodnia jest stała, natomiast długość miesiąca jest za każdym razem inna. InfluxDB może działać tylko w równych odstępach czasu. Jak dotąd mój mózg wystarczył, aby ustawić stały odstęp 30 dni. Tak, wykres będzie się trochę przesuwał przez cały rok, a słupki nie będą dokładnie odpowiadać poszczególnym miesiącom. Ale ponieważ interesuje mnie to po prostu jako miernik wyświetlacza, nie przeszkadza mi to.

Widzę co najmniej dwa rozwiązania:

  • Zrezygnuj z wykresów miesięcznych i ogranicz się do tygodniowych. 52 tygodniowe słupki na rok wyglądają całkiem nieźle
  • Rozważ samo miesięczne zużycie jako metodę nr 2, a grafanę używaj tylko do pięknych wykresów. Będzie to dość trafne rozwiązanie. Dla porównania możesz nawet nałożyć na siebie wykresy z poprzedniego roku – grafana też to potrafi.

wniosek

Nie wiem dlaczego, ale mam obsesję na punkcie tego typu wykresów. Pokazują, że życie toczy się pełną parą i wszystko się zmienia. Wczoraj było dużo, dziś mało, jutro będzie coś innego. Pozostaje tylko pracować z domownikami nad tematem konsumpcji. Ale nawet przy obecnych apetytach już sama duża i niezrozumiała liczba na odcinku płatności zmienia się w dość zrozumiały obraz konsumpcji.

Mimo prawie 20-letniej kariery programisty nie miałem praktycznie żadnego kontaktu z bazami danych. Dlatego instalacja zewnętrznej bazy danych wydawała się czymś tak zawiłym i niezrozumiałym. Zmieniłem wszystko powyższy artykuł — okazało się, że podpięcie odpowiedniego narzędzia odbywa się za pomocą kilku kliknięć, a dzięki specjalistycznemu narzędziu zadanie rysowania wykresów staje się nieco łatwiejsze.

W tytule wspomniałem o zużyciu energii elektrycznej. Niestety na chwilę obecną nie jestem w stanie udostępnić żadnych wykresów. Jeden miernik SDM120 umarł dla mnie, a drugi działa nieprawidłowo, gdy jest dostępny przez Modbus. Nie wpływa to jednak w żaden sposób na tematykę tego artykułu – wykresy będą konstruowane w taki sam sposób, jak dla wody.

W tym artykule przedstawiłem podejścia, które sam wypróbowałem. Z pewnością istnieją inne sposoby organizacji gromadzenia i wizualizacji danych, o których nie wiem. Opowiedz mi o tym w komentarzach, będzie mi bardzo miło. Chętnie przyjmę konstruktywną krytykę i nowe pomysły. Mam nadzieję, że przedstawiony materiał również komuś pomoże.

Źródło: www.habr.com

Dodaj komentarz