some new automations

This commit is contained in:
Your Name
2019-11-07 12:36:14 +03:00
parent 7a32cb74da
commit a00aaba52b
116 changed files with 6720 additions and 126 deletions
@@ -0,0 +1,103 @@
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):
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,8 @@
purifier_timer:
module: purifier
class: Purifier
on_time: "06:45:00"
off_time: "23:00:00"
entity: fan.xiaomi_miio_device
global_dependencies:
- globals
@@ -0,0 +1,29 @@
import appdaemon.plugins.hass.hassapi as hass
#
# Listen for homekit presence
#
# 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 HomekitPresense(hass.Hass):
def initialize(self):
if "sensor" not in self.args or "arrive_event" not in self.args or "leave_event" not in self.args:
self.error("Please provide sensor, arrive_event, leave_event in config!")
return
self.listen_state(self.sensor_trigger, self.args['sensor'])
def sensor_trigger(self, entity, attribute, old, new, kwargs):
if new == "on" and old == "off":
self.fire_event(self.args['arrive_event'])
elif new == "off" and old == "on":
self.fire_event(self.args['leave_event'])
self.log("{} turned {}".format(entity, new))
self.notify("{} turned {}".format(entity, new), name = self.args['notify'])
@@ -0,0 +1,35 @@
#################################
# HOMEKIT PRESENSE #
#################################
monster_home_presence:
module: homekitpresense
class: HomekitPresense
notify: telegram_monster
sensor: input_boolean.monster_home
arrive_event: monster_home_arrive
leave_event: monster_home_leave
constraint: input_boolean.presence_control
global_dependencies:
- globals
monster_work_presence:
module: homekitpresense
class: HomekitPresense
notify: telegram_monster
sensor: input_boolean.monster_work
arrive_event: monster_work_arrive
leave_event: monster_work_leave
constraint: input_boolean.presence_control
global_dependencies:
- globals
homekit_home_presence:
module: homekitpresense
class: HomekitPresense
notify: telegram_monster
sensor: input_boolean.homekit_presense
arrive_event: homekit_home_arrive
leave_event: homekit_home_leave
constraint: input_boolean.presence_control
global_dependencies:
- globals
@@ -0,0 +1,37 @@
import appdaemon.plugins.hass.hassapi as hass
import datetime
#
# Intercom auto open switch by presence
#
# Args:
# entity_id - intercom autp open switch
# arrive_event - Arrive event name.
# leave_event - Leave event name
# constraint - (optional, input_boolen), if turned off - no notifications will be sent.
#
# Release Notes
#
# Version 1.0:
# Initial Version
class IntercomSwitch(hass.Hass):
def initialize(self):
if "entity_id" not in self.args or "arrive_event" not in self.args or "leave_event" not in self.args:
self.error("Please provide entity_id, arrive_event, leave_event in config!")
return
self.listen_event(self.arrive_event, self.args['arrive_event'])
self.listen_event(self.leave_event, self.args['leave_event'])
def arrive_event(self, event_id, event_args, kwargs):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
entity_id = self.args['entity_id']
self.log("Somebody come home, turn on {}".format(entity_id))
self.turn_on(entity_id)
def leave_event(self, event_id, event_args, kwargs):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
entity_id = self.args['entity_id']
self.log("All persons leave home, turn off {}".format(entity_id))
self.turn_off(entity_id)
@@ -0,0 +1,11 @@
#################################
# WORK PRESENSE #
#################################
intercom_auto_open:
module: intercom_switch
class: IntercomSwitch
entity_id: switch.domofon_mode
arrive_event: homekit_home_arrive
leave_event: homekit_home_leave
global_dependencies:
- globals
@@ -0,0 +1,116 @@
import appdaemon.plugins.hass.hassapi as hass
import datetime
#
# Listen for homekit presence
#
# Args:
# arrive_event - Arrive event name.
# leave_event - Leave event name
# notify - notify platform
# constraint - (optional, input_boolen), if turned off - no notifications will be sent.
#
# Release Notes
#
# Version 1.0:
# Initial Version
class WorkTime(hass.Hass):
arrive_time = None
leave_time = None
notify_time = None
app_namespace = "worktime_namespace"
work_hours = 9
notify_before_leave_in_minutes = 15
notify_every_seconds = 300
timers = []
def initialize(self):
if 'notify' not in self.args or "arrive_event" not in self.args or "leave_event" not in self.args:
self.error("Please provide arrive_event, leave_event in config!")
return
self.listen_event(self.arrive_event, self.args['arrive_event'])
self.listen_event(self.leave_event, self.args['leave_event'])
self.run_daily(self.reset_timer_tick, self.parse_time("23:59:59"))
self.load_state()
self.arrive_event(None, None, None)
#self.save_state()
def arrive_event(self, event_id, event_args, kwargs):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
if self.arrive_time != None:
self.log('You have already arrived to the work today at {}'.format(self.arrive_time))
return
self.arrive_time = self.datetime()
self.leave_time = self.datetime()+datetime.timedelta(hours=self.work_hours)
self.notify_time = self.leave_time-datetime.timedelta(minutes=self.notify_before_leave_in_minutes)
if self.notify_time<self.datetime():
self.notify_time=self.datetime()+datetime.timedelta(seconds=self.notify_every_seconds)
self.save_state()
self.log("Monster has arrived to work at {}, work till {}, will notify at {}.".format(self.arrive_time, self.leave_time, self.notify_time))
self.timers.append(self.run_every(self.timer_tick, self.notify_time, self.notify_every_seconds))
self.notify("Добро пожаловать в офис. Сегодня работаешь до {}.".format(self.format_time(self.leave_time)), name = self.args['notify'])
def leave_event(self, event_id, event_args, kwargs):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
if self.arrive_time == None:
return
self.cancel_timers()
travelTime = ""
if "work_to_home_time" in self.args:
time_entity = self.get_state(self.args['work_to_home_time'], attribute='all')
travel_time = time_entity['state']
jams_rate = time_entity['attributes'].get('jamsrate', 0)
travelTime = " Время в пути до дома: {} мин, пробки: {} баллов.".format(travel_time, jams_rate)
if self.datetime()<self.notify_time:
self.log("Monster leave work too early: {}<{}".format(self.datetime(), self.notify_time))
message = "Ты рано ушел с работы (работаешь с {} до {}).{}".format(self.format_time(self.arrive_time), self.format_time(self.leave_time), travelTime)
else:
self.log("Monster leave work at {} - {}".format(self.arrive_time, self.datetime))
message = "Рабочий день окончен ({}-{}). Приятной дороги домой.{}".format(self.format_time(self.arrive_time), self.format_time(self.datetime()), travelTime)
self.notify(message, name = self.args['notify'])
def timer_tick(self, args) -> None:
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
if self.datetime()<self.leave_time:
return
message = "Ты пришел на работу в {}, работаешь до {}. Пора домой!".format(self.format_time(self.arrive_time), self.format_time(self.leave_time))
self.notify(message, name = self.args['notify'])
def cancel_timers(self) -> None:
for timer in self.timers:
self.cancel_timer(timer)
self.timers = []
def reset_timer_tick(self, kwargs):
self.arrive_time = None
self.leave_time = None
self.notify_time = None
self.save_state()
def load_state(self):
self.arrive_time=self.deserialize_datetime(self.get_state("sensor.arrive_time", namespace=self.app_namespace))
self.leave_time=self.deserialize_datetime(self.get_state("sensor.leave_time", namespace=self.app_namespace))
self.notify_time=self.deserialize_datetime(self.get_state("sensor.notify_time", namespace=self.app_namespace))
self.log("App is reloaded. Saved values - arrive_time: {}, leave_time: {}, notify_time: {}".format(self.arrive_time, self.leave_time, self.notify_time))
def save_state(self):
self.set_state("sensor.arrive_time", state=self.serialize_datetime(self.arrive_time), namespace=self.app_namespace)
self.set_state("sensor.leave_time", state=self.serialize_datetime(self.leave_time), namespace=self.app_namespace)
self.set_state("sensor.notify_time", state=self.serialize_datetime(self.notify_time), namespace=self.app_namespace)
def format_time(self, date):
return date.strftime("%H:%M")
def serialize_datetime(self, date):
if date is None:
return None
return date.isoformat()
def deserialize_datetime(seld, date):
if (date is None):
return None
return datetime.datetime.fromisoformat(date)
@@ -0,0 +1,13 @@
#################################
# WORK PRESENSE #
#################################
monster_worktime:
module: worktime
class: WorkTime
notify: telegram_monster
arrive_event: monster_work_arrive
leave_event: monster_work_leave
work_to_home_time: sensor.monster_travel_time_work_to_home
constraint: input_boolean.work_presence_report
global_dependencies:
- globals
@@ -1,47 +0,0 @@
import appdaemon.plugins.hass.hassapi as hass
#
# Work leave reminder
# Send reminder about 'time to leave your work'
#
# Args:
#
# Release Notes
#
# Version 1.0:
# Initial Version
class WorkPresence(hass.Hass):
def initialize(self):
self.listen_event(self.office_enter, "office_enter")
self.listen_event(self.office_leave, "office_leave")
self.listen_event(self.office_leave_reminder, "office_leave_reminder")
def office_leave_reminder(self, event_id, event_args, kwargs):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
self.log('leave_reminder')
enter_time = self.get_state('sensor.work_enter_time')
leave_time = self.get_state('sensor.work_plan_leave_time')
if 'payload' in event_args:
leave_time = event_args['payload']
message = "Ты пришел на работу в {}, работаешь до {}. Пора домой!".format(enter_time, leave_time)
self.call_service('notify/telegram', message=message)
def office_leave(self, event_id, event_args, kwargs):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
self.log('leave')
work_to_home_time = self.get_state('sensor.work_to_home_time')
message="Время в пути до дома {} минут.".format(work_to_home_time)
self.call_service('notify/telegram', message=message)
def office_enter(self, event_id, event_args, kwargs):
if 'constraint' in self.args and not self.constrain_input_boolean(self.args['constraint']):
return
self.log('enter')
enter_time = event_args.get('payload', None)
if enter_time == '' or enter_time == None:
return
self.log(enter_time)
self.call_service('notify/telegram', message='Добро пожаловать в офис. Приятного дня =)))')
@@ -1,9 +0,0 @@
#################################
# WORK PRESENSE #
#################################
work_presence:
module: work
class: WorkPresence
constraint: input_boolean.work_presence_report
global_dependencies:
- globals