updating configuration

This commit is contained in:
Your Name
2026-07-14 14:12:07 +00:00
parent 456f43d435
commit 6199c62362
83 changed files with 552 additions and 364 deletions
@@ -1,5 +1,6 @@
import appdaemon.plugins.hass.hassapi as hass
import os
import globals
#
# App to send notification when doorbell is ringing
@@ -26,10 +27,9 @@ class Doorbell(hass.Hass):
def ha_event(self, event_name, data, kwargs):
self.log('{}:{}'.format(event_name, data))
self.notify("Звонок в дверь!!!", name = self.args['notify'])
globals.send_telegram(self, "Звонок в дверь!!!", target = self.args['notify'])
if 'doorbell_pic' in data:
extra_data = {'photo': {'url':data['doorbell_pic']}}
self.notify("Фото звонившего", name = self.args['notify'], data=extra_data)
globals.send_telegram_photo(self, data['doorbell_pic'], target = self.args['notify'], caption = "Фото звонившего")
self.say('Звонок в дверь')
+51 -20
View File
@@ -2,22 +2,59 @@ import importlib
import subprocess
from typing import Any, Tuple, Union
#
# Global module
# contain global functions
#
# Args:
#
# None
#
# Release Notes
#
# Version 1.0:
# Initial Version
"""Define various constants."""
CONF_PEOPLE = 'people'
# --- Telegram notifications -------------------------------------------------
#
# HA 2026.2 deprecated the per-platform notify.telegram* services in favour
# of entity-based targeting (see repairs.issue_registry: telegram/migrate_notify).
# The generic notify.send_message service only supports message/title, so it
# can't carry parse_mode/photo/keyboard payloads our apps rely on - instead we
# target the telegram_bot integration's own (non-deprecated) domain services
# (telegram_bot.send_message / telegram_bot.send_photo) with entity_id, which
# is the current 1:1 replacement for the old chat_id-based notify.telegram*.
#
# Entity ids come from .storage/core.entity_registry (platform: telegram_bot),
# mapped from the friendly names ('telegram', 'telegram_monster',
# 'telegram_sveta') used throughout apps.yaml configs.
TELEGRAM_TARGETS = {
'telegram': 'notify.home_assistant_fonvizina_fonvizina_18_1001567589226',
'telegram_monster': 'notify.home_assistant_fonvizina_monster_123622180',
'telegram_sveta': 'notify.home_assistant_fonvizina_svetlana_205225134',
}
def send_telegram(self, message, target='telegram', parse_mode='html', **kwargs):
"""Send a Telegram text message via telegram_bot.send_message.
Replacement for the deprecated `self.notify(message, name=target)`.
`target` is a friendly name from TELEGRAM_TARGETS (falls back to the
default group chat if unknown). Extra kwargs (title, keyboard, etc.) are
passed straight through to the service call.
"""
entity_id = TELEGRAM_TARGETS.get(target, TELEGRAM_TARGETS['telegram'])
service_data = {'entity_id': entity_id, 'message': message}
if parse_mode:
service_data['parse_mode'] = parse_mode
service_data.update(kwargs)
self.call_service('telegram_bot/send_message', **service_data)
def send_telegram_photo(self, url, target='telegram', caption=None, parse_mode='html', **kwargs):
"""Send a photo via telegram_bot.send_photo.
Replacement for the deprecated `self.notify(msg, name=target,
data={'photo': {'url': url}})`.
"""
entity_id = TELEGRAM_TARGETS.get(target, TELEGRAM_TARGETS['telegram'])
service_data = {'entity_id': entity_id, 'url': url}
if caption:
service_data['caption'] = caption
if parse_mode:
service_data['parse_mode'] = parse_mode
service_data.update(kwargs)
self.call_service('telegram_bot/send_photo', **service_data)
# -----------------------------------------------------------------------------
def most_common(the_list: list) -> Any:
"""Return the most common element in a list."""
return max(set(the_list), key=the_list.count)
@@ -57,12 +94,8 @@ def get_group_entities(self, group):
return []
if 'attributes' in attributes:
attributes = attributes['attributes']
#group
if "entity_id" in attributes:
return attributes["entity_id"]
#simple item
return [group]
def turn_on(self, entity_id, state):
@@ -78,14 +111,12 @@ def turn_off(self, entity_id, state):
self.turn_off(entity_id, state)
def notification(self, to, message):
self.notify(message, name = "telegram")
send_telegram(self, message, target = "telegram")
def get_arg(args, key):
key = args[key]
return key
def get_arg_list(args, key):
arg_list = []
if isinstance(args[key], list):
+2 -2
View File
@@ -1,4 +1,5 @@
import appdaemon.plugins.hass.hassapi as hass
import globals
#
# Aqara lock notifications
@@ -51,5 +52,4 @@ class AqaraLock(hass.Hass):
self.notify_tg("Неизвестное событие замка: {}".format(eventname))
def notify_tg(self, msg):
extra_data = {'parse_mode': 'html'}
self.notify(msg, name = self.args['notify'], data=extra_data)
globals.send_telegram(self, msg, target = self.args['notify'])
+2 -2
View File
@@ -1,4 +1,5 @@
import datetime
import globals
from automation import Automation, Base # type: ignore
#
@@ -61,5 +62,4 @@ class Balance(Base):
def notify_tg(self, msg):
if not 'notify' in self.args:
return
extra_data = {'parse_mode': 'html'}
self.notify(msg, name = self.args['notify'], data=extra_data)
globals.send_telegram(self, msg, target = self.args['notify'])
+2 -1
View File
@@ -1,5 +1,6 @@
import appdaemon.plugins.hass.hassapi as hass
import datetime
import globals
#
# App to send email report for devices running low on battery
@@ -62,4 +63,4 @@ class Battery(hass.Hass):
if low: # or ("always_send" in self.args and self.args["always_send"] == 1) or ("force" in kwargs and kwargs["force"] == 1):
if message != "":
self.notify(message, name = "telegram")
globals.send_telegram(self, message)
@@ -1,5 +1,6 @@
import appdaemon.plugins.hass.hassapi as hass
import datetime
import globals
class BMSMonitor(hass.Hass):
def initialize(self):
@@ -159,7 +160,6 @@ class BMSMonitor(hass.Hass):
def send_telegram(self, message, parse_mode="html"):
try:
extra_data = {'parse_mode': parse_mode}
self.notify(message, name = self.notification_target, data=extra_data)
globals.send_telegram(self, message, target = self.notification_target, parse_mode = parse_mode)
except Exception as e:
self.log(f"Ошибка отправки Telegram: {e}")
+44 -29
View File
@@ -1,6 +1,4 @@
import appdaemon.plugins.hass.hassapi as hass
from datetime import timedelta
import datetime
#
# App to show dishwasher state
@@ -18,58 +16,75 @@ import datetime
class Dishwasher(hass.Hass):
listen_event_handle_list = []
run_state = ""
def initialize(self):
if 'run_state' not in self.args or 'door_sensor' not in self.args or 'counter' not in self.args:
if 'run_state' not in self.args or 'door_sensor' not in self.args or 'counter' not in self.args or 'state_extended' not in self.args:
self.log("Please define all args")
return
self.listen_event_handle_list.append(self.listen_state(self.door_state_change, self.args['door_sensor'])) #, attribute='action'
self.listen_event_handle_list.append(self.listen_state(self.run_state_change, self.args['run_state'])) #, attribute='action'
self.listen_event_handle_list.append(self.listen_state(self.door_state_change, self.args['door_sensor']))
self.listen_event_handle_list.append(self.listen_state(self.run_state_change, self.args['run_state']))
def get_extended_state(self):
return self.get_state(self.args['state_extended'])
def set_extended_state(self, state):
self.call_service("input_select/select_option", entity_id = self.args['state_extended'], option = state)
def door_state_change(self, entity, attribute, old, new, kwargs):
if (new == "on"):
self.call_service("counter/increment", entity_id = self.args['counter'])
if (self.run_state == "finished"):
self.run_state = "collecting"
self.set_light_state_by_counter()
if new != "on":
return
self.call_service("counter/increment", entity_id = self.args['counter'])
extended_state = self.get_extended_state()
open_count = int(self.get_state(self.args['counter']))
if extended_state == "Washed":
self.set_extended_state("Empty")
elif extended_state == "Empty":
if open_count < 10:
self.set_extended_state("Collecting Dishes")
elif open_count > 10:
self.set_extended_state("Ready to wash")
elif extended_state == "Collecting Dishes" and open_count > 10:
self.set_extended_state("Ready to wash")
self.set_light_state_by_counter()
def run_state_change(self, entity, attribute, old, new, kwargs):
self.log("event: {}: {}->{}".format(attribute,old,new))
if (new == "Run"):
self.log("event: {}: {}->{}".format(attribute, old, new))
if new == "Run":
self.log('resetting counter')
self.call_service("counter/reset", entity_id = self.args['counter'])
self.run_state = "washing"
if (new == "Finished"):
self.set_extended_state("Washing")
elif new == "Finished":
self.log('resetting counter')
self.call_service("counter/reset", entity_id = self.args['counter'])
self.run_state = "finished"
self.set_extended_state("Washed")
self.log('Current state is: {}'.format(self.run_state))
self.log('Current state is: {}'.format(self.get_extended_state()))
self.set_light_state_by_counter()
def set_light_state_by_counter(self):
state = self.get_state(self.args['counter'])
open_count = int(state)
self.log('counter state={}, machine state = {}'.format(state, self.run_state))
open_count = self.get_state(self.args['counter'])
extended_state = self.get_extended_state()
self.log('counter state={}, machine state = {}'.format(open_count, extended_state))
if (self.run_state == "finished"):
# Есть посуда, которую нужно разобрать
# red color
if extended_state == "Washed":
self.log('Time to take dishes out.')
if 'lamp' in self.args:
self.call_service("light/turn_on", entity_id = self.args['lamp'], rgb_color=[255, 0, 0]) #red
self.call_service("light/turn_on", entity_id = self.args['lamp'], rgb_color=[255, 0, 0])
elif (self.run_state == "washing"):
elif extended_state == "Washing":
self.log('washing in progress')
self.call_service("light/turn_off", entity_id = self.args['lamp'])
if 'lamp' in self.args:
self.call_service("light/turn_off", entity_id = self.args['lamp'])
elif (open_count > 10):
elif extended_state == "Ready to wash":
self.log('Time to run dishwasher.')
if 'lamp' in self.args:
self.call_service("light/turn_on", entity_id = self.args['lamp'], rgb_color=[245, 236, 0]) #yellow
self.call_service("light/turn_on", entity_id = self.args['lamp'], rgb_color=[245, 236, 0])
else:
elif 'lamp' in self.args:
self.call_service("light/turn_off", entity_id = self.args['lamp'])
@@ -5,9 +5,10 @@ dishwasher:
class: Dishwasher
module: dishwasher
constraint: input_boolean.dishwasher_state_light
counter: counter.dishwasher_door_open_count
door_sensor: binary_sensor.hc_dishwasher_door
run_state: sensor.hc_dishwasher_state
counter: counter.bosch_dishwasher_door_open_count
door_sensor: binary_sensor.bosch_dishwasher_door
run_state: sensor.bosch_dishwasher_operation_state
state_extended: input_select.bosch_dishwasher_state_extended
lamp: light.espresense_kitchen_led_1
global_dependencies:
- globals
@@ -0,0 +1,90 @@
import appdaemon.plugins.hass.hassapi as hass
import random
#
# App to remind about dishwasher when someone enters the kitchen
#
# Args:
#
# state_extended = input_select with extended dishwasher state
# motion_sensors = list of motion sensors to watch
# alice = Yandex Station media_player entity
# cooldown (optional) = seconds between reminders, default 1800
# constraint (optional) = input_boolean to enable/disable the app
#
# Release Notes
#
# Version 1.0:
# Initial Version
# Version 1.1:
# Added "Ready to wash" reminders
class DishwasherReminder(hass.Hass):
PHRASES_WASHED = [
"Посудомойка готова! Пора разобрать посуду.",
"Чистая посуда сидит в посудомойке как в Open Space — пора выпустить на волю.",
"Посудомойка отработала, теперь твоя очередь — разгрузить.",
"Тарелки уже высохли и скучают, спаси их из посудомойки.",
"Посудомойка не склад для чистого, разгрузи уже.",
"Грязной посуды нет, а чистая застряла внутри — спасательная операция!",
"Посудомойка помыла всё, осталось только разобрать. Ну же!",
"Чистые тарелки устроили вечеринку в посудомойке — пора их разогнать.",
"Не забудь разобрать посудомойку, иначе завтра некуда будет класть грязное.",
"Посудомойка ждёт разгрузки — всё помыто, высушено и нетерпеливо дребезжит.",
]
PHRASES_READY_TO_WASH = [
"Посудомойка скучает без работы — пора её запустить.",
"Гора посуды накопилась, посудомойка просит смелости нажать пуск.",
"Тарелки в посудомойке собрались на митинг — жми старт и отпусти их мыться.",
"Посудомойка готова к бою, осталось только нажать кнопку.",
"Хватит кормить посудомойку тарелками — пора включить и отдохнуть.",
"Посудомойка смотрит на тебя с надеждой — запускай программу.",
"Грязная посуда накопилась как снежный ком — время пустить посудомойку в ход.",
"Твои тарелки ждут водных процедур — включай посудомойку!",
"Посудомойка обидится, если её ещё раз оставят без дела — жми пуск.",
"Посуда застряла в посудомойке без мытья — самое время нажать старт и уйти пить чай.",
]
STATE_PHRASES = {
"Washed": PHRASES_WASHED,
"Ready to wash": PHRASES_READY_TO_WASH,
}
def initialize(self):
if 'state_extended' not in self.args or 'motion_sensors' not in self.args or 'alice' not in self.args:
self.log("Please define state_extended, motion_sensors and alice")
return
self.cooldown = self.args.get('cooldown', 1800)
self.last_announced = {}
for sensor in self.args['motion_sensors']:
self.listen_state(self.motion_detected, sensor)
def motion_detected(self, entity, attribute, old, new, kwargs):
if new != "on" or old == "on":
return
# if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
# self.log('disabled by constraint')
# return
state = self.get_state(self.args['state_extended'])
phrases = self.STATE_PHRASES.get(state)
if phrases is None:
return
last = self.last_announced.get(state)
if last is not None:
elapsed = (self.datetime() - last).total_seconds()
if elapsed < self.cooldown:
self.log('cooldown active for {}, skipping'.format(state))
return
self.say(random.choice(phrases))
self.last_announced[state] = self.datetime()
def say(self, command):
self.log('command = {}'.format(command))
self.call_service('media_player/play_media', entity_id=self.args['alice'], media_content_type='text', media_content_id=command)
@@ -0,0 +1,15 @@
#################################
# DISHWASHER REMINDER #
#################################
dishwasher_reminder:
class: DishwasherReminder
module: dishwasher_reminder
# constraint: input_boolean.dishwasher_reminder
state_extended: input_select.bosch_dishwasher_state_extended
motion_sensors:
- binary_sensor.motion_kitchenset_left_occupancy
- binary_sensor.motion_kitchenset_right_occupancy
alice: media_player.yandex_station_m00r46000m53db
cooldown: 3600
global_dependencies:
- globals
@@ -1,5 +1,6 @@
import appdaemon.plugins.hass.hassapi as hass
import datetime
import globals
#
# App to send reports about unsuccessfull auths
@@ -24,5 +25,5 @@ class Security(hass.Hass):
def state_change(self, entity, attribute, old, new, kwargs):
notifier = self.args.get('notify', 'telegram')
self.notify(new, name = notifier)
globals.send_telegram(self, new, target = notifier)
self.log(new)
@@ -1,6 +1,7 @@
import appdaemon.plugins.hass.hassapi as hass
from datetime import timedelta
import datetime
import globals
#
# App to send email report for devices running low on battery
@@ -78,5 +79,4 @@ class Teeth(hass.Hass):
notify = self.args["notify"]
now = datetime.datetime.now()+timedelta(hours=3)
message="Уже {}, а ты еще не почистил зубы. Самое время =)".format(now.strftime("%H:%M"))
self.notify(message, name = notify)
globals.send_telegram(self, message, target = notify)
@@ -69,7 +69,7 @@ class WaterCountersAlarm(hass.Hass):
if send_devices or ("always_send" in self.args and self.args["always_send"] == 1) or ("force" in kwargs and kwargs["force"] == 1):
if message != "":
self.notify(message, name = "telegram")
globals.send_telegram(self, message)
def check_checkup_dates(self, kwargs):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
@@ -106,4 +106,4 @@ class WaterCountersAlarm(hass.Hass):
if checkup_devices or ("always_send" in self.args and self.args["always_send"] == 1) or ("force" in kwargs and kwargs["force"] == 1):
if message != "":
self.notify(message, name = "telegram")
globals.send_telegram(self, message)
+2 -1
View File
@@ -1,4 +1,5 @@
import appdaemon.plugins.hass.hassapi as hass
import globals
#
# Notification system
@@ -42,7 +43,7 @@ class TelegramNotifyTarget(BaseNotifyTarget):
target = self.target_sveta
hass.log('notifying over telegram person {} with message: {}'.format(target, message))
hass.notify(message, name=target)
globals.send_telegram(hass, message, target=target)
class Notification(hass.Hass):
home_targets = [AliceNotifyTarget()]
@@ -32,7 +32,7 @@ class ReportByPresence(hass.Hass):
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'])
globals.send_telegram(self, "Добро пожаловать домой!", target = self.args['notify'])
############# AWAY REPORT ##########################
def send_report(self, kwargs):
@@ -46,6 +46,6 @@ class ReportByPresence(hass.Hass):
message += '{} ({}) = {}\n'.format(self.friendly_name(entity), entity, self.get_state(entity))
if any:
message = "В доме остались работать следующие устройства:\n" + message
self.notify(message, name = self.args['notify'])
globals.send_telegram(self, message, target = self.args['notify'])
else:
self.notify("Все устройства в доме выключены.", name = self.args['notify'])
globals.send_telegram(self, "Все устройства в доме выключены.", target = self.args['notify'])
@@ -1,5 +1,6 @@
import appdaemon.plugins.hass.hassapi as hass
import datetime
import globals
#
# Water control application.
@@ -56,11 +57,11 @@ class WaterValveControl(hass.Hass):
if name is None:
name = device
device_names += name
self.notify('В доме остались требующие воды устройства ({}), подача воды не будет отключена.'.format(device_names), name = self.args['notify'])
globals.send_telegram(self, 'В доме остались требующие воды устройства ({}), подача воды не будет отключена.'.format(device_names), target = 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'])
globals.send_telegram(self, 'Отключаю подачу воды.', target = self.args['notify'])
self.turn_off(self.args['water_valve'])
# for device in self.args['water_devices']:
# self.turn_off(device)
@@ -77,7 +78,7 @@ class WaterValveControl(hass.Hass):
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'])
globals.send_telegram(self, 'Устройства требующие воды закончили свою работу, отключаю подачу воды.', target = self.args['notify'])
self.turn_off_water_devices()
self.cancel_current_timer()
@@ -9,6 +9,6 @@ water_action:
constraint: input_boolean.water_control
water_devices:
- binary_sensor.washer_running # стиралка
- binary_sensor.hc_dishwasher_running # посудомойка
- binary_sensor.bosch_dishwasher_running # посудомойка
global_dependencies:
- globals
+4 -6
View File
@@ -1,5 +1,6 @@
import appdaemon.plugins.hass.hassapi as hass
import requests
import globals
from datetime import datetime
class TelegramInternetControl(hass.Hass):
@@ -39,8 +40,8 @@ class TelegramInternetControl(hass.Hass):
"event.home_assistant_fonvizina_update_event"
)
# Сервис для отправки ответов в Telegram
self.notify_service = self.args.get("notify_service", "notify/telegram")
# Цель (friendly name из globals.TELEGRAM_TARGETS) для отправки ответов в Telegram
self.notify_target = self.args.get("notify_target", "telegram")
# Сохраняем последнее обработанное время (для пропуска дублей)
self.last_processed_time = None
@@ -257,10 +258,7 @@ class TelegramInternetControl(hass.Hass):
Отправка ответа в Telegram.
"""
try:
self.call_service(
self.notify_service,
message=message
)
globals.send_telegram(self, message, target = self.notify_target)
self.log(f"Telegram message sent: {message}")
except Exception as e:
self.log(f"Error sending Telegram message: {str(e)}")
+4 -2
View File
@@ -23,5 +23,7 @@ keenetic:
# Entity для прослушивания событий
telegram_event_entity: "event.home_assistant_fonvizina_update_event"
# Сервис для отправки уведомлений в Telegram
notify_service: "notify/telegram"
# Цель отправки уведомлений (friendly name из globals.TELEGRAM_TARGETS,
# см. appdaemon/settings/apps/globals.py). Раньше здесь был deprecated
# notify_service: "notify/telegram".
notify_target: "telegram"
@@ -1,5 +1,6 @@
import appdaemon.plugins.hass.hassapi as hass
import fnmatch
import globals
#
# Fire sensors alarm notification
@@ -45,4 +46,4 @@ class FireSensorsReport(hass.Hass):
friendly_name = self.friendly_name(entity)
entity = entity.replace('_', '-')
message = "Сработал датчик пожарной сигнализации {} ({}) = {}-{}!".format(friendly_name, entity, old, new)
self.notify(message, name = self.args['notify'])
globals.send_telegram(self, message, target = self.args['notify'])
@@ -1,5 +1,6 @@
import appdaemon.plugins.hass.hassapi as hass
import fnmatch
import globals
#
# Security sensors alarm notification
@@ -56,4 +57,4 @@ class SecuritySensorsReport(hass.Hass):
friendly_name = self.friendly_name(entity)
entity = entity.replace('_', '-')
message = "В ваше отсутствие сработал датчик безопастности {} ({}) = {}->{}!".format(friendly_name, entity, old, new)
self.notify(message, name = self.args['notify'])
globals.send_telegram(self, message, target = self.args['notify'])
@@ -1,4 +1,5 @@
import appdaemon.plugins.hass.hassapi as hass
import globals
#
# Water leak detector
@@ -54,9 +55,9 @@ class WaterLeak(hass.Hass):
self.call_service("mqtt/publish", topic = 'home/watercontrol/bath/valve/set', payload = 'close')
message = "ВНИМАНИЕ! В ваше отстутствие сработал датчик протечки воды ({})!!! Выключаю подачу воды.".format(self.friendly_name(entity_id))
self.notify(message, name = self.args['notify'])
globals.send_telegram(self, message, target = self.args['notify'])
message = "Состояние датчиков протечки:\n"
for entity_id in self.sensors:
message += '{} ({}) = {}\n'.format(self.friendly_name(entity_id), entity_id, self.get_state(entity_id))
self.notify(message, name = self.args['notify'])
globals.send_telegram(self, message, target = self.args['notify'])
@@ -167,5 +167,4 @@ class EpdBalanceSensor(hass.Hass):
def notify_tg(self, msg):
if not 'notify' in self.args:
return
extra_data = {'parse_mode': 'html'}
self.notify(msg, name = self.args['notify'], data=extra_data)
globals.send_telegram(self, msg, target = self.args['notify'])
+11 -8
View File
@@ -7,14 +7,17 @@ Arguments:
- events: List of events to monitor
"""
class Test(hass.Hass):
notify = None
# notify = None
def initialize(self) -> None:
self.listen_state(self.sensor_trigger, 'sensor.0x00158d0003a361d8_action')
self.listen_state(self.sensor_trigger, 'binary_sensor.0x00158d0003f26d61_occupancy')
# self.listen_state(self.sensor_trigger, 'sensor.remote20_action')
self.log("hello")
# notifier = self.args.get("notify", "telegram")
# self.notify("hello world", name = "telegram")
# self.listen_state(self.sensor_trigger, "sensor.0x00158d0003a361d8_action")
# self.listen_state(self.sensor_trigger, "binary_sensor.0x00158d0003f26d61_occupancy")
# self.listen_state(self.sensor_trigger, "sensor.remote20_action")
def sensor_trigger(self, entity, attribute, old, new, kwargs):
if new != "" and new != "unknown":
self.log("doorbell call")
self.toggle("switch.0x00158d00020f3a29_switch")
# def sensor_trigger(self, entity, attribute, old, new, kwargs):
# if new != "" and new != "unknown":
# self.log("doorbell call")
# self.toggle("switch.0x00158d00020f3a29_switch")
+20 -18
View File
@@ -32,7 +32,7 @@ services:
max-size: 50m
hass:
image: "homeassistant/home-assistant:stable" #stable
image: "homeassistant/home-assistant:stable" #2026.4.2
#image: ghcr.io/home-assistant/home-assistant:stable
container_name: hass
volumes:
@@ -121,10 +121,12 @@ services:
volumes:
- ./zigbee2mqtt/settings:/app/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080"]
# в образе нет curl (Alpine), используем wget --spider
test: ["CMD", "wget", "--spider", "-q", "http://localhost:8080"]
interval: 30s
timeout: 10s
retries: 6
start_period: 60s
restart: always
logging:
driver: json-file
@@ -184,22 +186,22 @@ services:
max-size: "10m"
max-file: "5"
homeconnect2mqtt:
build:
context: ./homeconnect2mqtt/docker
dockerfile: Dockerfile
restart: always
container_name: homeconnect2mqtt
ports:
- "5001:5000"
env_file: ./homeconnect2mqtt/settings/homeconnect2mqtt.env
volumes:
- ./homeconnect2mqtt/settings/config.json:/app/config.json:ro
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
#homeconnect2mqtt:
# build:
# context: ./homeconnect2mqtt/docker
# dockerfile: Dockerfile
# restart: always
# container_name: homeconnect2mqtt
# ports:
# - "5001:5000"
# env_file: ./homeconnect2mqtt/settings/homeconnect2mqtt.env
# volumes:
# - ./homeconnect2mqtt/settings/config.json:/app/config.json:ro
# logging:
# driver: json-file
# options:
# max-size: "10m"
# max-file: "5"
matter-bridge:
image: ghcr.io/t0bst4r/home-assistant-matter-hub:latest
+1 -1
View File
@@ -1 +1 @@
2026.4.2
2026.7.2
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 924 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

