updating configuration
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import datetime
|
||||
import globals
|
||||
from automation import Automation, Base # type: ignore
|
||||
|
||||
#
|
||||
@@ -21,7 +22,7 @@ class Balance(Base):
|
||||
super().initialize()
|
||||
self.check_balance({"force": 1})
|
||||
self.run_daily(self.check_balance, datetime.time(10, 0, 0))
|
||||
|
||||
|
||||
def check_balance(self, kwargs):
|
||||
# if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
|
||||
# return
|
||||
@@ -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'])
|
||||
|
||||
@@ -1,65 +1,66 @@
|
||||
import appdaemon.plugins.hass.hassapi as hass
|
||||
import datetime
|
||||
|
||||
#
|
||||
# App to send email report for devices running low on battery
|
||||
#
|
||||
# Args:
|
||||
#
|
||||
# threshold = value below which battery levels are reported and email is sent
|
||||
# always_send = set to 1 to override threshold and force send
|
||||
#
|
||||
# None
|
||||
#
|
||||
# Release Notes
|
||||
#
|
||||
# Version 1.0:
|
||||
# Initial Version
|
||||
|
||||
class Battery(hass.Hass):
|
||||
|
||||
def initialize(self):
|
||||
#self.check_batteries({"force": 1})
|
||||
time = datetime.time(10, 0, 0)
|
||||
self.run_daily(self.check_batteries, time)
|
||||
self.check_batteries(None)
|
||||
|
||||
def check_batteries(self, kwargs):
|
||||
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
|
||||
return
|
||||
|
||||
devices = self.get_state()
|
||||
values = {}
|
||||
low = []
|
||||
for deviceName in devices:
|
||||
device = devices[deviceName]
|
||||
if device == None:
|
||||
continue
|
||||
battery = None
|
||||
if "attributes" in device:
|
||||
if "battery" in device["attributes"]:
|
||||
battery = device["attributes"]["battery"]
|
||||
elif "battery_level" in device["attributes"]:
|
||||
battery = device["attributes"]["battery_level"]
|
||||
elif '_battery' in device['entity_id']:
|
||||
battery = self.get_state(device['entity_id'])
|
||||
if not battery.isdigit():
|
||||
continue
|
||||
battery = int(battery)
|
||||
print('{} = {}'.format(device['entity_id'], battery))
|
||||
if battery != None:
|
||||
print('{} = {}'.format(device['entity_id'], battery))
|
||||
if battery < self.args["threshold"] and battery != 0:
|
||||
low.append(deviceName)
|
||||
values[deviceName] = battery
|
||||
|
||||
message=""
|
||||
if low:
|
||||
message += "У следующих датчиков садится батарея: (< {}) \n".format(self.args["threshold"])
|
||||
for device in low:
|
||||
message += "{}: {}%\n".format(self.friendly_name(device), values[device])
|
||||
message += "\n\n"
|
||||
|
||||
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")
|
||||
import appdaemon.plugins.hass.hassapi as hass
|
||||
import datetime
|
||||
import globals
|
||||
|
||||
#
|
||||
# App to send email report for devices running low on battery
|
||||
#
|
||||
# Args:
|
||||
#
|
||||
# threshold = value below which battery levels are reported and email is sent
|
||||
# always_send = set to 1 to override threshold and force send
|
||||
#
|
||||
# None
|
||||
#
|
||||
# Release Notes
|
||||
#
|
||||
# Version 1.0:
|
||||
# Initial Version
|
||||
|
||||
class Battery(hass.Hass):
|
||||
|
||||
def initialize(self):
|
||||
#self.check_batteries({"force": 1})
|
||||
time = datetime.time(10, 0, 0)
|
||||
self.run_daily(self.check_batteries, time)
|
||||
self.check_batteries(None)
|
||||
|
||||
def check_batteries(self, kwargs):
|
||||
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
|
||||
return
|
||||
|
||||
devices = self.get_state()
|
||||
values = {}
|
||||
low = []
|
||||
for deviceName in devices:
|
||||
device = devices[deviceName]
|
||||
if device == None:
|
||||
continue
|
||||
battery = None
|
||||
if "attributes" in device:
|
||||
if "battery" in device["attributes"]:
|
||||
battery = device["attributes"]["battery"]
|
||||
elif "battery_level" in device["attributes"]:
|
||||
battery = device["attributes"]["battery_level"]
|
||||
elif '_battery' in device['entity_id']:
|
||||
battery = self.get_state(device['entity_id'])
|
||||
if not battery.isdigit():
|
||||
continue
|
||||
battery = int(battery)
|
||||
print('{} = {}'.format(device['entity_id'], battery))
|
||||
if battery != None:
|
||||
print('{} = {}'.format(device['entity_id'], battery))
|
||||
if battery < self.args["threshold"] and battery != 0:
|
||||
low.append(deviceName)
|
||||
values[deviceName] = battery
|
||||
|
||||
message=""
|
||||
if low:
|
||||
message += "У следующих датчиков садится батарея: (< {}) \n".format(self.args["threshold"])
|
||||
for device in low:
|
||||
message += "{}: {}%\n".format(self.friendly_name(device), values[device])
|
||||
message += "\n\n"
|
||||
|
||||
if low: # or ("always_send" in self.args and self.args["always_send"] == 1) or ("force" in kwargs and kwargs["force"] == 1):
|
||||
if message != "":
|
||||
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):
|
||||
@@ -17,7 +18,7 @@ class BMSMonitor(hass.Hass):
|
||||
self.current_state = "IDLE" # IDLE, CHARGING, DISCHARGING
|
||||
self.timer_handle = None
|
||||
self.was_charging = False
|
||||
|
||||
|
||||
# Переменная для хранения времени начала отключения
|
||||
self.outage_start_time = None
|
||||
|
||||
@@ -45,15 +46,15 @@ class BMSMonitor(hass.Hass):
|
||||
# Логика переходов состояний
|
||||
if self.current_state != new_state:
|
||||
self.log(f"Смена состояния BMS: {self.current_state} -> {new_state}")
|
||||
|
||||
|
||||
# 1. Переход в разрядку (Отключили питание)
|
||||
if new_state == "DISCHARGING" and self.current_state != "DISCHARGING":
|
||||
# Фиксируем время начала отключения
|
||||
self.outage_start_time = datetime.datetime.now()
|
||||
|
||||
|
||||
self.send_telegram("⚠️ <b>ВНИМАНИЕ: Отключено питание!</b>\nБатарея перешла в режим разрядки.", "html")
|
||||
self.start_discharge_timer()
|
||||
|
||||
|
||||
# 2. Выход из разрядки (Питание восстановлено)
|
||||
# Срабатывает при переходе DISCHARGING -> IDLE или DISCHARGING -> CHARGING
|
||||
elif self.current_state == "DISCHARGING" and new_state in ("IDLE", "CHARGING"):
|
||||
@@ -62,14 +63,14 @@ class BMSMonitor(hass.Hass):
|
||||
duration = datetime.datetime.now() - self.outage_start_time
|
||||
duration_msg = f"\n⏱ <b>Время без электричества: {self._format_timedelta(duration)}</b>"
|
||||
self.outage_start_time = None # Сбрасываем таймер
|
||||
|
||||
|
||||
self.send_telegram(f"✅ <b>Питание восстановлено!</b>\nБатарея вышла из режима разрядки.{duration_msg}", "html")
|
||||
self.stop_discharge_timer()
|
||||
|
||||
|
||||
# 3. Переход в простой после зарядки (Зарядка окончена)
|
||||
elif new_state == "IDLE" and self.current_state == "CHARGING":
|
||||
self.send_telegram("🔋 <b>Зарядка завершена!</b>\nБатарея полностью заряжена или нагрузка отключена.", "html")
|
||||
|
||||
|
||||
# 4. Переход IDLE -> CHARGING (если не было разрядки перед этим)
|
||||
elif new_state == "CHARGING" and self.current_state == "IDLE":
|
||||
# Можно добавить отдельное уведомление, если нужно
|
||||
@@ -84,14 +85,14 @@ class BMSMonitor(hass.Hass):
|
||||
soc = float(new)
|
||||
if soc >= 100 and self.current_state == "CHARGING" and not self.was_charging:
|
||||
# Небольшая защита от повторных уведомлений
|
||||
self.was_charging = True
|
||||
self.was_charging = True
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
def start_discharge_timer(self):
|
||||
if self.timer_handle is None:
|
||||
# Запускаем таймер: сразу первое сообщение, потом каждые N секунд
|
||||
self.send_status_report()
|
||||
self.send_status_report()
|
||||
self.timer_handle = self.run_every(self.periodic_status, datetime.datetime.now(), self.interval)
|
||||
self.log("Таймер статуса разрядки запущен")
|
||||
|
||||
@@ -113,12 +114,12 @@ class BMSMonitor(hass.Hass):
|
||||
total_seconds = int(td.total_seconds())
|
||||
hours, remainder = divmod(total_seconds, 3600)
|
||||
minutes, _ = divmod(remainder, 60)
|
||||
|
||||
|
||||
parts = []
|
||||
if hours > 0:
|
||||
parts.append(f"{hours} ч")
|
||||
parts.append(f"{minutes} мин")
|
||||
|
||||
|
||||
return " ".join(parts)
|
||||
|
||||
def send_status_report(self):
|
||||
@@ -134,16 +135,16 @@ class BMSMonitor(hass.Hass):
|
||||
soc = round(float(soc_raw), 1) if soc_raw not in (None, 'unknown', 'unavailable') else 0
|
||||
current = round(float(current_raw), 2) if current_raw not in (None, 'unknown', 'unavailable') else 0
|
||||
voltage = round(float(voltage_raw), 2) if voltage_raw not in (None, 'unknown', 'unavailable') else 0
|
||||
|
||||
|
||||
# Определяем цвет/иконку для направления тока
|
||||
direction = "🔻 Разряд" if power < 0 else "🔺 Заряд"
|
||||
|
||||
|
||||
# Добавляем время без электричества, если известно
|
||||
outage_info = ""
|
||||
if self.outage_start_time:
|
||||
duration = datetime.datetime.now() - self.outage_start_time
|
||||
outage_info = f"\n⏳ Без света: <b>{self._format_timedelta(duration)}</b>"
|
||||
|
||||
|
||||
msg = (
|
||||
f"📊 <b>Статус батареи (JK BMS)</b>\n\n"
|
||||
f"🔋 SOC: <b>{soc}%</b>\n"
|
||||
@@ -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}")
|
||||
self.log(f"Ошибка отправки Telegram: {e}")
|
||||
|
||||
@@ -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:
|
||||
self.call_service("light/turn_off", entity_id = self.args['lamp'])
|
||||
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,28 +1,29 @@
|
||||
import appdaemon.plugins.hass.hassapi as hass
|
||||
import datetime
|
||||
|
||||
#
|
||||
# App to send reports about unsuccessfull auths
|
||||
#
|
||||
# Args:
|
||||
#
|
||||
# threshold = value below which battery levels are reported and email is sent
|
||||
# always_send = set to 1 to override threshold and force send
|
||||
#
|
||||
# None
|
||||
#
|
||||
# Release Notes
|
||||
#
|
||||
# Version 1.0:
|
||||
# Initial Version
|
||||
|
||||
class Security(hass.Hass):
|
||||
def initialize(self):
|
||||
self.log('---------------------')
|
||||
self.listen_event_handle_list = []
|
||||
self.listen_event_handle_list.append(self.listen_state(self.state_change, 'persistent_notification.http_login', attribute='message'))
|
||||
|
||||
def state_change(self, entity, attribute, old, new, kwargs):
|
||||
notifier = self.args.get('notify', 'telegram')
|
||||
self.notify(new, name = notifier)
|
||||
self.log(new)
|
||||
import appdaemon.plugins.hass.hassapi as hass
|
||||
import datetime
|
||||
import globals
|
||||
|
||||
#
|
||||
# App to send reports about unsuccessfull auths
|
||||
#
|
||||
# Args:
|
||||
#
|
||||
# threshold = value below which battery levels are reported and email is sent
|
||||
# always_send = set to 1 to override threshold and force send
|
||||
#
|
||||
# None
|
||||
#
|
||||
# Release Notes
|
||||
#
|
||||
# Version 1.0:
|
||||
# Initial Version
|
||||
|
||||
class Security(hass.Hass):
|
||||
def initialize(self):
|
||||
self.log('---------------------')
|
||||
self.listen_event_handle_list = []
|
||||
self.listen_event_handle_list.append(self.listen_state(self.state_change, 'persistent_notification.http_login', attribute='message'))
|
||||
|
||||
def state_change(self, entity, attribute, old, new, kwargs):
|
||||
notifier = self.args.get('notify', 'telegram')
|
||||
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
|
||||
@@ -24,10 +25,10 @@ class Teeth(hass.Hass):
|
||||
# Устанавливаем сброс в 10 утра
|
||||
reset_time = datetime.time(10, 0, 0)
|
||||
self.run_daily(self.reset_action, reset_time)
|
||||
|
||||
|
||||
# Запускаем проверку напоминаний
|
||||
self.timer = self.run_every(self.remind_if_needed, self.datetime()+timedelta(seconds=1), self.args['remind_interval'])
|
||||
|
||||
|
||||
# Слушаем изменения состояния кнопки
|
||||
self.listen_event_handle_list.append(self.listen_state(self.button_state_change, self.args['mute_button']))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -24,7 +24,7 @@ class WaterCountersAlarm(hass.Hass):
|
||||
return
|
||||
self.checkup_threasold = self.args['checkup_threasold']
|
||||
self.send_threasold = self.args['send_threasold']
|
||||
|
||||
|
||||
self.check_send_dates({"force": 1})
|
||||
self.run_daily(self.check_checkup_dates, datetime.time(10, 0, 0))
|
||||
self.run_daily(self.check_send_dates, datetime.time(10, 1, 0))
|
||||
@@ -69,8 +69,8 @@ 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']):
|
||||
return
|
||||
@@ -78,7 +78,7 @@ class WaterCountersAlarm(hass.Hass):
|
||||
entities = self.get_state()
|
||||
if entities == None:
|
||||
return
|
||||
|
||||
|
||||
values = {}
|
||||
checkup_devices = []
|
||||
for entity_id in entities:
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user