Как настроить Home Assistant чтобы термостат включал несколько обогревателей с паузой между включением

Я тут продолжаю экспериментировать с Home Assistant. Придумал себе небольшой проект. Решил сделать обогрев одной комнаты на даче.

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

Сервер Home Assistant знает температуру с датчика и может включать-выключать розетки. Ну а дальше дело техники — говорю серверу что я хочу чтобы температура была +24. Home Assistant включает обогреватели и они шпарят до тех пор пока в комнате не будет +24. Потом они выключаются. Температура постепенно падает, через некоторое время они опять включаются и опять добивают температуру до +24.

Если есть один обогреватель, то для того чтобы это настроить в Home Assistant нужно добавить в конфиг всего несколько строк:

climate:
  - platform: generic_thermostat
    heater: switch.smart_plug
    target_sensor: sensor.room_temperature

Тут как раз указывается умная розетка ("switch.smart_plug") и датчик который показывает температуру ("sensor.room_temperature").

Но моя задача — подключить два обогревателя. Можно сделать следующее. Создать группу "group.heater_smart_plugs" и добавить в нее две умные розетки, а в конфиге HA указать:

climate:
  - platform: generic_thermostat
    heater: group.heater_smart_plugs
    target_sensor: sensor.room_temperature

Когда температура ниже заданной Home Assistant будет включать "виртуальное" устройство "group.heater_smart_plugs" и это будет включать обе розетки.

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

Я мало что понимаю в электричестве, но мне кажется что ситуация с паузой более правильная. Обогреватели это достаточно мощные устройства, которые дают большую нагрузку. Мне бы хотелось чтобы на электрическую сеть не было сразу большой нагрузки, а нагрузка приходила бы постепенно: вот сейчас включили два киловатта, чуть позже еще два. А не так: не было никакой нагрузки, а тут фигакс и сразу 4 кВт.

Так что я решил убедить Home Assistant что обогреватели нужно включать с паузой.

Пошел настраивать.

Тестовый стенд

Мой настоящий сервер HA — это Raspberry Pi 3 B+. Не очень мощное устройство. Плюс на нем уже крутится некоторая автоматизация. Мне очень нравится экспериментировать с конфигурированием Home Assistant не на настоящем продакшн сервере, а на специальном тестовом стенде, который я разворачиваю на своем ноутбуке.

Поднять сервер с HA на ноутбуке невероятно просто. Нужно чтобы на ноуте был установлен Docker, а потом одна команда и Home Assistant работает:

docker run --detach --rm -it --publish=8123:8123 --volume=`pwd`/config/:/config/ --name=ha homeassistant/qemux86-64-homeassistant

С помощью этой команды я поднял тестовую инсталляцию Home Assistant на которой можно делать все что угодно и это никак не повлияет на работу моего настоящего сервера HA. Плюс, поскольку эта тестовая инсталляция поднята на моем ноутбуке перезагрузка сервера HA выполняется сильно-сильно быстрее чем на Raspberry Pi. Поэтому цикл настройки поправил-перезагрузил-проверил проходит гораздо быстрее и приятнее.

Итак, у меня есть сервер Home Assistant на котором можно играться. К нему не подключены никакие датчики температуры и не подключены никакие розетки. Я решил создать тестовые версии этих устройств.

Вот что у меня получилось. Вот все содержимое файла "configuration.yaml":

default_config:

frontend:

logger:
  default: debug

input_boolean:
  input_boolean_1:
    initial: off
  input_boolean_2:
    initial: off

input_number:
  input_number_1:
    initial: 18
    min: 0
    max: 35
    step: 0.5

sensor:
  - platform: template
    sensors:
      fake_temperature:
        unit_of_measurement: "degrees"
        value_template: "{{ states('input_number.input_number_1') | float }}"

switch:
  - platform: template
    switches:
      fake_heater_1:
        value_template: "{{ is_state('input_boolean.input_boolean_1', 'on') }}"
        turn_on:
          service: input_boolean.turn_on
          data:
            entity_id: input_boolean.input_boolean_1
        turn_off:
          service: input_boolean.turn_off
          data:
            entity_id: input_boolean.input_boolean_1

      fake_heater_2:
        value_template: "{{ is_state('input_boolean.input_boolean_2', 'on') }}"
        turn_on:
          service: input_boolean.turn_on
          data:
            entity_id: input_boolean.input_boolean_2
        turn_off:
          service: input_boolean.turn_off
          data:
            entity_id: input_boolean.input_boolean_2

climate:
  - platform: generic_thermostat
    heater: switch.fake_heater_1
    target_sensor: sensor.fake_temperature

(Я тут завел 2 переменные "input_boolean_1" и "input_boolean_2", каждая из них хранит статус "виртуальной" умной розетки — что она — включена или выключена. И завел переменную "input_number_1" в которой хранится "виртуальная" температура в комнате. Дальше из этой переменной делаю сенсор температуры, а из первых двух переменных делаю switch)

