From e62daaea5a43ce0560f11e28d507157ebaf771f0 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 5 Dec 2021 10:56:42 +0100 Subject: [PATCH 01/75] update 05/12/2021 --- apps/notifier/gh_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/notifier/gh_manager.py b/apps/notifier/gh_manager.py index 1e44729..cbc5908 100644 --- a/apps/notifier/gh_manager.py +++ b/apps/notifier/gh_manager.py @@ -173,7 +173,7 @@ def worker(self): if playing and (temp_auth_sig !=''): self.call_service("media_player/play_media", entity_id = k, media_content_id = temp_media_id, media_content_type = temp_media_type, authSig = temp_auth_sig) elif playing and temp_app_name =='Spotify': - self.call_service("spotcast/start", entity_id = k) + self.call_service("spotcast/start", entity_id = k, force_playback = True) elif playing: self.call_service("media_player/play_media", entity_id = k, media_content_id = temp_media_id, media_content_type = temp_media_type) # It is empty, make callbacks From 862b2551044b23501b733ae80b267b7e26086dcd Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sat, 5 Feb 2022 15:23:15 +0100 Subject: [PATCH 02/75] Update gh_manager.py beta 5/2/22 ytube player resume --- apps/notifier/gh_manager.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/notifier/gh_manager.py b/apps/notifier/gh_manager.py index cbc5908..44879de 100644 --- a/apps/notifier/gh_manager.py +++ b/apps/notifier/gh_manager.py @@ -26,7 +26,9 @@ def initialize(self)->None: #self.gh_wait_time = globals.get_arg(self.args, "gh_wait_time") self.gh_wait_time = self.args["gh_wait_time"] self.gh_select_media_player = self.args["gh_select_media_player"] - + self.ytube_player = self.args["gh_select_media_player"] + self.ytube_called = False + self.queue = Queue(maxsize=0) self._when_tts_done_callback_queue = Queue() t = Thread(target=self.worker) @@ -126,6 +128,13 @@ def worker(self): entity = gh_player[0] else: entity = gh_player + ##### YTUBE ##### + if self.get_state(self.ytube_player) == "playing" and self.get_state(entity) == "playing": + self.call_service("ytube_music_player/call_method", entity_id = self.ytube_player, command = "interrupt_start") + self.ytube_called = True + time.sleep(1) + #self.volume_set(entity,data["volume"]) + ################# self.call_service(__TTS__ + data["gh_notifier"], entity_id = entity, message = data["text"])#, language = data["language"]) if (type(entity) is list) or entity == "all" or \ (self.get_state(entity, attribute='media_duration') is None) or \ @@ -170,6 +179,8 @@ def worker(self): if k1 == 'authSig': temp_auth_sig = v1 self.log("Costruzione del servizio: {} - {} - {} - {} - {}".format(k, temp_media_id, temp_media_type, temp_app_name,temp_auth_sig )) + if self.ytube_called: + self.call_service("ytube_music_player/call_method", entity_id = self.ytube_player, command = "interrupt_resume") if playing and (temp_auth_sig !=''): self.call_service("media_player/play_media", entity_id = k, media_content_id = temp_media_id, media_content_type = temp_media_type, authSig = temp_auth_sig) elif playing and temp_app_name =='Spotify': From 320853680e91ac7837e565e5f5a09b21d083529b Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sat, 5 Feb 2022 15:24:01 +0100 Subject: [PATCH 03/75] beta 5/2/22 ytube media player resume --- apps/notifier/gh_manager.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/notifier/gh_manager.yaml b/apps/notifier/gh_manager.yaml index 6c434f6..dd13e1a 100644 --- a/apps/notifier/gh_manager.yaml +++ b/apps/notifier/gh_manager.yaml @@ -5,3 +5,4 @@ GH_Manager: gh_restore_volume: input_number.default_restore_volume gh_wait_time: input_number.tts_wait_time gh_select_media_player: input_select.notification_media_player_google + ytube_player: media_player.ytube_music_player From 8670751b42fa10d5d404e61861cb1d73390c13da Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Wed, 10 Aug 2022 09:35:25 +0200 Subject: [PATCH 04/75] beta 10/08/2022 added a new duration message algorithm with GH --- apps/notifier/gh_manager.py | 42 +++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/apps/notifier/gh_manager.py b/apps/notifier/gh_manager.py index 44879de..9d06226 100644 --- a/apps/notifier/gh_manager.py +++ b/apps/notifier/gh_manager.py @@ -19,6 +19,15 @@ __NOTIFY__ = "notify/" __TTS__ = "tts/" SUB_TTS = [("[\*\-\[\]_\(\)\{\~\|\}\s]+"," ")] +SUB_VOICE = [ + # ("[.]{2,}", "."), + ("[\?\.\!,]+(?=[\?\.\!,])", ""), # Exclude duplicate + ("(\s+\.|\s+\.\s+|[\.])(?! )(?![^{]*})(?![^\d.]*\d)", ". "), + ("&", " and "), # escape + # ("(?") + return re.sub(regex, "", str(text).strip()) + + def has_numbers(self, string): + numbers = re.compile("\d{4,}|\d{3,}\.\d") + return numbers.search(string) + def speak(self, google, gh_mode: bool, gh_notifier: str): """Speak the provided text through the media player""" gh_player = self.check_mplayer(self.split_device_list(google["media_player"])) gh_volume = self.check_volume(self.get_state(self.gh_select_media_player, attribute="options")) - #self.log("gh_player {}:".format(gh_player)) self.volume_get(gh_volume,float(self.get_state(self.args["gh_restore_volume"]))/100) self.mediastate_get(gh_volume,float(self.get_state(self.args["gh_restore_volume"]))/100) - #float(self.get_state(globals.get_arg(self.args, "gh_restore_volume")))/100 wait_time = float(self.get_state(self.gh_wait_time)) message = self.replace_regular(google["message_tts"], SUB_TTS) ### set volume @@ -128,23 +143,38 @@ def worker(self): entity = gh_player[0] else: entity = gh_player - ##### YTUBE ##### + ############# YTUBE ############## if self.get_state(self.ytube_player) == "playing" and self.get_state(entity) == "playing": self.call_service("ytube_music_player/call_method", entity_id = self.ytube_player, command = "interrupt_start") self.ytube_called = True time.sleep(1) #self.volume_set(entity,data["volume"]) - ################# + ########### MSG DURATION ######### + message_clean = self.replace_regular(data["text"], SUB_VOICE) + # Speech time calculator + words = len(self.remove_tags(message_clean).split()) + chars = self.remove_tags(message_clean).count("") + duration = (words * 0.007) * 60 + if self.has_numbers(message_clean): + duration = 4 + if (chars / words) > 7 and chars > 90: + duration = 7 + ################################## self.call_service(__TTS__ + data["gh_notifier"], entity_id = entity, message = data["text"])#, language = data["language"]) if (type(entity) is list) or entity == "all" or \ (self.get_state(entity, attribute='media_duration') is None) or \ float(self.get_state(entity, attribute='media_duration')) > 60 or \ float(self.get_state(entity, attribute='media_duration')) == -1: - duration = float(len(data["text"].split())) / 3 + data["wait_time"] + #duration = float(len(data["text"].split())) / 3 + data["wait_time"] + duration += data["wait_time"] else: duration = float(self.get_state(entity, attribute='media_duration')) + data["wait_time"] #Sleep and wait for the tts to finish time.sleep(duration) + ################################## + if self.ytube_called: + self.call_service("media_player/volume_set", entity_id = entity, volume_level = 0) + ################################## except Exception as ex: self.log("An error occurred in GH Manager - Errore nel Worker: {}".format(ex),level="ERROR") self.log(sys.exc_info()) From 8a42e1968169f8f5fd8205d32f0bbf94ef7f29e1 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Wed, 10 Aug 2022 09:53:04 +0200 Subject: [PATCH 05/75] update 10/08/2022 add actionable notifications with Telegram --- apps/notifier/notification_manager.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/apps/notifier/notification_manager.py b/apps/notifier/notification_manager.py index d25aa53..1146d58 100644 --- a/apps/notifier/notification_manager.py +++ b/apps/notifier/notification_manager.py @@ -58,6 +58,7 @@ def send_notify(self, data, notify_name, assistant_name: str): timestamp = datetime.datetime.now().strftime("%H:%M:%S") title = data["title"] message = data["message"] + inline = data["inline"] image = data["image"] caption = data["caption"] link = data["link"] @@ -76,7 +77,7 @@ def send_notify(self, data, notify_name, assistant_name: str): #### TELEGRAM ####################### if item.find("telegram") != -1: messaggio, titolo = self.prepare_text(html, message, title, timestamp, assistant_name) - extra_data = "" + extra_data = {} if str(html).lower() not in ["true","on","yes","1"]: messaggio = messaggio.replace("_","\_") if link !="": @@ -95,9 +96,13 @@ def send_notify(self, data, notify_name, assistant_name: str): "caption": caption, "timeout": 90} } + if inline !="": + extra_data.update({"inline_keyboard":inline}) if image != "": self.call_service(item, message = "", data = extra_data) - else: + elif extra_data: + self.call_service(item, message = messaggio, title = titolo, data = extra_data) + else: self.call_service(item, message = messaggio, title = titolo) #### WHATSAPP ####################### elif item.find("whatsapp") != -1: @@ -112,9 +117,9 @@ def send_notify(self, data, notify_name, assistant_name: str): titolo = titolo.replace("*","") extra_data = {} if image != "" and image.find("http") != -1: - extra_data.update({"url": image}) + extra_data.update({"url":image}) if image != "" and image.find("http") == -1: - extra_data.update({"attachment": image}) + extra_data.update({"attachment":image}) if extra_data: self.call_service( item, message = messaggio, title = titolo, data = extra_data) else: @@ -127,7 +132,7 @@ def send_notify(self, data, notify_name, assistant_name: str): if link !="": messaggio = ("{} {}".format(messaggio,link)) if image != "" and image.find("http") != -1: - extra_data.update( {"url": image}) + extra_data.update({"url": image}) if image != "" and image.find("http") == -1: extra_data.update({"file": image}) if extra_data: @@ -196,7 +201,7 @@ def send_notify(self, data, notify_name, assistant_name: str): self.call_service( item, message = messaggio, title = titolo, data = extra_data) else: self.call_service( item, message = messaggio, title = titolo) - #### OTHER ######################### + #### other ######################### else: if title != "": title = "[{} - {}] {}".format(assistant_name, timestamp, title) @@ -205,7 +210,7 @@ def send_notify(self, data, notify_name, assistant_name: str): if link !="": message = ("{} {}".format(message,link)) self.call_service(item, message=message, title=title) - + def send_persistent(self, data, persistent_notification_info): timestamp = datetime.datetime.now().strftime("%H:%M:%S") messaggio="" From e8361168e3ec5047a1bc8bdc05dc97f25b7f6b40 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Wed, 10 Aug 2022 10:21:10 +0200 Subject: [PATCH 06/75] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index aecf39f..bafe690 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,8 @@ Package-Notification-HUB-AppDaemon
The app works with Appdaemon v4.x. ## Installation -Use [HACS](https://github.com/custom-components/hacs) or [download](https://github.com/jumping2000/notifier) the `notifier` directory from inside the `apps` directory here to your local `apps` directory. +Use [HACS](https://github.com/custom-components/hacs) or [download](https://github.com/jumping2000/notifier) the `notifier` directory from inside the `apps` directory here to your local `apps` directory. +Remember to enable [Appdaemon in HACS](https://hacs.xyz/docs/categories/appdaemon_apps#enable-appdaemon-apps-in-hacs). ## Remember it! The app doesn't work standalone but togheter with [Centro Notifiche](https://github.com/caiosweet/Package-Notification-HUB-AppDaemon) From f5669aee68d0c28ce2c2fd3bf7349a7c29569a73 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Mon, 19 Sep 2022 12:27:54 +0200 Subject: [PATCH 07/75] Update 19/09/2022 Added gotify and whatsapp addon --- apps/notifier/notification_manager.py | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/apps/notifier/notification_manager.py b/apps/notifier/notification_manager.py index 1146d58..ad24498 100644 --- a/apps/notifier/notification_manager.py +++ b/apps/notifier/notification_manager.py @@ -64,6 +64,7 @@ def send_notify(self, data, notify_name, assistant_name: str): link = data["link"] html = data["html"] mobile = data["mobile"] + whatsapp_addon = data["whatsapp"] discord = data["discord"] notify_vector = self.check_notifier(self.split_device_list(str(data["notify"])),self.split_device_list(str(notify_name))) ########## SAVE IN INPUT_TEXT ########### @@ -104,6 +105,26 @@ def send_notify(self, data, notify_name, assistant_name: str): self.call_service(item, message = messaggio, title = titolo, data = extra_data) else: self.call_service(item, message = messaggio, title = titolo) + #### WHATSAPP ADDON ################# + elif item.find("whatsapp_addon") != -1: + messaggio, titolo = self.prepare_text(html, message, title, timestamp, assistant_name) + messaggio = titolo + " " + messaggio + extra_data = {} + if isinstance(whatsapp_addon, dict): + extra_data = whatsapp_addon + if messaggio != "": + extra_data.update({"body": + {"text": messaggio } + } ) + #dict[extra_data]["body"]["text"]= messaggio + if image != "": + extra_data.update({"image": + {"url": image } + } ) + if caption!= "": + extra_data.update({"caption": caption }) + if extra_data: + self.call_service( "whatsapp/send_message", data = extra_data) #### WHATSAPP ####################### elif item.find("whatsapp") != -1: messaggio, titolo = self.prepare_text(html, message, title, timestamp, assistant_name) @@ -201,6 +222,14 @@ def send_notify(self, data, notify_name, assistant_name: str): self.call_service( item, message = messaggio, title = titolo, data = extra_data) else: self.call_service( item, message = messaggio, title = titolo) + + #### GOTIFY ########################### + elif item.find("gotify") != -1: + messaggio, titolo = self.prepare_text(html, message, title, timestamp, assistant_name) + titolo = titolo.replace("*","") + if link !="": + messaggio = ("{} {}".format(messaggio,link)) + self.call_service( item, message = messaggio, title = titolo) #### other ######################### else: if title != "": From 3186136261c419f23c789211d87e5b14f5498b59 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Mon, 19 Sep 2022 18:14:20 +0200 Subject: [PATCH 08/75] beta 19/09/22 --- apps/notifier/notification_manager.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/apps/notifier/notification_manager.py b/apps/notifier/notification_manager.py index ad24498..302a048 100644 --- a/apps/notifier/notification_manager.py +++ b/apps/notifier/notification_manager.py @@ -63,6 +63,8 @@ def send_notify(self, data, notify_name, assistant_name: str): caption = data["caption"] link = data["link"] html = data["html"] + priority = data["priority"] + pushover = data["pushover"] mobile = data["mobile"] whatsapp_addon = data["whatsapp"] discord = data["discord"] @@ -137,10 +139,13 @@ def send_notify(self, data, notify_name, assistant_name: str): messaggio, titolo = self.prepare_text(html, message, title, timestamp, assistant_name) titolo = titolo.replace("*","") extra_data = {} - if image != "" and image.find("http") != -1: - extra_data.update({"url":image}) - if image != "" and image.find("http") == -1: - extra_data.update({"attachment":image}) + if isinstance(pushover, dict): + if image != "" and image.find("http") != -1: + extra_data.update({"url":image}) + if image != "" and image.find("http") == -1: + extra_data.update({"attachment":image}) + if priority != "": + extra_data.update({"priority":priority}) if extra_data: self.call_service( item, message = messaggio, title = titolo, data = extra_data) else: @@ -222,14 +227,19 @@ def send_notify(self, data, notify_name, assistant_name: str): self.call_service( item, message = messaggio, title = titolo, data = extra_data) else: self.call_service( item, message = messaggio, title = titolo) - #### GOTIFY ########################### elif item.find("gotify") != -1: messaggio, titolo = self.prepare_text(html, message, title, timestamp, assistant_name) - titolo = titolo.replace("*","") if link !="": messaggio = ("{} {}".format(messaggio,link)) - self.call_service( item, message = messaggio, title = titolo) + if image !="" and caption !="": + messaggio = ("{} ![{}]({})".format(messaggio,caption,image)) + elif image !="" : + messaggio = ("{} ![]({})".format(messaggio,image)) + if priority !="": + self.call_service( item, message = messaggio, title = titolo, target = priority) + else: + self.call_service( item, message = messaggio, title = titolo) #### other ######################### else: if title != "": From a36aa9b9a286b3a0aa65bd1e1c1b9e57e3147346 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sat, 15 Oct 2022 11:03:26 +0200 Subject: [PATCH 09/75] Update notifier_dispatch.py Management of "message_tts" changed in "message" --- apps/notifier/notifier_dispatch.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/notifier/notifier_dispatch.py b/apps/notifier/notifier_dispatch.py index 6ec55a1..2eb43e8 100644 --- a/apps/notifier/notifier_dispatch.py +++ b/apps/notifier/notifier_dispatch.py @@ -201,15 +201,15 @@ def notify_hub(self, event_name, data, kwargs): google["media_content_id"] = "" if "media_content_type" not in google: google["media_content_type"] = "" - if "message_tts" not in google: - google["message_tts"] = data["message"] + if "message" not in google: + google["message"] = data["message"] if "language" not in google: google["language"] = self.get_state(self.tts_language).lower() self.gh_manager.speak(google, self.get_state(self.gh_tts_google_mode), gh_notifica) if alexa_switch == "on" and alexa_flag: if (data["alexa"]) != "": - if "message_tts" not in alexa: - alexa["message_tts"] = data["message"] + if "message" not in alexa: + alexa["message"] = data["message"] if "title" not in alexa: alexa["title"] = data["title"] if "volume" not in alexa: From fd567698b85cd6d26560b9203eb73775538e7bdb Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sat, 15 Oct 2022 11:06:09 +0200 Subject: [PATCH 10/75] Update notification_manager.py Discord enhancement --- apps/notifier/notification_manager.py | 32 +++++++++++++++------------ 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/apps/notifier/notification_manager.py b/apps/notifier/notification_manager.py index 302a048..be76853 100644 --- a/apps/notifier/notification_manager.py +++ b/apps/notifier/notification_manager.py @@ -172,21 +172,22 @@ def send_notify(self, data, notify_name, assistant_name: str): if isinstance(discord, dict): if "embed" in discord: extra_data = discord - extra_data.update({"title":titolo.replace("*","")}) - extra_data.update({"description":messaggio}) + extra_data.update({"title": titolo.replace("*","")}) + extra_data.update({"description": messaggio}) if link !="": extra_data.update({"url":link}) + if image != "": + extra_data.update({"images":image.replace("config/www","local")}) elif "images" in discord: extra_data = discord messaggio = titolo.replace("*","") + " " + messaggio + if extra_data and "embed" in discord: + self.call_service( item, message = "", data = extra_data) + elif extra_data and "images" in discord: + self.call_service( item, message = messaggio, data = extra_data) else: - messaggio = titolo.replace("*","") + " " + messaggio - # if image != "": - # extra_data.update({"images":image}) - # if extra_data: - # self.call_service( item, message = messaggio, data = extra_data) - #else: - self.call_service( item, message = messaggio) + self.call_service( item, message = messaggio) + #self.call_service( item, message = messaggio) #### MAIL ########################### elif item.find("mail") != -1: messaggio, titolo = self.prepare_text(html, message, title, timestamp, assistant_name) @@ -227,20 +228,23 @@ def send_notify(self, data, notify_name, assistant_name: str): self.call_service( item, message = messaggio, title = titolo, data = extra_data) else: self.call_service( item, message = messaggio, title = titolo) - #### GOTIFY ########################### + #### GOTIFY ######################### elif item.find("gotify") != -1: messaggio, titolo = self.prepare_text(html, message, title, timestamp, assistant_name) - if link !="": - messaggio = ("{} {}".format(messaggio,link)) + titolo = titolo.replace("*","") + if link !="" and caption !="": + messaggio = ("{} [{}]({})".format(messaggio,caption,link)) + elif link !="" : + messaggio = ("{} [{}]({})".format(messaggio,link,link)) if image !="" and caption !="": messaggio = ("{} ![{}]({})".format(messaggio,caption,image)) elif image !="" : - messaggio = ("{} ![]({})".format(messaggio,image)) + messaggio = ("{} ![{}]({})".format(messaggio,image,image)) if priority !="": self.call_service( item, message = messaggio, title = titolo, target = priority) else: self.call_service( item, message = messaggio, title = titolo) - #### other ######################### + #### other ########################## else: if title != "": title = "[{} - {}] {}".format(assistant_name, timestamp, title) From bc150bd16f673f7d6f77f43e108619e0061a4edd Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sat, 15 Oct 2022 11:09:55 +0200 Subject: [PATCH 11/75] Update gh_manager.yaml added: gh_service helper --- apps/notifier/gh_manager.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/notifier/gh_manager.yaml b/apps/notifier/gh_manager.yaml index dd13e1a..022824f 100644 --- a/apps/notifier/gh_manager.yaml +++ b/apps/notifier/gh_manager.yaml @@ -2,6 +2,7 @@ GH_Manager: module: gh_manager class: GH_Manager + gh_service: tts.google gh_restore_volume: input_number.default_restore_volume gh_wait_time: input_number.tts_wait_time gh_select_media_player: input_select.notification_media_player_google From c9fd50ad999d2582777c306a098bcb9b420dce94 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sat, 15 Oct 2022 11:12:31 +0200 Subject: [PATCH 12/75] Update gh_manager.py added gh_service helper --- apps/notifier/gh_manager.py | 51 +++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/apps/notifier/gh_manager.py b/apps/notifier/gh_manager.py index 9d06226..80cbe02 100644 --- a/apps/notifier/gh_manager.py +++ b/apps/notifier/gh_manager.py @@ -33,11 +33,13 @@ class GH_Manager(hass.Hass): def initialize(self)->None: #self.gh_wait_time = globals.get_arg(self.args, "gh_wait_time") + self.gh_service = self.args.get("gh_service") self.gh_wait_time = self.args["gh_wait_time"] self.gh_select_media_player = self.args["gh_select_media_player"] self.ytube_player = self.args["gh_select_media_player"] self.ytube_called = False - + self.check_gh_service = self.check_gh(self.gh_service) + # self.queue = Queue(maxsize=0) self._when_tts_done_callback_queue = Queue() t = Thread(target=self.worker) @@ -56,9 +58,9 @@ def check_volume(self, gh_volume): media_state = self.get_state("media_player") gh = [] for entity, state in media_state.items(): - friendly_name = state["attributes"].get("friendly_name") + friendly_name = state["attributes"].get("friendly_name") if state["attributes"].get("friendly_name") is not None else "" for item in gh_volume: - if "gruppo" not in str(item).lower() and item == friendly_name: + if "gruppo" not in str(item).lower() and str(friendly_name).lower() == str(item).lower(): gh.append(entity) return gh @@ -78,7 +80,7 @@ def mediastate_get(self, media_player:list, volume: float): for i in media_player: self.dict_info_mplayer[i] = {} for i in media_player: - #self.dict_info_mplayer[i]['volume'] = self.get_state(i, attribute="volume_level", default=volume) + self.dict_info_mplayer[i]['volume'] = self.get_state(i, attribute="volume_level", default=volume) self.dict_info_mplayer[i]['state'] = self.get_state(i, default='idle') self.dict_info_mplayer[i]['media_id'] = self.get_state(i, attribute="media_content_id", default='') self.dict_info_mplayer[i]['media_type'] = self.get_state(i, attribute="media_content_type", default='') @@ -103,14 +105,31 @@ def has_numbers(self, string): numbers = re.compile("\d{4,}|\d{3,}\.\d") return numbers.search(string) + def set_sensor(self, state, error): + attributes = {} + attributes["icon"] = "mdi:google" + attributes["Error"] = error + self.set_state("sensor.centro_notifiche", state=state, attributes=attributes) + + def check_gh(self, service): + """ check if tts service exist in HA """ + self.hass_config = self.get_plugin_config() + components = self.hass_config["components"] + return next((True for comp in components if service in comp), False) + def speak(self, google, gh_mode: bool, gh_notifier: str): - """Speak the provided text through the media player""" + """Speak the provided text through the media player.""" + if not self.check_gh_service: + self.set_sensor( + "I can't find the TTS Google component", "https://www.home-assistant.io/integrations/tts" + ) + return gh_player = self.check_mplayer(self.split_device_list(google["media_player"])) gh_volume = self.check_volume(self.get_state(self.gh_select_media_player, attribute="options")) self.volume_get(gh_volume,float(self.get_state(self.args["gh_restore_volume"]))/100) self.mediastate_get(gh_volume,float(self.get_state(self.args["gh_restore_volume"]))/100) wait_time = float(self.get_state(self.gh_wait_time)) - message = self.replace_regular(google["message_tts"], SUB_TTS) + message = self.replace_regular(google["message"], SUB_TTS) ### set volume self.volume_set(gh_player,google["volume"]) # queues the message to be handled async, use when_tts_done_do method to supply callback when tts is done @@ -120,6 +139,7 @@ def speak(self, google, gh_mode: bool, gh_notifier: str): media_content_type = google["media_content_type"]) except Exception as ex: self.log("An error occurred in GH Manager - Errore in media_content: {}".format(ex),level="ERROR") + self.set_sensor("GH Manager - media_content Error ", ex) self.log(sys.exc_info()) else: self.queue.put({"type": "tts", "text": message, "volume": google["volume"], "language": self.replace_language(google["language"]), @@ -143,15 +163,14 @@ def worker(self): entity = gh_player[0] else: entity = gh_player - ############# YTUBE ############## + ############ YTUBE ############### if self.get_state(self.ytube_player) == "playing" and self.get_state(entity) == "playing": self.call_service("ytube_music_player/call_method", entity_id = self.ytube_player, command = "interrupt_start") self.ytube_called = True time.sleep(1) #self.volume_set(entity,data["volume"]) - ########### MSG DURATION ######### + ##### Speech time calculator ##### message_clean = self.replace_regular(data["text"], SUB_VOICE) - # Speech time calculator words = len(self.remove_tags(message_clean).split()) chars = self.remove_tags(message_clean).count("") duration = (words * 0.007) * 60 @@ -165,10 +184,11 @@ def worker(self): (self.get_state(entity, attribute='media_duration') is None) or \ float(self.get_state(entity, attribute='media_duration')) > 60 or \ float(self.get_state(entity, attribute='media_duration')) == -1: - #duration = float(len(data["text"].split())) / 3 + data["wait_time"] + #duration = float(len(data["text"].split())) / 2 + data["wait_time"] duration += data["wait_time"] else: duration = float(self.get_state(entity, attribute='media_duration')) + data["wait_time"] + self.log("DURATION {}: ".format(duration)) #Sleep and wait for the tts to finish time.sleep(duration) ################################## @@ -178,6 +198,7 @@ def worker(self): except Exception as ex: self.log("An error occurred in GH Manager - Errore nel Worker: {}".format(ex),level="ERROR") self.log(sys.exc_info()) + self.set_sensor("GH Manager -Worker Error ", ex) self.queue.task_done() @@ -188,7 +209,7 @@ def worker(self): for i,j in self.dict_volumes.items(): self.call_service("media_player/volume_set", entity_id = i, volume_level = j) # Force Set state - self.set_state(i, state="", attributes = {"volume_level": j}) + self.set_state(i, state="", attributes = {"volume_level": j}) ## RESTORE MUSIC if self.dict_info_mplayer: for k,v in self.dict_info_mplayer.items(): @@ -211,9 +232,10 @@ def worker(self): self.log("Costruzione del servizio: {} - {} - {} - {} - {}".format(k, temp_media_id, temp_media_type, temp_app_name,temp_auth_sig )) if self.ytube_called: self.call_service("ytube_music_player/call_method", entity_id = self.ytube_player, command = "interrupt_resume") - if playing and (temp_auth_sig !=''): + self.call_service("media_player/volume_set", entity_id = k, volume_level = 0.4) + elif playing and (temp_auth_sig !=''): self.call_service("media_player/play_media", entity_id = k, media_content_id = temp_media_id, media_content_type = temp_media_type, authSig = temp_auth_sig) - elif playing and temp_app_name =='Spotify': + elif playing and temp_app_name =="Spotify": self.call_service("spotcast/start", entity_id = k, force_playback = True) elif playing: self.call_service("media_player/play_media", entity_id = k, media_content_id = temp_media_id, media_content_type = temp_media_type) @@ -225,5 +247,6 @@ def worker(self): self._when_tts_done_callback_queue.task_done() except: self.log("An error occurred in GH Manager - Errore nel CallBack", level="ERROR") - self.log(sys.exc_info()) + self.log(sys.exc_info()) + self.set_sensor("GH Manager - CallBack Error ", ex) pass # Nothing in queue From a6e016ca5ba27a27f1bb96a9abdbbe5b51813f0b Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sat, 15 Oct 2022 11:15:16 +0200 Subject: [PATCH 13/75] Update notifier_dispatch.yaml upgrade 2022-10 --- apps/notifier/notifier_dispatch.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/notifier/notifier_dispatch.yaml b/apps/notifier/notifier_dispatch.yaml index 3507f69..4333fdb 100644 --- a/apps/notifier/notifier_dispatch.yaml +++ b/apps/notifier/notifier_dispatch.yaml @@ -7,6 +7,7 @@ Notifier_Dispatch: gh_selected_media_player: sensor.media_player_google alexa_switch: input_boolean.alexa_switch + alexa_selected_media_player: sensor.media_player_alexa tts_period_of_day_volume: sensor.period_of_day_volume tts_language: input_select.language @@ -15,7 +16,7 @@ Notifier_Dispatch: screen_notifications: input_boolean.screen_notifications speech_notifications: input_boolean.speech_notifications phone_notifications: input_boolean.phone_notifications - + html_mode: input_boolean.html_mode persistent_notification_info: persistent_notification.info_messages @@ -29,6 +30,13 @@ Notifier_Dispatch: personal_assistant_name: input_text.personal_assistant_name phone_called_number: input_text.phone_called_number + + tts_google: secret_tts_google + tts_google_cloud: secret_tts_google_cloud + reverso_tts: secret_reverso_tts + notify_google: secret_notify_google + notify_alexa: secret_notify_alexa + sip_server: secret_sip_server sensor: sensor.centro_notifiche From 3388bbc1d95dd858e76eb9630d965738700d7582 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sat, 15 Oct 2022 23:20:19 +0200 Subject: [PATCH 14/75] add skill ID add skill ID --- apps/notifier/notifier_dispatch.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/notifier/notifier_dispatch.py b/apps/notifier/notifier_dispatch.py index 2eb43e8..02d2eee 100644 --- a/apps/notifier/notifier_dispatch.py +++ b/apps/notifier/notifier_dispatch.py @@ -7,7 +7,7 @@ # # Args: # -# Version 2.0: +# Version 2022.10: # Initial Version @@ -43,7 +43,7 @@ def initialize(self): self.sensor = self.args.get("sensor") self.set_state(self.sensor, state="on") -#### FROM SECRET FILE ### + #### FROM SECRET FILE ### config = self.get_plugin_config() config_dir = config["config_dir"] self.log(f"configuration dir: {config_dir}") @@ -55,6 +55,7 @@ def initialize(self): self.phone_sip_server = cfg.get("sip_server_name", "fritz.box:5060") self.gh_tts_cloud = cfg.get("tts_google_cloud", "google_cloud") self.reverso_tts = cfg.get("reverso_tts", "reversotts_say") + self.alexa_skill_id = cfg.get("hub_alexa_actionable_skil_id", "") ### APP MANAGER ### self.notification_manager = self.get_app("Notification_Manager") From 58f546761f52515ac86a2a66208cf6472385419b Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sat, 15 Oct 2022 23:24:50 +0200 Subject: [PATCH 15/75] added skill_id added skill_id --- apps/notifier/notifier_dispatch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/notifier/notifier_dispatch.py b/apps/notifier/notifier_dispatch.py index 02d2eee..646607b 100644 --- a/apps/notifier/notifier_dispatch.py +++ b/apps/notifier/notifier_dispatch.py @@ -217,7 +217,7 @@ def notify_hub(self, event_name, data, kwargs): alexa["volume"] = float(self.get_state(self.tts_period_of_day_volume)) / 100 if "language" not in alexa: alexa["language"] = self.get_state(self.tts_language) - self.alexa_manager.speak(alexa) + self.alexa_manager.speak(alexa, self.alexa_skill_id) if usePhone: try: language = self.get_state(self.tts_language) From 78c125c90606d924ab827b91266c2a5d2ef9ea6d Mon Sep 17 00:00:00 2001 From: caiosweet <24454580+caiosweet@users.noreply.github.com> Date: Sun, 16 Oct 2022 10:10:33 +0200 Subject: [PATCH 16/75] Update notifier_dispatch.py --- apps/notifier/notifier_dispatch.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/notifier/notifier_dispatch.py b/apps/notifier/notifier_dispatch.py index 646607b..1392b0c 100644 --- a/apps/notifier/notifier_dispatch.py +++ b/apps/notifier/notifier_dispatch.py @@ -1,5 +1,6 @@ -import hassapi as hass import sys + +import hassapi as hass import yaml # @@ -55,7 +56,7 @@ def initialize(self): self.phone_sip_server = cfg.get("sip_server_name", "fritz.box:5060") self.gh_tts_cloud = cfg.get("tts_google_cloud", "google_cloud") self.reverso_tts = cfg.get("reverso_tts", "reversotts_say") - self.alexa_skill_id = cfg.get("hub_alexa_actionable_skil_id", "") + self.alexa_skill_id = cfg.get("hub_alexa_actionable_skill_id", "") ### APP MANAGER ### self.notification_manager = self.get_app("Notification_Manager") From 340cbdedfb124f61dbb09a9515bdaa48e5227053 Mon Sep 17 00:00:00 2001 From: caiosweet <24454580+caiosweet@users.noreply.github.com> Date: Sun, 16 Oct 2022 10:18:20 +0200 Subject: [PATCH 17/75] beta 2022-10-16 fix typo in dispatch New Alexa Actionable notification --- apps/notifier/alexa_manager.py | 28 +++++++++++++++++++++------- apps/notifier/alexa_manager.yaml | 1 + 2 files changed, 22 insertions(+), 7 deletions(-) mode change 100644 => 100755 apps/notifier/alexa_manager.py mode change 100644 => 100755 apps/notifier/alexa_manager.yaml diff --git a/apps/notifier/alexa_manager.py b/apps/notifier/alexa_manager.py old mode 100644 new mode 100755 index 99796a2..2d70b40 --- a/apps/notifier/alexa_manager.py +++ b/apps/notifier/alexa_manager.py @@ -1,10 +1,10 @@ -import hassapi as hass - -import re -import sys -import time +import json from queue import Queue +import re from threading import Thread +import time + +import hassapi as hass """ Class Alexa Manager handles sending text to speech messages to Alexa media players @@ -272,6 +272,7 @@ def initialize(self) -> None: self.alexa_sensor_media_player = self.args.get("alexa_sensor_media_player") self.alexa_voice = self.args.get("alexa_voice") # self.alexa_language = self.args.get("alexa_language") + self.alexa_actionable = self.args.get("alexa_actionable") ## NEW self.prosody = self.args.get("prosody") self.wait_time = self.args.get("wait_time") self.cehck_alexa_service = self._check_alexa(self.alexa_service) @@ -283,7 +284,7 @@ def initialize(self) -> None: t.daemon = True t.start() - def speak(self, alexa): + def speak(self, alexa, skill_id): #### NEW ### """Speak the provided text through the media player.""" if not self.cehck_alexa_service: self.set_sensor( @@ -302,6 +303,8 @@ def speak(self, alexa): alexa_type = ( str(alexa.get("type", self.get_state(self.alexa_type))).lower().replace("dropin", "dropin_notification") ) + if event_id := alexa.get("event_id"): #### NEW ### + self.set_textvalue(self.alexa_actionable, json.dumps({"text": "", "event": event_id})) # Push notification push = bool(self.check_bool(alexa.get("push"))) @@ -336,6 +339,8 @@ def speak(self, alexa): { "text": message, "volume": volume, + "event_id": event_id, #### NEW ### + "skill_id": skill_id, #### NEW ### "alexa_type": alexa_type, "alexa_player": alexa_player, # media_player "default_restore_volume": default_restore_volume, @@ -480,7 +485,7 @@ def set_sensor(self, state, error): attributes["icon"] = "mdi:amazon-alexa" attributes["Error"] = error self.set_state("sensor.centro_notifiche", state=state, attributes=attributes) - + def when_tts_done_do(self, callback: callable) -> None: """Callback when the queue of tts messages are done.""" self._when_tts_done_callback_queue.put(callback) @@ -557,6 +562,15 @@ def worker(self): message=message_clean.strip(), ) + if data["event_id"]: #### NEW ### + self.call_service( + "media_player/play_media", + entity_id=alexa_player, + media_content_id=data["skill_id"], + media_content_type="skill", + ) + duration += 10 + time.sleep(duration if duration > 0 else 0) # Restore volume diff --git a/apps/notifier/alexa_manager.yaml b/apps/notifier/alexa_manager.yaml old mode 100644 new mode 100755 index 50807aa..4803bf7 --- a/apps/notifier/alexa_manager.yaml +++ b/apps/notifier/alexa_manager.yaml @@ -15,6 +15,7 @@ Alexa_Manager: alexa_sensor_media_player: sensor.media_player_alexa # alexa_language: input_select.alexa_language alexa_voice: input_select.alexa_voice + alexa_actionable: input_text.alexa_actionable_notification ssml_switch: input_boolean.alexa_ssml prosody: rate: input_number.alexa_prosody_rate From 4e60e4234ab6a95e308e5aec0a5b7596f05b9e64 Mon Sep 17 00:00:00 2001 From: caiosweet <24454580+caiosweet@users.noreply.github.com> Date: Sun, 16 Oct 2022 10:33:22 +0200 Subject: [PATCH 18/75] Beta 2022-10-16 Alexa actionable notification fixed notifyhub suffix in secret file --- apps/notifier/notifier_dispatch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/notifier/notifier_dispatch.py b/apps/notifier/notifier_dispatch.py index 1392b0c..8bbbe2e 100644 --- a/apps/notifier/notifier_dispatch.py +++ b/apps/notifier/notifier_dispatch.py @@ -56,7 +56,7 @@ def initialize(self): self.phone_sip_server = cfg.get("sip_server_name", "fritz.box:5060") self.gh_tts_cloud = cfg.get("tts_google_cloud", "google_cloud") self.reverso_tts = cfg.get("reverso_tts", "reversotts_say") - self.alexa_skill_id = cfg.get("hub_alexa_actionable_skill_id", "") + self.alexa_skill_id = cfg.get("notifyhub_alexa_actionable_skill_id", "") ### APP MANAGER ### self.notification_manager = self.get_app("Notification_Manager") From 587b3b7d2368c877910cc5e1ba1596e4ffad208f Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 16 Oct 2022 10:33:41 +0200 Subject: [PATCH 19/75] beta 16/10 changed debug_sensor --- apps/notifier/gh_manager.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/notifier/gh_manager.py b/apps/notifier/gh_manager.py index 80cbe02..fbd532a 100644 --- a/apps/notifier/gh_manager.py +++ b/apps/notifier/gh_manager.py @@ -38,6 +38,8 @@ def initialize(self)->None: self.gh_select_media_player = self.args["gh_select_media_player"] self.ytube_player = self.args["gh_select_media_player"] self.ytube_called = False + self.debug_sensor = self.args.get("debug_sensor") + self.set_state(self.debug_sensor, state="on") self.check_gh_service = self.check_gh(self.gh_service) # self.queue = Queue(maxsize=0) @@ -105,11 +107,11 @@ def has_numbers(self, string): numbers = re.compile("\d{4,}|\d{3,}\.\d") return numbers.search(string) - def set_sensor(self, state, error): + def set_debug_sensor(self, state, error): attributes = {} attributes["icon"] = "mdi:google" attributes["Error"] = error - self.set_state("sensor.centro_notifiche", state=state, attributes=attributes) + self.set_state(self.debug_sensor, state=state, attributes=attributes) def check_gh(self, service): """ check if tts service exist in HA """ @@ -120,7 +122,7 @@ def check_gh(self, service): def speak(self, google, gh_mode: bool, gh_notifier: str): """Speak the provided text through the media player.""" if not self.check_gh_service: - self.set_sensor( + self.set_debug_sensor( "I can't find the TTS Google component", "https://www.home-assistant.io/integrations/tts" ) return @@ -139,7 +141,7 @@ def speak(self, google, gh_mode: bool, gh_notifier: str): media_content_type = google["media_content_type"]) except Exception as ex: self.log("An error occurred in GH Manager - Errore in media_content: {}".format(ex),level="ERROR") - self.set_sensor("GH Manager - media_content Error ", ex) + self.set_debug_sensor("GH Manager - media_content Error ", ex) self.log(sys.exc_info()) else: self.queue.put({"type": "tts", "text": message, "volume": google["volume"], "language": self.replace_language(google["language"]), @@ -198,7 +200,7 @@ def worker(self): except Exception as ex: self.log("An error occurred in GH Manager - Errore nel Worker: {}".format(ex),level="ERROR") self.log(sys.exc_info()) - self.set_sensor("GH Manager -Worker Error ", ex) + self.set_debug_sensor("GH Manager -Worker Error ", ex) self.queue.task_done() @@ -248,5 +250,6 @@ def worker(self): except: self.log("An error occurred in GH Manager - Errore nel CallBack", level="ERROR") self.log(sys.exc_info()) - self.set_sensor("GH Manager - CallBack Error ", ex) + self.set_debug_sensor("GH Manager - CallBack Error ", ex) pass # Nothing in queue + From 89cbe707bd52fb6a02f8208c906243c8f5af68df Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 16 Oct 2022 10:34:28 +0200 Subject: [PATCH 20/75] update 16/10 --- apps/notifier/gh_manager.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/notifier/gh_manager.yaml b/apps/notifier/gh_manager.yaml index 022824f..bfd11ff 100644 --- a/apps/notifier/gh_manager.yaml +++ b/apps/notifier/gh_manager.yaml @@ -7,3 +7,5 @@ GH_Manager: gh_wait_time: input_number.tts_wait_time gh_select_media_player: input_select.notification_media_player_google ytube_player: media_player.ytube_music_player + + debug_sensor: sensor.centro_notifiche From 3c7ff566b068b1461bc17a3d221cc6b7b40e939e Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 16 Oct 2022 10:39:16 +0200 Subject: [PATCH 21/75] update 16/10 self.set_debug_sensor --- apps/notifier/notifier_dispatch.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/notifier/notifier_dispatch.py b/apps/notifier/notifier_dispatch.py index 1392b0c..c6e72b3 100644 --- a/apps/notifier/notifier_dispatch.py +++ b/apps/notifier/notifier_dispatch.py @@ -79,6 +79,12 @@ def check_notify(self, data): def convert(self, lst): return {lst[1]: lst[3]} + def set_debug_sensor(self, state, error): + attributes = {} + attributes["icon"] = "mdi:wrench" + attributes["dispatch_error"] = error + self.set_state(self.debug_sensor, state=state, attributes=attributes) + def createTTSdict(self, data) -> list: dizionario = "" if data == "" or (not self.check_notify(data)): @@ -183,14 +189,14 @@ def notify_hub(self, event_name, data, kwargs): self.notification_manager.send_persistent(data, self.persistent_notification_info) except Exception as ex: self.log("An error occurred in persistent notification: {}".format(ex), level="ERROR") - self.set_state(self.sensor, state="Error in Persistent Notification: {}".format(ex)) + self.set_debug_sensor("Error in Persistent Notification: ", ex) self.log(sys.exc_info()) if useNotification: try: self.notification_manager.send_notify(data, notify_name, self.get_state(self.personal_assistant_name)) except Exception as ex: self.log("An error occurred in text-telegram notification: {}".format(ex), level="ERROR") - self.set_state(self.sensor, state="Error in Text Notification: {}".format(ex)) + self.set_debug_sensor("Error in Text Notification: ", ex) self.log(sys.exc_info()) if useTTS: if gh_switch == "on" and google_flag: @@ -225,7 +231,7 @@ def notify_hub(self, event_name, data, kwargs): self.phone_manager.send_voice_call(data, phone_notify_name, self.phone_sip_server, language) except Exception as ex: self.log("An error occurred in phone notification: {}".format(ex), level="ERROR") - self.set_state(self.sensor, state="Error in Phone Notification: {}".format(ex)) + self.set_debug_sensor("Error in Phone Notification: ", ex)) self.log(sys.exc_info()) ### ripristino del priority a OFF if self.get_state(self.priority_message) == "on": From 1fb095a13800013c759036377fd6c6f0ea86f2c4 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 16 Oct 2022 10:40:18 +0200 Subject: [PATCH 22/75] update 16/10 --- apps/notifier/notifier_dispatch.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/notifier/notifier_dispatch.yaml b/apps/notifier/notifier_dispatch.yaml index 4333fdb..390e900 100644 --- a/apps/notifier/notifier_dispatch.yaml +++ b/apps/notifier/notifier_dispatch.yaml @@ -38,7 +38,7 @@ Notifier_Dispatch: notify_alexa: secret_notify_alexa sip_server: secret_sip_server - sensor: sensor.centro_notifiche + debug_sensor: sensor.centro_notifiche dependencies: - Notification_Manager From 0485c20b6af3eeeec646b40ca6a72727926b9add Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 16 Oct 2022 10:42:27 +0200 Subject: [PATCH 23/75] update 16/10 --- apps/notifier/gh_manager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/notifier/gh_manager.py b/apps/notifier/gh_manager.py index fbd532a..ab46037 100644 --- a/apps/notifier/gh_manager.py +++ b/apps/notifier/gh_manager.py @@ -110,7 +110,7 @@ def has_numbers(self, string): def set_debug_sensor(self, state, error): attributes = {} attributes["icon"] = "mdi:google" - attributes["Error"] = error + attributes["google_error"] = error self.set_state(self.debug_sensor, state=state, attributes=attributes) def check_gh(self, service): @@ -200,7 +200,7 @@ def worker(self): except Exception as ex: self.log("An error occurred in GH Manager - Errore nel Worker: {}".format(ex),level="ERROR") self.log(sys.exc_info()) - self.set_debug_sensor("GH Manager -Worker Error ", ex) + self.set_debug_sensor("GH Manager - Worker Error ", ex) self.queue.task_done() @@ -250,6 +250,6 @@ def worker(self): except: self.log("An error occurred in GH Manager - Errore nel CallBack", level="ERROR") self.log(sys.exc_info()) - self.set_debug_sensor("GH Manager - CallBack Error ", ex) + self.set_debug_sensor("GH Manager - CallBack Error ", ex) pass # Nothing in queue From f2acdde69b8106ade0e0c6c28e3a4e37f0112d52 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 16 Oct 2022 10:48:23 +0200 Subject: [PATCH 24/75] update 16/10 change set_sensor in set_debug_sensor --- apps/notifier/alexa_manager.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/notifier/alexa_manager.py b/apps/notifier/alexa_manager.py index 2d70b40..f6a4294 100755 --- a/apps/notifier/alexa_manager.py +++ b/apps/notifier/alexa_manager.py @@ -287,7 +287,7 @@ def initialize(self) -> None: def speak(self, alexa, skill_id): #### NEW ### """Speak the provided text through the media player.""" if not self.cehck_alexa_service: - self.set_sensor( + self.set_debug_sensor( "I can't find the Alexa Media component", "https://github.com/custom-components/alexa_media_player" ) return @@ -480,10 +480,10 @@ def has_numbers(self, string): numbers = re.compile("\d{4,}|\d{3,}\.\d") return numbers.search(string) - def set_sensor(self, state, error): + def set_debug_sensor(self, state, error): attributes = {} attributes["icon"] = "mdi:amazon-alexa" - attributes["Error"] = error + attributes["alexa_error"] = error self.set_state("sensor.centro_notifiche", state=state, attributes=attributes) def when_tts_done_do(self, callback: callable) -> None: @@ -578,7 +578,7 @@ def worker(self): except Exception as ex: self.log("An error occurred in Alexa Manager (worker): {}".format(ex), level="ERROR") self.log(f"DATA: {data}", level="ERROR") - self.set_sensor("Alexa Manager - Worker Error ", ex) + self.set_debug_sensor("Alexa Manager - Worker Error ", ex) self.queue.task_done() if self.queue.qsize() == 0: @@ -590,7 +590,7 @@ def worker(self): self._when_tts_done_callback_queue.task_done() except: self.log("Errore nel CallBack", level="ERROR") - self.set_sensor("Alexa Manager - CallBack Error ", ex) + self.set_debug_sensor("Alexa Manager - CallBack Error ", ex) pass # Nothing in queue self.lg("---------------------------------------------------------\n") From 15e0ba02c9180fe8ca3341d4d8c4ceade56d9143 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 16 Oct 2022 10:51:54 +0200 Subject: [PATCH 25/75] Update 16/10 change in set_sensor --> set_debug_sensor --- apps/notifier/alexa_manager.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/notifier/alexa_manager.py b/apps/notifier/alexa_manager.py index f6a4294..a6bbfb3 100755 --- a/apps/notifier/alexa_manager.py +++ b/apps/notifier/alexa_manager.py @@ -276,6 +276,8 @@ def initialize(self) -> None: self.prosody = self.args.get("prosody") self.wait_time = self.args.get("wait_time") self.cehck_alexa_service = self._check_alexa(self.alexa_service) + self.debug_sensor = self.args.get("debug_sensor") + self.set_state(self.debug_sensor, state="on") self.queue = Queue(maxsize=0) self._when_tts_done_callback_queue = Queue() @@ -484,7 +486,7 @@ def set_debug_sensor(self, state, error): attributes = {} attributes["icon"] = "mdi:amazon-alexa" attributes["alexa_error"] = error - self.set_state("sensor.centro_notifiche", state=state, attributes=attributes) + self.set_state(self.debug_sensor, state=state, attributes=attributes) def when_tts_done_do(self, callback: callable) -> None: """Callback when the queue of tts messages are done.""" From f409eaa355db1381bf95e3697105f4d3c91fdf8a Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 16 Oct 2022 10:53:56 +0200 Subject: [PATCH 26/75] update 16/10 change in set_sensor --> set_debug_sensor --- apps/notifier/alexa_manager.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/notifier/alexa_manager.yaml b/apps/notifier/alexa_manager.yaml index 4803bf7..591af7f 100755 --- a/apps/notifier/alexa_manager.yaml +++ b/apps/notifier/alexa_manager.yaml @@ -24,4 +24,7 @@ Alexa_Manager: # Main hub default_restore_volume: input_number.default_restore_volume - wait_time: input_number.tts_wait_time + wait_time: input_number.tts_wait_timec + + # Debug Sensor + debug_sensor: sensor.centro_notifiche From e422bd9057209bdd8f678479fac4859aff802c72 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 16 Oct 2022 10:54:55 +0200 Subject: [PATCH 27/75] Update 16/10 --- apps/notifier/gh_manager.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/notifier/gh_manager.yaml b/apps/notifier/gh_manager.yaml index bfd11ff..be15f46 100644 --- a/apps/notifier/gh_manager.yaml +++ b/apps/notifier/gh_manager.yaml @@ -8,4 +8,9 @@ GH_Manager: gh_select_media_player: input_select.notification_media_player_google ytube_player: media_player.ytube_music_player + # Main hub + gh_restore_volume: input_number.default_restore_volume + gh_wait_time: input_number.tts_wait_time + + # Debug Sensor debug_sensor: sensor.centro_notifiche From cb6b8ad82024941cd29a9ac8a4167ab51a988491 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 16 Oct 2022 11:31:24 +0200 Subject: [PATCH 28/75] update 16/10 --- apps/notifier/notifier_dispatch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/notifier/notifier_dispatch.py b/apps/notifier/notifier_dispatch.py index 9d78819..28fa6fc 100644 --- a/apps/notifier/notifier_dispatch.py +++ b/apps/notifier/notifier_dispatch.py @@ -42,7 +42,7 @@ def initialize(self): self.personal_assistant_name = self.args.get("personal_assistant_name") self.phone_called_number = self.args.get("phone_called_number") - self.sensor = self.args.get("sensor") + self.sensor = self.args.get("debug_sensor") self.set_state(self.sensor, state="on") #### FROM SECRET FILE ### config = self.get_plugin_config() From 868f008c6700e219982e0ec81e9f66853fc14091 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 16 Oct 2022 11:35:40 +0200 Subject: [PATCH 29/75] update 16/10 --- apps/notifier/notifier_dispatch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/notifier/notifier_dispatch.py b/apps/notifier/notifier_dispatch.py index 28fa6fc..adf2880 100644 --- a/apps/notifier/notifier_dispatch.py +++ b/apps/notifier/notifier_dispatch.py @@ -231,7 +231,7 @@ def notify_hub(self, event_name, data, kwargs): self.phone_manager.send_voice_call(data, phone_notify_name, self.phone_sip_server, language) except Exception as ex: self.log("An error occurred in phone notification: {}".format(ex), level="ERROR") - self.set_debug_sensor("Error in Phone Notification: ", ex)) + self.set_debug_sensor("Error in Phone Notification: ", ex) self.log(sys.exc_info()) ### ripristino del priority a OFF if self.get_state(self.priority_message) == "on": From 0ec36c2c664d90ebc85540991860d431e62921a5 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Tue, 18 Oct 2022 17:56:55 +0200 Subject: [PATCH 30/75] Update alexa_manager.yaml --- apps/notifier/alexa_manager.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/notifier/alexa_manager.yaml b/apps/notifier/alexa_manager.yaml index 591af7f..5544ecd 100755 --- a/apps/notifier/alexa_manager.yaml +++ b/apps/notifier/alexa_manager.yaml @@ -24,7 +24,7 @@ Alexa_Manager: # Main hub default_restore_volume: input_number.default_restore_volume - wait_time: input_number.tts_wait_timec + wait_time: input_number.tts_wait_time # Debug Sensor debug_sensor: sensor.centro_notifiche From 7619e761e1413565f2ca70ae3697499c6ffc6cfe Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sat, 22 Oct 2022 12:15:32 +0200 Subject: [PATCH 31/75] Update gh_manager.yaml --- apps/notifier/gh_manager.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/notifier/gh_manager.yaml b/apps/notifier/gh_manager.yaml index be15f46..277e0db 100644 --- a/apps/notifier/gh_manager.yaml +++ b/apps/notifier/gh_manager.yaml @@ -3,14 +3,12 @@ GH_Manager: class: GH_Manager gh_service: tts.google - gh_restore_volume: input_number.default_restore_volume - gh_wait_time: input_number.tts_wait_time - gh_select_media_player: input_select.notification_media_player_google ytube_player: media_player.ytube_music_player # Main hub gh_restore_volume: input_number.default_restore_volume gh_wait_time: input_number.tts_wait_time + gh_select_media_player: input_select.notification_media_player_google # Debug Sensor debug_sensor: sensor.centro_notifiche From ef12c90d24a374861bcee4ddacee3bab09db5277 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Tue, 25 Oct 2022 19:08:06 +0200 Subject: [PATCH 32/75] Create helpermodule.py --- apps/notifier/helpermodule.py | 74 +++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 apps/notifier/helpermodule.py diff --git a/apps/notifier/helpermodule.py b/apps/notifier/helpermodule.py new file mode 100644 index 0000000..f37ba95 --- /dev/null +++ b/apps/notifier/helpermodule.py @@ -0,0 +1,74 @@ +'''Miscellaneous support functions for notifier''' +import re + +def check_location(data, location)->bool: + return (str(data).lower() =="" or str(data).lower()==location) + +def check_notify(data)->bool: + return False if (str(data).lower() in ["false","off","no"] or data == "0" or data == 0) else True + +def convert(lst): + return {lst[1]: lst[3]} + +# check if is true +def check_boolean(value)->bool: + return str(value).lower() in ["true", "on", "yes", "1"] + +def get_arg(args, key): + key = args[key] + if type(key) is str and key.startswith("secret_"): + if key in secret_dict: + return secret_dict[key] + else: + raise KeyError("Could not find {} in secret_dict".format(key)) + else: + return key + +def get_arg_list(args, key): + arg_list = [] + if isinstance(args[key], list): + arg = args[key] + else: + arg = (args[key]).split(",") + for key in arg: + if type(key) is str and key.startswith("secret_"): + if key in secrets.secret_dict: + arg_list.append(secrets.secret_dict[key]) + else: + raise KeyError("Could not find {} in secret_dict".format(key)) + else: + arg_list.append(key) + return arg_list + +def lg(message): + self.log(message, level="DEBUG", ascii_encode=False) + +# """Remove a key from a dict.""" +def remove_key(d, key)->dict: + r = dict(d) + del r[key] + return r + +# """check if is an array """ +def check_array(target): + if isinstance(target, list): + return target + else: + return list(target.replace(" ","").split(",")) + +def replace_regular(text: str, substitutions: list)->str: + for old,new in substitutions: + text = re.sub(old, new, text.strip()) + return text + +def replace_language(s: str)->str: + return (s[:2]) + +# """Remove all tags from a string.""" +def remove_tags(text: str)->str: + regex = re.compile("<.*?>") + return re.sub(regex, "", str(text).strip()) + +def has_numbers(string): + numbers = re.compile("\d{4,}|\d{3,}\.\d") + return numbers.search(string) From 3376543eed778548ea5f478e1badcf7bf460ce7f Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Tue, 25 Oct 2022 19:11:21 +0200 Subject: [PATCH 33/75] dev 25/10 --- apps/notifier/notifier_dispatch.py | 138 ++++++++++++----------------- 1 file changed, 56 insertions(+), 82 deletions(-) diff --git a/apps/notifier/notifier_dispatch.py b/apps/notifier/notifier_dispatch.py index adf2880..11f30c9 100644 --- a/apps/notifier/notifier_dispatch.py +++ b/apps/notifier/notifier_dispatch.py @@ -1,49 +1,45 @@ -import sys - import hassapi as hass -import yaml - +import sys +import helpermodule as h # # Centralizes messaging. # # Args: # -# Version 2022.10: +# Version 1.0: # Initial Version - class Notifier_Dispatch(hass.Hass): def initialize(self): - self.gh_tts_google_mode = self.args.get("gh_tts_google_mode") - self.gh_switch_entity = self.args.get("gh_switch") - self.gh_selected_media_player = self.args.get("gh_selected_media_player") + self.gh_tts_google_mode = h.get_arg(self.args, "gh_tts_google_mode") + self.gh_switch_entity = h.get_arg(self.args, "gh_switch") - self.alexa_switch_entity = self.args.get("alexa_switch") + self.alexa_switch_entity = h.get_arg(self.args, "alexa_switch") - self.tts_language = self.args.get("tts_language") - self.tts_period_of_day_volume = self.args.get("tts_period_of_day_volume") - self.tts_dnd = self.args.get("dnd") + self.tts_language = h.get_arg(self.args, "tts_language") + self.tts_period_of_day_volume = h.get_arg(self.args, "tts_period_of_day_volume") + self.tts_dnd = h.get_arg(self.args, "dnd") - self.text_notifications = self.args.get("text_notifications") - self.screen_notifications = self.args.get("screen_notifications") - self.speech_notifications = self.args.get("speech_notifications") - self.phone_notifications = self.args.get("phone_notifications") + self.text_notifications = h.get_arg(self.args, "text_notifications") + self.screen_notifications = h.get_arg(self.args, "screen_notifications") + self.speech_notifications = h.get_arg(self.args, "speech_notifications") + self.phone_notifications = h.get_arg(self.args, "phone_notifications") - self.html_mode = self.args.get("html_mode") + self.html_mode = h.get_arg(self.args, "html_mode") - self.text_notify = self.args.get("text_notify") - self.phone_notify = self.args.get("phone_notify") - self.priority_message = self.args.get("priority_message") - self.guest_mode = self.args.get("guest_mode") + self.text_notify = h.get_arg(self.args, "text_notify") + self.phone_notify = h.get_arg(self.args, "phone_notify") + self.priority_message = h.get_arg(self.args, "priority_message") + self.guest_mode = h.get_arg(self.args, "guest_mode") - self.persistent_notification_info = self.args.get("persistent_notification_info") + self.persistent_notification_info = h.get_arg(self.args, "persistent_notification_info") - self.location_tracker = self.args.get("location_tracker") - self.personal_assistant_name = self.args.get("personal_assistant_name") - self.phone_called_number = self.args.get("phone_called_number") + self.location_tracker = h.get_arg(self.args, "location_tracker") + self.personal_assistant_name = h.get_arg(self.args, "personal_assistant_name") + self.phone_called_number = h.get_arg(self.args, "phone_called_number") - self.sensor = self.args.get("debug_sensor") - self.set_state(self.sensor, state="on") + self.debug_sensor = h.get_arg(self.args, "debug_sensor") + self.set_state(self.debug_sensor, state="on") #### FROM SECRET FILE ### config = self.get_plugin_config() config_dir = config["config_dir"] @@ -66,64 +62,49 @@ def initialize(self): ### LISTEN EVENT ### self.listen_event(self.notify_hub, "hub") - ##################################################################### - def check_flag(self, data): - return str(data).lower() in ["1", "true", "on", "yes"] - - def check_location(self, data, location): - return str(data).lower() == "" or str(data).lower() == location - - def check_notify(self, data): - return False if (str(data).lower() in ["false", "off", "no"] or data == "0" or data == 0) else True - - def convert(self, lst): - return {lst[1]: lst[3]} - +##################################################################### def set_debug_sensor(self, state, error): attributes = {} attributes["icon"] = "mdi:wrench" attributes["dispatch_error"] = error self.set_state(self.debug_sensor, state=state, attributes=attributes) - def createTTSdict(self, data) -> list: + def createTTSdict(self,data) -> list: dizionario = "" - if data == "" or (not self.check_notify(data)): + if data == "" or (not h.check_notify(data)): flag = False elif str(data).lower() in ["1","true","on","yes"]: flag = True dizionario = {} else: if "OrderedDict([(" in str(data): - dizionario = self.convert(list(data.split("'"))) + dizionario = h.convert(list(data.split("'"))) if dizionario.get("mode") != None: - flag = self.check_flag(dizionario["mode"]) + flag = h.check_boolean(dizionario["mode"]) else: flag = True else: dizionario = data if isinstance(data, dict) else eval(data) # convert to dict if dizionario.get("mode") != None: - flag = self.check_flag(dizionario["mode"]) + flag = h.check_boolean(dizionario["mode"]) else: flag = True return [flag,dizionario] def notify_hub(self, event_name, data, kwargs): self.log("#### START NOTIFIER_DISPATCH ####") - location_status = self.get_state(self.location_tracker) ### FLAG - priority_flag = self.check_flag(data["priority"]) - noshow_flag = self.check_flag(data["no_show"]) - location_flag = self.check_location(data["location"], location_status) - notify_flag = self.check_notify(data["notify"]) - + priority_flag = h.check_boolean(data["priority"]) + noshow_flag = h.check_boolean(data["no_show"]) + location_flag = h.check_location(data["location"],location_status) + notify_flag = h.check_notify(data["notify"]) ### GOOGLE #### google_flag = self.createTTSdict(data["google"])[0] if len(str(data["google"])) != 0 else False google = self.createTTSdict(data["google"])[1] if len(str(data["google"])) != 0 else False ### ALEXA #### alexa_flag = self.createTTSdict(data["alexa"])[0] if len(str(data["alexa"])) != 0 else False alexa = self.createTTSdict(data["alexa"])[1] if len(str(data["alexa"])) != 0 else False - ### FROM INPUT BOOLEAN ### dnd_status = self.get_state(self.tts_dnd) guest_status = self.get_state(self.guest_mode) @@ -134,34 +115,28 @@ def notify_hub(self, event_name, data, kwargs): ### NOTIFICATION ### if priority_status: useNotification = True - elif ( - self.get_state(self.text_notifications) == "on" and data["message"] != "" and notify_flag and location_flag - ): + elif self.get_state(self.text_notifications) == "on" and data["message"] !="" and notify_flag and location_flag: useNotification = True else: useNotification = False ### PERSISTENT ### if priority_status: usePersistentNotification = True - elif self.get_state(self.screen_notifications) == "on" and data["message"] != "" and not noshow_flag: + elif self.get_state(self.screen_notifications) == "on" and data["message"] !="" and not noshow_flag: usePersistentNotification = True else: usePersistentNotification = False ### TTS ### if priority_status: useTTS = True - elif ( - self.get_state(self.speech_notifications) == "on" - and dnd_status == "off" - and (location_status == "home" or guest_status == "on") - ): + elif self.get_state(self.speech_notifications) == "on" and dnd_status == "off" and (location_status == "home" or guest_status == "on"): useTTS = True else: useTTS = False ### PHONE ### if priority_status: usePhone = True - elif self.get_state(self.phone_notifications) == "on" and data["message"] != "" and dnd_status == "off": + elif self.get_state(self.phone_notifications) == "on" and data["message"] !="" and dnd_status == "off": usePhone = True else: usePhone = False @@ -188,51 +163,50 @@ def notify_hub(self, event_name, data, kwargs): try: self.notification_manager.send_persistent(data, self.persistent_notification_info) except Exception as ex: - self.log("An error occurred in persistent notification: {}".format(ex), level="ERROR") + self.log("An error occurred in persistent notification: {}".format(ex),level="ERROR") self.set_debug_sensor("Error in Persistent Notification: ", ex) - self.log(sys.exc_info()) + self.log(sys.exc_info()) if useNotification: try: self.notification_manager.send_notify(data, notify_name, self.get_state(self.personal_assistant_name)) except Exception as ex: - self.log("An error occurred in text-telegram notification: {}".format(ex), level="ERROR") + self.log("An error occurred in text notification: {}".format(ex), level="ERROR") self.set_debug_sensor("Error in Text Notification: ", ex) self.log(sys.exc_info()) if useTTS: if gh_switch == "on" and google_flag: if (data["google"]) != "": - if "media_player" not in google: - google["media_player"] = self.get_state(self.gh_selected_media_player) + if "message" not in google: + google["message"] = data["message"] if "volume" not in google: - google["volume"] = float(self.get_state(self.tts_period_of_day_volume)) / 100 + google["volume"] = float(self.get_state(self.tts_period_of_day_volume))/100 + if "language" not in google: + google["language"] = self.get_state(self.tts_language).lower() if "media_content_id" not in google: google["media_content_id"] = "" if "media_content_type" not in google: google["media_content_type"] = "" - if "message" not in google: - google["message"] = data["message"] - if "language" not in google: - google["language"] = self.get_state(self.tts_language).lower() self.gh_manager.speak(google, self.get_state(self.gh_tts_google_mode), gh_notifica) if alexa_switch == "on" and alexa_flag: if (data["alexa"]) != "": - if "message" not in alexa: + if "message" not in alexa: alexa["message"] = data["message"] - if "title" not in alexa: + if "title" not in alexa: alexa["title"] = data["title"] if "volume" not in alexa: - alexa["volume"] = float(self.get_state(self.tts_period_of_day_volume)) / 100 - if "language" not in alexa: - alexa["language"] = self.get_state(self.tts_language) - self.alexa_manager.speak(alexa, self.alexa_skill_id) + alexa["volume"] = self.get_state(self.tts_period_of_day_volume) + if "language" not in alexa: + alexa["language"] = self.get_state(self.tts_language) + self.alexa_manager.speak(alexa) if usePhone: try: language = self.get_state(self.tts_language) self.phone_manager.send_voice_call(data, phone_notify_name, self.phone_sip_server, language) except Exception as ex: - self.log("An error occurred in phone notification: {}".format(ex), level="ERROR") + self.log("An error occurred in phone notification: {}".format(ex),level="ERROR") self.set_debug_sensor("Error in Phone Notification: ", ex) self.log(sys.exc_info()) + ### ripristino del priority a OFF - if self.get_state(self.priority_message) == "on": - self.set_state(self.priority_message, state="off") + if (self.get_state(self.priority_message) == "on"): + self.set_state(self.priority_message, state = "off") From 1d4306b0e467d0f72db96597ffae42bcd9f6d804 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Tue, 25 Oct 2022 19:13:01 +0200 Subject: [PATCH 34/75] dev 25/10 --- apps/notifier/notifier_dispatch.yaml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/apps/notifier/notifier_dispatch.yaml b/apps/notifier/notifier_dispatch.yaml index 390e900..996355c 100644 --- a/apps/notifier/notifier_dispatch.yaml +++ b/apps/notifier/notifier_dispatch.yaml @@ -31,13 +31,6 @@ Notifier_Dispatch: personal_assistant_name: input_text.personal_assistant_name phone_called_number: input_text.phone_called_number - tts_google: secret_tts_google - tts_google_cloud: secret_tts_google_cloud - reverso_tts: secret_reverso_tts - notify_google: secret_notify_google - notify_alexa: secret_notify_alexa - sip_server: secret_sip_server - debug_sensor: sensor.centro_notifiche dependencies: From 961a115bf5512d273c148d2bfb1175a8e265d817 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Tue, 25 Oct 2022 19:18:25 +0200 Subject: [PATCH 35/75] dev 25/10 --- apps/notifier/gh_manager.py | 50 +++++++++++++------------------------ 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/apps/notifier/gh_manager.py b/apps/notifier/gh_manager.py index ab46037..23b8c10 100644 --- a/apps/notifier/gh_manager.py +++ b/apps/notifier/gh_manager.py @@ -1,12 +1,11 @@ import hassapi as hass import time import datetime -import re import sys from queue import Queue from threading import Thread - -#from threading import Event +# +import helpermodule as h """ Class TTS Manager handles sending text to speech messages to media players @@ -32,13 +31,13 @@ class GH_Manager(hass.Hass): def initialize(self)->None: - #self.gh_wait_time = globals.get_arg(self.args, "gh_wait_time") - self.gh_service = self.args.get("gh_service") - self.gh_wait_time = self.args["gh_wait_time"] - self.gh_select_media_player = self.args["gh_select_media_player"] - self.ytube_player = self.args["gh_select_media_player"] + self.gh_service = h.get_arg(self.args, "gh_service") + self.gh_wait_time = h.get_arg(self.args, "gh_wait_time") + self.gh_select_media_player = h.get_arg(self.args, "gh_select_media_player") + self.gh_sensor_media_player = h.get_arg(self.args, "gh_sensor_media_player") + self.ytube_player = h.get_arg(self.args, "ytube_player") self.ytube_called = False - self.debug_sensor = self.args.get("debug_sensor") + self.debug_sensor = h.get_arg(self.args, "debug_sensor") self.set_state(self.debug_sensor, state="on") self.check_gh_service = self.check_gh(self.gh_service) # @@ -90,23 +89,6 @@ def mediastate_get(self, media_player:list, volume: float): self.dict_info_mplayer[i]['authSig'] = self.get_state(i, attribute="authSig", default='') return self.dict_info_mplayer - def replace_regular(self, text: str, substitutions: list): - for old,new in substitutions: - text = re.sub(old, new, str(text).strip()) - return text - - def replace_language(self, s: str): - return (s[:2]) - - def remove_tags(self, text: str): - """Remove all tags from a string.""" - regex = re.compile("<.*?>") - return re.sub(regex, "", str(text).strip()) - - def has_numbers(self, string): - numbers = re.compile("\d{4,}|\d{3,}\.\d") - return numbers.search(string) - def set_debug_sensor(self, state, error): attributes = {} attributes["icon"] = "mdi:google" @@ -126,12 +108,15 @@ def speak(self, google, gh_mode: bool, gh_notifier: str): "I can't find the TTS Google component", "https://www.home-assistant.io/integrations/tts" ) return + if "media_player" not in google: + google["media_player"] = self.get_state(self.gh_sensor_media_player) + ### gh_player = self.check_mplayer(self.split_device_list(google["media_player"])) gh_volume = self.check_volume(self.get_state(self.gh_select_media_player, attribute="options")) self.volume_get(gh_volume,float(self.get_state(self.args["gh_restore_volume"]))/100) self.mediastate_get(gh_volume,float(self.get_state(self.args["gh_restore_volume"]))/100) wait_time = float(self.get_state(self.gh_wait_time)) - message = self.replace_regular(google["message"], SUB_TTS) + message = h.replace_regular(google["message"], SUB_TTS) ### set volume self.volume_set(gh_player,google["volume"]) # queues the message to be handled async, use when_tts_done_do method to supply callback when tts is done @@ -144,7 +129,7 @@ def speak(self, google, gh_mode: bool, gh_notifier: str): self.set_debug_sensor("GH Manager - media_content Error ", ex) self.log(sys.exc_info()) else: - self.queue.put({"type": "tts", "text": message, "volume": google["volume"], "language": self.replace_language(google["language"]), + self.queue.put({"type": "tts", "text": message, "volume": google["volume"], "language": h.replace_language(google["language"]), "gh_player": google["media_player"], "wait_time": wait_time, "gh_mode": gh_mode, "gh_notifier": gh_notifier}) def when_tts_done_do(self, callback:callable)->None: @@ -172,11 +157,11 @@ def worker(self): time.sleep(1) #self.volume_set(entity,data["volume"]) ##### Speech time calculator ##### - message_clean = self.replace_regular(data["text"], SUB_VOICE) - words = len(self.remove_tags(message_clean).split()) - chars = self.remove_tags(message_clean).count("") + message_clean = h.replace_regular(data["text"], SUB_VOICE) + words = len(h.remove_tags(message_clean).split()) + chars = h.remove_tags(message_clean).count("") duration = (words * 0.007) * 60 - if self.has_numbers(message_clean): + if h.has_numbers(message_clean): duration = 4 if (chars / words) > 7 and chars > 90: duration = 7 @@ -252,4 +237,3 @@ def worker(self): self.log(sys.exc_info()) self.set_debug_sensor("GH Manager - CallBack Error ", ex) pass # Nothing in queue - From 9f43a354bdd52a32d747eb7d4e7e512df77faa66 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Tue, 25 Oct 2022 19:23:16 +0200 Subject: [PATCH 36/75] dev 25/10 --- apps/notifier/notification_manager.py | 97 ++++++++++++++------------- 1 file changed, 51 insertions(+), 46 deletions(-) diff --git a/apps/notifier/notification_manager.py b/apps/notifier/notification_manager.py index be76853..9aa8c5c 100644 --- a/apps/notifier/notification_manager.py +++ b/apps/notifier/notification_manager.py @@ -1,6 +1,7 @@ import hassapi as hass import datetime -import re +# +import helpermodule as h """ Class Notification_Manager handles sending text to notfyng service @@ -14,28 +15,23 @@ class Notification_Manager(hass.Hass): def initialize(self): #self.text_last_message = globals.get_arg(self.args, "text_last_message") - self.text_last_message = self.args["text_last_message"] - self.boolean_wrap_text = self.args["boolean_wrap_text"] - self.boolean_tts_clock = self.args["boolean_tts_clock"] + self.text_last_message = h.get_arg(self.args, "text_last_message") + self.boolean_wrap_text = h.get_arg(self.args, "boolean_wrap_text") + self.boolean_tts_clock = h.get_arg(self.args, "boolean_tts_clock") def prepare_text(self, html, message, title, timestamp, assistant_name): if str(html).lower() in ["true","on","yes","1"]: title = ("[{} - {}] {}".format(assistant_name, timestamp, title)) - title = self.replace_regular(title,[("\s<","<")]) + title = h.replace_regular(title,[("\s<","<")]) else: title = ("*[{} - {}] {}*".format(assistant_name, timestamp, title)) - title = self.replace_regular(title,[("\s\*","*")]) + title = h.replace_regular(title,[("\s\*","*")]) if self.get_state(self.boolean_wrap_text) == 'on': - message = self.replace_regular(message, SUB_NOTIFICHE_WRAP) + message = h.replace_regular(message, SUB_NOTIFICHE_WRAP) else: - message = self.replace_regular(message, SUB_NOTIFICHE_NOWRAP) + message = h.replace_regular(message, SUB_NOTIFICHE_NOWRAP) return message, title - def removekey(self, d, key): - r = dict(d) - del r[key] - return r - def check_notifier(self, notifier, notify_name): notifier_list = [] notify_name_list = [] @@ -58,49 +54,53 @@ def send_notify(self, data, notify_name, assistant_name: str): timestamp = datetime.datetime.now().strftime("%H:%M:%S") title = data["title"] message = data["message"] - inline = data["inline"] + target = data["target"] image = data["image"] caption = data["caption"] link = data["link"] html = data["html"] priority = data["priority"] + telegram = data["telegram"] pushover = data["pushover"] mobile = data["mobile"] - whatsapp_addon = data["whatsapp"] discord = data["discord"] - notify_vector = self.check_notifier(self.split_device_list(str(data["notify"])),self.split_device_list(str(notify_name))) + whatsapp_addon = data["whatsapp"] + notify_vector = self.check_notifier(h.check_array(data["notify"]),self.split_device_list(str(notify_name))) + ## target ## + if target !='': + target_vector = h.check_array(target) ########## SAVE IN INPUT_TEXT ########### self.set_state(self.text_last_message, state = message[:245]) ######################################### for item in notify_vector: if item.find("notify.") == -1: - item = __NOTIFY__ + str(self.replace_regular(item,SUB_NOTIFIER)).lower() + item = __NOTIFY__ + str(h.replace_regular(item,SUB_NOTIFIER)).lower() else: - item = str(self.replace_regular(item,SUB_NOTIFIER)).lower() + item = str(h.replace_regular(item,SUB_NOTIFIER)).lower() #### TELEGRAM ####################### if item.find("telegram") != -1: messaggio, titolo = self.prepare_text(html, message, title, timestamp, assistant_name) extra_data = {} + if isinstance(telegram, dict): + extra_data = telegram + if caption == "": + caption = ("{}\n{}".format(titolo,messaggio)) + if image != "" and image.find("http") != -1: + url_data = {"url": image, + "caption": caption, + "timeout": 90 + } + extra_data.update({"photo":url_data}) + if image != "" and image.find("http") == -1: + file_data = {"file": image, + "caption": caption, + "timeout": 90 + } + extra_data.update({"photo":file_data}) if str(html).lower() not in ["true","on","yes","1"]: messaggio = messaggio.replace("_","\_") if link !="": messaggio = ("{} {}".format(messaggio,link)) - if caption == "": - caption = ("{}\n{}".format(titolo,messaggio)) - if image != "" and image.find("http") != -1: - extra_data = { "photo": - {"url": image, - "caption": caption, - "timeout": 90} - } - if image != "" and image.find("http") == -1: - extra_data = { "photo": - {"file": image, - "caption": caption, - "timeout": 90} - } - if inline !="": - extra_data.update({"inline_keyboard":inline}) if image != "": self.call_service(item, message = "", data = extra_data) elif extra_data: @@ -140,14 +140,19 @@ def send_notify(self, data, notify_name, assistant_name: str): titolo = titolo.replace("*","") extra_data = {} if isinstance(pushover, dict): + extra_data = pushover if image != "" and image.find("http") != -1: extra_data.update({"url":image}) if image != "" and image.find("http") == -1: extra_data.update({"attachment":image}) if priority != "": extra_data.update({"priority":priority}) - if extra_data: + if extra_data and target_vector: + self.call_service( item, message = messaggio, title = titolo, data = extra_data, target = target_vector) + elif extra_data: self.call_service( item, message = messaggio, title = titolo, data = extra_data) + elif target_vector: + self.call_service( item, message = messaggio, title = titolo, target = target_vector) else: self.call_service( item, message = messaggio, title = titolo) #### PUSHBULLET ##################### @@ -157,12 +162,18 @@ def send_notify(self, data, notify_name, assistant_name: str): extra_data = {} if link !="": messaggio = ("{} {}".format(messaggio,link)) + if image != "" and image.find("http") != -1 and image.find(".") != -1: + extra_data.update({"file_url": image}) if image != "" and image.find("http") != -1: extra_data.update({"url": image}) if image != "" and image.find("http") == -1: extra_data.update({"file": image}) - if extra_data: + if extra_data and target_vector: + self.call_service( item, message = messaggio, title = titolo, data = extra_data, target = target_vector) + elif extra_data: self.call_service( item, message = messaggio, title = titolo, data = extra_data) + elif target_vector: + self.call_service( item, message = messaggio, title = titolo, target = target_vector) else: self.call_service( item, message = messaggio, title = titolo) #### DISCORD ######################## @@ -187,7 +198,6 @@ def send_notify(self, data, notify_name, assistant_name: str): self.call_service( item, message = messaggio, data = extra_data) else: self.call_service( item, message = messaggio) - #self.call_service( item, message = messaggio) #### MAIL ########################### elif item.find("mail") != -1: messaggio, titolo = self.prepare_text(html, message, title, timestamp, assistant_name) @@ -205,10 +215,10 @@ def send_notify(self, data, notify_name, assistant_name: str): if "tts" in mobile: if str(mobile.get("tts")).lower() in ["true","on","yes","1"]: tts_flag = True - extra_data = self.removekey(mobile,"tts") + extra_data = h.remove_key(mobile,"tts") else: tts_flag = False - extra_data = self.removekey(mobile,"tts") + extra_data = h.remove_key(mobile,"tts") else: extra_data = mobile if image != "": @@ -262,16 +272,11 @@ def send_persistent(self, data, persistent_notification_info): except: per_not_info = "null" if self.get_state(self.boolean_wrap_text) == 'on': - messaggio = self.replace_regular(data["message"], SUB_NOTIFICHE_WRAP) + messaggio = h.replace_regular(data["message"], SUB_NOTIFICHE_WRAP) else: - messaggio = self.replace_regular(data["message"], SUB_NOTIFICHE_NOWRAP) + messaggio = h.replace_regular(data["message"], SUB_NOTIFICHE_NOWRAP) messaggio = ("{} - {}".format(timestamp, messaggio)) if per_not_info == "notifying": old_messaggio = self.get_state(persistent_notification_info, attribute="message") messaggio = (old_messaggio + "\n" + messaggio) if len(old_messaggio)<2500 else messaggio self.call_service("persistent_notification/create", notification_id = "info_messages", message = messaggio, title = "Centro Messaggi" ) - - def replace_regular(self, text: str, substitutions: list): - for old,new in substitutions: - text = re.sub(old, new, text.strip()) - return text From b756a6017419c6068ba1510131057b44969bc6b7 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Tue, 25 Oct 2022 19:24:37 +0200 Subject: [PATCH 37/75] dev 25/10 --- apps/notifier/phone_manager.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/notifier/phone_manager.py b/apps/notifier/phone_manager.py index 508c514..06d3ec6 100644 --- a/apps/notifier/phone_manager.py +++ b/apps/notifier/phone_manager.py @@ -1,6 +1,7 @@ import hassapi as hass import datetime -import re +# +import helpermodule as h """ Class Phone_Manager handles sending call to voice notfyng service @@ -21,11 +22,6 @@ def initialize(self): "es-ES": "es-ES-Standard-A", } - def replace_regular(self, text: str, substitutions: list): - for old, new in substitutions: - text = re.sub(old, new, text.strip()) - return text - def send_voice_call(self, data, phone_name: str, sip_server_name: str, language: str): message = self.replace_regular(data["message"], SUB_TTS) message_tts = message.replace(" ", "%20") From 0d1b9744d0b7be468ec2c857b774613d244f3c36 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Tue, 25 Oct 2022 19:25:05 +0200 Subject: [PATCH 38/75] dev 25/10 --- apps/notifier/phone_manager.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/notifier/phone_manager.py b/apps/notifier/phone_manager.py index 06d3ec6..3dc2090 100644 --- a/apps/notifier/phone_manager.py +++ b/apps/notifier/phone_manager.py @@ -10,7 +10,6 @@ __NOTIFY__ = "notify/" SUB_TTS = [("[\*\-\[\]_\(\)\{\~\|\}\s]+", " ")] - class Phone_Manager(hass.Hass): def initialize(self): self.dict_lingua = { @@ -26,7 +25,6 @@ def send_voice_call(self, data, phone_name: str, sip_server_name: str, language: message = self.replace_regular(data["message"], SUB_TTS) message_tts = message.replace(" ", "%20") called_number = data["called_number"] - lang = self.dict_lingua.get(language) phone_name = phone_name.lower().replace(" ", "_") if phone_name.find("voip_call") != -1: From afd5dea26220f366ea6cf4cbcbdbbe7d81e9fc3d Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 30 Oct 2022 09:35:52 +0100 Subject: [PATCH 39/75] dev 30/10 --- apps/notifier/notifier_dispatch.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/notifier/notifier_dispatch.py b/apps/notifier/notifier_dispatch.py index 11f30c9..9de9650 100644 --- a/apps/notifier/notifier_dispatch.py +++ b/apps/notifier/notifier_dispatch.py @@ -1,5 +1,6 @@ import hassapi as hass import sys +import yaml import helpermodule as h # # Centralizes messaging. From 4932e6354350945f45a8cfba4226ea3b12022156 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 30 Oct 2022 09:43:26 +0100 Subject: [PATCH 40/75] dev 30/10 --- apps/notifier/gh_manager.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/notifier/gh_manager.yaml b/apps/notifier/gh_manager.yaml index 277e0db..4addfdf 100644 --- a/apps/notifier/gh_manager.yaml +++ b/apps/notifier/gh_manager.yaml @@ -9,6 +9,7 @@ GH_Manager: gh_restore_volume: input_number.default_restore_volume gh_wait_time: input_number.tts_wait_time gh_select_media_player: input_select.notification_media_player_google + gh_sensor_media_player: sensor.media_player_google # Debug Sensor debug_sensor: sensor.centro_notifiche From bd6d757bb32ab6370bf5212f0dca3a6cc2dacfbc Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 30 Oct 2022 17:51:30 +0100 Subject: [PATCH 41/75] dev 30/10 --- apps/notifier/gh_manager.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/notifier/gh_manager.py b/apps/notifier/gh_manager.py index 23b8c10..6a5d7cc 100644 --- a/apps/notifier/gh_manager.py +++ b/apps/notifier/gh_manager.py @@ -35,6 +35,8 @@ def initialize(self)->None: self.gh_wait_time = h.get_arg(self.args, "gh_wait_time") self.gh_select_media_player = h.get_arg(self.args, "gh_select_media_player") self.gh_sensor_media_player = h.get_arg(self.args, "gh_sensor_media_player") + self.tts_language = h.get_arg(self.args, "tts_language") + self.tts_period_of_day_volume = h.get_arg(self.args, "tts_period_of_day_volume") self.ytube_player = h.get_arg(self.args, "ytube_player") self.ytube_called = False self.debug_sensor = h.get_arg(self.args, "debug_sensor") @@ -110,15 +112,19 @@ def speak(self, google, gh_mode: bool, gh_notifier: str): return if "media_player" not in google: google["media_player"] = self.get_state(self.gh_sensor_media_player) + if "volume" not in google: + google["volume"] = float(self.get_state(self.tts_period_of_day_volume))/100 + if "language" not in google: + google["language"] = self.get_state(self.tts_language).lower() + ### + self.volume_set(gh_player,google["volume"]) ### gh_player = self.check_mplayer(self.split_device_list(google["media_player"])) gh_volume = self.check_volume(self.get_state(self.gh_select_media_player, attribute="options")) - self.volume_get(gh_volume,float(self.get_state(self.args["gh_restore_volume"]))/100) - self.mediastate_get(gh_volume,float(self.get_state(self.args["gh_restore_volume"]))/100) + self.volume_get(gh_volume,float(self.get_state(self.args["tts_period_of_day_volume"]))/100) + self.mediastate_get(gh_volume,float(self.get_state(self.args["tts_period_of_day_volume"]))/100) wait_time = float(self.get_state(self.gh_wait_time)) message = h.replace_regular(google["message"], SUB_TTS) - ### set volume - self.volume_set(gh_player,google["volume"]) # queues the message to be handled async, use when_tts_done_do method to supply callback when tts is done if google["media_content_id"] != "": try: From 28616bf6ffd6e7904c4442b31a7294278cd3aafb Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 30 Oct 2022 17:52:47 +0100 Subject: [PATCH 42/75] dev 30/10 --- apps/notifier/gh_manager.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/notifier/gh_manager.yaml b/apps/notifier/gh_manager.yaml index 4addfdf..6372614 100644 --- a/apps/notifier/gh_manager.yaml +++ b/apps/notifier/gh_manager.yaml @@ -6,10 +6,11 @@ GH_Manager: ytube_player: media_player.ytube_music_player # Main hub - gh_restore_volume: input_number.default_restore_volume gh_wait_time: input_number.tts_wait_time gh_select_media_player: input_select.notification_media_player_google gh_sensor_media_player: sensor.media_player_google + tts_period_of_day_volume: sensor.period_of_day_volume + tts_language: input_select.language # Debug Sensor debug_sensor: sensor.centro_notifiche From 71395e448c3b9dc468ea4972263a7f89cd622e55 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 30 Oct 2022 17:54:28 +0100 Subject: [PATCH 43/75] dev 30/10 --- apps/notifier/notification_manager.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/notifier/notification_manager.py b/apps/notifier/notification_manager.py index 9aa8c5c..99c8f18 100644 --- a/apps/notifier/notification_manager.py +++ b/apps/notifier/notification_manager.py @@ -2,7 +2,6 @@ import datetime # import helpermodule as h - """ Class Notification_Manager handles sending text to notfyng service """ @@ -67,6 +66,7 @@ def send_notify(self, data, notify_name, assistant_name: str): whatsapp_addon = data["whatsapp"] notify_vector = self.check_notifier(h.check_array(data["notify"]),self.split_device_list(str(notify_name))) ## target ## + target_vector = [] if target !='': target_vector = h.check_array(target) ########## SAVE IN INPUT_TEXT ########### @@ -192,10 +192,16 @@ def send_notify(self, data, notify_name, assistant_name: str): elif "images" in discord: extra_data = discord messaggio = titolo.replace("*","") + " " + messaggio - if extra_data and "embed" in discord: + if extra_data and "embed" in discord and target_vector: + self.call_service( item, message = "", data = extra_data, target = target_vector) + elif extra_data and "images" in discord and target_vector: + self.call_service( item, message = messaggio, data = extra_data, target = target_vector) + elif extra_data and "embed" in discord: self.call_service( item, message = "", data = extra_data) elif extra_data and "images" in discord: self.call_service( item, message = messaggio, data = extra_data) + elif target_vector: + self.call_service( item, message = messaggio, target = target_vector) else: self.call_service( item, message = messaggio) #### MAIL ########################### From 8d7f1a9e406fc8d2a4e2f2c8aa0199afb101e6f4 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 30 Oct 2022 17:58:45 +0100 Subject: [PATCH 44/75] dev 30/10 --- apps/notifier/notifier_dispatch.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/apps/notifier/notifier_dispatch.py b/apps/notifier/notifier_dispatch.py index 9de9650..3bcf409 100644 --- a/apps/notifier/notifier_dispatch.py +++ b/apps/notifier/notifier_dispatch.py @@ -14,11 +14,8 @@ class Notifier_Dispatch(hass.Hass): def initialize(self): self.gh_tts_google_mode = h.get_arg(self.args, "gh_tts_google_mode") self.gh_switch_entity = h.get_arg(self.args, "gh_switch") - self.alexa_switch_entity = h.get_arg(self.args, "alexa_switch") - self.tts_language = h.get_arg(self.args, "tts_language") - self.tts_period_of_day_volume = h.get_arg(self.args, "tts_period_of_day_volume") self.tts_dnd = h.get_arg(self.args, "dnd") self.text_notifications = h.get_arg(self.args, "text_notifications") @@ -177,12 +174,8 @@ def notify_hub(self, event_name, data, kwargs): if useTTS: if gh_switch == "on" and google_flag: if (data["google"]) != "": - if "message" not in google: + if "message" not in google: google["message"] = data["message"] - if "volume" not in google: - google["volume"] = float(self.get_state(self.tts_period_of_day_volume))/100 - if "language" not in google: - google["language"] = self.get_state(self.tts_language).lower() if "media_content_id" not in google: google["media_content_id"] = "" if "media_content_type" not in google: @@ -194,10 +187,6 @@ def notify_hub(self, event_name, data, kwargs): alexa["message"] = data["message"] if "title" not in alexa: alexa["title"] = data["title"] - if "volume" not in alexa: - alexa["volume"] = self.get_state(self.tts_period_of_day_volume) - if "language" not in alexa: - alexa["language"] = self.get_state(self.tts_language) self.alexa_manager.speak(alexa) if usePhone: try: From 394cbd637c3646815c9f4aae8041a648792ed304 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 30 Oct 2022 18:02:29 +0100 Subject: [PATCH 45/75] dev 30/10 --- apps/notifier/notifier_dispatch.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/notifier/notifier_dispatch.yaml b/apps/notifier/notifier_dispatch.yaml index 996355c..d8364f0 100644 --- a/apps/notifier/notifier_dispatch.yaml +++ b/apps/notifier/notifier_dispatch.yaml @@ -4,13 +4,8 @@ Notifier_Dispatch: gh_tts_google_mode: input_select.tts_notify gh_switch: input_boolean.google_switch - gh_selected_media_player: sensor.media_player_google alexa_switch: input_boolean.alexa_switch - alexa_selected_media_player: sensor.media_player_alexa - - tts_period_of_day_volume: sensor.period_of_day_volume - tts_language: input_select.language text_notifications: input_boolean.text_notifications screen_notifications: input_boolean.screen_notifications From f6f189432d296ee298fd9e4681fdd56c788d1ba8 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 30 Oct 2022 19:20:43 +0100 Subject: [PATCH 46/75] dev 30/10 --- apps/notifier/notifier_dispatch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/notifier/notifier_dispatch.py b/apps/notifier/notifier_dispatch.py index 3bcf409..f34d42b 100644 --- a/apps/notifier/notifier_dispatch.py +++ b/apps/notifier/notifier_dispatch.py @@ -187,7 +187,7 @@ def notify_hub(self, event_name, data, kwargs): alexa["message"] = data["message"] if "title" not in alexa: alexa["title"] = data["title"] - self.alexa_manager.speak(alexa) + self.alexa_manager.speak(alexa, self.alexa_skill_id) if usePhone: try: language = self.get_state(self.tts_language) From 90170de6564ff79d5249d7d5259dbb89df2680e1 Mon Sep 17 00:00:00 2001 From: Gianpiero Date: Sun, 30 Oct 2022 19:23:27 +0100 Subject: [PATCH 47/75] dev 30/10 --- apps/notifier/notification_manager.py | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/apps/notifier/notification_manager.py b/apps/notifier/notification_manager.py index 99c8f18..a7d262b 100644 --- a/apps/notifier/notification_manager.py +++ b/apps/notifier/notification_manager.py @@ -83,20 +83,20 @@ def send_notify(self, data, notify_name, assistant_name: str): extra_data = {} if isinstance(telegram, dict): extra_data = telegram - if caption == "": - caption = ("{}\n{}".format(titolo,messaggio)) - if image != "" and image.find("http") != -1: - url_data = {"url": image, - "caption": caption, - "timeout": 90 - } - extra_data.update({"photo":url_data}) - if image != "" and image.find("http") == -1: - file_data = {"file": image, - "caption": caption, - "timeout": 90 - } - extra_data.update({"photo":file_data}) + if caption == "": + caption = ("{}\n{}".format(titolo,messaggio)) + if image != "" and image.find("http") != -1: + url_data = {"url": image, + "caption": caption, + "timeout": 90 + } + extra_data.update({"photo":url_data}) + if image != "" and image.find("http") == -1: + file_data = {"file": image, + "caption": caption, + "timeout": 90 + } + extra_data.update({"photo":file_data}) if str(html).lower() not in ["true","on","yes","1"]: messaggio = messaggio.replace("_","\_") if link !="": From a39346b24371b90f62b3e3b2c1d10bf0881d94df Mon Sep 17 00:00:00 2001 From: caiosweet <24454580+caiosweet@users.noreply.github.com> Date: Sun, 30 Oct 2022 19:56:46 +0100 Subject: [PATCH 48/75] Alexa Action Beta Alexa Action --- apps/notifier/alexa_manager.py | 749 ++++++++++++++++--------------- apps/notifier/alexa_manager.yaml | 29 +- 2 files changed, 412 insertions(+), 366 deletions(-) diff --git a/apps/notifier/alexa_manager.py b/apps/notifier/alexa_manager.py index a6bbfb3..3559f73 100755 --- a/apps/notifier/alexa_manager.py +++ b/apps/notifier/alexa_manager.py @@ -4,7 +4,7 @@ from threading import Thread import time -import hassapi as hass +import hassapi as hass # type: ignore """ Class Alexa Manager handles sending text to speech messages to Alexa media players @@ -12,10 +12,43 @@ - Speak text to choosen media_player - Full queue support to manage async multiple TTS commands - Full wait to tts to finish to be able to supply a callback method + - Mobile PUSH message + - Media content + - SSML, language, voice + - Alexa Actions: Actionable Notification """ +ALEXA_SERVICE = "alexa_media" +CUSTOM_COMPONENT_URL = "https://github.com/custom-components/alexa_media_player" NOTIFY = "notify/" - +SKILL_ID = "skill_id" +DEFAULT_VOL = "default_vol" + +# Parameters +# MODE = "mode" +TITLE = "title" +MESSAGE = "message" + +AUDIO = "audio" +EVENT_ID = "event_id" +TYPE = "type" +LANGUAGE = "language" +MEDIA_CONTENT_ID = "media_content_id" +MEDIA_CONTENT_TYPE = "media_content_type" +MEDIA_PLAYER = "media_player" +METHOD = "method" +NOTIFIER = "notifier" +PITCH = "pitch" +PUSH = "push" +RATE = "rate" +SSML = "ssml" +SSML_VOL = "ssml_volume" +VOICE = "voice" +VOLUME = "volume" +WAIT_TIME = "wait_time" +WHISPER = "whisper" + +MOBILE_PUSH_TYPE = (PUSH, "dropin", "dropin_notification") SUB_VOICE = [ # ("[.]{2,}", "."), ("[\?\.\!,]+(?=[\?\.\!,])", ""), # Exclude duplicate @@ -25,69 +58,8 @@ ("[\n\*]", " "), (" +", " "), ] - SUB_TEXT = [(" +", " "), ("\s\s+", "\n")] - -VOICE_NAMES = ( - "Carla", - "Giorgio", - "Bianca", - "Ivy", - "Joanna", - "Joey", - "Justin", - "Kendra", - "Kimberly", - "Matthew", - "Salli", - "Nicole", - "Russell", - "Amy", - "Brian", - "Emma", - "Aditi", - "Raveena", - "Chantal", - "Celine", - "Lea", - "Mathieu", - "Hans", - "Marlene", - "Vicki", - "Aditi", - "Mizuki", - "Takumi", - "Vitoria", - "Camila", - "Ricardo", - "Penelope", - "Lupe", - "Miguel", - "Conchita", - "Enrique", - "Lucia", - "Mia", -) - -SUPPORTED_LANGUAGES = [ - "it-IT", - "en-US", - "en-CA", - "en-AU", - "en-GB", - "en-IN", - "fr-CA", - "fr-FR", - "de-DE", - "hi-IN", - "ja-JP", - "pt-BR", - "es-US", - "es-ES", - "es-MX", -] - -SPEECHCON = [ +SPEECHCON_IT = ( "a ah", "abracadabra", "accidenti", @@ -256,238 +228,374 @@ "yippii", "zac", "zap", -] - -MOBILE_PUSH = ["push", "dropin", "dropin_notification"] +) +SUPPORTED_LANGUAGES = ( + "it-IT", + "en-US", + "en-CA", + "en-AU", + "en-GB", + "en-IN", + "fr-CA", + "fr-FR", + "de-DE", + "hi-IN", + "ja-JP", + "pt-BR", + "es-US", + "es-ES", + "es-MX", +) +VOICE_NAMES = ( + "Carla", + "Giorgio", + "Bianca", + "Ivy", + "Joanna", + "Joey", + "Justin", + "Kendra", + "Kimberly", + "Matthew", + "Salli", + "Nicole", + "Russell", + "Amy", + "Brian", + "Emma", + "Aditi", + "Raveena", + "Chantal", + "Celine", + "Lea", + "Mathieu", + "Hans", + "Marlene", + "Vicki", + "Aditi", + "Mizuki", + "Takumi", + "Vitoria", + "Camila", + "Ricardo", + "Penelope", + "Lupe", + "Miguel", + "Conchita", + "Enrique", + "Lucia", + "Mia", +) class Alexa_Manager(hass.Hass): def initialize(self) -> None: - # self.set_log_level("DEBUG") - self.alexa_service = self.args.get("alexa_service") - # self.alexa_switch_entity = self.args.get("alexa_switch") - self.alexa_select_media_player = self.args.get("alexa_select_media_player") - self.alexa_type = self.args.get("alexa_type") - self.alexa_method = self.args.get("alexa_method") - self.alexa_sensor_media_player = self.args.get("alexa_sensor_media_player") - self.alexa_voice = self.args.get("alexa_voice") - # self.alexa_language = self.args.get("alexa_language") - self.alexa_actionable = self.args.get("alexa_actionable") ## NEW - self.prosody = self.args.get("prosody") - self.wait_time = self.args.get("wait_time") - self.cehck_alexa_service = self._check_alexa(self.alexa_service) self.debug_sensor = self.args.get("debug_sensor") - self.set_state(self.debug_sensor, state="on") + self.component_installed = self.is_component_installed(ALEXA_SERVICE) + self.notify_services = self.list_notify_services(ALEXA_SERVICE) + self.service2player = self.alexa_services_to_players(self.notify_services) + self.volumes_saved = {} # dict media players volume saved + + # Entity + self.sensor_player = self.args.get("sensor_player") + self.sensor_volume = self.args.get("sensor_day_volume") + self.select_language = self.args.get("select_language") + self.select_player = self.args.get("select_player") + self.select_type = self.args.get("select_type") + self.select_method = self.args.get("select_method") + self.select_voice = self.args.get("select_voice") + self.bool_smart_volume_set = self.args.get("bool_smart_volume_set") + self.bool_ssml = self.args.get("bool_ssml") + self.prosody = self.args.get("prosody") + self.number_wait_time = self.args.get("number_wait_time") + self.text_actionable_notification = self.args.get("actionable_notification") + # self.queue = Queue(maxsize=0) self._when_tts_done_callback_queue = Queue() - t = Thread(target=self.worker) t.daemon = True t.start() + self.set_state(self.debug_sensor, state="on") - def speak(self, alexa, skill_id): #### NEW ### + def speak(self, alexa: dict, skill_id: str) -> None: """Speak the provided text through the media player.""" - if not self.cehck_alexa_service: - self.set_debug_sensor( - "I can't find the Alexa Media component", "https://github.com/custom-components/alexa_media_player" - ) + if not self.service2player: + self.set_debug_sensor("I can't find the Alexa Media services", CUSTOM_COMPONENT_URL) return - self.lg(f"-------------------- ALEXA START DISPATCH --------------------") + self.lg(f"------ ALEXA START DISPATCH ------") self.lg(f"FROM DISPATCH: {type(alexa)} value {alexa}") - # remove keys with None value from a dict # TODO - alexa = {k: v for k, v in alexa.items() if v not in [None, "None", ""]} - self.lg(f"REMOVE [NONE] VALUE: {type(alexa)} value {alexa}") - default_restore_volume = float(self.get_state(self.args.get("default_restore_volume"))) / 100 - volume = float(alexa.get("volume", default_restore_volume)) - message = str(alexa.get("message", alexa.get("message_tts", ""))) - alexa_player = self.player_get(alexa.get("media_player", self.get_state(self.alexa_sensor_media_player))) - alexa_type = ( - str(alexa.get("type", self.get_state(self.alexa_type))).lower().replace("dropin", "dropin_notification") - ) - if event_id := alexa.get("event_id"): #### NEW ### - self.set_textvalue(self.alexa_actionable, json.dumps({"text": "", "event": event_id})) - - # Push notification - push = bool(self.check_bool(alexa.get("push"))) - if push or alexa_type in MOBILE_PUSH and message: + + # Backwards compatible message_tts + message = str(alexa.get(MESSAGE, alexa.get("message_tts", ""))) + get_players = alexa.get(MEDIA_PLAYER, self.get_state(self.sensor_player)) + media_player = self.check_media_player(get_players) + get_type = alexa.get(TYPE, self.get_state(self.select_type, default="tts")) + data_type = str(get_type).lower().replace("dropin", "dropin_notification") + default_vol = float(self.get_state(self.sensor_volume, default=10)) / 100 + volume = float(alexa.get(VOLUME, default_vol)) + + # Actionable notification + if event_id := alexa.get(EVENT_ID): + self.set_textvalue( + self.text_actionable_notification, + json.dumps({"text": "", "event": event_id}), + ) + + # Push notification - Only one device is needed + push = self.check_bool(alexa.get(PUSH)) + if (push or data_type in MOBILE_PUSH_TYPE) and message: message_push = self.remove_tags(self.replace_regular(message, SUB_TEXT)) + type_ = {TYPE: PUSH} if push else {TYPE: data_type} self.call_service( - NOTIFY + self.alexa_service, - data={"type": "push"} if push else {"type": alexa_type}, - target=alexa_player[0], # only one device - title=str(alexa.get("title", "")), + NOTIFY + ALEXA_SERVICE, + data=type_, + target=media_player[0], + title=str(alexa.get(TITLE, "")), message=message_push, ) - self.lg(f"PUSH: {push} - TYPE: {alexa_type} - MESSAGE: {message_push}") + # Media Content # TODO Restore volume?? - media_content_id = alexa.get("media_content_id") - media_content_type = alexa.get("media_content_type") - if media_content_id: - self.volume_get(alexa_player, default_restore_volume) - self.volume_set(alexa_player, volume) + if media_content_id := alexa.get(MEDIA_CONTENT_ID): + self.volume_get_and_save(media_player, volume, default_vol) + self.volume_set(media_player, volume) self.call_service( "media_player/play_media", - entity_id=alexa_player, + entity_id=media_player, media_content_id=media_content_id, - media_content_type=media_content_type, - # extra = {"timer": 10} ##?? + media_content_type=alexa.get(MEDIA_CONTENT_TYPE), + extra={"timer": alexa.get("extra", 0)}, ) - self.lg(f"Content id: {media_content_id} - Content type: {media_content_type}") - # Queues the message to be handled async, use when_tts_done_do method to supply callback when tts is done - elif alexa_type not in MOBILE_PUSH and message: + # Queues the message to be handled async, use when_tts_done_do method + # to supply callback when tts is done + elif data_type not in MOBILE_PUSH_TYPE and message: self.queue.put( { - "text": message, - "volume": volume, - "event_id": event_id, #### NEW ### - "skill_id": skill_id, #### NEW ### - "alexa_type": alexa_type, - "alexa_player": alexa_player, # media_player - "default_restore_volume": default_restore_volume, - "alexa_notifier": str(alexa.get("notifier", self.alexa_service)), - "wait_time": float(alexa.get("wait_time", self.get_state(self.wait_time))), - "language": alexa.get("language"), # self.get_state(self.alexa_language)), - "alexa_method": str(alexa.get("method", self.get_state(self.alexa_method)).lower()), - "alexa_voice": str(alexa.get("voice", self.get_state(self.alexa_voice))).capitalize(), - "alexa_audio": alexa.get("audio", None), - "rate": float(alexa.get("rate", self.get_state(self.prosody["rate"]))), - "pitch": float(alexa.get("pitch", self.get_state(self.prosody["pitch"]))), - "ssml_volume": float(alexa.get("ssml_volume", self.get_state(self.prosody["volume"]))), - "whisper": bool(self.check_bool(alexa.get("whisper", False))), - "ssml_switch": bool(self.check_bool(alexa.get("ssml", self.get_state(self.args["ssml_switch"])))), + MESSAGE: message, + MEDIA_PLAYER: media_player, + TYPE: data_type, + DEFAULT_VOL: default_vol, + VOLUME: volume, + EVENT_ID: event_id, + SKILL_ID: skill_id, + AUDIO: alexa.get(AUDIO, None), + NOTIFIER: str(alexa.get(NOTIFIER, ALEXA_SERVICE)), + LANGUAGE: str(alexa.get(LANGUAGE, self.get_state(self.select_language, default="it-IT"))), + METHOD: str(alexa.get(METHOD, self.get_state(self.select_method, default="all")).lower()), + VOICE: str(alexa.get(VOICE, self.get_state(self.select_voice, default="Alexa"))).capitalize(), + WAIT_TIME: float(alexa.get(WAIT_TIME, self.get_state(self.number_wait_time))), + RATE: float(alexa.get(RATE, self.get_state(self.prosody[RATE], default=100.0))), + PITCH: float(alexa.get(PITCH, self.get_state(self.prosody[PITCH], default=0.0))), + SSML_VOL: float(alexa.get(SSML_VOL, self.get_state(self.prosody[VOLUME], default=0.0))), + WHISPER: self.check_bool(alexa.get(WHISPER, False)), + SSML: self.check_bool(alexa.get(SSML, self.get_state(self.bool_ssml, default="off"))), } ) - self.lg(f"-------------------- ALEXA END DISPATCH --------------------") - def lg(self, message): - self.log(message, level="DEBUG", ascii_encode=False) + def lg(self, message: str) -> None: + self.log(str(message), level="DEBUG", ascii_encode=False) - def check_bool(self, value): + def check_bool(self, value) -> bool: + """Check if user input is a boolean.""" return str(value).lower() in ["true", "on", "yes", "1"] - def inbetween(self, minv, value, maxv): + def inbetween(self, minv: float, value: float, maxv: float) -> float: + """Check input number between minimum and maximum values range.""" return sorted([minv, value, maxv])[1] - def speak_tag(self, value): # TODO tags - return value if "" in value or not "{value}" + def replace_regular(self, text: str, substitutions: list) -> str: + for old, new in substitutions: + regex = re.compile(old) + text = re.sub(regex, new, str(text).strip()) + return text - def effect_tag(self, value): + def str2list(self, string: str) -> list: + """Convert string to list.""" + regex = re.compile(r"\s*,\s*") + return self.split_device_list(re.sub(regex, ",", string)) + + def has_numbers(self, string: str): + """Check if a string contains a number.""" + numbers = re.compile("\d{2}:\d{2}|\d{4,}|\d{3,}\.\d") + return numbers.search(string) + + def remove_tags(self, text: str) -> str: + """Remove all tags from a string.""" + regex = re.compile("<.*?>") + return re.sub(regex, "", str(text).strip()) + + def speak_tags(self, value: str) -> str: + """This will add a tag when using tts method""" + return f"{value}" if not "" in value or " str: + """This will add a tag and applies a whispering effect.""" return f"{value}" - def prosody_tag(self, value, rate, pitch, volume): + def prosody_tags(self, value: str, rate: float, pitch: float, volume: float) -> str: + """This will add a tag for volume, pitch, and rate""" if rate != 100.0 or pitch != 0.0 or volume != 0.0: - rate = f"{self.inbetween(20, rate, 200)}%" # min 20% max 200% - pitch = f"{self.inbetween(-33.3, pitch, 50):+g}%" # min -33.3 max +50 - volume = f"{self.inbetween(-50, volume, 4.08):+g}dB" # max +4.08dB - return f" {value} " + r = f"{self.inbetween(20, rate, 200)}%" + p = f"{self.inbetween(-33.3, pitch, 50):+g}%" + v = f"{self.inbetween(-50, volume, 4.08):+g}dB" + return f" {value} " return value - def audio_tag(self, value: None): + def audio_tags(self, value: None) -> str: + """This will add the