+1 -1
View File
@@ -1 +1 @@
{"pid": 238780, "version": 1, "ha_version": "2026.4.2", "start_ts": 1781684834.86627}
{"pid": 71, "version": 1, "ha_version": "2026.7.2", "start_ts": 1784034083.5601983}
+48 -38
View File
@@ -21,55 +21,65 @@
# {{ states('sensor.dishwasher_program_progress') + "%" }}
# {% endif %}
mqtt:
sensor:
- name: hc_dishwasher_state
unique_id: hc_dishwasher_state
state_topic: "homeconnect/dishwasher/state"
value_template: "{{ value_json.state }}"
json_attributes_topic: "homeconnect/dishwasher/state"
- name: hc_dishwasher_remaining
unique_id: hc_dishwasher_remaining
state_topic: "homeconnect/dishwasher/state"
value_template: "{{ value_json.remaining }}"
json_attributes_topic: "homeconnect/dishwasher/state"
binary_sensor:
- state_topic: "homeconnect/dishwasher/state"
name: hc_dishwasher_door
unique_id: hc_dishwasher_door
device_class: opening
payload_on: "Open"
payload_off: "Closed"
value_template: "{{ value_json.door }}"
json_attributes_topic: "homeconnect/dishwasher/state"
- state_topic: "homeconnect/dishwasher/state"
name: hc_dishwasher_power
unique_id: hc_dishwasher_power
payload_on: true
payload_off: false
value_template: "{{ value_json.power }}"
json_attributes_topic: "homeconnect/dishwasher/state"
# mqtt:
# sensor:
# - name: hc_dishwasher_state
# unique_id: hc_dishwasher_state
# state_topic: "homeconnect/dishwasher/state"
# value_template: "{{ value_json.state }}"
# json_attributes_topic: "homeconnect/dishwasher/state"
# - name: hc_dishwasher_remaining
# unique_id: hc_dishwasher_remaining
# state_topic: "homeconnect/dishwasher/state"
# value_template: "{{ value_json.remaining }}"
# json_attributes_topic: "homeconnect/dishwasher/state"
# binary_sensor:
# - state_topic: "homeconnect/dishwasher/state"
# name: hc_dishwasher_door
# unique_id: hc_dishwasher_door
# device_class: opening
# payload_on: "Open"
# payload_off: "Closed"
# value_template: "{{ value_json.door }}"
# json_attributes_topic: "homeconnect/dishwasher/state"
# - state_topic: "homeconnect/dishwasher/state"
# name: hc_dishwasher_power
# unique_id: hc_dishwasher_power
# payload_on: true
# payload_off: false
# value_template: "{{ value_json.power }}"
# json_attributes_topic: "homeconnect/dishwasher/state"
template:
binary_sensor:
- name: hc_dishwasher_running
unique_id: hc_dishwasher_running
state: "{{ is_state('sensor.hc_dishwasher_state', 'Run') }}"
- name: bosch_dishwasher_running
unique_id: bosch_dishwasher_running
state: "{{ is_state('sensor.bosch_dishwasher_operation_state', 'Run') }}"
counter:
dishwasher_door_open_count:
name: dishwasher_door_open_count
bosch_dishwasher_door_open_count:
name: bosch_dishwasher_door_open_count
input_select:
bosch_dishwasher_state_extended:
name: bosch_dishwasher_state_extended
options:
- 'Empty'
- 'Washing'
- 'Washed'
- 'Collecting Dishes'
- 'Ready to wash'
homeassistant:
customize:
sensor.hc_dishwasher_state:
sensor.bosch_dishwasher_state:
friendly_name: Посудомойка Статус
binary_sensor.hc_dishwasher_door:
binary_sensor.bosch_dishwasher_door:
friendly_name: Посудомойка Дверца
binary_sensor.hc_dishwasher_remaining:
binary_sensor.bosch_dishwasher_remaining:
friendly_name: Посудомойка До конца программы
sensor.hc_dishwasher_running:
sensor.bosch_dishwasher_running:
friendly_name: Посудомоечная машина
binary_sensor.hc_dishwasher_power:
binary_sensor.bosch_dishwasher_power:
friendly_name: Посудомойка Питание
@@ -1,21 +1,14 @@
telegram_bot:
- platform: polling
api_key: !secret telegram_key
allowed_chat_ids:
- !secret telegram_group_chat
- !secret telegram_monster_chat
- !secret telegram_sveta_chat
notify:
- platform: telegram
name: telegram
chat_id: !secret telegram_group_chat
parse_mode: html
- platform: telegram
name: telegram_monster
chat_id: !secret telegram_monster_chat
parse_mode: html
- platform: telegram
name: telegram_sveta
chat_id: !secret telegram_sveta_chat
parse_mode: html
# telegram_bot: секция удалена — интеграция уже настроена через config entry
# (UI, импортирован 2025-12-28), YAML-платформа с ней конфликтовала:
# ERROR integration telegram_bot cannot be merged, expected a dict
#
# notify: платформы (legacy, deprecated) тоже убраны — все appdaemon-скрипты
# мигрированы на entity-based telegram_bot.send_message/send_photo (см.
# appdaemon/settings/apps/globals.py: TELEGRAM_TARGETS, send_telegram(),
# send_telegram_photo()). Проверено: тестовые сообщения через новый механизм
# успешно доставлены во все 3 чата (группа, Monster, Svetlana) 2026-07-14.
#
# Telegram bot notify-сущности теперь берутся из config entry:
# notify.home_assistant_fonvizina_fonvizina_18_1001567589226
# notify.home_assistant_fonvizina_monster_123622180
# notify.home_assistant_fonvizina_svetlana_205225134
@@ -0,0 +1,21 @@
telegram_bot:
- platform: polling
api_key: !secret telegram_key
allowed_chat_ids:
- !secret telegram_group_chat
- !secret telegram_monster_chat
- !secret telegram_sveta_chat
notify:
- platform: telegram
name: telegram
chat_id: !secret telegram_group_chat
parse_mode: html
- platform: telegram
name: telegram_monster
chat_id: !secret telegram_monster_chat
parse_mode: html
- platform: telegram
name: telegram_sveta
chat_id: !secret telegram_sveta_chat
parse_mode: html
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long