diff --git a/custom_components/alexa_media/__init__.py b/custom_components/alexa_media/__init__.py index 1cde47af..59995a35 100644 --- a/custom_components/alexa_media/__init__.py +++ b/custom_components/alexa_media/__init__.py @@ -429,8 +429,10 @@ async def update_devices(login_obj): for dev in preferences['devicePreferences']: if dev['deviceSerialNumber'] == device['serialNumber']: device['locale'] = dev['locale'] - _LOGGER.debug("Locale %s found for %s", + device['timeZoneId'] = dev['timeZoneId'] + _LOGGER.debug("Locale %s timezone %s found for %s", device['locale'], + device['timeZoneId'], hide_serial(device['serialNumber'])) if 'doNotDisturbDeviceStatusList' in dnd: @@ -496,6 +498,8 @@ async def process_notifications(login_obj, raw_notifications=None): for notification in raw_notifications: n_dev_id = notification['deviceSerialNumber'] n_type = notification['type'] + if n_type == "MusicAlarm": + n_type = "Alarm" n_id = notification['notificationIndex'] n_date = notification['originalDate'] n_time = notification['originalTime'] @@ -634,6 +638,7 @@ async def ws_connect() -> WebsocketEchoClient: _LOGGER.debug("%s: Websocket creation failed: %s", hide_email(email), exception_) + return return websocket async def ws_handler(message_obj): @@ -755,11 +760,14 @@ async def ws_handler(message_obj): async def ws_open_handler(): """Handle websocket open.""" + import time email: Text = login_obj.email _LOGGER.debug("%s: Websocket succesfully connected", hide_email(email)) (hass.data[DATA_ALEXAMEDIA] ['accounts'][email]['websocketerror']) = 0 # set errors to 0 + (hass.data[DATA_ALEXAMEDIA]['accounts'] + [email]['websocket_lastattempt']) = time.time() async def ws_close_handler(): """Handle websocket close. @@ -767,20 +775,29 @@ async def ws_close_handler(): This should attempt to reconnect up to 5 times """ from asyncio import sleep + import time email: Text = login_obj.email errors: int = (hass.data [DATA_ALEXAMEDIA]['accounts'][email]['websocketerror']) delay: int = 5 * 2 ** errors - if (errors < 5): + last_attempt = (hass.data[DATA_ALEXAMEDIA]['accounts'] + [email]['websocket_lastattempt']) + now = time.time() + if ((now - last_attempt) < delay): + return + while (errors < 5 and not (hass.data[DATA_ALEXAMEDIA]['accounts'] + [email]['websocket'])): _LOGGER.debug("%s: Websocket closed; reconnect #%i in %is", hide_email(email), errors, delay) await sleep(delay) - if (not (hass.data - [DATA_ALEXAMEDIA]['accounts'][email]['websocket'])): - (hass.data[DATA_ALEXAMEDIA]['accounts'] - [email]['websocket']) = await ws_connect() + (hass.data[DATA_ALEXAMEDIA]['accounts'] + [email]['websocket_lastattempt']) = time.time() + (hass.data[DATA_ALEXAMEDIA]['accounts'] + [email]['websocket']) = await ws_connect() + errors += 1 + delay = 5 * 2 ** errors else: _LOGGER.debug("%s: Websocket closed; retries exceeded; polling", hide_email(email)) @@ -828,6 +845,10 @@ async def ws_error_handler(message): ['entities']) = {'media_player': {}} (hass.data[DATA_ALEXAMEDIA] ['accounts'][email]['new_devices']) = True # force initial update + (hass.data[DATA_ALEXAMEDIA] + ['accounts'][email]['websocket_lastattempt']) = 0 + (hass.data[DATA_ALEXAMEDIA] + ['accounts'][email]['websocketerror']) = 0 # set errors to 0 (hass.data[DATA_ALEXAMEDIA]['accounts'][email]['websocket']) = \ await ws_connect() await update_devices(login_obj, no_throttle=True) diff --git a/custom_components/alexa_media/config_flow.py b/custom_components/alexa_media/config_flow.py index b5cc3aac..9f7b4e78 100644 --- a/custom_components/alexa_media/config_flow.py +++ b/custom_components/alexa_media/config_flow.py @@ -276,7 +276,8 @@ async def _test_login(self): ): _LOGGER.debug("Creating config_flow to request 2FA") message = "> {0}".format( - login.status["error_message"] if "error_message" in login.status else "" + login.status["error_message"] + if "error_message" in login.status else "" ) return await self._show_form( "twofactor", @@ -292,10 +293,12 @@ async def _test_login(self): "claimspicker_required" in login.status and login.status["claimspicker_required"] ): - message = "> {0}".format( - login.status["error_message"] if "error_message" in login.status else "" + error_message = "> {0}".format( + login.status["error_message"] + if "error_message" in login.status else "" ) _LOGGER.debug("Creating config_flow to select verification method") + claimspicker_message = login.status["claimspicker_message"] return await self._show_form( "claimspicker", data_schema=vol.Schema(self.claimspicker_schema), @@ -303,7 +306,8 @@ async def _test_login(self): placeholders={ "email": login.email, "url": login.url, - "message": message, + "message": "> {0}\n> {1}".format(claimspicker_message, + error_message), }, ) elif ( @@ -312,7 +316,8 @@ async def _test_login(self): ): _LOGGER.debug("Creating config_flow to select OTA method") error_message = ( - login.status["error_message"] if "error_message" in login.status else "" + login.status["error_message"] + if "error_message" in login.status else "" ) authselect_message = login.status["authselect_message"] return await self._show_form( @@ -321,7 +326,8 @@ async def _test_login(self): placeholders={ "email": login.email, "url": login.url, - "message": "> {0}\n> {1}".format(authselect_message, error_message), + "message": "> {0}\n> {1}".format(authselect_message, + error_message), }, ) elif ( diff --git a/custom_components/alexa_media/const.py b/custom_components/alexa_media/const.py index 5d12e40c..280e6440 100644 --- a/custom_components/alexa_media/const.py +++ b/custom_components/alexa_media/const.py @@ -9,7 +9,7 @@ """ from datetime import timedelta -__version__ = '2.3.0' +__version__ = '2.3.1' PROJECT_URL = "https://github.com/custom-components/alexa_media_player/" ISSUE_URL = "{}issues".format(PROJECT_URL) diff --git a/custom_components/alexa_media/manifest.json b/custom_components/alexa_media/manifest.json index 5792b25e..97f57e06 100644 --- a/custom_components/alexa_media/manifest.json +++ b/custom_components/alexa_media/manifest.json @@ -5,6 +5,6 @@ "documentation": "https://github.com/custom-components/alexa_media_player/wiki", "dependencies": [], "codeowners": ["@keatontaylor", "@alandtse"], - "requirements": ["alexapy==1.3.1"], + "requirements": ["alexapy==1.3.2"], "homeassistant": "0.96.0" } diff --git a/custom_components/alexa_media/media_player.py b/custom_components/alexa_media/media_player.py index 3def6f6b..d612d48f 100644 --- a/custom_components/alexa_media/media_player.py +++ b/custom_components/alexa_media/media_player.py @@ -306,6 +306,8 @@ async def refresh(self, device=None): self._cluster_members = device['clusterMembers'] self._bluetooth_state = device['bluetooth_state'] self._locale = device['locale'] if 'locale' in device else 'en-US' + self._timezone = (device['timeZoneId'] + if 'timeZoneId' in device else 'UTC') self._dnd = device['dnd'] if 'dnd' in device else None await self._set_authentication_details(device['auth_info']) session = None diff --git a/custom_components/alexa_media/sensor.py b/custom_components/alexa_media/sensor.py index 0d28ae85..4f1411af 100644 --- a/custom_components/alexa_media/sensor.py +++ b/custom_components/alexa_media/sensor.py @@ -162,10 +162,20 @@ def __init__(self, self._all = (sorted(self._n_dict.items(), key=lambda x: x[1][self._sensor_property]) if self._n_dict else []) + self._all = list(map(self._fix_alarm_date_time, self._all)) self._sorted = list(filter(lambda x: x[1]['status'] == 'ON', self._all)) if self._all else [] self._next = self._sorted[0][1] if self._sorted else None + def _fix_alarm_date_time(self, value): + import pytz + if self._sensor_property != "date_time" or not value: + return value + naive_time = dt.parse_datetime(value[1][self._sensor_property]) + timezone = pytz.timezone(self._client._timezone) + value[1][self._sensor_property] = timezone.localize(naive_time) + return value + async def async_added_to_hass(self): """Store register state change callback.""" try: @@ -224,7 +234,7 @@ def should_poll(self): @property def state(self): """Return the state of the sensor.""" - return dt.parse_datetime(self._next[self._sensor_property]).replace( + return self._next[self._sensor_property].replace( tzinfo=LOCAL_TIMEZONE) if self._next else 'None' @property @@ -254,6 +264,7 @@ async def async_update(self): self._all = (sorted(self._n_dict.items(), key=lambda x: x[1][self._sensor_property]) if self._n_dict else []) + self._all = list(map(self._fix_alarm_date_time, self._all)) self._sorted = list(filter(lambda x: x[1]['status'] == 'ON', self._all)) if self._all else [] self._next = self._sorted[0][1] if self._sorted else None @@ -291,8 +302,8 @@ def device_state_attributes(self): 'recurrence': self.recurrence, 'total_active': len(self._sorted), 'total_all': len(self._all), - 'sorted_active': json.dumps(self._sorted), - 'sorted_all': json.dumps(self._all), + 'sorted_active': json.dumps(self._sorted, default=str), + 'sorted_all': json.dumps(self._all, default=str), } return attr diff --git a/custom_components/hacs/.translations/de.json b/custom_components/hacs/.translations/de.json index 9b308508..2988d400 100644 --- a/custom_components/hacs/.translations/de.json +++ b/custom_components/hacs/.translations/de.json @@ -51,6 +51,7 @@ } }, "repository": { + "authors": "Autoren", "available": "Verfügbar", "back_to": "Zurück zu", "changelog": "Changelog", @@ -90,6 +91,6 @@ "upgrade_all": "Alle aktualisieren" }, "store": { - "placeholder_search": "Suchbegriff eingeben..." + "placeholder_search": "Suchbegriff eingeben…" } } \ No newline at end of file diff --git a/custom_components/hacs/.translations/fr.json b/custom_components/hacs/.translations/fr.json index 10ad4c3e..f27070e3 100644 --- a/custom_components/hacs/.translations/fr.json +++ b/custom_components/hacs/.translations/fr.json @@ -51,6 +51,7 @@ } }, "repository": { + "authors": "Auteurs", "available": "Disponible", "back_to": "Retour", "changelog": "Change log", @@ -77,9 +78,9 @@ "upgrade": "Mettre à jour" }, "settings": { - "add_custom_repository": "AJOUTER UN DÉPÔT PERSONNALISE", + "add_custom_repository": "AJOUTER UN DÉPÔT PERSONNALISÉ", "category": "Catégorie", - "custom_repositories": "DÉPÔT PERSONNALISE", + "custom_repositories": "DÉPÔTS PERSONNALISÉS", "delete": "Supprimer", "display": "Affichage", "grid": "Grille", diff --git a/custom_components/hacs/.translations/it.json b/custom_components/hacs/.translations/it.json new file mode 100644 index 00000000..ef2242fb --- /dev/null +++ b/custom_components/hacs/.translations/it.json @@ -0,0 +1,96 @@ +{ + "common": { + "appdaemon": "AppDaemon", + "appdaemon_apps": "Applicazioni AppDaemon", + "background_task": "Attività in esecuzione, questa pagina sarà ricaricata al termine.", + "installed": "Installato", + "integration": "Integrazione", + "integrations": "Integrazioni", + "plugin": "Plugin", + "plugins": "Plugin", + "python_script": "Script python", + "python_scripts": "Script python", + "repositories": "Repository", + "settings": "Impostazioni", + "theme": "Tema", + "themes": "Temi", + "version": "Versione" + }, + "config": { + "abort": { + "single_instance_allowed": "È consentita una sola configurazione di HACS." + }, + "error": { + "auth": "Il token di accesso personale non è corretto." + }, + "step": { + "user": { + "data": { + "appdaemon": "Abilita il rilevamento e il monitoraggio delle app AppDaemon", + "python_script": "Abilita il rilevamento e il monitoraggio dei python_scripts", + "sidepanel_icon": "Icona nel pannello laterale", + "sidepanel_title": "Titolo nel pannello laterale", + "theme": "Abilita individuazione e tracciamento dei temi", + "token": "Token di accesso personale GitHub" + }, + "description": "Se hai bisogno di aiuto con la configurazione dai un'occhiata qui: https:\/\/hacs.netlify.com\/installation\/configuration\/", + "title": "HACS (Home Assistant Community Store)" + } + }, + "title": "HACS (Home Assistant Community Store)" + }, + "options": { + "step": { + "user": { + "data": { + "country": "Filtra con prefisso internazionale.", + "experimental": "Abilita funzionalità sperimentali", + "release_limit": "Numero di versioni da mostrare." + } + } + } + }, + "repository": { + "authors": "Autori", + "available": "Disponibile", + "back_to": "Indietro", + "changelog": "Change log", + "flag_this": "Spunta questo", + "hide": "Nascondi", + "hide_beta": "Nascondi beta", + "install": "Installa", + "installed": "Installato", + "lovelace_copy_example": "Copia l'esempio negli appunti", + "lovelace_instruction": "Quando lo aggiungi nella configurazione lovelace usa questo ", + "lovelace_no_js_type": "Impossibile determinare il tipo di plugin, verificare il repository.", + "newest": "Nuovo", + "note_appdaemon": "dovrai aggiungerlo nel file 'apps.yaml'", + "note_installed": "Quando installato, sarà posizionato in", + "note_integration": "dovrai aggiungerlo nel file 'configuration.yaml'", + "note_plugin": "Dovrai aggiungerlo nel file 'ui-lovelace.yaml' oppure via editor di configurazione RAW della UI.", + "open_issue": "Apri anomalia", + "open_plugin": "Apri plugin", + "reinstall": "Reinstalla", + "repository": "Repository", + "show_beta": "Visualizza beta", + "uninstall": "Rimuovi", + "update_information": "Aggiorna informazioni", + "upgrade": "Aggiorna" + }, + "settings": { + "add_custom_repository": "AGGIUNGI REPOSITORY PERSONALIZZATA", + "category": "Categoria", + "custom_repositories": "REPOSITORY PERSONALIZZATE", + "delete": "Cancella", + "display": "Visualizza", + "grid": "Griglia", + "hacs_repo": "HACS repo", + "reload_data": "Ricarica i dati", + "save": "Salva", + "table": "Tabella", + "upgrade_all": "Aggiorna tutto" + }, + "store": { + "placeholder_search": "Prego inserire una stringa di ricerca" + } +} \ No newline at end of file diff --git a/custom_components/hacs/.translations/pt_BR.json b/custom_components/hacs/.translations/pt-BR.json similarity index 100% rename from custom_components/hacs/.translations/pt_BR.json rename to custom_components/hacs/.translations/pt-BR.json diff --git a/custom_components/hacs/.translations/sl.json b/custom_components/hacs/.translations/sl.json new file mode 100644 index 00000000..a4f2bd58 --- /dev/null +++ b/custom_components/hacs/.translations/sl.json @@ -0,0 +1,96 @@ +{ + "common": { + "appdaemon": "AppDaemon", + "appdaemon_apps": "AppDaemon Aplikacije", + "background_task": "v ozadju se izvaja naloga, ko se konča, se bo stran osvežila.", + "installed": "Nameščeno", + "integration": "Integracija", + "integrations": "Integracije", + "plugin": "vtičnik", + "plugins": "Vtičniki", + "python_script": "Python skripta", + "python_scripts": "Python skripte", + "repositories": "Repozitoriji", + "settings": "nastavitve", + "theme": "Tema", + "themes": "Teme", + "version": "Različica" + }, + "config": { + "abort": { + "single_instance_allowed": "Dovoljena je samo ena konfiguracija HACS." + }, + "error": { + "auth": "Osebni dostopni žeton ni pravilen." + }, + "step": { + "user": { + "data": { + "appdaemon": "Omogoči odkrivanje in sledenje aplikacij AppDaemon", + "python_script": "Omogoči odkrivanje in sledenje python_scripts", + "sidepanel_icon": "Ikona stranske plošče", + "sidepanel_title": "Naslov stranske plošče", + "theme": "Omogoči odkrivanje in sledenje tem", + "token": "GitHub žeton za osebni dostop" + }, + "description": "Če potrebujete pomoč pri konfiguraciji, poglejte tukaj: https:\/\/hacs.netlify.com\/installation\/configuration\/", + "title": "HACS (Home Assistant Community Store)" + } + }, + "title": "HACS (Home Assistant Community Store)" + }, + "options": { + "step": { + "user": { + "data": { + "country": "Filtrirajte s kodo države.", + "experimental": "Omogočite poskusne funkcije", + "release_limit": "Število izdaj, ki jih želite prikazati." + } + } + } + }, + "repository": { + "authors": "Avtorji", + "available": "Na voljo", + "back_to": "Nazaj na", + "changelog": "Dnevnik sprememb", + "flag_this": "Označite to", + "hide": "Skrij", + "hide_beta": "Skrij različico beta", + "install": "Namestite", + "installed": "Nameščeno", + "lovelace_copy_example": "Kopirajte primer v odložišče", + "lovelace_instruction": "Ko ga boste dodajali v svojo lovelace konfiguracijo uporabite to:", + "lovelace_no_js_type": "Ni bilo mogoče določiti vrsto tega vtičnika, preverite repozitorij.", + "newest": "najnovejše", + "note_appdaemon": "Še vedno ga morate dodati v svojo 'apps.yaml' datoteko", + "note_installed": "Ko bo nameščen, se bo nahajal v", + "note_integration": "Še vedno ga morate dodati v svojo 'configuration.yaml' datoteko", + "note_plugin": "vendar ga še vedno morate dodati v svojo lovelace konfiguracijo ('ui-lovelace.yaml \" ali \"raw\" UI config urejevalnik)", + "open_issue": "Odprite težavo", + "open_plugin": "Odprite vtičnik", + "reinstall": "Znova namestite", + "repository": "Repozitorij", + "show_beta": "Pokaži različico beta", + "uninstall": "Odstranite", + "update_information": "Posodobite podatke", + "upgrade": "Nadgradnja" + }, + "settings": { + "add_custom_repository": "DODAJTE SVOJ REPOZITORIJ", + "category": "Kategorija", + "custom_repositories": "VAŠI REPOZITORIJI", + "delete": "Izbriši", + "display": "Prikaz", + "grid": "Mreža", + "hacs_repo": "HACS repo", + "reload_data": "Ponovno naloži podatke", + "save": "Shranite", + "table": "Tabela", + "upgrade_all": "Nadgradite vse" + }, + "store": { + "placeholder_search": "Prosim vnesite iskalni izraz..." + } +} \ No newline at end of file diff --git a/custom_components/hacs/.translations/sv.json b/custom_components/hacs/.translations/sv.json index d5ecba4c..78077056 100644 --- a/custom_components/hacs/.translations/sv.json +++ b/custom_components/hacs/.translations/sv.json @@ -10,7 +10,7 @@ "plugins": "Plugins", "python_script": "Python skript", "python_scripts": "Python skript", - "repositories": "Git repon", + "repositories": "Repositories", "settings": "inställningar", "theme": "Tema", "themes": "Teman", @@ -62,25 +62,25 @@ "installed": "Installerad", "lovelace_copy_example": "Kopiera exemplet till urklipp", "lovelace_instruction": "När du lägger till denna till din lovelace konfiguration, använd", - "lovelace_no_js_type": "Kan inte avgöra villken typ av plugin, kontrollera i git \nrepot", + "lovelace_no_js_type": "Kan inte avgöra villken typ av plugin, kontrollera i GIT \nrepository", "newest": "nyaste", "note_appdaemon": "du behöver fortfarande lägga till den till filen 'apps.yaml'", "note_installed": "När den är installerad kommer den finnas i", "note_integration": "du behöver fortfarande lägga den till filen 'configuration.yaml'", "note_plugin": "du behöver fortfarande lägga till den till din lovelace konfiguration ('ui-lovelace.yaml' eller raw UI config redigerare)", - "open_issue": "Öppna issue", + "open_issue": "Rapportera problem", "open_plugin": "Öppna plugin", "reinstall": "Ominstallera", - "repository": "Git repo", + "repository": "Repository", "show_beta": "Visa betaversioner", "uninstall": "Avinstallera", "update_information": "Uppdatera information", "upgrade": "Uppdatera" }, "settings": { - "add_custom_repository": "LÄGG TILL ETT GIT REPO", + "add_custom_repository": "LÄGG TILL ETT REPOSITORY", "category": "Kategori", - "custom_repositories": "GIT REPON", + "custom_repositories": "REPOSITORIES", "delete": "Ta bort", "display": "Visa", "grid": "Rutnät", diff --git a/custom_components/hacs/.translations/zh_CN.json b/custom_components/hacs/.translations/zh-Hans.json similarity index 98% rename from custom_components/hacs/.translations/zh_CN.json rename to custom_components/hacs/.translations/zh-Hans.json index 606c1f4f..9cb049a5 100644 --- a/custom_components/hacs/.translations/zh_CN.json +++ b/custom_components/hacs/.translations/zh-Hans.json @@ -65,7 +65,6 @@ "lovelace_no_js_type": "无法确定此插件的类型,请检查仓库。", "newest": "最新", "note_appdaemon": "您仍然需要将其添加到“ apps.yaml”文件中", - "note_installed": "已安装,它将位于", "note_integration": "您仍然需要将其添加到“ configuration.yaml”文件中", "note_plugin": "您仍然需要将其添加到lovelace配置中(“ ui-lovelace.yaml”或原始配置编辑器)ui-lovelace.yaml", "open_issue": "提交问题", diff --git a/custom_components/hacs/const.py b/custom_components/hacs/const.py index 35ce19ad..1c63cbf8 100644 --- a/custom_components/hacs/const.py +++ b/custom_components/hacs/const.py @@ -1,7 +1,7 @@ """Constants for HACS""" NAME_LONG = "HACS (Home Assistant Community Store)" NAME_SHORT = "HACS" -VERSION = "0.15.1" +VERSION = "0.15.2" DOMAIN = "hacs" PROJECT_URL = "https://github.com/custom-components/hacs/" CUSTOM_UPDATER_LOCATIONS = [ diff --git a/custom_components/hacs/frontend/elements/hacs.css.gz b/custom_components/hacs/frontend/elements/hacs.css.gz index 22c384e9..1c6d0d19 100644 Binary files a/custom_components/hacs/frontend/elements/hacs.css.gz and b/custom_components/hacs/frontend/elements/hacs.css.gz differ diff --git a/custom_components/hacs/frontend/elements/hacs.js.gz b/custom_components/hacs/frontend/elements/hacs.js.gz index 9993ba48..a36d9457 100644 Binary files a/custom_components/hacs/frontend/elements/hacs.js.gz and b/custom_components/hacs/frontend/elements/hacs.js.gz differ diff --git a/custom_components/hacs/frontend/templates/modal/wrong_ha_version.html b/custom_components/hacs/frontend/templates/modal/wrong_ha_version.html index ffa9f01a..baea02b7 100644 --- a/custom_components/hacs/frontend/templates/modal/wrong_ha_version.html +++ b/custom_components/hacs/frontend/templates/modal/wrong_ha_version.html @@ -1,8 +1,12 @@