diff --git a/README.md b/README.md index f5829f4..74e1f9b 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,14 @@ [![hacs_badge](https://img.shields.io/badge/HACS-Default-orange.svg)](https://github.com/custom-components/hacs) -## New in v1.0.6: Door/Window Open Delay, and Close Announcement Control +## New in v1.1.1: +- Ability to override the announcement prefix spoken by Alexa. -Alexa and other smart speakers (media_player) announce your doors/windows opening and closing. Comes in handy specially for garage doors or side/main exits for homes and shops where you need to stay informed of any changes. Trust me, it's a secured feeling to know the status of your garage, main/side exits. +## Overview -Ever since we've set this up in our home, we don't think we can do without it now. Your home suddenly gets a voice, something like Jarvis ... Awesome! +Alexa and other smart speakers (media_player) announce your doors/windows opening and closing. Comes in handy specially for garage doors or side/main exits for homes and shops where you need to stay informed of any changes. Trust me, it's a secured feeling to know the status of your garage, main/side exits. + +Ever since we've set this up in our home, we don't think we can do without it now. Your home suddenly gets a voice, something like Jarvis ... Awesome! Please ⭐ this repo if you like my work and also check out my other repos like - [Home Assistant 'STEROIDS' Configuration](https://github.com/UbhiTS/ha-config-ataraxis) @@ -42,6 +45,7 @@ alexa_door_window_announce: close: True start_time: "00:00:00" end_time: "23:59:59" + announcement_prefix: "Attention " debug: false ``` @@ -55,6 +59,7 @@ key | optional | type | default | description `announcements\|close` | True | bool | True | Announce the closing of the door. Set to False if you just want opening announcements. `announcements\|start_time` | True | time | 00:00:00 | The time to enable the service. (24h format) `announcements\|end_time` | True | time | 23:59:59 | The time to disable the service. (24h format) +`announcements\|announcement_prefix` | True | string | Your attention please. The | The initial phrase spoken by Alexa during alerts `debug` | True | bool | False | if True, outputs messages to the AppDaemon Log ## Thank you! :raised_hands: @@ -66,7 +71,7 @@ If you like my work and feel gracious, you can buy me a beer below ;) Buy Me A Beer diff --git a/apps/alexa_door_window_announce.py b/apps/alexa_door_window_announce.py index ff1ccae..be41c1d 100644 --- a/apps/alexa_door_window_announce.py +++ b/apps/alexa_door_window_announce.py @@ -32,53 +32,55 @@ def initialize(self): self.announce_close = True self.time_start = datetime.strptime("00:00:00", '%H:%M:%S').time() self.time_end = datetime.strptime("23:59:59", '%H:%M:%S').time() + self.announcement_prefix = "Your attention please. The " self.closing_handles = [] if "announcements" in self.args: delay = datetime.strptime(self.args["announcements"]["delay"], '%H:%M:%S').time() if "delay" in self.args["announcements"] else datetime.strptime("00:00:00", '%H:%M:%S').time() - + self.delay = timedelta(hours = delay.hour, minutes = delay.minute, seconds = delay.second) self.announce_close = bool(self.args["announcements"]["close"]) if "close" in self.args["announcements"] else self.announce_close self.time_start = datetime.strptime(self.args["announcements"]["start_time"], '%H:%M:%S').time() if "start_time" in self.args["announcements"] else self.time_start self.time_end = datetime.strptime(self.args["announcements"]["end_time"], '%H:%M:%S').time() if "end_time" in self.args["announcements"] else self.time_end + self.announcement_prefix = self.args["announcements"]["announcement_prefix"] if "announcement_prefix" in self.args["announcements"] else self.announcement_prefix if "doors_windows" in self.args: for door_window_sensor in self.args["doors_windows"]: - + domain = door_window_sensor.split(".")[0].lower() if domain in ["binary_sensor"]: - self.listen_state(self.door_window_state_changed, door_window_sensor, old = "off", new = "on", duration = self.delay.total_seconds()) - + self.listen_state(self.door_window_state_changed, door_window_sensor, old = "off", new = "on", duration = self.delay.total_seconds(), announcement_prefix = self.announcement_prefix) + elif domain in ["cover"]: - self.listen_state(self.door_window_state_changed, door_window_sensor, old = "closed", new = "open", duration = self.delay.total_seconds()) - self.listen_state(self.door_window_state_changed, door_window_sensor, old = "opening", new = "open", duration = self.delay.total_seconds()) + self.listen_state(self.door_window_state_changed, door_window_sensor, old = "closed", new = "open", duration = self.delay.total_seconds(), announcement_prefix = self.announcement_prefix) + self.listen_state(self.door_window_state_changed, door_window_sensor, old = "opening", new = "open", duration = self.delay.total_seconds(), announcement_prefix = self.announcement_prefix) else: self.debug_log("UNSUPPORTED DOMAIN: " + door_window_sensor) - + init_log = [f" START {self.time_start}\n END {self.time_end}"] if self.delay.total_seconds() > 0: init_log += [f"\n DELAY {int(self.delay.total_seconds())}"] if self.announce_close: init_log += [f"\n CLOSE ANNOUNCE"] - + self.debug_log("\n**** INIT - ALEXA DOOR WINDOW ANNOUNCE ****\n" + "".join(init_log)) - + self.debug = bool(self.args["debug"]) if "debug" in self.args else self.debug def door_window_state_changed(self, entity, attribute, old, new, kwargs): - + domain = entity.split(".")[0].lower() # cover, binary_sensor - + if self.announce_close: - + if new in ["on","open"]: - + # add closing state listener for this entity - + if domain == "binary_sensor": self.closing_handles += [ self.listen_state(self.door_window_state_changed, entity, old = "on", new = "off", oneshot = True) @@ -88,11 +90,11 @@ def door_window_state_changed(self, entity, attribute, old, new, kwargs): self.listen_state(self.door_window_state_changed, entity, old = "open", new = "closed", oneshot = True), self.listen_state(self.door_window_state_changed, entity, old = "closing", new = "closed", oneshot = True) ] - + elif new in ["off", "closed"]: - + # delete closing state listeners for this entity - + # unregister all closing handles if exists, this is a workaround for the bug in HA # where garage door openers have different open / close states when triggered # from HA > open, closing, closed, opening, open @@ -106,33 +108,34 @@ def door_window_state_changed(self, entity, attribute, old, new, kwargs): del self.closing_handles[i] except: del self.closing_handles[i] - + friendly_name = self.get_state(entity, attribute = "friendly_name") - + state = "changed" if new in ["off","closed"]: state = "closed" elif new in ["on","open"]: state = "opened" - + if not self.is_time_okay(self.time_start, self.time_end): self.debug_log(f"DOOR/WINDOW TIME LOG ONLY: {entity.split('.')[1]}|{state}") return - + delay = 0 if "alexas" in self.args: for alexa in self.args["alexas"]: - self.run_in(self.announce_state, delay, sensor_name = entity, friendly_name = friendly_name, state = state, alexa = alexa) + self.run_in(self.announce_state, delay, sensor_name = entity, friendly_name = friendly_name, state = state, alexa = alexa, announcement_prefix = self.announcement_prefix) delay = delay + 5 def announce_state(self, kwargs): - + sensor_name = kwargs["sensor_name"] friendly_name = kwargs["friendly_name"] state = kwargs["state"] alexa = kwargs["alexa"] - + announcement_prefix = kwargs["announcement_prefix"] + try: - self.call_service("notify/alexa_media", data = {"type":"tts", "method":"all"}, target = alexa, title = "Home Assistant: Door/Window Announce", message = f"Your attention please. The {friendly_name} has been {state}.") + self.call_service("notify/alexa_media", data = {"type":"tts", "method":"all"}, target = alexa, title = "Home Assistant: Door/Window Announce", message = f"{announcement_prefix} {friendly_name} has been {state}.") finally: self.debug_log(f"DOOR/WINDOW ANNOUNCE: {sensor_name.split('.')[1]}|{state}|{alexa.split('.')[1]}") @@ -143,7 +146,7 @@ def is_time_okay(self, start, end): return start <= current_time and current_time <= end else: return start <= current_time or current_time <= end - + def debug_log(self, message): if self.debug: self.log(message)