А вот yaml с настройкой интерфейса:

title: Home
views:
  - badges: []
    cards:
      - entities:
          - entity: switch.fake_heater_1
          - entity: switch.fake_heater_2
          - entity: input_number.input_number_1
            name: fake_temperature
        type: entities
      - entity: climate.generic_thermostat
        type: thermostat
    path: default_view
    title: Home

Видео как это работает:

Итак, есть тестовый стенд, который очень похож на то что что у меня есть по настоящему.

Виртуальный выключатель

В конце концов, много раз обратившись за помощью к Жене мне удалось сделать решение которое делает то что мне нужно.

Я сделал виртуальный выключатель. За ним прячутся 2 выключателя и он берет на себе всю логику чтобы включать-выключать эти два выключателя с паузой.

Вот его описание в файле configuration.yaml:

 switch:
   - platform: template
     switches:
       smart_switch:
         value_template: "{{ is_state('switch.fake_heater_1', 'on') or is_state('switch.fake_heater_2', 'on') }}"
         turn_on:
           service: script.toggle
           data:
             entity_id: script.turn_on_with_delay
         turn_off:
           service: script.toggle
           data:
             entity_id: script.turn_off_with_delay

Что тут важно. У выключателя статус может быть либо "on" (включен), либо "off" (выключен). У этого виртуального выключателя статус "on" будет в ситуации когда хотя бы один из двух выключателей включен

При включении этого виртуального выключателя дергается скрипт "turn_on_with_delay", а при выключении — "turn_off_with_delay".

Вот описание этих скриптов в файле configuration.yaml:

script:
  turn_on_with_delay:
    sequence:
      - service: script.turn_off
        data:
          entity_id: script.turn_off_with_delay
      - service: switch.turn_on
        data:
          entity_id: switch.fake_heater_1
      - delay:
          seconds: 1
      - service: switch.turn_on
        data:
          entity_id: switch.fake_heater_2

  turn_off_with_delay:
    sequence:
      - service: script.turn_off
        data:
          entity_id: script.turn_on_with_delay
      - service: switch.turn_off
        data:
          entity_id: switch.fake_heater_1
      - delay:
          seconds: 1
      - service: switch.turn_off
        data:
          entity_id: switch.fake_heater_2

Каждый скрипт — это последовательность (sequence) из трех действий. Включить первый, подождать, включить второй. Очень важно что в начале каждой последовательности выполняется действие "выключи другой скрипт". Благодаря этому не происходит проблемы в ситуации, когда этот виртуальный выключатель быстро включается-выключается.

Видео как это работает:

Полный конфиг

Вот целиком файл configuration.yaml с этим примером:

default_config:

frontend:

logger:
  default: debug

input_boolean:
  input_boolean_1:
    initial: off
  input_boolean_2:
    initial: off

input_number:
  input_number_1:
    initial: 18
    min: 0
    max: 35
    step: 0.5

sensor:
  - platform: template
    sensors:
      fake_temperature:
        unit_of_measurement: "degrees"
        value_template: "{{ states('input_number.input_number_1') | float }}"

script:
  turn_on_with_delay:
    sequence:
      - service: script.turn_off
        data:
          entity_id: script.turn_off_with_delay
      - service: switch.turn_on
        data:
          entity_id: switch.fake_heater_1
      - delay:
          seconds: 1
      - service: switch.turn_on
        data:
          entity_id: switch.fake_heater_2

  turn_off_with_delay:
    sequence:
      - service: script.turn_off
        data:
          entity_id: script.turn_on_with_delay
      - service: switch.turn_off
        data:
          entity_id: switch.fake_heater_1
      - delay:
          seconds: 1
      - service: switch.turn_off
        data:
          entity_id: switch.fake_heater_2

switch:
  - platform: template
    switches:
      fake_heater_1:
        value_template: "{{ is_state('input_boolean.input_boolean_1', 'on') }}"
        turn_on:
          service: input_boolean.turn_on
          data:
            entity_id: input_boolean.input_boolean_1
        turn_off:
          service: input_boolean.turn_off
          data:
            entity_id: input_boolean.input_boolean_1

      fake_heater_2:
        value_template: "{{ is_state('input_boolean.input_boolean_2', 'on') }}"
        turn_on:
          service: input_boolean.turn_on
          data:
            entity_id: input_boolean.input_boolean_2
        turn_off:
          service: input_boolean.turn_off
          data:
            entity_id: input_boolean.input_boolean_2

      smart_switch:
        value_template: "{{ is_state('switch.fake_heater_1', 'on') or is_state('switch.fake_heater_2', 'on') }}"
        turn_on:
          service: script.toggle
          data:
            entity_id: script.turn_on_with_delay
        turn_off:
          service: script.toggle
          data:
            entity_id: script.turn_off_with_delay

climate:
  - platform: generic_thermostat
    heater: switch.smart_switch
    target_sensor: sensor.fake_temperature

Иван Бессарабов
ivan@bessarabov.ru

22 января 2020