Использование utility_meter в Home Assistant
В системе Home Assistant есть специальный инструмент utility_meter.
С помощью utility_meter Home Assistant может считать сколько набежало за период. Очень часто этот инструмент используется для того чтобы считать сколько кВт*ч было потрачено за день или месяц. Другое частое использование utility_meter — это подсчет сколько литров холодной/горячей воды было использовано за день/месяц.
Вода и электричество — это самые частые вещи которые считаются с помощью utility_meter, но с его помощью можно считать все что угодно.
Пример использования
У меня на ввод электричества в доме установлен датчик PZEM-004t (подробности).
Благодаря этому у меня в Home Assistant есть сенсор sensor.pzem_004t_v3_energy значение которого — это накопленная энергия в кВт*ч. Это то сколько было израсходовано кВт*ч с момента установки устройства. Это значение всегда увеличивается.
Значение сенсора sensor.pzem_004t_v3_energy это именно сколько набежало (кВт*ч), а не мгновенное потребление (кВт) (сенсор с мгновенным потреблением у меня тоже есть, но для utility_meter нужно не мгновенное потребление, а накопленное)
Этот сенсор нужно указать для utility_meter. Вот код configuration.yaml Home Assistant для подсчета сколько было потрачено за день:
Этот код создаст новый сенсор sensor.daily_energy_pzem, значение которого — сколько кВт*ч было израсходовано за сегодня:
Значение sensor.daily_energy_pzem растет в течении дня, а в 00:00:00 сбрасывается в ноль и начинает считаться заново.
У этого сенсора есть атрибут last_period, значение этого атрибута — сколько utility_meter насчитал за прошлый период. Это utility_meter считает за день, так что в значении last_period содержится то сколько было потрачено за вчера:
Создание нескольких utility_meter
Вот пример кода configuration.yaml как создать два utility_meter, один который считает за день, второй — за месяц.
Возможные значения для cycle
В описании utility_meter обязательно нужно указать cycle — за какой период utility_meter будет считать. (то как часто он будет сбрасываться в ноль). Чаще всего используется daily и monthly, но есть много вариантов как часто utility_meter будет сбрасывать в ноль:
Проблема с переключением
Сенсор созданный с помощью utility_meter считает сколько набежало, а в определенный момент сбрасывает в ноль и начинает считать заново. Например, при использовании cycle: daily сброс будет происходить каждый день в 00:00:00.
В том случае если в момент сброса Home Assistant не работает (например, сервер выключен или ровно в этот момент сервер перезагружается), то сброса уже не произойдет. HA продолжит дальше суммировать все в этот сенсор и сбросит в ноль только в следующий раз.
Долговременное хранение данных
Сенсоры которые создает utility_meter хранит информацию только за текущий период (находится в state сенсора) и данные за прошлый период (находятся в атрибуте last_period). Встроенными средствами Home Assistant не очень удобно сделать хранение и отображение данных за много периодов. Например, показать сколько были израсходовано кВт*ч за каждый день месяца. Я пришел к тому что с помощью utility_meter считаю только данна по дням, а дальше сохраняю эти данные в табличку Google Sheets. (Подробности как это сделано).
Тарифы
В некоторых ситуациях нужно по разному считать в зависимости от времени. Например, если используется многотарифные счетчики электричества.
Вот что нужно написать в configuration.yaml для того чтобы считать два тарифа:
Этот код создает два сенсора:
Плюс создается сущность utility_meter.daily_energy_pzem_tariff
Если оставить только такой код, то данные все время будут записывать в первый сенсор, sensor.daily_energy_pzem_tariff_day.
Для того чтобы менять в какой сенсор будут накапливаться данные нужно еще написать автоматизацию. Вот пример который используется у меня С помощью time триггера происходит перещелкивание тарифа:
Мониторинг потребления электричества с помощью pzem-004t, Home Assistant и ESPHome
Есть несколько разных способов как можно замерить потребление электричества. Очень часто используются умные розетки. Например, хочется считать сколько потребляет кВтч электрический обогреватель. Его можно подключить в умную розетку и снимать с этой розетки данные — прямо сейчас потребление 1838 ватт, за сутки набежало 12.7 кВтч. Есть огромный выбор умных розеток.
Другой вариант — это умное реле. Вот большой список разных умных реле, некоторые из них умеют замерять электроэнергию.
Но умные розетки и умные реле очень ограничены по мощности. Я не знаю ни одного устройства через которое можно было бы подключать больше 16 ампер (это 3680 ватт).
Иногда нужно снимать данные про потребление электричества с очень мощного прибора. Например, считать сколько потребляет электроплита. Или считать потребление всей квартиры/дома.
Для этих целей можно использовать устройство pzem-004t. Огромный плюс этого устройства — то что снятие данных происходит неинвазивно. Т.е. не нужно ставить какое-то устройство в разрыв электролинии. Нужно только пропустить провод в специальное кольцо и pzem будет замерять то что идет по проводу.
Pzem-004t — это не законченное устройство, это комонент. Это датчик который нужно подключить к какому-то устройству которое будет снимать данные с этого датчика.
Выбор pzem-004t
Я купил себе pzem-004t на AliExpress. Покупал вот в этом магазине. Можно найти это же устройство в виде отдельной платы, но я решил купить сразу с корпусом, мне не до конца было понятно как будет выглядеть законченное устройство поэтому на всякий случай я купил не только плату, но еще и корпус.
Очень выжный момент при покупке — обязательно нужно покупать pzem004t который расчитан на 100 ампер (бывает еще вариант на 10 ампер, смысла в нем особо нет).
И еще одни момент про который стоит подумать при покупке — то как выглядит кольцо которое снимает данные. Бывает 2 варианта: либо оно цельное, либо его можно открыть. Кольцо которое можно открыть удобнее при установке — не нужно отсоединять кабель с которого нужно снимать данные, можно просто защелкнуть кольцо на кабеле (и кольцо тоже должно быть рассчитано на 100 ампер).
Что в посылке
Я купил pzem-004t на AliExpress, через несколько недель забрал с почты посылку. Внутри — аккуратная коробочка в которой находится платка pzem-00t в корпусе, кольцо и инструкция.
Если снять корпус, то на плате pzem-004t видно что устройство рассчитано на 100 ампер:
Информация про 100 ампер так же есть и на кольце:
Сборка устройства
В качестве первого подхода я собрал самую простую схему подключения. Это не самая удобная в использовании конструкция, но зато это самый простой способ получить работающее устройство. И этот вариант собирается без использования паяльника.
Нужны следующие компоненты:
Вот что получилось:
Недостаток этого решения — то что устройство занимает 2 розетки. Нужно подавать питание и на плату nodemcu и на сам pzem.
Некоторые уточнения про схему подключения:
Контакты с правой стороны pzem которые идут на nodemcu:
На этом сборка закончена.
Прошивка ESPHome
Следующий момент — нужно написать прошивку которая будет работать на nodemcu. При использовании ESPHome самый простой вариант прошивки следующий.
Тут есть важный момент. В ESPHome есть 2 платформы:
Я изначально пытался использовать платформу pzem004t — и у меня ничего не работало. Оказывается, это неправильно. Для этого устройства (pzem-004t v3) нужно использовать платформу pzemac.
С помощью ESPHome собрал из этого yaml файла прошивку, залил ее на nodemcu. Устройство подключилось к WiFi и автоматически появилось в Home Assistant.
Проверка работы
Для того чтобы протестировать работу pzem я собрал тестовый стенд. Взял умную лампочку Ikea, навесил кольцо на провод и все подключил:
Включаю лампочку — вижу потребление: 12.6 ватт:
Выключаю лампочку — тоже вижу потребление, но гораздо меньше:
Как не будет работать
Кольцо нужно надевать на отдельный кабель — на фазу или на ноль. Если кольцо надеть на кабель где идет и фаза, и ноль, то устройство ничего показывать не будет. Вот пример неправильного подключения — кольцо надето на общий кабель который идет к электрическому чайнику, там внутри фаза, ноль и земля. Чайник кипит, но pzem показывает нули.
Умный дом: Строим графики потребления воды и электричества в Home Assistant
Каждый раз получая платежку за электричество и воду я удивляюсь — неужели моя семья стооооолько потребляет? Ну да, в ванной установлен теплый пол и бойлер, но ведь они же не кочегарят постоянно. Воду тоже вроде экономим (хотя поплескаться в ванной тоже любим). Несколько лет назад я уже подключил счетчики воды и электричества к умному дому, но на этом дело так и застряло. До анализа потребления руки дошли только сейчас, о чем, собственно, вот эта статья.
Недавно я перешел на Home Assistant в качестве системы умного дома. Одной из причин была как раз возможность организовать сбор большого количества данных с возможностью удобного построения различного рода графиков.
Информация описанная в этой статье не нова, все эти штуки под разными соусами уже были описаны в Интернетах. Но каждая статья, как правило, описывает только один подход или аспект. Сравнивать все эти подходы и выбирать наиболее подходящий пришлось самому. Статья все равно не дает исчерпывающей информации по сбору данных, но является своего рода конспектом того как сделал я. Так что конструктивная критика и предложения по улучшению приветствуются.
Постановка задачи
Итак, цель сегодняшнего упражнения в том, чтобы получить красивые графики потребления воды и электричества:
Если хорошо поискать, то можно найти сторонние компоненты, которые расширяют возможности стандартного графика. Для home assistant, в принципе, неплох и красив компонент mini-graph-card, но и он несколько ограничен:
Хуже если устройство может просто измерять некий мгновенный параметр (например мгновенную мощность или ток), или просто генерировать импульсы каждые X ватт-часов или литров. Тогда нужно думать как и чем это интегрировать и где накапливать значение. Есть риск пропустить очередной отчет по какой либо причине, да и точность системы в целом вызывает вопросы. Можно, конечно, это все поручить системе умного дома вроде home assistant, но пункт про количество записей в базе никто не отменял, да и опрос датчиков чаще чем раз в секунду устроить не получится (ограничение архитектуры home assistant).
Подход 1
Сначала посмотрим что предоставляется home assistant из коробки. Измерение потребления за период — весьма востребованная функциональность. Разумеется, ее давным давно реализовали в виде специализированного компонента — utility_meter.
Суть компонента в том, что он внутри заводит переменную текущее_накопленное_значение, и сбрасывает ее по истечении заданного периода (час/неделя/месяц). Компонент сам мониторит входящую переменную (значение какого нибудь сенсора), сам подписывается на изменения значения — вы просто получаете готовый результат. Описывается эта штука всего несколькими строчками в конфигурационном файле
Тут sensor.water_meter_cold это текущее значение счетчика в литрах, которые я получаю непосредственно от железяки по mqtt. Конструкция создает 2 новых сенсора water_cold_hour_um и water_cold_day_um, которые накапливают часовые и дневные показания, обнуляя их по истечении периода. Вот график часового аккумулятора за полдня.
Код часового и дневного графиков для lovelace-UI выглядит так:
Собственно, в этом алгоритме и кроется проблема такого подхода. Как я уже упоминал, на каждое входящее значение (текущее показание счетчика на каждый следующий литр) генерируется по 1кб записи в базе. Каждый utility meter также генерирует по новому значению, которое также складывается в базу. Если я хочу собирать часовые/дневные/недельные/месячные показания, да по нескольким стоякам воды, да еще пачку электросчетчиков добавить — это будет очень много данных. Ну точнее данных то не много, но поскольку home assistant в базу пишет кучу лишней информации размер базы будет расти как на дрожжах. Боюсь даже прикидывать размер базы для понедельных и помесячных графиков.
Помимо этого utility meter сам по себе не решает поставленную задачу. График значений, которые выдает utility meter это монотонно возрастающая функция, которая сбрасывается в 0 каждый час. Нам же нужен понятный для пользователя график потребления, сколько же литров было съедено за период. Стандартный компонент history-graph такого не умеет, но нам может помочь внешний компонент mini-graph-card.
Это код карточки для lovelace-UI:
Помимо стандартных настроек вроде имени сенсора, типа графика, цвета (стандартный оранжевый мне не понравился) тут важно отметить 3 настройки:
На ряд столбиков слева не обращайте внимания — это стандартное поведение компонента если нет данных. А данных и не было — я только пару часов назад включил сбор данных по utility meter только ради этой статьи (свой текущий подход я расскажу чуть ниже).
На этой картинке я хотел показать, что иногда отображение данных даже работает, и столбики действительно отражают правильные значения. Только вот далеко не все. Выделенный столбик за промежуток с 11 до 12 утра почему то отображает 19 литров, хотя на зубастом графике чуть выше за этот же самый период с того же самого сенсора видим потребление 62 литра. Либо баг, либо руки кривые. А вот почему отломались данные справа я пока не понял — потребление там было в норме, что также видно по зубастому графику.
В общем, правдоподобности это этого подхода мне добиться не удалось — график почти всегда показывает какую-то ересь.
Аналогичный код для дневного сенсора.
Обратите внимание что параметр group_by установлен в значение interval, и рулит всем параметр points_per_hour. И в этом заключается другая проблема этого компонента — points_per_hour хорошо работает на графиках за час или менее, но отвратительно на бОльших промежутках. Так чтобы получить один столбик за один день пришлось вписать значение 1/24=0.04166666. Я уже не говорю про недельные и месячные графики.
Подход 2
Еще только разбираясь с home assistant я наткнулся на вот это видео:
Товарищ собирает данные потребления с нескольких видов розеток Xiaomi. Задача у него чуть проще — просто выводить значение потребления за сегодня, вчера и за месяц. Никаких графиков не требуется.
Оставим в стороне рассуждения о ручном интегрировании мгновенных значений мощности — о “точности” такого подхода я уже писал выше. Не ясно почему он не стал использовать накопленные значения потребления, которые уже собираются той же розеткой. На мой взгляд интегрирование внутри железяки будет работать лучше.
От видео мы возьмем идею ручного подсчета потребления за период. У мужика считаются только значения за сегодня и за вчера, но мы пойдем дальше и попробуем нарисовать график. Суть предложенного метода в моем случае заключается в следующем.
Кода придется написать несколько больше чем в предыдущем подходе. Для начала заведем эти самые “переменные”. Из коробки у нас нет сущности “переменная”, но можно воспользоваться услугами mqtt брокера. Будем отправлять туда значения с флагом retain=true — это сохранит значение внутри брокера, и его в любой момент можно оттуда выдернуть, даже при перезагрузке home assistant. Я сделал сразу часовые и дневные счетчики.
Вся магия происходит в автоматизации, которая запускается каждый час и каждую ночь соответственно.
Обе автоматизации выполняют 2 действия:
В принципе это уже то, что нужно. Плюсом данного метода является то, что данные генерируются один раз за интервал. Т.е. всего 24 записи за сутки для часового графика.
К сожалению, общую проблему растущей базы это все равно не решает. Если я захочу график помесячного потребления, то придется хранить данные как минимум за год. А поскольку home assistant предоставляет только одну настройку длительности хранения на всю базу, то это означает что ВСЕ данные в системе придется хранить целый год. Например за год я потребляю 200 кубов воды, а значит это 200000 записей в базу. А если учесть еще и другие сенсоры, то цифра вообще неприличной становится.
Подход 3
К счастью, умные люди уже решили эту проблему написав базу данных InfluxDB. Эта база специальным образом оптимизирована под хранение time-based данных и идеально подходит для хранения значений разных сенсоров. Система также предоставляет SQL-подобный язык запросов, который позволяет выковыривать из базы значения, и потом их агрегировать различными способами. Наконец, разные данные можно хранить разное время. Например, часто меняющиеся показания вроде температуры или влажности можно хранить всего пару недель, тогда как дневные показания потребления воды можно хранить целый год.
Помимо InfluxDB умные люди также изобрели Grafana — систему рисования графиков по данным из InfluxDB. Графана умеет рисовать разные виды графиков, детально их кастомизировать, и, что самое главное, эти графики можно “воткнуть” на lovelace-UI home assistant’а.
Вдохновляться тут и тут. В статьях подробно описан процесс установки и подключения InfluxDB и Grafana к home assistant. Я же сосредоточусь на решении своей конкретной задачи.
Итак, первым делом начнем складывать значение счетчика в influxDB. Кусок конфигурации home assistant (в этом примере я буду развлекаться не только холодной, но и горячей водой):
Отключим сохранение этих же самых данных внутреннюю базу home assistant, чтобы не раздувать ее лишний раз:
Перейдем теперь в консоль InfluxDB и настроим нашу базу. В частности нужно настроить сколько времени будут хранится те или иные данные. Это регулируется т.н. retention policy — это похоже на базы данных внутри основной базы данных, причем каждая внутренняя база имеет свои настройки. По умолчанию все данные складываются в retention policy под названием autogen, эти данные будут хранится неделю. Я бы хотел, чтобы часовые данные хранились месяц, недельные — год, а месячные вообще никогда не удалялись. Создадим соответствующие retention policy
Теперь, собственно, главный трюк — агрегация данных с помощью continuous query. Это механизм, который автоматически запускает запрос через заданные промежутки времени, агрегирует данные по этому запросу, а результат складывает в новое значение. Разберем на примере (я пишу в столбик для удобочитаемости, но на деле мне пришлось вводить эту команду одной строкой)
К сожалению, у continuous query есть особенность: трюк fill(previous) не работает и записи просто не создаются. Причем это какая-то непреодолимая проблема, которая обсуждается уже не первый год. С этой проблемой мы разберемся позже, а fill(previous) в continuous query пусть будет — оно не мешает.
Проверим что получилось (разумеется, нужно выждать пару часиков):
Обратите внимание, что значения в базе сохраняются в UTC, поэтому в этом списке отличаются на 3 часа — значения за 7 утра в выводе InfluxDB соответствуют значениям за 10 утра на графиках выше. Также обратите внимание, что между 2 и 5 утра записей просто нету — это та самая особенность continuous query.
Как видите, агрегированное значение также является монотонно возрастающей последовательностью, только записи идут реже — раз в час. Но это не проблема — мы можем написать еще один запрос, который будет добывать правильные данные для графика.
С 2 до 5 утра (UTC) потребления не было. Тем не менее запрос вернет одно и тоже значение потребления благодаря fill(previous), а функция difference это значение вычтет само из себя и на выходе получим 0, что собственно и требуется.
Осталось дело за малым — построить график. Для этого откроем Grafana, откроем какой нибудь существующий (или создадим новый) дашборд, создадим новую панель. Настройки графиков будут такими.
Я буду отображать данные по холодной и горячей воде на одном графике. Запрос точно такой же как я описал выше.
Параметры отображения задаются так. У меня это будет график линиями (lines), который идет ступеньками (stairs). Параметр Stack я объясню чуть ниже. Там ниже еще пара параметров отображения, но они не так интересны.
Чтобы добавить полученный график в home assistant нужно:
Обратите внимание что временной диапазон (последние 2 дня) задается именно тут, а не в настройках дашборда.
Выглядит график вот так. Горячую воду я не за последние 2 дня не использовал, поэтому рисуется только график холодной воды.
Я так для себя и не решил какой график мне больше нравится, линией-ступенькой, или реальными столбиками. Поэтому просто приведу пример дневного графика потребления, только на этот раз столбиками. Запросы строятся аналогично вышеописанным. Параметры отображения такие:
Выглядит этот график так:
Так вот про параметр Stack. В этом графике столбик холодной воды рисуется поверх столбика горячей. Общая высота соответствует суммарному потреблению по холодной и горячей воде за период.
Все показанные графики — динамические. Можно навести мышкой на интересующую точку и посмотреть детали и значение в конкретной точке.
К сожалению без пары ложек дегтя не обошлось. На столбиковом графике (в отличии от графика линиями-ступеньками) середина столбика находится не в середине суток, а в 00:00. Т.е. левая половина столбика нарисована на месте предыдущего дня. Так вот графики за субботу и воскресенье нарисованы чуть левее чем синеватая зона. Пока я не придумал как это победить.
Другая проблема заключается в невозможности правильно работать с интервалами в месяц. Дело в том, что длина часа/дня/недели фиксирована, а вот длина месяца каждый раз разная. InfluxDB умеет работать только с одинаковыми интервалами. Пока моих мозгов хватило чтобы задать фиксированный интервал в 30 дней. Да, график в течении года немного поплывет и столбики не совсем точно будут соответствовать месяцам. Но поскольку мне это штука интересна просто в качестве показометра, то я с этим ок.
Решений вижу как минимум два:
Заключение
Не знаю почему, но я тащусь от такого рода графиков. Они показывают что жизнь кипит и все меняется. Вчера было много, сегодня мало, завтра будет как нибудь еще. Осталось поработать с домочадцами на тему потребления. Но даже при текущих аппетитах просто большая и непонятная цифра в платежке уже превращается в достаточно понятную картину потребления.
Несмотря на почти 20-летнюю карьеру программиста, с базами данных я практически не пересекался. Поэтому установка внешней базы данных казалось чем-то таким заумным и непонятным. Все изменила вышеупомянутая статья — оказалось что прикручивание подходящего инструмента делается в пару кликов, а со специализированным инструментом задача построения графиков становится немного проще.
В заголовке я упомянул потребление электричества. К сожалению в данный момент я не могу привести ни одного графика. Один счетчик SDM120 у меня сдох, а другой глючит при обращении по Modbus. Впрочем, на тему данной статьи это никак не влияет — графики будут строится тем же самым способом, как и для воды.
В этой статье я привел те подходы, которые испробовал сам. Наверняка есть еще какие-то способы организации сбора и визуализации данных, о которых я не знаю. Расскажите мне об этом в комментариях, мне будет очень интересно. Буду рад конструктивной критике и новым идеям. Надеюсь изложенный материал также кому-то поможет.