updating configuration

This commit is contained in:
Your Name
2026-03-10 07:08:59 +00:00
commit 9498a076ee
238 changed files with 18119 additions and 0 deletions
@@ -0,0 +1,46 @@
import appdaemon.plugins.hass.hassapi as hass
#
# Listen for presence sensor change state and change alarm control panel state.
#
# Args:
# sensor - home presence 'sensor'
# ha_panel - alarm control panel entity (to arm and disarm).
# constraint - (optional, input_boolen), if turned off - alarm panel will be not armed\disarmed.
#
# Release Notes
#
# Version 1.0:
# Initial Version
class AlarmPanelBySensor(hass.Hass):
def initialize(self):
if "sensor" not in self.args or "ha_panel" not in self.args:
self.error("Please provide sensor and ha_panel in config!")
return
self.listen_state(self.sensor_trigger, self.args['sensor'])
self.listen_event(self.ha_event, "ha_started")
def ha_event(self, event_name, data, kwargs):
self.log('Starting up!')
state = self.get_state(self.args['sensor'])
self.log('Updating alarm_control_panel state: {}'.format(state))
if state == "off":
self.away_mode()
def sensor_trigger(self, entity, attribute, old, new, kwargs):
self.log("{} turned {}".format(entity, new))
if new == "off" and old == "on":
self.away_mode()
if new == "on" and old == "off":
self.return_home_mode()
def away_mode(self):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
self.call_service("alarm_control_panel/alarm_arm_away", entity_id = self.args['ha_panel'])
def return_home_mode(self):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
self.call_service("alarm_control_panel/alarm_disarm", entity_id = self.args['ha_panel'])
@@ -0,0 +1,11 @@
#################################
# HOME PRESENSE #
#################################
alarm_panel:
module: alarm_panel
class: AlarmPanelBySensor
sensor: sensor.presence_home
ha_panel: alarm_control_panel.ha_alarm
constraint: input_boolean.presence_control
global_dependencies:
- globals
@@ -0,0 +1,77 @@
import appdaemon.plugins.hass.hassapi as hass
#
# Listen for Alarm panel state change and fire an events ('away_mode' and 'return_home_mode')
#
# Args:
# ha_panel - alarm control panel entity.
# Release Notes
#
# Version 1.0:
# Initial Version
class AlarmPanelAction(hass.Hass):
extended_timeout = 5*60
timers = []
def initialize(self):
if "ha_panel" not in self.args:
self.error("Please provide ha_panel in config!")
return
self.listen_state(self.ha_panel_trigger, self.args['ha_panel'])
extended_timeout = self.args.get('extended_timeout', self.extended_timeout)
self.log('extended_timeout: {}'.format(self.extended_timeout))
def ha_panel_trigger(self, entity, attribute, old, new, kwargs):
# не срабатываем на triggered.
if new == "armed_away" and old != "triggered":
self.away_mode()
if new == "disarmed" and old == "armed_away":
self.return_home_mode()
def away_mode(self):
self.log('away_mode')
self.fire_event('away_mode')
if 'presence_extended' in self.args:
self.fire_event('presence_extended_just_left')
self.set_mode('Just Left')
self.cancel_current_timer()
self.timers.append(self.run_in(self.run_in_set_mode, self.extended_timeout, mode='Away'))
def return_home_mode(self):
self.log('return_home_mode')
self.fire_event('return_home_mode')
if 'presence_extended' in self.args:
self.set_mode('Just Arrived')
self.fire_event('presence_extended_just_arrived')
self.cancel_current_timer()
self.timers.append(self.run_in(self.run_in_set_mode, self.extended_timeout, mode='Home'))
def set_mode(self, mode):
if 'presence_extended' not in self.args:
return
entity_id = self.args['presence_extended']
self.log('setting mode direct: {}={}'.format(entity_id, mode))
self.call_service("input_select/select_option", entity_id = entity_id, option = mode)
def run_in_set_mode(self, kwargs):
if not 'mode' in kwargs:
return
mode = kwargs['mode']
entity_id = self.args['presence_extended']
event = 'presence_extended_{}'.format(mode.lower())
self.log('firing event: {}'.format(event))
self.fire_event(event)
self.log('setting mode by timer: {}={}'.format(entity_id, mode))
self.call_service("input_select/select_option", entity_id = entity_id, option = mode)
def cancel_current_timer(self):
for timer in self.timers:
self.log('canceling timer')
self.cancel_timer(timer)
self.timers = []
@@ -0,0 +1,11 @@
#################################
# HOME PRESENSE #
#################################
alarm_panel_action:
module: alarm_panel_action
class: AlarmPanelAction
ha_panel: alarm_control_panel.ha_alarm
presence_extended: input_select.presence_extended
extended_timeout: 300
global_dependencies:
- globals
@@ -0,0 +1,80 @@
import appdaemon.plugins.hass.hassapi as hass
#
# Light control by presence events
# Listen for presence events and change light state
#
# Args:
# entities - entities to turn on and off when presence is changed.
# Release Notes
#
# Version 1.0:
# Initial Version
class EntitiesByPresence(hass.Hass):
mode = None
def initialize(self):
if 'away_entities' not in self.args or 'return_entities' not in self.args:
self.error("Please provide away_entities and return_entities in config!")
return
self.listen_event(self.away_mode, "away_mode")
self.listen_event(self.return_home_mode, "return_home_mode")
self.determine_current_mode()
self.set_thermostat_by_mode(None)
self.timer = self.run_every(self.set_thermostat_by_mode, 'now', 5*60)
def determine_current_mode(self):
state = self.get_state('input_select.presence_extended')
if state == 'Home' or state == 'Just Arrived':
self.mode = 'home'
else:
self.mode = 'away'
def away_mode(self, event_id, event_args, kwargs):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
self.mode = 'away'
for entity_id in self.args["away_entities"]:
self.turn_off_custom(entity_id)
self.set_thermostat_by_mode(None)
def return_home_mode(self, event_id, event_args, kwargs):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
self.mode = 'home'
entities = self.args["return_entities"]
if entities == None:
entities=[]
for entity_id in entities:
self.turn_on_custom(entity_id)
self.set_thermostat_by_mode(None)
def set_thermostat_by_mode(self, kwargs):
if "thremostats" not in self.args:
return
preset = 'away'
if self.mode == 'home':
preset = 'manual'
for entity_id in self.args["thremostats"]:
state = self.get_state(entity_id, 'preset_mode')
if state != preset:
self.log('Set thermostat ({}), current state = {}, set mode to {}'.format(entity_id, state, preset))
self.call_service("climate/set_preset_mode", entity_id=entity_id, preset_mode = preset)
def turn_on_custom(self, entity_id):
if 'cover.' in entity_id:
self.call_service("cover/open_cover", entity_id=entity_id)
return
if 'climate.' in entity_id:
self.call_service("climate/turn_on", entity_id=entity_id)
return
self.turn_on(entity_id)
def turn_off_custom(self, entity_id):
if 'cover.' in entity_id:
self.call_service("cover/close_cover", entity_id=entity_id)
return
if 'climate.' in entity_id:
self.call_service("climate/turn_off", entity_id=entity_id)
return
self.turn_off(entity_id)
@@ -0,0 +1,82 @@
#################################
# HOME PRESENSE #
#################################
entities_action:
module: entities_action
class: EntitiesByPresence
away_entities:
# air conditioners
- climate.ac_bedroom
- climate.ac_childroom
- climate.ac_kitchen
- climate.ac_mainroom
# din rail lights
- light.light_mainroom_mainlamp
- light.light_mainroom_spotlights
- light.light_mainroom_pc_spotlight
# balcony
- light.light_balcony_spotlight
# bedroom
- light.light_bedroom_spotlights
- light.light_bedroom_nightlight_left
- light.light_bedroom_nightlight_right
- light.light_bedroom_pc_spotlight
- light.light_bedroom_mainlight
- light.light_bedroom_pc_nightlight
# bath
- light.light_bath
- light.light_bath_shelf
# shower
- light.light_shower_main_spotlights
- light.light_shower_shower_spotlights
- light.light_shower_shelf_light
# hall
- light.light_hall_long
# childroom
- light.light_childroom_main
- light.light_childroom_spotlights
- light.light_childroom_bed
# kitchen
- light.light_kitchen_spotlights
- light.light_kitchen_table_lamp
- light.light_kitchen_bar_lamp
- light.light_kitchen_set
# ventilation
- fan.ventilation_shower
- fan.ventilation_bath
# bedside lamps
- light.danil_bedside_lamp_rgbww_light
- light.svetlana_bedside_lamp_rgbww_light
# mirrors and heaters
- switch.shower_mirror
- switch.switch_mirror_shower_heater
- switch.light_bath_mirror
- switch.switch_mirror_bath_heater
# media
- media_player.bedroom_tv
- media_player.kitchen_tv
- media_player.mainroom_tv
# alice
- media_player.yandex_station_m00r46000m53db
- media_player.yandex_station_m00fhe2003seqr
- media_player.yandex_station_ly00000000000008674600007209d3f5
- media_player.yandex_station_ff98f029ab48468d28c557be
- media_player.yandex_station_u003jc100phn9k
return_entities:
# - light.light_kitchen_set
thremostats:
- climate.radiator_childroom
- climate.radiator_mainroom
- climate.radiator_kitchen
- climate.radiator_bedroom
- climate.radiator_bedroom_balcony
global_dependencies:
- globals
@@ -0,0 +1,9 @@
purifier_timer:
module: purifier
class: Purifier
on_time: "06:45:00"
off_time: "23:00:00"
entity: fan.xiaomi_miio_device
ha_panel: alarm_control_panel.ha_alarm
global_dependencies:
- globals
@@ -0,0 +1,107 @@
import appdaemon.plugins.hass.hassapi as hass
import globals
import datetime
#
# Purifier controller
# Turn on and off purifier by light sensor and timers
#
# Args:
#
# None
#
# Release Notes
#
# Version 1.0:
# Initial Version
class Purifier(hass.Hass):
away_fan_speed = 8 #1-14
listen_event_handle_list = []
mode = 'auto'
def initialize(self):
if not globals.check_args(self, ["on_time", "off_time"]):
return
on_time = self.parse_time(self.args["on_time"])
off_time = self.parse_time(self.args["off_time"])
self.on_timer = self.run_daily(self.day_mode_timer_event, on_time)
self.off_timer = self.run_daily(self.night_mode_timer_event, off_time)
self.listen_event_handle_list.append(self.listen_event(self.away_mode_event, "away_mode"))
self.listen_event_handle_list.append(self.listen_event(self.return_home_mode_event, "return_home_mode"))
self.listen_event_handle_list.append(self.listen_state(self.state_change, self.args['entity'], attribute='illuminance'))
def state_change(self, entity, attribute, old, new, kwargs):
presence_state = self.get_state(self.args['ha_panel'])
if presence_state != "disarmed":
# self.log('Nobody home, ignoring illuminance changes.')
return
self.log("{} changed from {} to {}".format(attribute, old, new))
if old > 0 and new == 0 and self.time_is_between(self.datetime(), self.args["on_time"], self.args["off_time"]):
self.night_mode()
elif old == 0 and new > 0 and self.time_is_between(self.datetime(), self.args["on_time"], self.args["off_time"]):
self.auto_mode()
#self.auto_mode()
def return_home_mode_event(self, event_id, event_args, kwargs):
self.auto_mode()
def away_mode_event(self, event_id, event_args, kwargs):
self.away_mode()
def night_mode_timer_event(self, kwargs):
self.night_mode()
def day_mode_timer_event(self, kwargs):
self.auto_mode()
def away_mode(self):
self.mode='away'
self.log('Set purifier mode to favorite, speed: {}'.format(self.away_fan_speed))
if 'entity' in self.args:
self.call_service("fan/set_speed", entity_id = self.args['entity'], speed='favorite')
self.call_service("fan/xiaomi_miio_set_favorite_level", entity_id = self.args['entity'], level=self.away_fan_speed)
self.call_service("fan/xiaomi_miio_set_led_on", entity_id = self.args['entity'])
# self.call_service("fan/xiaomi_miio_set_buzzer_on", entity_id = self.args['entity'])
def auto_mode(self):
self.mode='auto'
self.log('Set purifier mode to auto.')
if 'entity' in self.args:
self.call_service("fan/set_speed", entity_id = self.args['entity'], speed='auto')
self.call_service("fan/xiaomi_miio_set_led_on", entity_id = self.args['entity'])
# self.call_service("fan/xiaomi_miio_set_buzzer_on", entity_id = self.args['entity'])
def night_mode(self):
self.mode='night'
self.log('Set purifier mode to silent.')
if 'entity' in self.args:
self.call_service("fan/xiaomi_miio_set_buzzer_off", entity_id = self.args['entity'])
self.call_service("fan/set_speed", entity_id = self.args['entity'], speed='silent')
self.call_service("fan/xiaomi_miio_set_led_off", entity_id = self.args['entity'])
def time_is_between(
hass, target_dt: datetime, start_time: str,
end_time: str) -> bool:
"""Generalization of AppDaemon's now_is_between method."""
start_time_dt = hass.parse_time(start_time) # type: datetime
end_time_dt = hass.parse_time(end_time) # type: datetime
start_dt = target_dt.replace(
hour=start_time_dt.hour,
minute=start_time_dt.minute,
second=start_time_dt.second)
end_dt = target_dt.replace(
hour=end_time_dt.hour,
minute=end_time_dt.minute,
second=end_time_dt.second)
if end_dt < start_dt:
# Spans midnight
if target_dt < start_dt and target_dt < end_dt:
target_dt = target_dt + timedelta(days=1)
end_dt = end_dt + timedelta(days=1)
return start_dt <= target_dt <= end_dt
@@ -0,0 +1,51 @@
import appdaemon.plugins.hass.hassapi as hass
import globals
#
# Home and away report
# Send report about home state after presence_actions was done.
#
# Args:
# entity - group of entities to send state report
# notify - notify entity to send message
#
# Release Notes
#
# Version 1.0:
# Initial Version
class ReportByPresence(hass.Hass):
report_delay = 15
def initialize(self):
if 'entity' not in self.args or 'notify' not in self.args:
self.error("Please provide entity and notify in config!")
return
self.listen_event(self.away_mode, "away_mode")
self.listen_event(self.return_home_mode, "return_home_mode")
def away_mode(self, event_id, event_args, kwargs):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
#wait 15 seconds before all devices will change thair states.
self.run_in(self.send_report, self.report_delay)
def return_home_mode(self, event_id, event_args, kwargs):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
self.notify("Добро пожаловать домой!", name = self.args['notify'])
############# AWAY REPORT ##########################
def send_report(self, kwargs):
any = False
message = ""
entities = globals.get_group_entities(self, self.args['entity'])
for entity in entities:
state = self.get_state(entity)
if state == "on":
any = True
message += '{} ({}) = {}\n'.format(self.friendly_name(entity), entity, self.get_state(entity))
if any:
message = "В доме остались работать следующие устройства:\n" + message
self.notify(message, name = self.args['notify'])
else:
self.notify("Все устройства в доме выключены.", name = self.args['notify'])
@@ -0,0 +1,10 @@
#################################
# HOME PRESENSE #
#################################
report_action:
module: report_action
class: ReportByPresence
entity: group.report_entities
notify: telegram
global_dependencies:
- globals
@@ -0,0 +1,136 @@
import appdaemon.plugins.hass.hassapi as hass
#
# Tags counter
# This app count 'at home' BLE tags and set home presence state.
# tag names must start from 'tag_'. Room presence sensors will be generated.
#
# Args:
# tag_prefix = tag prefix to search (in my case 'sensor.tag_')
# sensor_prefix = sensor prefix for room presence sensor (ex: if prefix 'sensor.presence_', than sensor name will be 'sensor.presence_hall')
# rooms = rooms list, where tags will be discovered (sensor will be created for each room)
# constraint_prefix (input_boolean) = constraint for tag (ex: input_boolean.tag_monster)
#
# Release Notes
#
# Version 1.0:
# Initial Version
class TagsPresence(hass.Hass):
tags = []
constraint_list = []
tag_by_room_cache = {}
def initialize(self):
if 'tag_prefix' not in self.args or 'sensor_prefix' not in self.args or 'rooms' not in self.args or 'constraint_prefix' not in self.args:
self.error("Please provide tag_prefix, sensor_prefix, constraint_prefix and rooms in config!")
return
self.listen_tags()
# self.listen_event(self.ha_event, "plugin_started")
self.refresh_presence_state()
# def ha_event(self, event_name, data, kwargs):
# self.run_in(self.refresh_presence_state_timer, 10)
def refresh_presence_state_timer(self, kwargs):
self.refresh_presence_state()
def sensor_trigger(self, entity, attribute, old, new, kwargs):
self.refresh_presence_state()
def constraint_trigger(self, entity, attribute, old, new, kwargs):
self.refresh_presence_state()
def listen_tags(self):
self.fill_tags_and_constraints()
for tag in self.tags:
self.listen_state(self.sensor_trigger, tag)
for constraint in self.constraint_list:
self.listen_state(self.constraint_trigger, constraint)
def refresh_presence_state(self):
tags_by_room = self.get_tags_state_by_room(self.tags, self.constraint_list)
tags_by_person = self.get_tags_state_by_person(self.tags, self.constraint_list)
homePresence = 'off'
for room in self.args['rooms']:
sensor = '{}{}'.format(self.args['sensor_prefix'],room)
if room in tags_by_room and len(tags_by_room[room]) > 0:
self.create_sensor(sensor, 'on')
homePresence = 'on'
else:
self.create_sensor(sensor, 'off')
for person in tags_by_person:
if len(tags_by_person[person])>0 and tags_by_person[person] != 'not home':
attr = self.get_state(person, attribute='all').get('attributes', None)
# self.log(attr)
# attr['state'] = tags_by_person[person][0]
# disable set person state
# self.set_state(person, state = tags_by_person[person][0], attributes = attr)
homeSensor = '{}{}'.format(self.args['sensor_prefix'],'home')
self.create_sensor(homeSensor, homePresence)
def get_tags_state_by_room(self, tags, constraint_list):
tags_by_room = {}
for tag in tags:
constraint = '{}{}'.format(self.args['constraint_prefix'],tag.replace(self.args['tag_prefix'],''))
if constraint in constraint_list and not self.constrain_input_boolean(constraint):
continue
room = self.get_state(tag)
if room not in tags_by_room:
tags_by_room[room] = []
tags_by_room[room].append(tag)
return tags_by_room
def get_tags_state_by_person(self, tags, constraint_list):
tags_by_person = {}
for tag in tags:
constraint = '{}{}'.format(self.args['constraint_prefix'],tag.replace(self.args['tag_prefix'],''))
if constraint in constraint_list and not self.constrain_input_boolean(constraint):
continue
tagName = tag.replace(self.args['tag_prefix'],'')
if '_' in tagName:
tagName = tagName.split('_')[0]
person = '{}{}'.format(self.args['person_prefix'], tagName)
person_state = self.get_state(person)
if person_state != None:
# self.log('{}: {}'.format(person, person_state))
if person not in tags_by_person:
tags_by_person[person] = []
tags_by_person[person].append(self.get_state(tag))
return tags_by_person
# if person_state in self.get_state('person'):
# self.log('{} found'.format(person))
# else:
# self.log('{} not found'.format(person))
# self.log('{}: {}'.format(person, person_state))
# tag_state = self.get_state(tag)
# if room not in tags_by_room:
# tags_by_room[room] = []
# tags_by_room[room].append(tag)
# return tags_by_room
def fill_tags_and_constraints(self):
self.tags = []
self.constraint_list = []
devices = self.get_state()
for tag in devices:
if not tag.startswith(self.args['tag_prefix']):
continue
self.tags.append(tag)
constraint = '{}{}'.format(self.args['constraint_prefix'],tag.replace(self.args['tag_prefix'],''))
if constraint in devices and constraint not in self.constraint_list:
self.constraint_list.append(constraint)
def create_sensor(self, entity_id, state, attributes = None):
current_state = self.get_state(entity_id)
if (current_state == state):
return
# self.log('Updating {} state ({}->{})'.format(entity_id, current_state, state))
if attributes == None:
attributes = {}
attributes['description'] = 'Created and updated from appdaemon (tags_presence)'
self.set_state(entity_id, state = state, attributes = attributes)
@@ -0,0 +1,16 @@
#################################
# HOME PRESENSE #
#################################
tags_presence:
module: tags_presence
class: TagsPresence
tag_prefix: sensor.tag_
sensor_prefix: sensor.presence_
constraint_prefix: input_boolean.tag_
person_prefix: person.
rooms:
- kladovka
- bedroom
- mainroom
global_dependencies:
- globals
@@ -0,0 +1,107 @@
import appdaemon.plugins.hass.hassapi as hass
import datetime
#
# Water control application.
# Controls water valve when all leave and no water needed devices is working.
#
# Args:
# water_valve = water valve entity
# notify - notify entity to send message
# constraint (optional) = input_boolean to enable\disable this automation
#
# Release Notes
#
# Version 1.0:
# Initial Version
class WaterValveControl(hass.Hass):
standby_power_limit = 15
current_wait_cycle = 0
wait_cycles = 2
timer = None
listen_event_handle_list = []
timers = []
def initialize(self):
if 'water_valve' not in self.args or 'water_devices' not in self.args or 'notify' not in self.args:
self.error("Please provide water_valve, water_devices and notify in config!")
return
self.listen_event_handle_list.append(self.listen_event(self.away_mode, "away_mode"))
self.listen_event_handle_list.append(self.listen_event(self.return_home_mode, "return_home_mode"))
self.log(self.get_turned_on_devices())
def return_home_mode(self, event_id, event_args, kwargs):
self.timer = None
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
self.turn_on(self.args['water_valve'])
for device in self.args['water_devices']:
self.turn_on(device)
self.cancel_current_timer()
def away_mode(self, event_id, event_args, kwargs):
self.timer = None
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
powered_on = self.get_turned_on_devices()
self.log('away entities: {}'.format(powered_on))
if (len(powered_on) > 0):
device_names = ""
for device in powered_on:
if device_names != '':
device_names += ", "
name = self.friendly_name(device)
if name is None:
name = device
device_names += name
self.notify('В доме остались требующие воды устройства ({}), подача воды не будет отключена.'.format(device_names), name = self.args['notify'])
self.cancel_current_timer()
self.timers.append(self.run_every(self.wait_when_device_is_done, self.datetime()+datetime.timedelta(seconds=5), 5*60))
else:
self.notify('Отключаю подачу воды.', name = self.args['notify'])
self.turn_off(self.args['water_valve'])
# for device in self.args['water_devices']:
# self.turn_off(device)
def wait_when_device_is_done(self, kwargs):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
powered_on = self.get_turned_on_devices()
self.log('still powered on: {}'.format(powered_on))
if len(powered_on) == 1:
self.current_wait_cycle = 0
elif len(powered_on) == 0 and self.current_wait_cycle<self.wait_cycles:
self.log("Current wait cycle: {}".format(self.current_wait_cycle))
self.current_wait_cycle = self.current_wait_cycle+1
elif len(powered_on) == 0 and self.current_wait_cycle>=self.wait_cycles:
self.current_wait_cycle = 0
self.notify('Устройства требующие воды закончили свою работу, отключаю подачу воды.', name = self.args['notify'])
self.turn_off_water_devices()
self.cancel_current_timer()
def turn_off_water_devices(self):
self.log("Turning off water devices.")
self.turn_off(self.args['water_valve'])
for device in self.args['water_devices']:
if 'switch' in device:
self.log('switching off: {}'.format(device))
self.turn_off(device)
def get_turned_on_devices(self):
powered_on_devices = []
devices = self.args['water_devices']
for device in devices:
state = self.get_state(device)
self.log('{} state: {}'.format(device, state))
if state == 'off' or state == None:
continue
powered_on_devices.append(device)
return powered_on_devices
def cancel_current_timer(self):
for timer in self.timers:
self.log('canceling timer')
self.cancel_timer(timer)
self.timers = []
@@ -0,0 +1,14 @@
#################################
# HOME PRESENSE #
#################################
water_action:
module: water_action
class: WaterValveControl
water_valve: switch.watercontrol_valves
notify: telegram
constraint: input_boolean.water_control
water_devices:
- binary_sensor.washer_running # стиралка
- binary_sensor.hc_dishwasher_running # посудомойка
global_dependencies:
- globals