Не так давно мне пришел счёт за газ от которого стало не по себе, и я решил интегрировать обычный счетчик газа в свой умный дом на базе Raspberry Pi + Home Assistant, чтобы прогнозировать стоимость расходов и получать предупреждения сразу же как только расход начинает превышать ожидания.

Первым делом я полез на Хабр, и к моему удивлению, среди не малого количества статей о том как считывать показания счетчиков, и даже пары статей непосредственно о снятии показаний со счетчика газа, ни в одной из них я не нашел того что искал.

Есть довольно интересная статья 2014 года об оптическом снятии показаний с любого счетчика с помощью смартфона, но в ней ни слова ни о Home Assistant вообще ни о его компоненте для оптического распознавания счетчиков в частности.

Есть статья 2018 года об универсальном недорогом устройстве для оптического снятия показаний с любого счетчика, которое я на тот момент был бы рад купить, но в свободную продажу оно до сих пор не попало.

Читая эти и другие статьи (например статью 2018 года про Вотериус, или статью 2020 года Умная хрущёвка на максималках) я понял, что счетчики делятся не на два поколения (offline и online), а на три. Помимо 3-го поколения счетчиков, которое умеет отправлять показания счетчика куда надо, есть еще 2-е, которое само передавать данные по сети не умеет, но снабжено передатчиком импульсов (оптических или магнитных), позволяющим подключить к счетчику модуль, который эти импульсы считывает и передает дальше.

Погуглив свой счетчик газа (им оказался BK-G4) я с радостью обнаружил не только то, что генератор магнитных импульсов в него встроен (магнитик на барабане младшего разряда), но и даже то, что уже есть успешные примеры его интеграции в Home Assistant.

Однако перед тем как заказывать специализированный (герконовый) датчик импульсов IN-Z61 (1640р с доставкой, устанавливается в специально предусмотренную для него выемку в корпусе счётчика), плату esp8266 (788р с доставкой), паяльник, олово, канифоль, ждать пока все это приедет, а потом канифолиться с этим конструктором, я решил проверить гипотезу, нельзя ли решить задачу существенно проще и дешевле.

Удача улыбнулась мне, и вместо недели ожидания и нескольких тысяч расходов, я в тот же день интегрировал счетчик в Home Assistant обычным датчиком открытия двери Xiaomi (модель MCCGQ01LM), горсть которых когда-то приобрел на Авито по 600р за штуку.

Стоит заметить, что не снимая корпус с платы датчика, подбор положения в котором датчик справляется со считыванием импульсов требует усилий. Батарейки говорят на долго не хватит, хотя у меня за месяц-два использования не закончилась и новые продаются на AliExpress около 20р за штуку.

Для того чтобы завести счетчик в Home Assistant первым делом я создал сам счетчик в configuration.yaml

counter:
  gas_counter:
    step: 10

и добавил в automations.yaml автоматизацию которая увеличивает его значение в

- id: '1606010744418'
  alias: Gas count
  description: ''
  trigger:
  - entity_id: binary_sensor.openclose_gas
    platform: state
    from: 'on'
    to: 'off'
  action:
  - data:
      entity_id:
      - counter.gas_counter
    service: counter.increment

Затем добавил в configuration.yaml строку utility_meter: !include utility_meter.yaml, а в файл utility_meter.yaml следующие сущности, собирающие значения счетчика газа по интервалам (месяц, день, час)

gas_monthly:
  source: sensor.gas_counter_sensor
  cycle: monthly
  tariffs:
    - single
gas_daily:
  source: sensor.gas_counter_sensor
  cycle: daily
  tariffs:
    - single
gas_hourly:
  source: sensor.gas_counter_sensor
  cycle: hourly
  tariffs:
    - single

и уже на основе этих сущностей создал сенсоры, которые превращают кубометры в рубли

- platform: template
  sensors:
    gas_counter_sensor:
      friendly_name: "Показания счетика газа"
      unit_of_measurement: 'М3'
      value_template: "{{ (states('counter.gas_counter') | float) / 1000 }}"
      icon_template: mdi:counter
- platform: template
  sensors:
    gas_last_month:
      friendly_name: "Стоимость газа (прошлый месяц)"
      unit_of_measurement: '?'
      value_template: "{{ ((state_attr('sensor.gas_monthly_single', 'last_period') | float) / 1000 * 6056.4) | round(2) }}"
      icon_template: mdi:cash-100
- platform: template
  sensors:
    gas_this_month:
      friendly_name: "Стоимость газа (этот месяц)"
      unit_of_measurement: '?'
      value_template: "{{ ((states('sensor.gas_monthly_single') | float) / 1000 * 6056.4) | round(2) }}"
      icon_template: mdi:cash-100
- platform: template
  sensors:
    gas_today:
      friendly_name: "Стоимость газа (сегодня)"
      unit_of_measurement: '?'
      value_template: "{{ ((states('sensor.gas_daily_single') | float) / 1000 * 6056.4) | round(2) }}"
      icon_template: mdi:cash-100
- platform: template
  sensors:
    gas_yesterday:
      friendly_name: "Стоимость газа (вчера)"
      unit_of_measurement: '?'
      value_template: "{{ ((state_attr('sensor.gas_daily_single', 'last_period') | float) / 1000 * 6056.4) | round(2) }}"
      icon_template: mdi:cash-100
- platform: template
  sensors:
    gas_this_hour:
      friendly_name: "Стоимость газа (текущий час)"
      unit_of_measurement: '?'
      value_template: "{{ ((states('sensor.gas_hourly_single') | float) / 1000 * 6056.4) | round(2) }}"
      icon_template: mdi:cash-100
- platform: template
  sensors:
    gas_last_hour:
      friendly_name: "Стоимость газа (прошлый час)"
      unit_of_measurement: '?'
      value_template: "{{ ((state_attr('sensor.gas_hourly_single', 'last_period') | float) / 1000 * 6056.4) | round(2) }}"
      icon_template: mdi:cash-100
- platform: template
  sensors:
    gas_hour_based_monthly_estimate:
      friendly_name: "Прогноз стоимости (час->месяц)"
      unit_of_measurement: '?'
      value_template: "{{ ((state_attr('sensor.gas_hourly_single', 'last_period') | float) / 1000 * 6056.4 * 24 * 30) | int }}"
      icon_template: mdi:chart-line-variant
- platform: template
  sensors:
    gas_day_based_monthly_estimate:
      friendly_name: "Прогноз стоимости (день->месяц)"
      unit_of_measurement: '?'
      value_template: "{{ ((state_attr('sensor.gas_daily_single', 'last_period') | float) / 1000 * 6056.4 * 30) | int }}"
      icon_template: mdi:chart-line-variant

Чтобы счетчик не убил SD карту на которой бегает Home Assistant в кратчайшие сроки, и интерфейс Home Assistant не вешался при открытии состояния датчика, отключил датчику историю, добавив в configuration.yaml

recorder:
  exclude:
    entities:
      - binary_sensor.openclose_gas

После перезагрузки Home Assistant остаётся только ввести в систему текущее показание счетчика

У данного решения есть существенный минус, при каждой перезагрузке Home Assistant система будет пропускать часть импульсов, но прогнозировать стоимость расходов за месяц на основе расходов за час (или за день) это фактически не мешает, как и получать предупреждения о скачке расходов.

А для того чтобы в конце месяца автоматически посчитать точную фактическую стоимость расходов (например чтобы скинуть их арендодателю) достаточно скорректировать показания (если расхождения появились) за день до конца месяца.