{"id":74421,"date":"2020-03-17T08:43:08","date_gmt":"2020-03-17T05:43:08","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/umnyj-dom-stroim-grafiki-potrebleniya-vody-i-elektrichestva-v-home-assistant"},"modified":"2020-03-17T08:43:08","modified_gmt":"2020-03-17T05:43:08","slug":"umnyj-dom-stroim-grafiki-potrebleniya-vody-i-elektrichestva-v-home-assistant","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/umnyj-dom-stroim-grafiki-potrebleniya-vody-i-elektrichestva-v-home-assistant","title":{"rendered":"Inteligentny dom: Budujemy wykresy zu\u017cycia wody i energii elektrycznej w Home Assistant","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Inteligentny dom: Budujemy wykresy zu\u017cycia wody i energii elektrycznej w Home Assistant\" src=\"\/wp-content\/uploads\/2020\/03\/f1133a4c391e901ed64bf0825a774fc6.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nZ ka\u017cdym razem, gdy otrzymuj\u0119 rachunek za pr\u0105d i wod\u0119, zastanawiam si\u0119 \u2013 czy moja rodzina naprawd\u0119 tyle zu\u017cywa? Tak, w \u0142azience mamy ogrzewanie pod\u0142ogowe i bojler, ale przecie\u017c nie pracuj\u0105 non-stop. Wod\u0119 tak\u017ce ekonomicznie wykorzystujemy (cho\u0107 lubimy si\u0119 powylegiwa\u0107 w wannie). Kilka lat temu ju\u017c <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/411259\/\">pod\u0142\u0105czy\u0142em liczniki wody<\/a><\/noindex> i <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=XKvunh29sZo&amp;list=PLkt_cQxT0oUmfdxhbmTjytjaJjZjSVUOu\">pr\u0105du<\/a><\/noindex> do inteligentnego domu, ale na tym si\u0119 sko\u0144czy\u0142o. Do analizy zu\u017cycia zmobilizowa\u0142em si\u0119 dopiero teraz, o czym zreszt\u0105 jest ten artyku\u0142.<\/p>\n<p>Niedawno przeszed\u0142em na Home Assistant jako system inteligentnego domu. Jednym z powod\u00f3w by\u0142a mo\u017cliwo\u015b\u0107 zorganizowania zbierania du\u017cej ilo\u015bci danych z mo\u017cliwo\u015bci\u0105 wygodnego tworzenia r\u00f3\u017cnych rodzaj\u00f3w wykres\u00f3w.<\/p>\n<p>Informacje opisane w tym artykule nie s\u0105 nowe, wszystkie te rzeczy w r\u00f3\u017cnych ods\u0142onach by\u0142y ju\u017c opisane w internecie. Jednak ka\u017cdy artyku\u0142 zazwyczaj opisuje tylko jedno podej\u015bcie lub aspekt. Musia\u0142em por\u00f3wna\u0107 wszystkie te podej\u015bcia i wybra\u0107 najbardziej odpowiednie. Artyku\u0142 i tak nie daje wyczerpuj\u0105cych informacji na temat zbierania danych, ale jest pewnego rodzaju konspektem tego, jak to zrobi\u0142em. Tak wi\u0119c konstruktywna krytyka i propozycje ulepsze\u0144 s\u0105 mile widziane.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Sformu\u0142owanie zadania<\/h2>\n<p>\nCelem dzisiejszego \u0107wiczenia jest uzyskanie \u0142adnych wykres\u00f3w zu\u017cycia wody i pr\u0105du:<\/p>\n<ul>\n<li>Godzinowy za 2 dni<\/li>\n<li>Dzienny za 2 tygodnie<\/li>\n<li>(opcjonalnie) tygodniowy i miesi\u0119czny<\/li>\n<\/ul>\n<p>\nW tym czekaj\u0105 nas pewne trudno\u015bci:<\/p>\n<ul>\n<li>Standardowe komponenty wykres\u00f3w s\u0105 zazwyczaj do\u015b\u0107 ubogie. W najlepszym przypadku mo\u017cna stworzy\u0107 wykres liniowy na podstawie punkt\u00f3w.\n<p>Je\u015bli dobrze poszuka\u0107, mo\u017cna znale\u017a\u0107 komponenty zewn\u0119trzne, kt\u00f3re rozszerzaj\u0105 mo\u017cliwo\u015bci standardowego wykresu. Dla Home Assistant przyzwoity i \u0142adny komponent to <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/kalkih\/mini-graph-card\">mini-graph-card<\/a><\/noindex>, ale on tak\u017ce jest nieco ograniczony:<\/p>\n<ul>\n<li>Trudno ustawi\u0107 parametry wykresu s\u0142upkowego na wi\u0119kszych odst\u0119pach (szeroko\u015b\u0107 s\u0142upka jest ustawiana w u\u0142amkach godziny, co oznacza, \u017ce odst\u0119py d\u0142u\u017csze ni\u017c godzina b\u0119d\u0105 ustalane jako liczby dziesi\u0119tne)<\/li>\n<li>Nie mo\u017cna na jednym wykresie dodawa\u0107 r\u00f3\u017cnych encji (na przyk\u0142ad temperatury i wilgotno\u015bci, lub po\u0142\u0105czy\u0107 wykres s\u0142upkowy z liniowym)<\/li>\n<\/ul>\n<\/li>\n<li>Nie tylko to, \u017ce home assistant domy\u015blnie korzysta z najbardziej prymitywnej bazy danych SQLite (a ja, nieudacznik, nie poradzi\u0142em sobie z instalacj\u0105 MySQL lub Postgresa), ale tak\u017ce dane s\u0105 przechowywane w spos\u00f3b niezbyt optymalny. Na przyk\u0142ad przy ka\u017cdej zmianie nawet najdrobniejszego parametru cyfrowego do bazy zapisywany jest ogromny json o rozmiarze oko\u0142o kilobajta.\n<pre><code class=\"json\">{&quot;entity_id&quot;: &quot;sensor.water_cold_hourly&quot;, &quot;old_state&quot;: {&quot;entity_id&quot;: &quot;sensor.water_cold_hourly&quot;, &quot;state&quot;: &quot;3&quot;, &quot;attributes&quot;: {&quot;source&quot;: &quot;sensor.water_meter_cold&quot;, &quot;status&quot;: &quot;collecting&quot;, &quot;last_period&quot;: &quot;29&quot;, &quot;last_reset&quot;: &quot;2020-02-23T21:00:00.022246+02:00&quot;, &quot;meter_period&quot;: &quot;hourly&quot;, &quot;unit_of_measurement&quot;: &quot;l&quot;, &quot;friendly_name&quot;: &quot;water_cold_hourly&quot;, &quot;icon&quot;: &quot;mdi:counter&quot;}, &quot;last_changed&quot;: &quot;2020-02-23T19:05:06.897604+00:00&quot;, &quot;last_updated&quot;: &quot;2020-02-23T19:05:06.897604+00:00&quot;, &quot;context&quot;: {&quot;id&quot;: &quot;aafc8ca305ba4e49ad4c97f0eddd8893&quot;, &quot;parent_id&quot;: null, &quot;user_id&quot;: null}}, &quot;new_state&quot;: {&quot;entity_id&quot;: &quot;sensor.water_cold_hourly&quot;, &quot;state&quot;: &quot;4&quot;, &quot;attributes&quot;: {&quot;source&quot;: &quot;sensor.water_meter_cold&quot;, &quot;status&quot;: &quot;collecting&quot;, &quot;last_period&quot;: &quot;29&quot;, &quot;last_reset&quot;: &quot;2020-02-23T21:00:00.022246+02:00&quot;, &quot;meter_period&quot;: &quot;hourly&quot;, &quot;unit_of_measurement&quot;: &quot;l&quot;, &quot;friendly_name&quot;: &quot;water_cold_hourly&quot;, &quot;icon&quot;: &quot;mdi:counter&quot;}, &quot;last_changed&quot;: &quot;2020-02-23T19:11:11.251545+00:00&quot;, &quot;last_updated&quot;: &quot;2020-02-23T19:11:11.251545+00:00&quot;, &quot;context&quot;: {&quot;id&quot;: &quot;0de64b8af6f14bb9a419dcf3b200ef56&quot;, &quot;parent_id&quot;: null, &quot;user_id&quot;: null}}}<\/code><\/pre>\n<p>\nMam ca\u0142kiem sporo czujnik\u00f3w (czujniki temperatury w ka\u017cdym pokoju, liczniki wody i energii elektrycznej), a niekt\u00f3re z nich generuj\u0105 do\u015b\u0107 du\u017co danych. Na przyk\u0142ad licznik energii elektrycznej SDM220 generuje oko\u0142o dziesi\u0119ciu warto\u015bci co 10-15 sekund, a chcia\u0142bym zainstalowa\u0107 oko\u0142o 8 takich licznik\u00f3w. Jest te\u017c ca\u0142a masa parametr\u00f3w, kt\u00f3re s\u0105 obliczane na podstawie innych czujnik\u00f3w. Tak wi\u0119c te warto\u015bci mog\u0105 \u0142atwo rozrosn\u0105\u0107 baz\u0119 danych o 100-200 MB dziennie. Po tygodniu system b\u0119dzie ledwo dzia\u0142a\u0142, a po miesi\u0105cu karta pami\u0119ci (przy typowej instalacji home assistant na Raspberry Pi) umrze, a ju\u017c o przechowywaniu danych przez rok nie ma mowy.<\/li>\n<li>Je\u015bli masz szcz\u0119\u015bcie, tw\u00f3j licznik potrafi sam liczy\u0107 zu\u017cycie. Mo\u017cesz w dowolnym momencie zwr\u00f3ci\u0107 si\u0119 do licznika i zapyta\u0107, kt\u00f3re godziny skumulowanej warto\u015bci zu\u017cycia. Zazwyczaj wszystkie liczniki energii elektrycznej z interfejsem cyfrowym (RS232\/RS485\/Modbus\/Zigbee) oferuj\u0105 t\u0119 mo\u017cliwo\u015b\u0107.\n<p>Gorsze, je\u015bli urz\u0105dzenie mo\u017ce jedynie mierzy\u0107 jaki\u015b chwilowy parametr (na przyk\u0142ad chwilow\u0105 moc lub pr\u0105d), albo po prostu generowa\u0107 impulsy co X watogodzin lub litr\u00f3w. Wtedy trzeba pomy\u015ble\u0107 jak i czym to zintegrowa\u0107 oraz gdzie gromadzi\u0107 warto\u015bci. Istnieje ryzyko, \u017ce z jakiego\u015b powodu przegapimy kolejny raport, a dok\u0142adno\u015b\u0107 systemu og\u00f3lnie budzi w\u0105tpliwo\u015bci. Oczywi\u015bcie mo\u017cna to wszystko powierzy\u0107 systemowi inteligentnego domu, jak home assistant, ale kwestia liczby zapis\u00f3w w bazie danych nie znika, a pytanie o cz\u0119stotliwo\u015b\u0107 odpytywania czujnik\u00f3w co wi\u0119cej ni\u017c raz na sekund\u0119 te\u017c pozostaje bez odpowiedzi (ograniczenie architektury home assistant).<\/li>\n<\/ul>\n<p><\/p>\n<h2>Podej\u015bcie 1<\/h2>\n<p>\nNa pocz\u0105tku przyjrzyjmy si\u0119, co home assistant oferuje od razu po wyj\u0119ciu z pude\u0142ka. Pomiar zu\u017cycia w okresie \u2014 to bardzo poszukiwana funkcjonalno\u015b\u0107. Oczywi\u015bcie, dawno temu zrealizowano to w postaci specjalizowanego komponentu \u2014 utility_meter. <\/p>\n<p>Istota komponentu polega na tym, \u017ce wewn\u0119trznie tworzy zmienn\u0105 current_accumulated_value i zeruje j\u0105 po up\u0142ywie zadanego okresu (godzina\/tydzie\u0144\/miesi\u0105c). Komponent sam monitoruje wej\u015bciow\u0105 zmienn\u0105 (warto\u015b\u0107 jakiego\u015b czujnika), sam zapisuje si\u0119 na zmiany warto\u015bci \u2014 po prostu otrzymujesz gotowy wynik. Opisuje si\u0119 to w kilku linijkach w pliku konfiguracyjnym.<\/p>\n<pre><code class=\"python\">utility_meter:\n  water_cold_hour_um:\n    source: sensor.water_meter_cold\n    cycle: hourly\n  water_cold_day_um:\n    source: sensor.water_meter_cold\n    cycle: daily\n<\/code><\/pre>\n<p>\nTutaj sensor.water_meter_cold to bie\u017c\u0105ca warto\u015b\u0107 licznika w litrach, kt\u00f3r\u0105 otrzymuj\u0119 <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/411259\/\">bezpo\u015brednio od urz\u0105dzenia<\/a><\/noindex> przez mqtt. Konstrukcja tworzy dwa nowe czujniki water_cold_hour_um i water_cold_day_um, kt\u00f3re gromadz\u0105 dane godzinne i dzienne, resetuj\u0105c je po up\u0142ywie okresu. Oto wykres godzinnego akumulatora za p\u00f3\u0142 dnia.<\/p>\n<p><img decoding=\"async\" alt=\"Inteligentny dom: Budujemy wykresy zu\u017cycia wody i energii elektrycznej w Home Assistant\" src=\"\/wp-content\/uploads\/2020\/03\/d3c3ea29c10b17142e51ebe756ab7123.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nKod dla wykres\u00f3w godzinnych i dziennych w lovelace-UI wygl\u0105da tak:<\/p>\n<pre><code class=\"python\">      - type: history-graph\n        title: 'Godzinne zu\u017cycie wody z wykorzystaniem zmiennych'\n        hours_to_show: 48\n        entities:\n          - sensor.water_hour\n\n      - type: history-graph\n        title: 'Dzienna zu\u017cycie wody z wykorzystaniem zmiennych'\n        hours_to_show: 360\n        entities:\n          - sensor.water_day\n<\/code><\/pre>\n<p>\nW rzeczywisto\u015bci to w tym algorytmie kryj\u0105 si\u0119 problemy tego podej\u015bcia. Jak ju\u017c wspomnia\u0142em, dla ka\u017cdego wej\u015bciowego warto\u015bci (obecny odczyt licznika na ka\u017cdy kolejny litr) generowana jest 1 kB wpisu w bazie. Ka\u017cdy licznik zu\u017cycia r\u00f3wnie\u017c generuje now\u0105 warto\u015b\u0107, kt\u00f3ra jest sumowana w bazie. Je\u015bli chc\u0119 zbiera\u0107 dane godzinowe\/dzienne\/tygodniowe\/miesi\u0119czne, na przyk\u0142ad dla kilku pion\u00f3w wodnych, a do tego doda\u0107 kilka licznik\u00f3w elektrycznych \u2014 b\u0119dzie to bardzo du\u017co danych. Dok\u0142adniej, danych nie b\u0119dzie du\u017co, ale poniewa\u017c home assistant zapisuje w bazie wiele niepotrzebnych informacji, rozmiar bazy b\u0119dzie r\u00f3s\u0142 jak na dro\u017cd\u017cach. Obawiam si\u0119 nawet szacowa\u0107 rozmiar bazy dla wykres\u00f3w tygodniowych i miesi\u0119cznych.<\/p>\n<p>Opr\u00f3cz tego, sam utility meter nie rozwi\u0105zuje postawionego zadania. Wykres warto\u015bci, kt\u00f3re podaje utility meter, to monotonicznie rosn\u0105ca funkcja, kt\u00f3ra co godzin\u0119 resetuje si\u0119 do 0. Potrzebujemy zrozumia\u0142ego wykresu zu\u017cycia dla u\u017cytkownika, czyli ile litr\u00f3w zosta\u0142o zu\u017cytych w danym okresie. Standardowy komponent history-graph tego nie potrafi, ale mo\u017ce nam pom\u00f3c zewn\u0119trzny komponent mini-graph-card.<\/p>\n<p>To kod karty dla lovelace-UI:<\/p>\n<pre><code class=\"python\">      - aggregate_func: max\n        entities:\n          - color: var(--primary-color)\n            entity: sensor.water_cold_hour_um\n        group_by: hour\n        hours_to_show: 48\n        name: &quot;Zagregowane zu\u017cycie wody godzinowo wed\u0142ug wodomierza&quot;\n        points_per_hour: 1\n        show:\n          graph: bar\n        type: 'custom:mini-graph-card'<\/code><\/pre>\n<p>\nOpr\u00f3cz standardowych ustawie\u0144, takich jak nazwa sensora, typ wykresu, kolor (standardowy pomara\u0144czowy mi si\u0119 nie podoba\u0142), warto zwr\u00f3ci\u0107 uwag\u0119 na 3 ustawienia:<\/p>\n<ul>\n<li>group_by:hour \u2014 wykres b\u0119dzie generowany z wyr\u00f3wnaniem s\u0142upk\u00f3w do pocz\u0105tku godziny<\/li>\n<li>points_per_hour: 1 \u2014 jeden s\u0142upek na ka\u017cd\u0105 godzin\u0119<\/li>\n<li>I najwa\u017cniejsze, aggregate_func: max \u2014 branie maksymalnej warto\u015bci w ramach ka\u017cdej godziny. To w\u0142a\u015bnie ten parametr przekszta\u0142ca z\u0105bkowany wykres w s\u0142upki<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Inteligentny dom: Budujemy wykresy zu\u017cycia wody i energii elektrycznej w Home Assistant\" src=\"\/wp-content\/uploads\/2020\/03\/5bd866c39b23299e5f15dcf4a9bce38f.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNie zwracajcie uwagi na kilka s\u0142upk\u00f3w z lewej \u2014 to standardowe zachowanie komponentu, gdy brak danych. A danych nie by\u0142o \u2014 w\u0142\u0105czy\u0142em zbieranie danych z utility metera dopiero przed chwil\u0105 tylko na potrzeby tego artyku\u0142u (o swoim obecnym podej\u015bciu opowiem troch\u0119 poni\u017cej). <\/p>\n<p>Na tym obrazku chcia\u0142em pokaza\u0107, \u017ce czasami wy\u015bwietlanie danych dzia\u0142a i s\u0142upki rzeczywi\u015bcie odzwierciedlaj\u0105 w\u0142a\u015bciwe warto\u015bci. Tylko \u017ce nie wszystkie. Wyr\u00f3\u017cniony s\u0142upek za okres od 11 do 12 w nocy pokazuje 19 litr\u00f3w, chocia\u017c na z\u0105batego wykresu nieco wy\u017cej za ten sam okres z tego samego czujnika widzimy zu\u017cycie 62 litr\u00f3w. Albo b\u0142\u0105d, albo win\u0119 ponosz\u0105 niew\u0142a\u015bciwe r\u0119ce. A dlaczego dane po prawej stronie si\u0119 urwa\u0142y, na razie nie rozumiem \u2014 zu\u017cycie tam by\u0142o norm\u0105, co r\u00f3wnie\u017c wida\u0107 na z\u0105batym wykresie.<\/p>\n<p>Og\u00f3lnie rzecz bior\u0105c, nie uda\u0142o mi si\u0119 osi\u0105gn\u0105\u0107 prawdopodobie\u0144stwa tego podej\u015bcia \u2014 wykres prawie zawsze pokazuje jakie\u015b bzdury.<\/p>\n<p>Analogiczny kod dla czujnika dziennego. <\/p>\n<pre><code class=\"python\">      - aggregate_func: max\n        entities:\n          - color: var(--primary-color)\n            entity: sensor.water_cold_day_um\n        group_by: interval\n        hours_to_show: 360\n        name: &quot;Zagregowane zu\u017cycie wody dziennie wed\u0142ug wodomierza&quot;\n        points_per_hour: 0.0416666666\n        show:\n          graph: bar\n        type: 'custom:mini-graph-card'\n<\/code><\/pre>\n<p>\nZwr\u00f3\u0107 uwag\u0119, \u017ce parametr group_by jest ustawiony na warto\u015b\u0107 interval, i rz\u0105dzi nim ca\u0142y parametr points_per_hour. W tym tkwi inny problem tego komponentu \u2014 points_per_hour dzia\u0142a dobrze na wykresach za godzin\u0119 lub mniej, ale strasznie na wi\u0119kszych odst\u0119pach. \u017beby dosta\u0107 jeden s\u0142upek za jeden dzie\u0144 trzeba wpisa\u0107 warto\u015b\u0107 1\/24=0.04166666. Nie m\u00f3wi\u0119 ju\u017c o wykresach tygodniowych i miesi\u0119cznych.<\/p>\n<h2>Podej\u015bcie 2<\/h2>\n<p>\nZaledwie zaczynaj\u0105c z home assistant natkn\u0105\u0142em si\u0119 na to wideo:<\/p>\n<p><center><div class=\"youtube-placeholder\" data-id=\"-0HrYFCRH0M\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/-0HrYFCRH0M\/hqdefault.jpg\" alt=\"Odtwarzaj wideo\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nKolega zbiera dane o zu\u017cyciu z kilku rodzaj\u00f3w gniazdek Xiaomi. Jego zadanie jest nieco prostsze \u2014 po prostu wy\u015bwietla\u0107 warto\u015b\u0107 zu\u017cycia za dzisiaj, wczoraj i za miesi\u0105c. \u017badne wykresy nie s\u0105 potrzebne. <\/p>\n<p>Odstawmy na bok rozwa\u017cania o r\u0119cznym integracji chwilowych warto\u015bci mocy \u2014 o \u201edok\u0142adno\u015bci\u201d tego podej\u015bcia pisa\u0142em ju\u017c powy\u017cej. Niejasne jest, dlaczego nie zdecydowa\u0142 si\u0119 wykorzysta\u0107 zgromadzonych warto\u015bci zu\u017cycia, kt\u00f3re ju\u017c gromadzi to samo gniazdko. Moim zdaniem integracja w \u015brodku urz\u0105dzenia b\u0119dzie dzia\u0142a\u0107 lepiej. <\/p>\n<p>Z wideo we\u017amiemy pomys\u0142 r\u0119cznego liczenia zu\u017cycia za okres. U tego go\u015bcia liczone s\u0105 tylko warto\u015bci za dzisiaj i wczoraj, ale p\u00f3jdziemy dalej i spr\u00f3bujemy narysowa\u0107 wykres. Istota zaproponowanej metody w moim przypadku sprowadza si\u0119 do nast\u0119puj\u0105cych kwestii.<\/p>\n<p>Utworzymy zmienn\u0105 warto\u015b\u0107_na_pocz\u0105tku_godziny, w kt\u00f3rej zapiszemy bie\u017c\u0105ce odczyty licznika.<br \/>\nNa koniec godziny (lub na pocz\u0105tku nast\u0119pnej) obliczymy r\u00f3\u017cnic\u0119 mi\u0119dzy aktualnym odczytem a zapami\u0119tan\u0105 na pocz\u0105tku godziny. Ta r\u00f3\u017cnica b\u0119dzie zu\u017cyciem za bie\u017c\u0105c\u0105 godzin\u0119 \u2014 zapisujemy t\u0119 warto\u015b\u0107 w czujniku i w przysz\u0142o\u015bci na jej podstawie b\u0119dziemy budowa\u0107 wykres. <br \/>\nNale\u017cy r\u00f3wnie\u017c \u201ezerowa\u0107\u201d zmienn\u0105 warto\u015b\u0107_w_pocz\u0105tku_godziny, zapisuj\u0105c tam aktualn\u0105 warto\u015b\u0107 licznika.<\/p>\n<p>Wszystko to mo\u017cna zrobi\u0107 za pomoc\u0105\u2026 \u015brodk\u00f3w samego Home Assistant. <\/p>\n<p>Kod b\u0119dzie trzeba napisa\u0107 nieco wi\u0119cej ni\u017c w poprzednim podej\u015bciu. Na pocz\u0105tku utworzymy te \u201ezmienne\u201d. Z pude\u0142ka nie mamy encji \u201ezmienna\u201d, ale mo\u017cemy skorzysta\u0107 z brokera mqtt. B\u0119dziemy tam wysy\u0142a\u0107 warto\u015bci z flag\u0105 retain=true \u2014 to zapisze warto\u015b\u0107 w brokerze i w dowolnym momencie mo\u017cna j\u0105 stamt\u0105d wyci\u0105gn\u0105\u0107, nawet po restarcie home assistant. Zrobi\u0142em od razu liczniki godzinowe i dzienne.<\/p>\n<pre><code class=\"python\">- platform: mqtt\n  state_topic: &quot;test\/water\/hour&quot;\n  name: water_hour\n  unit_of_measurement: l\n\n- platform: mqtt\n  state_topic: &quot;test\/water\/hour_begin&quot;\n  name: water_hour_begin\n  unit_of_measurement: l\n\n- platform: mqtt\n  state_topic: &quot;test\/water\/day&quot;\n  name: water_day\n  unit_of_measurement: l\n\n- platform: mqtt\n  state_topic: &quot;test\/water\/day_begin&quot;\n  name: water_day_begin\n  unit_of_measurement: l<\/code><\/pre>\n<p>\nCa\u0142a magia dzieje si\u0119 w automatyzacji, kt\u00f3ra uruchamia si\u0119 co godzin\u0119 i ka\u017cdej nocy.<\/p>\n<pre><code class=\"python\">- id: water_new_hour\n  alias: water_new_hour\n  initial_state: true\n  trigger:\n    - platform: time_pattern\n      minutes: 0\n  action:\n    - service: mqtt.publish\n      data:\n        topic: &quot;test\/water\/hour&quot;\n        payload_template: &gt;\n          {{ (states.sensor.water_meter_cold.state|int) - (states.sensor.water_hour_begin.state|int) }}\n        retain: true\n    - service: mqtt.publish\n      data:\n        topic: &quot;test\/water\/hour_begin&quot;\n        payload_template: &gt;\n          {{ states.sensor.water_meter_cold.state }}\n        retain: true\n\n- id: water_new_day\n  alias: water_new_day\n  initial_state: true\n  trigger:\n    - platform: time\n      at: &quot;00:00:00&quot;\n  action:\n    - service: mqtt.publish\n      data:\n        topic: &quot;test\/water\/day&quot;\n        payload_template: &gt;\n          {{ (states.sensor.water_meter_cold.state|int) - (states.sensor.water_day_begin.state|int) }}\n        retain: true\n    - service: mqtt.publish\n      data:\n        topic: &quot;test\/water\/day_begin&quot;\n        payload_template: &gt;\n          {{ states.sensor.water_meter_cold.state }}\n        retain: true<\/code><\/pre>\n<p>\nObie automatyzacje wykonuj\u0105 2 dzia\u0142ania:<\/p>\n<ul>\n<li>Obliczaj\u0105 warto\u015b\u0107 za interwa\u0142 jako r\u00f3\u017cnic\u0119 mi\u0119dzy warto\u015bci\u0105 pocz\u0105tkow\u0105 a ko\u0144cow\u0105<\/li>\n<li>Aktualizuj\u0105 podstawow\u0105 warto\u015b\u0107 dla nast\u0119pnego interwa\u0142u<\/li>\n<\/ul>\n<p>\nBudow\u0119 wykres\u00f3w w tym przypadku rozwi\u0105zuje zwyk\u0142y history-graph:<\/p>\n<pre><code class=\"python\">      - type: history-graph\n        title: 'Godzinne zu\u017cycie wody z wykorzystaniem zmiennych'\n        hours_to_show: 48\n        entities:\n          - sensor.water_hour\n\n      - type: history-graph\n        title: 'Dzienna zu\u017cycie wody z wykorzystaniem zmiennych'\n        hours_to_show: 360\n        entities:\n          - sensor.water_day<\/code><\/pre>\n<p>\nWygl\u0105da to tak:<\/p>\n<p><img decoding=\"async\" alt=\"Inteligentny dom: Budujemy wykresy zu\u017cycia wody i energii elektrycznej w Home Assistant\" src=\"\/wp-content\/uploads\/2020\/03\/ebde2fc5f0a72d7d6ba565c3686dc9c6.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nW zasadzie to ju\u017c to, czego potrzebujemy. Zalet\u0105 tej metody jest to, \u017ce dane s\u0105 generowane raz za interwa\u0142. Tzn. \u0142\u0105cznie 24 zapisy na dob\u0119 dla wykresu godzinowego. <\/p>\n<p>Niestety, og\u00f3lny problem rosn\u0105cej bazy danych pozostaje nierozwi\u0105zany. Je\u015bli b\u0119d\u0119 chcia\u0142 uzyska\u0107 wykres miesi\u0119cznego zu\u017cycia, b\u0119d\u0119 musia\u0142 przechowywa\u0107 dane co najmniej przez rok. A poniewa\u017c home assistant oferuje tylko jedn\u0105 opcj\u0119 d\u0142ugo\u015bci przechowywania dla ca\u0142ej bazy, oznacza to, \u017ce WSZYSTKIE dane w systemie musz\u0105 by\u0107 przechowywane przez ca\u0142y rok. Na przyk\u0142ad w ci\u0105gu roku zu\u017cywam 200 m\u00b3 wody, co oznacza 200000 zapis\u00f3w w bazie. A je\u015bli uwzgl\u0119dni\u0107 inne czujniki, to liczba ta staje si\u0119 wr\u0119cz nieprzyzwoita.<\/p>\n<h2>Podej\u015bcie 3<\/h2>\n<p>\nNa szcz\u0119\u015bcie, m\u0105drzy ludzie ju\u017c rozwi\u0105zali ten problem, tworz\u0105c baz\u0119 danych InfluxDB. Ta baza jest w specjalny spos\u00f3b zoptymalizowana pod k\u0105tem przechowywania danych czasowych i idealnie nadaje si\u0119 do przechowywania warto\u015bci r\u00f3\u017cnych czujnik\u00f3w. System oferuje r\u00f3wnie\u017c j\u0119zyk zapyta\u0144 podobny do SQL, kt\u00f3ry pozwala na wydobywanie warto\u015bci z bazy, a nast\u0119pnie ich agregowanie na r\u00f3\u017cne sposoby. Wreszcie, r\u00f3\u017cne dane mo\u017cna przechowywa\u0107 przez r\u00f3\u017cny czas. Na przyk\u0142ad cz\u0119sto zmieniaj\u0105ce si\u0119 pomiary, takie jak temperatura czy wilgotno\u015b\u0107, mo\u017cna przechowywa\u0107 tylko przez kilka tygodni, podczas gdy dzienne pomiary zu\u017cycia wody mo\u017cna przechowywa\u0107 przez ca\u0142y rok.<\/p>\n<p>Opr\u00f3cz InfluxDB, m\u0105drzy ludzie wynale\u017ali r\u00f3wnie\u017c Grafana \u2013 system do tworzenia wykres\u00f3w na podstawie danych z InfluxDB. Grafana potrafi rysowa\u0107 r\u00f3\u017cne rodzaje wykres\u00f3w, szczeg\u00f3\u0142owo je dostosowywa\u0107, a co najwa\u017cniejsze, te wykresy mo\u017cna \u201ewstawi\u0107\u201d do UI lovelace home assistant.<\/p>\n<p>Inspiracje <noindex><a rel=\"nofollow\" href=\"https:\/\/dummylabs.com\/ru\/post\/2019-01-13-influxdb-part1\/\">tutaj <\/a><\/noindex> i <noindex><a rel=\"nofollow\" href=\"https:\/\/dummylabs.com\/ru\/post\/2019-05-28-influxdb-part2\/\">tutaj<\/a><\/noindex>. W artyku\u0142ach szczeg\u00f3\u0142owo opisano proces instalacji i pod\u0142\u0105czenia InfluxDB oraz Grafany do home assistant. Ja skupi\u0119 si\u0119 na rozwi\u0105zaniu mojego konkretnego problemu.<\/p>\n<p>Zatem pierwszym krokiem jest rozpocz\u0119cie zapisywania warto\u015bci licznika do InfluxDB. Fragment konfiguracji home assistant (w tym przyk\u0142adzie b\u0119d\u0119 bawi\u0107 si\u0119 nie tylko zimn\u0105, ale r\u00f3wnie\u017c gor\u0105c\u0105 wod\u0105):<\/p>\n<pre><code class=\"python\">influxdb:\n  host: localhost\n  max_retries: 3\n  default_measurement: state\n  database: homeassistant\n  include:\n    entities:\n      - sensor.water_meter_hot\n      - sensor.water_meter_cold<\/code><\/pre>\n<p>\nWy\u0142\u0105czymy zapisanie tych samych danych do wewn\u0119trznej bazy home assistant, aby nie powi\u0119ksza\u0107 jej niepotrzebnie:<\/p>\n<pre><code class=\"python\">recorder:\n  purge_keep_days: 10\n  purge_interval: 1\n  exclude:\n    entities:\n      - sensor.water_meter_hot\n      - sensor.water_meter_cold<\/code><\/pre>\n<p>\nPrzejd\u017amy teraz do konsoli InfluxDB i skonfigurujmy nasz\u0105 baz\u0119. W szczeg\u00f3lno\u015bci musimy ustawi\u0107, jak d\u0142ugo b\u0119d\u0105 przechowywane r\u00f3\u017cne dane. Reguluje to tzw. polityka retencji - jest to podobne do baz danych wewn\u0105trz g\u0142\u00f3wnej bazy danych, przy czym ka\u017cda wewn\u0119trzna baza ma swoje ustawienia. Domy\u015blnie wszystkie dane trafiaj\u0105 do polityki retencji o nazwie autogen, te dane b\u0119d\u0105 przechowywane przez tydzie\u0144. Chcia\u0142bym, aby dane godzinowe by\u0142y przechowywane przez miesi\u0105c, tygodniowe - przez rok, a miesi\u0119czne w og\u00f3le nie by\u0142y usuwane. Stw\u00f3rzmy odpowiednie polityki retencji.<\/p>\n<pre><code class=\"sql\">UTW\u00d3RZ POLITYK\u0118 RETENCJI &quot;month&quot; NA &quot;homeassistant&quot; CZAS TRWANIA 30d REPLIKACJA 1\nUTW\u00d3RZ POLITYK\u0118 RETENCJI &quot;year&quot; NA &quot;homeassistant&quot; CZAS TRWANIA 52w REPLIKACJA 1\nUTW\u00d3RZ POLITYK\u0118 RETENCJI &quot;infinite&quot; NA &quot;homeassistant&quot; CZAS TRWANIA INF REPLIKACJA 1<\/code><\/pre>\n<p>\nTeraz, przechodz\u0105c do g\u0142\u00f3wnego triku - agregacja danych za pomoc\u0105 zapytania ci\u0105g\u0142ego. Jest to mechanizm, kt\u00f3ry automatycznie uruchamia zapytanie w okre\u015blonych odst\u0119pach czasu, agreguje dane na podstawie tego zapytania, a wynik zapisuje jako now\u0105 warto\u015b\u0107. Rozbijmy to na przyk\u0142ad (pisz\u0119 w kolumnach dla lepszej czytelno\u015bci, ale w rzeczywisto\u015bci musia\u0142em wprowadzi\u0107 t\u0119 komend\u0119 w jednej linii)<\/p>\n<pre><code class=\"sql\">CREATE CONTINUOUS QUERY cq_water_hourly ON homeassistant \nBEGIN \n  SELECT max(value) AS value \n  INTO homeassistant.month.water_meter_hour \n  FROM homeassistant.autogen.l \n  GROUP BY time(1h), entity_id fill(previous) \nEND<\/code><\/pre>\n<p>\nTa komenda:<\/p>\n<ul>\n<li>Tworzy zapytanie ci\u0105g\u0142e o nazwie cq_water_cold_hourly w bazie homeassistant<\/li>\n<li>Zapytanie b\u0119dzie wykonywane co godzin\u0119 (time(1h))<\/li>\n<li>Zapytanie b\u0119dzie pobiera\u0107 wszystkie dane z miary homeassistant.autogen.l (litry), w tym odczyty zimnej i ciep\u0142ej wody<\/li>\n<li>Agregowane dane b\u0119d\u0105 grupowane wed\u0142ug entity_id, co utworzy osobne warto\u015bci dla zimnej i ciep\u0142ej wody<\/li>\n<li>Poniewa\u017c licznik litr\u00f3w to monotonicznie rosn\u0105ca sekwencja, w ramach ka\u017cdej godziny nale\u017cy wzi\u0105\u0107 maksymaln\u0105 warto\u015b\u0107, dlatego agregacja b\u0119dzie przeprowadzana funkcj\u0105 max(value) <\/li>\n<li>Nowa warto\u015b\u0107 zostanie zapisana w homeassistant.month.water_meter_hour, gdzie month to nazwa polityki retencji z okresem przechowywania wynosz\u0105cym miesi\u0105c. Przy czym dane dotycz\u0105ce zimnej i ciep\u0142ej wody b\u0119d\u0105 rozdzielone na osobne rekordy z odpowiednim entity_id i warto\u015bci\u0105 w polu value.<\/li>\n<\/ul>\n<p>\nW nocy lub kiedy nikogo nie ma w domu, zu\u017cycie wody nie wyst\u0119puje, a tym samym nowych rekord\u00f3w w homeassistant.autogen.l r\u00f3wnie\u017c nie ma. Aby unikn\u0105\u0107 brak\u00f3w warto\u015bci w zwyk\u0142ych zapytaniach, mo\u017cna u\u017cy\u0107 fill(previous). To sprawi, \u017ce InfluxDB u\u017cyje warto\u015bci z poprzedniej godziny. <\/p>\n<p>Niestety, zapytanie ci\u0105g\u0142e ma swoj\u0105 specyfik\u0119: sztuczka fill(previous) nie dzia\u0142a i zapisy po prostu nie s\u0105 tworzone. To jest pewien nieprzezwyci\u0119\u017cony problem, kt\u00f3ry <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/influxdata\/influxdb\/issues\/3220\">jest omawiany ju\u017c od kilku lat.<\/a><\/noindex>Z tym problemem poradzimy sobie p\u00f3\u017aniej, a fill(previous) w zapytaniu ci\u0105g\u0142ym niech b\u0119dzie \u2013 nie przeszkadza. <\/p>\n<p>Sprawd\u017amy, co uda\u0142o si\u0119 uzyska\u0107 (oczywi\u015bcie trzeba poczeka\u0107 kilka godzin):<\/p>\n<pre><code class=\"python\">&gt; select * from homeassistant.month.water_meter_hour group by entity_id\n...\nname: water_meter_hour\ntags: entity_id=water_meter_cold\ntime                 value\n----                 -----\n...\n2020-03-08T01:00:00Z 370511\n2020-03-08T02:00:00Z 370513\n2020-03-08T05:00:00Z 370527\n2020-03-08T06:00:00Z 370605\n2020-03-08T07:00:00Z 370635\n2020-03-08T08:00:00Z 370699\n2020-03-08T09:00:00Z 370761\n2020-03-08T10:00:00Z 370767\n2020-03-08T11:00:00Z 370810\n2020-03-08T12:00:00Z 370818\n2020-03-08T13:00:00Z 370827\n2020-03-08T14:00:00Z 370849\n2020-03-08T15:00:00Z 370921\n<\/code><\/pre>\n<p>\nZauwa\u017c, \u017ce warto\u015bci w bazie s\u0105 przechowywane w UTC, wi\u0119c w tej li\u015bcie r\u00f3\u017cni\u0105 si\u0119 o 3 godziny \u2014 warto\u015bci z 7 rano w wynikach InfluxDB odpowiadaj\u0105 warto\u015bciom z 10 rano na powy\u017cszych wykresach. Zauwa\u017c tak\u017ce, \u017ce mi\u0119dzy 2 a 5 rano zapisy po prostu nie istniej\u0105 \u2014 to jest ta specyfika zapytania ci\u0105g\u0142ego.<\/p>\n<p>Jak wida\u0107, agregowana warto\u015b\u0107 r\u00f3wnie\u017c jest monotonicznie rosn\u0105c\u0105 sekwencj\u0105, tylko zapisy s\u0105 rzadsze \u2014 raz na godzin\u0119. Ale to nie problem \u2014 mo\u017cemy napisa\u0107 jeszcze jedno zapytanie, kt\u00f3re wyci\u0105gnie odpowiednie dane do wykresu.<\/p>\n<pre><code class=\"sql\">SELECT difference(max(value)) \nFROM homeassistant.month.water_meter_hour \nWHERE entity_id='water_meter_cold' and time &gt;= now() -24h \nGROUP BY time(1h), entity_id \nfill(previous)<\/code><\/pre>\n<p>\nRozja\u015bni\u0119:<\/p>\n<ul>\n<li>Z bazy homeassistant.month.water_meter_hour wyci\u0105gniemy dane dla entity_id='water_meter_cold' z ostatnich 24 godzin (time &gt;= now() -24h). <\/li>\n<li>Jak ju\u017c wspomnia\u0142em w sekwencji homeassistant.month.water_meter_hour mog\u0105 brakowa\u0107 pewnych zapis\u00f3w. Te dane wygenerujemy ponownie, uruchamiaj\u0105c zapytanie z GROUP BY time(1h). Tym razem fill(previous) zadzia\u0142a jak nale\u017cy, generuj\u0105c brakuj\u0105ce dane (funkcja we\u017amie poprzedni\u0105 warto\u015b\u0107).<\/li>\n<li>Najwa\u017cniejsze w tym zapytaniu jest funkcja difference, kt\u00f3ra obliczy r\u00f3\u017cnic\u0119 mi\u0119dzy znacznikami czasowymi. Sama w sobie nie dzia\u0142a i wymaga funkcji agreguj\u0105cej. Niech to b\u0119dzie max() u\u017cywana wcze\u015bniej.<\/li>\n<\/ul>\n<p>\nWynik wykonania wygl\u0105da tak:<\/p>\n<pre><code class=\"python\">name: water_meter_hour\ntags: entity_id=water_meter_cold\ntime                 difference\n----                 ----------\n...\n2020-03-08T02:00:00Z 2\n2020-03-08T03:00:00Z 0\n2020-03-08T04:00:00Z 0\n2020-03-08T05:00:00Z 14\n2020-03-08T06:00:00Z 78\n2020-03-08T07:00:00Z 30\n2020-03-08T08:00:00Z 64\n2020-03-08T09:00:00Z 62\n2020-03-08T10:00:00Z 6\n2020-03-08T11:00:00Z 43\n2020-03-08T12:00:00Z 8\n2020-03-08T13:00:00Z 9\n2020-03-08T14:00:00Z 22\n2020-03-08T15:00:00Z 72<\/code><\/pre>\n<p>\nOd 2 do 5 rano (UTC) zu\u017cycia nie by\u0142o. Niemniej jednak zapytanie zwr\u00f3ci t\u0119 sam\u0105 warto\u015b\u0107 zu\u017cycia dzi\u0119ki fill(previous), a funkcja difference odejmie t\u0119 warto\u015b\u0107 sama od siebie, co da w rezultacie 0, co jest dok\u0142adnie tym, co jest wymagane.<\/p>\n<p>Pozosta\u0142o tylko jedno \u2014 zbudowa\u0107 wykres. W tym celu otworzymy Grafana, otworzymy istniej\u0105cy (lub stworzymy nowy) dashboard, stworzymy now\u0105 plansz\u0119. Ustawienia wykres\u00f3w b\u0119d\u0105 nast\u0119puj\u0105ce.<\/p>\n<p><img decoding=\"async\" alt=\"Inteligentny dom: Budujemy wykresy zu\u017cycia wody i energii elektrycznej w Home Assistant\" src=\"\/wp-content\/uploads\/2020\/03\/c6f551590cd141438b644b24aa4ddebf.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nB\u0119d\u0119 wy\u015bwietla\u0107 dane dotycz\u0105ce zimnej i ciep\u0142ej wody na jednym wykresie. Zapytanie jest dok\u0142adnie takie samo jak opisa\u0142em powy\u017cej. <\/p>\n<p>Parametry wy\u015bwietlania s\u0105 okre\u015blane w ten spos\u00f3b. U mnie b\u0119dzie to wykres liniowy (lines), kt\u00f3ry idzie ze schodkami (stairs). Parametr Stack wyja\u015bni\u0119 nieco poni\u017cej. Poni\u017cej jeszcze kilka parametr\u00f3w wy\u015bwietlania, ale nie s\u0105 tak interesuj\u0105ce.<\/p>\n<p><img decoding=\"async\" alt=\"Inteligentny dom: Budujemy wykresy zu\u017cycia wody i energii elektrycznej w Home Assistant\" src=\"\/wp-content\/uploads\/2020\/03\/cb47fc8570b7fd1305ce3451e0518f11.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAby doda\u0107 otrzymany wykres do home assistant, nale\u017cy:<\/p>\n<ul>\n<li>wyj\u015b\u0107 z trybu edycji wykresu. Dlaczego\u015b poprawne ustawienia udost\u0119pniania wykres\u00f3w s\u0105 proponowane tylko ze strony dashboardu.<\/li>\n<li>Klikn\u0105\u0107 na tr\u00f3jk\u0105t obok nazwy wykresu, w menu wybra\u0107 share.<\/li>\n<li>W otwartym oknie przej\u015b\u0107 na zak\u0142adk\u0119 embed.<\/li>\n<li>Odznaczy\u0107 opcj\u0119 current time range \u2014 zakres czasowy b\u0119dziemy okre\u015bla\u0107 przez URL. <\/li>\n<li>Wybra\u0107 potrzebny motyw. W moim przypadku to light.<\/li>\n<li>Skopiowa\u0107 otrzymany URL do karty ustawie\u0144 lovelace-UI.<\/li>\n<\/ul>\n<p><\/p>\n<pre><code class=\"python\">      - type: iframe\n        id: graf_water_hourly\n        url: &quot;http:\/\/192.168.10.200:3000\/d-solo\/rZARemQWk\/water?orgId=1&amp;panelId=2&amp;from=now-2d&amp;to=now&amp;theme=light&quot;\n<\/code><\/pre>\n<p>\nZwr\u00f3\u0107 uwag\u0119, \u017ce zakres czasowy (ostatnie 2 dni) jest okre\u015blany w\u0142a\u015bnie tutaj, a nie w ustawieniach dashboardu. <\/p>\n<p>Wykres wygl\u0105da tak. Ciep\u0142ej wody nie u\u017cywa\u0142em przez ostatnie 2 dni, dlatego rysowany jest tylko wykres zimnej wody.<\/p>\n<p><img decoding=\"async\" alt=\"Inteligentny dom: Budujemy wykresy zu\u017cycia wody i energii elektrycznej w Home Assistant\" src=\"\/wp-content\/uploads\/2020\/03\/d18c82712d3b829a97ada8c8e2adce24.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNie zdecydowa\u0142em, kt\u00f3ry wykres bardziej mi si\u0119 podoba, czy schodkowy, czy rzeczywiste s\u0142upki. Dlatego po prostu podam przyk\u0142ad dziennego wykresu zu\u017cycia, tym razem tylko w formie s\u0142upk\u00f3w. Zapytania s\u0105 budowane analogicznie do opisanych powy\u017cej. Parametry wy\u015bwietlania s\u0105 nast\u0119puj\u0105ce:<\/p>\n<p><img decoding=\"async\" alt=\"Inteligentny dom: Budujemy wykresy zu\u017cycia wody i energii elektrycznej w Home Assistant\" src=\"\/wp-content\/uploads\/2020\/03\/557297e666f9cd73c3d2aa2fd80c0a2d.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWykres wygl\u0105da tak:<\/p>\n<p><img decoding=\"async\" alt=\"Inteligentny dom: Budujemy wykresy zu\u017cycia wody i energii elektrycznej w Home Assistant\" src=\"\/wp-content\/uploads\/2020\/03\/ac8c53569c6b05aeb22e05969de4cd6d.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTak wi\u0119c o parametrze Stack. W tym wykresie s\u0142upek zimnej wody jest rysowany na wierzchu s\u0142upka ciep\u0142ej. Ca\u0142kowita wysoko\u015b\u0107 odpowiada ca\u0142kowemu zu\u017cyciu zimnej i ciep\u0142ej wody w danym okresie. <\/p>\n<p>Wszystkie przedstawione wykresy s\u0105 dynamiczne. Mo\u017cna najecha\u0107 myszk\u0105 na interesuj\u0105cy punkt i zobaczy\u0107 szczeg\u00f3\u0142y i warto\u015b\u0107 w konkretnej lokalizacji. <\/p>\n<p>Niestety, nie oby\u0142o si\u0119 bez paru \u0142y\u017cek dziegciu. Na wykresie s\u0142upkowym (w przeciwie\u0144stwie do wykresu liniowego) \u015brodek s\u0142upka nie znajduje si\u0119 w \u015brodku doby, lecz o 00:00. To znaczy, \u017ce lewa po\u0142owa s\u0142upka jest rysowana na miejscu poprzedniego dnia. Tak wi\u0119c wykresy za sobot\u0119 i niedziel\u0119 s\u0105 nieco przesuni\u0119te w lewo od niebieskiej strefy. Na razie nie wymy\u015bli\u0142em, jak to naprawi\u0107. <\/p>\n<p>Inny problem polega na niemo\u017cno\u015bci prawid\u0142owego pracy z przedzia\u0142ami miesi\u0119cznymi. Chodzi o to, \u017ce d\u0142ugo\u015b\u0107 godziny\/dnia\/tygodnia jest sta\u0142a, a d\u0142ugo\u015b\u0107 miesi\u0105ca za ka\u017cdym razem jest r\u00f3\u017cna. InfluxDB mo\u017ce pracowa\u0107 tylko z r\u00f3wnymi przedzia\u0142ami. Na razie wystarczy\u0142o mi pomy\u015ble\u0107 o sta\u0142ym przedziale 30 dni. Tak, wykres w ci\u0105gu roku b\u0119dzie troch\u0119 si\u0119 rozje\u017cd\u017ca\u0142, a s\u0142upki nie do ko\u0144ca b\u0119d\u0105 odpowiada\u0107 miesi\u0105com. Ale poniewa\u017c to dla mnie ciekawe jako wska\u017anik, to mi to odpowiada. <\/p>\n<p>Widz\u0119 co najmniej dwa rozwi\u0105zania:<\/p>\n<ul>\n<li>Zrezygnowa\u0107 z miesi\u0119cznych wykres\u00f3w i skupi\u0107 si\u0119 na tygodniowych. 52 tygodniowe s\u0142upki w roku wygl\u0105daj\u0105 ca\u0142kiem nie\u017ale.<\/li>\n<li>Samo miesi\u0119czne zu\u017cycie liczy\u0107 jako spos\u00f3b \u21162, a Grafana u\u017cywa\u0107 tylko do \u0142adnych wykres\u00f3w. To b\u0119dzie ca\u0142kiem dok\u0142adne rozwi\u0105zanie. Mo\u017cna nawet na\u0142o\u017cy\u0107 wykresy z zesz\u0142ego roku dla por\u00f3wnania \u2014 Grafana tak\u017ce to potrafi.<\/li>\n<\/ul>\n<h2>Podsumowanie<\/h2>\n<p>\nNie wiem dlaczego, ale uwielbiam tego rodzaju wykresy. Pokazuj\u0105, \u017ce \u017cycie t\u0119tni i wszystko si\u0119 zmienia. Wczoraj by\u0142o du\u017co, dzi\u015b ma\u0142o, a jutro b\u0119dzie jako\u015b jeszcze. Zosta\u0142o tylko popracowa\u0107 z domownikami na temat zu\u017cycia. Ale nawet przy obecnych apetytach, du\u017ca i niezrozumia\u0142a liczba na rachunku ju\u017c staje si\u0119 do\u015b\u0107 zrozumia\u0142ym obrazem zu\u017cycia.<\/p>\n<p>Mimo prawie 20-letniej kariery programisty, prawie nie mia\u0142em styczno\u015bci z bazami danych. Dlatego instalacja zewn\u0119trznej bazy danych wydawa\u0142a si\u0119 czym\u015b tak trudnym i niezrozumia\u0142ym. Wszystko zmieni\u0142a <noindex><a rel=\"nofollow\" href=\"https:\/\/dummylabs.com\/ru\/post\/2019-01-13-influxdb-part1\">wy\u017cej wspomniana artyku\u0142<\/a><\/noindex> \u2013 okaza\u0142o si\u0119, \u017ce pod\u0142\u0105czenie odpowiedniego narz\u0119dzia mo\u017cna zrobi\u0107 w kilka klikni\u0119\u0107, a z wyspecjalizowanym narz\u0119dziem zadanie budowy wykres\u00f3w staje si\u0119 troch\u0119 \u0142atwiejsze.<\/p>\n<p>W tytule wspomnia\u0142em o zu\u017cyciu energii elektrycznej. Niestety w tej chwili nie mog\u0119 przedstawi\u0107 \u017cadnych wykres\u00f3w. Jeden licznik SDM120 mi pad\u0142, a drugi ma problemy z komunikacj\u0105 przez Modbus. Niemniej jednak, nie wp\u0142ywa to w \u017caden spos\u00f3b na temat tego artyku\u0142u \u2013 wykresy b\u0119d\u0105 budowane w ten sam spos\u00f3b, co dla wody.<\/p>\n<p>W tym artykule przedstawi\u0142em podej\u015bcia, kt\u00f3re sam wypr\u00f3bowa\u0142em. Z pewno\u015bci\u0105 istniej\u0105 jeszcze inne sposoby organizacji zbierania i wizualizacji danych, o kt\u00f3rych nie wiem. Podzielcie si\u0119 nimi w komentarzach, bardzo mnie to zainteresuje. B\u0119d\u0119 wdzi\u0119czny za konstruktywn\u0105 krytyk\u0119 i nowe pomys\u0142y. Mam nadziej\u0119, \u017ce przedstawiony materia\u0142 r\u00f3wnie\u017c komu\u015b pomo\u017ce.<br \/>\n<br \/>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/492314\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043f\u043e\u043b\u0443\u0447\u0430\u044f \u043f\u043b\u0430\u0442\u0435\u0436\u043a\u0443 \u0437\u0430 \u044d\u043b\u0435\u043a\u0442\u0440\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0438 \u0432\u043e\u0434\u0443 \u044f \u0443\u0434\u0438\u0432\u043b\u044f\u044e\u0441\u044c \u2014 \u043d\u0435\u0443\u0436\u0435\u043b\u0438 \u043c\u043e\u044f \u0441\u0435\u043c\u044c\u044f \u0441\u0442\u043e\u043e\u043e\u043e\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u0435\u0442? \u041d\u0443 \u0434\u0430, \u0432 \u0432\u0430\u043d\u043d\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0442\u0435\u043f\u043b\u044b\u0439 \u043f\u043e\u043b \u0438 \u0431\u043e\u0439\u043b\u0435\u0440, \u043d\u043e \u0432\u0435\u0434\u044c \u043e\u043d\u0438 \u0436\u0435 \u043d\u0435 \u043a\u043e\u0447\u0435\u0433\u0430\u0440\u044f\u0442 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e. \u0412\u043e\u0434\u0443 \u0442\u043e\u0436\u0435 \u0432\u0440\u043e\u0434\u0435 \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u043c (\u0445\u043e\u0442\u044f \u043f\u043e\u043f\u043b\u0435\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0432 \u0432\u0430\u043d\u043d\u043e\u0439 \u0442\u043e\u0436\u0435 \u043b\u044e\u0431\u0438\u043c). \u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043b\u0435\u0442 \u043d\u0430\u0437\u0430\u0434 \u044f \u0443\u0436\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b \u0441\u0447\u0435\u0442\u0447\u0438\u043a\u0438 \u0432\u043e\u0434\u044b \u0438 \u044d\u043b\u0435\u043a\u0442\u0440\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043a \u0443\u043c\u043d\u043e\u043c\u0443 \u0434\u043e\u043c\u0443, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":74422,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-74421","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/umnyj-dom-stroim-grafiki-potrebleniya-vody-i-elektrichestva-v-home-assistant\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0423\u043c\u043d\u044b\u0439 \u0434\u043e\u043c: \u0421\u0442\u0440\u043e\u0438\u043c \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u0432\u043e\u0434\u044b \u0438 \u044d\u043b\u0435\u043a\u0442\u0440\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432 Home Assistant | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/umnyj-dom-stroim-grafiki-potrebleniya-vody-i-elektrichestva-v-home-assistant\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-03-17T05:43:08+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-03-17T05:43:08+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Inteligentny dom: Tworzenie wykres\u00f3w zu\u017cycia wody i energii elektrycznej w Home Assistant | ProHoster","description":"Za ka\u017cdym razem.","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/umnyj-dom-stroim-grafiki-potrebleniya-vody-i-elektrichestva-v-home-assistant","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0423\u043c\u043d\u044b\u0439 \u0434\u043e\u043c: \u0421\u0442\u0440\u043e\u0438\u043c \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u0432\u043e\u0434\u044b \u0438 \u044d\u043b\u0435\u043a\u0442\u0440\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432 Home Assistant | ProHoster","og:description":"\u041a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437.","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/umnyj-dom-stroim-grafiki-potrebleniya-vody-i-elektrichestva-v-home-assistant","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-03-17T05:43:08+00:00","article:modified_time":"2020-03-17T05:43:08+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"74421","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 18:15:28","updated":"2022-09-27 16:07:45","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/74421","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=74421"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/74421\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/74422"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=74421"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=74421"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=74421"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}