91 lines
4.5 KiB
Python
91 lines
4.5 KiB
Python
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)
|