Пример #1
0
    async def ws_close_handler():
        """Handle websocket close.

        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
        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,
            )
            hass.data[DATA_ALEXAMEDIA]["accounts"][email][
                "websocket_lastattempt"
            ] = time.time()
            hass.data[DATA_ALEXAMEDIA]["accounts"][email][
                "websocket"
            ] = await ws_connect()
            errors = hass.data[DATA_ALEXAMEDIA]["accounts"][email]["websocketerror"] = (
                hass.data[DATA_ALEXAMEDIA]["accounts"][email]["websocketerror"] + 1
            )
            delay = 5 * 2 ** errors
            await sleep(delay)
            errors = hass.data[DATA_ALEXAMEDIA]["accounts"][email]["websocketerror"]
        _LOGGER.debug(
            "%s: Websocket closed; retries exceeded; polling", hide_email(email)
        )
        hass.data[DATA_ALEXAMEDIA]["accounts"][email]["websocket"] = None
        await update_devices(  # pylint: disable=unexpected-keyword-arg
            login_obj, no_throttle=True
        )
Пример #2
0
async def _catch_login_errors(func, instance, args, kwargs) -> Any:
    """Detect AlexapyLoginError and attempt relogin."""

    result = None
    if instance is None and args:
        instance = args[0]
    if hasattr(instance, "check_login_changes"):
        # _LOGGER.debug(
        #     "%s checking for login changes", instance,
        # )
        instance.check_login_changes()
    try:
        result = await func(*args, **kwargs)
    except AlexapyLoginCloseRequested:
        _LOGGER.debug(
            "%s.%s: Ignoring attempt to access Alexa after HA shutdown",
            func.__module__[func.__module__.find(".") + 1:],
            func.__name__,
        )
        return None
    except AlexapyLoginError as ex:
        login = None
        email = None
        all_args = list(args) + list(kwargs.values())
        # _LOGGER.debug("Func %s instance %s %s %s", func, instance, args, kwargs)
        if instance:
            if hasattr(instance, "_login"):
                login = instance._login
                hass = instance.hass
        else:
            for arg in all_args:
                _LOGGER.debug("Checking %s", arg)

                if isinstance(arg, AlexaLogin):
                    login = arg
                    break
                if hasattr(arg, "_login"):
                    login = instance._login
                    hass = instance.hass
                    break

        if login:
            email = login.email
            _LOGGER.debug(
                "%s.%s: detected bad login for %s: %s",
                func.__module__[func.__module__.find(".") + 1:],
                func.__name__,
                hide_email(email),
                EXCEPTION_TEMPLATE.format(type(ex).__name__, ex.args),
            )
        try:
            hass
        except NameError:
            hass = None
        report_relogin_required(hass, login, email)
        return None
    return result
Пример #3
0
 async def async_step_check_proxy(self, user_input=None):
     """Check status of proxy for login."""
     _LOGGER.debug(
         "Checking proxy response for %s - %s",
         hide_email(self.login.email),
         self.login.url,
     )
     self.proxy_view.reset()
     return self.async_external_step_done(next_step_id="finish_proxy")
Пример #4
0
 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()
Пример #5
0
    async def ws_open_handler():
        """Handle websocket open."""

        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()
Пример #6
0
    async def ws_connect() -> WebsocketEchoClient:
        """Open WebSocket connection.

        This will only attempt one login before failing.
        """
        websocket: Optional[WebsocketEchoClient] = None
        try:
            websocket = WebsocketEchoClient(login_obj, ws_handler,
                                            ws_open_handler, ws_close_handler,
                                            ws_error_handler)
            _LOGGER.debug("%s: Websocket created: %s", hide_email(email),
                          websocket)
            await websocket.async_run()
        except BaseException as exception_:
            _LOGGER.debug("%s: Websocket creation failed: %s",
                          hide_email(email), exception_)
            return
        return websocket
Пример #7
0
    def __init__(self, device, login) -> None:
        # pylint: disable=unexpected-keyword-arg
        """Initialize the Alexa device."""

        # Class info
        self._login = login
        self.alexa_api = AlexaAPI(device, login)
        self.email = login.email
        self.account = hide_email(login.email)
Пример #8
0
    async def ws_close_handler():
        """Handle websocket close.

        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
        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,
            )
            hass.data[DATA_ALEXAMEDIA]["accounts"][email][
                "websocket_lastattempt"] = time.time()
            hass.data[DATA_ALEXAMEDIA]["accounts"][email][
                "websocket"] = await ws_connect()
            errors = hass.data[DATA_ALEXAMEDIA]["accounts"][email][
                "websocketerror"] = (hass.data[DATA_ALEXAMEDIA]["accounts"]
                                     [email]["websocketerror"] + 1)
            delay = 5 * 2**errors
            await sleep(delay)
            errors = hass.data[DATA_ALEXAMEDIA]["accounts"][email][
                "websocketerror"]
        _LOGGER.debug("%s: Websocket closed; retries exceeded; polling",
                      hide_email(email))
        hass.data[DATA_ALEXAMEDIA]["accounts"][email]["websocket"] = None
        coordinator = hass.data[DATA_ALEXAMEDIA]["accounts"][email].get(
            "coordinator")
        if coordinator:
            coordinator.update_interval = scan_interval
            await coordinator.async_request_refresh()
Пример #9
0
async def async_unload_entry(hass, entry) -> bool:
    """Unload a config entry."""
    email = entry.data["email"]
    _LOGGER.debug("Attempting to unload entry for %s", hide_email(email))
    for component in ALEXA_COMPONENTS:
        await hass.config_entries.async_forward_entry_unload(entry, component)
    # notify has to be handled manually as the forward does not work yet
    await notify_async_unload_entry(hass, entry)
    await close_connections(hass, email)
    for listener in hass.data[DATA_ALEXAMEDIA]["accounts"][email][
            DATA_LISTENER]:
        listener()
    hass.data[DATA_ALEXAMEDIA]["accounts"].pop(email)
    # Clean up config flows in progress
    flows_to_remove = []
    if hass.data[DATA_ALEXAMEDIA].get("config_flows"):
        for key, flow in hass.data[DATA_ALEXAMEDIA]["config_flows"].items():
            if key.startswith(email) and flow:
                _LOGGER.debug("Aborting flow %s %s", key, flow)
                flows_to_remove.append(key)
                try:
                    hass.config_entries.flow.async_abort(flow.get("flow_id"))
                except UnknownFlow:
                    pass
        for flow in flows_to_remove:
            hass.data[DATA_ALEXAMEDIA]["config_flows"].pop(flow)
    # Clean up hass.data
    if not hass.data[DATA_ALEXAMEDIA]["accounts"]:
        _LOGGER.debug("Removing accounts data and services")
        hass.data[DATA_ALEXAMEDIA].pop("accounts")
        alexa_services = hass.data[DATA_ALEXAMEDIA].get("services")
        if alexa_services:
            await alexa_services.unregister()
            hass.data[DATA_ALEXAMEDIA].pop("services")
    if not hass.data[DATA_ALEXAMEDIA]["config_flows"]:
        _LOGGER.debug("Removing config_flows data")
        hass.components.persistent_notification.async_dismiss(
            f"alexa_media_{slugify(email)}{slugify((entry.data['url'])[7:])}")
        hass.data[DATA_ALEXAMEDIA].pop("config_flows")
    if not hass.data[DATA_ALEXAMEDIA]:
        _LOGGER.debug("Removing alexa_media data structure")
        hass.data.pop(DATA_ALEXAMEDIA)
    _LOGGER.debug("Unloaded entry for %s", hide_email(email))
    return True
Пример #10
0
async def close_connections(hass, email: Text) -> None:
    """Clear open aiohttp connections for email."""
    if (email not in hass.data[DATA_ALEXAMEDIA]["accounts"] or "login_obj"
            not in hass.data[DATA_ALEXAMEDIA]["accounts"][email]):
        return
    account_dict = hass.data[DATA_ALEXAMEDIA]["accounts"][email]
    login_obj = account_dict["login_obj"]
    await login_obj.close()
    _LOGGER.debug("%s: Connection closed: %s", hide_email(email),
                  login_obj.session.closed)
Пример #11
0
 async def login_success(event=None) -> None:
     """Relogin to Alexa."""
     for email, _ in hass.data[DATA_ALEXAMEDIA]["accounts"].items():
         if hide_email(email) == event.data.get("email"):
             _LOGGER.debug("Received Login success: %s", event)
             email = account.get(CONF_EMAIL)
             login_obj: AlexaLogin = hass.data[DATA_ALEXAMEDIA]["accounts"][
                 email].get("login_obj")
             await setup_alexa(hass, config_entry, login_obj)
             break
 async def async_step_check_proxy(self, user_input=None):
     """Check status of proxy for login."""
     _LOGGER.debug(
         "Checking proxy response for %s - %s",
         hide_email(self.login.email),
         self.login.url,
     )
     if self.proxy:
         await self.proxy.stop_proxy()
         self._cancel_proxy_listener()
     return self.async_external_step_done(next_step_id="finish_proxy")
Пример #13
0
async def close_connections(hass, email: Text) -> None:
    """Clear open aiohttp connections for email."""
    if (email not in hass.data[DATA_ALEXAMEDIA]['accounts'] or 'login_obj'
            not in hass.data[DATA_ALEXAMEDIA]['accounts'][email]):
        return
    account_dict = hass.data[DATA_ALEXAMEDIA]['accounts'][email]
    login_obj = account_dict['login_obj']
    await login_obj.close()
    _LOGGER.debug("%s: Connection closed: %s", hide_email(email),
                  login_obj._session.closed)
    await clear_configurator(hass, email)
Пример #14
0
def report_relogin_required(hass, login, email) -> bool:
    """Send message for relogin required."""
    if hass and login and email:
        if login.status:
            _LOGGER.debug(
                "Reporting need to relogin to %s with %s stats: %s",
                login.url,
                hide_email(email),
                login.stats,
            )
            hass.bus.async_fire(
                "alexa_media_relogin_required",
                event_data={
                    "email": hide_email(email),
                    "url": login.url,
                    "stats": login.stats,
                },
            )
            return True
    return False
Пример #15
0
 async def async_step_check_proxy(self, user_input=None):
     """Check status of proxy for login."""
     _LOGGER.debug(
         "Checking proxy response for %s - %s",
         hide_email(self.login.email),
         self.login.url,
     )
     if self.proxy:
         await self.proxy.stop_proxy()
     if await self.login.test_loggedin():
         await self.login.finalize_login()
         return self.async_external_step_done(next_step_id="finish_proxy")
     return self.async_abort(reason=self.login.status.get("login_failed"))
Пример #16
0
    async def update_dnd_state(login_obj) -> None:
        """Update the dnd state on ws dnd combo event."""
        dnd = await AlexaAPI.get_dnd_state(login_obj)

        if "doNotDisturbDeviceStatusList" in dnd:
            async_dispatcher_send(
                hass,
                f"{DOMAIN}_{hide_email(email)}"[0:32],
                {"dnd_update": dnd["doNotDisturbDeviceStatusList"]},
            )
            return
        _LOGGER.debug("%s: get_dnd_state failed: dnd:%s", hide_email(email), dnd)
        return
Пример #17
0
    async def ws_error_handler(message):
        """Handle websocket error.

        This currently logs the error.  In the future, this should invalidate
        the websocket and determine if a reconnect should be done. By
        specification, websockets will issue a close after every error.
        """
        email = login_obj.email
        errors = hass.data[DATA_ALEXAMEDIA]["accounts"][email]["websocketerror"]
        _LOGGER.debug(
            "%s: Received websocket error #%i %s: type %s",
            hide_email(email),
            errors,
            message,
            type(message),
        )
        hass.data[DATA_ALEXAMEDIA]["accounts"][email]["websocket"] = None
        if message == "<class 'aiohttp.streams.EofStream'>":
            hass.data[DATA_ALEXAMEDIA]["accounts"][email]["websocketerror"] = 5
            _LOGGER.debug("%s: Immediate abort on EoFstream", hide_email(email))
            return
        hass.data[DATA_ALEXAMEDIA]["accounts"][email]["websocketerror"] = errors + 1
Пример #18
0
    async def ws_error_handler(message):
        """Handle websocket error.

        This currently logs the error.  In the future, this should invalidate
        the websocket and determine if a reconnect should be done. By
        specification, websockets will issue a close after every error.
        """
        email = login_obj.email
        errors = hass.data[DATA_ALEXAMEDIA]["accounts"][email]["websocketerror"]
        _LOGGER.debug(
            "%s: Received websocket error #%i %s", hide_email(email), errors, message
        )
        (hass.data[DATA_ALEXAMEDIA]["accounts"][email]["websocket"]) = None
        (hass.data[DATA_ALEXAMEDIA]["accounts"][email]["websocketerror"]) = errors + 1
Пример #19
0
    async def ws_close_handler():
        """Handle websocket close.

        This should attempt to reconnect up to 5 times
        """
        from asyncio import sleep
        email: Text = login_obj.email
        errors: int = (
            hass.data[DATA_ALEXAMEDIA]['accounts'][email]['websocketerror'])
        delay: int = 5 * 2**errors
        if (errors < 5):
            _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()
        else:
            _LOGGER.debug("%s: Websocket closed; retries exceeded; polling",
                          hide_email(email))
            (hass.data[DATA_ALEXAMEDIA]['accounts'][email]['websocket']) = None
            await update_devices(login_obj, no_throttle=True)
Пример #20
0
    async def update_last_called(login_obj, last_called=None):
        """Update the last called device for the login_obj.

        This will store the last_called in hass.data and also fire an event
        to notify listeners.
        """
        from alexapy import AlexaAPI
        if not last_called:
            last_called = await AlexaAPI.get_last_device_serial(login_obj)
        _LOGGER.debug("%s: Updated last_called: %s", hide_email(email),
                      hide_serial(last_called))
        stored_data = hass.data[DATA_ALEXAMEDIA]['accounts'][email]
        if (('last_called' in stored_data
             and last_called != stored_data['last_called']) or
            ('last_called' not in stored_data and last_called is not None)):
            _LOGGER.debug(
                "%s: last_called changed: %s to %s", hide_email(email),
                hide_serial(stored_data['last_called'] if 'last_called' in
                            stored_data else None), hide_serial(last_called))
            hass.bus.async_fire(f'{DOMAIN}_{hide_email(email)}'[0:32],
                                {'last_called_change': last_called})
        (hass.data[DATA_ALEXAMEDIA]['accounts'][email]['last_called']
         ) = last_called
Пример #21
0
    async def update_last_called(login_obj, last_called=None, force=False):
        """Update the last called device for the login_obj.

        This will store the last_called in hass.data and also fire an event
        to notify listeners.
        """
        if not last_called or not (last_called and last_called.get("summary")):
            try:
                last_called = await AlexaAPI.get_last_device_serial(login_obj)
            except TypeError:
                _LOGGER.debug(
                    "%s: Error updating last_called: %s",
                    hide_email(email),
                    hide_serial(last_called),
                )
                return
        _LOGGER.debug("%s: Updated last_called: %s", hide_email(email),
                      hide_serial(last_called))
        stored_data = hass.data[DATA_ALEXAMEDIA]["accounts"][email]
        if (force or "last_called" in stored_data
                and last_called != stored_data["last_called"]) or (
                    "last_called" not in stored_data
                    and last_called is not None):
            _LOGGER.debug(
                "%s: last_called changed: %s to %s",
                hide_email(email),
                hide_serial(stored_data["last_called"] if "last_called" in
                            stored_data else None),
                hide_serial(last_called),
            )
            async_dispatcher_send(
                hass,
                f"{DOMAIN}_{hide_email(email)}"[0:32],
                {"last_called_change": last_called},
            )
        hass.data[DATA_ALEXAMEDIA]["accounts"][email][
            "last_called"] = last_called
Пример #22
0
 async def relogin(event=None) -> None:
     """Relogin to Alexa."""
     if hide_email(email) == event.data.get("email"):
         _LOGGER.debug("%s: Received relogin request: %s",
                       hide_email(email), event)
         login_obj: AlexaLogin = hass.data[DATA_ALEXAMEDIA]["accounts"][
             email].get("login_obj")
         if login_obj is None:
             login_obj = AlexaLogin(
                 url=url,
                 email=email,
                 password=password,
                 outputpath=hass.config.path,
                 debug=account.get(CONF_DEBUG),
                 otp_secret=account.get(CONF_OTPSECRET, ""),
                 oauth=account.get(CONF_OAUTH, {}),
                 uuid=await hass.helpers.instance_id.async_get(),
             )
             hass.data[DATA_ALEXAMEDIA]["accounts"][email][
                 "login_obj"] = login_obj
         await login_obj.reset()
         # await login_obj.login()
         if await test_login_status(hass, config_entry, login_obj):
             await setup_alexa(hass, config_entry, login_obj)
Пример #23
0
async def async_unload_entry(hass, entry) -> bool:
    """Unload a config entry."""
    hass.services.async_remove(DOMAIN, SERVICE_UPDATE_LAST_CALLED)
    hass.services.async_remove(DOMAIN, SERVICE_CLEAR_HISTORY)
    for component in ALEXA_COMPONENTS:
        await hass.config_entries.async_forward_entry_unload(entry, component)
    # notify has to be handled manually as the forward does not work yet
    from .notify import async_unload_entry
    await async_unload_entry(hass, entry)
    email = entry.data['email']
    await close_connections(hass, email)
    await clear_configurator(hass, email)
    hass.data[DATA_ALEXAMEDIA]['accounts'].pop(email)
    _LOGGER.debug("Unloaded entry for %s", hide_email(email))
    return True
 async def async_step_reauth(self, user_input=None):
     """Handle reauth processing for the config flow."""
     self.config = user_input
     self.login = self.hass.data[DATA_ALEXAMEDIA]["accounts"][
         user_input[CONF_EMAIL]].get("login_obj")
     try:
         _LOGGER.debug(
             "Attempting relogin for %s to %s",
             hide_email(self.config[CONF_EMAIL]),
             self.config[CONF_URL],
         )
         await self.login.login(data=self.config)
         return await self._test_login()
     except AlexapyConnectionError:
         return self.async_show_form(step_id="reauth",
                                     errors={"base": "connection_error"})
Пример #25
0
 async def wrapper(*args, **kwargs) -> Any:
     instance = args[0]
     result = None
     if hasattr(instance, "check_login_changes"):
         instance.check_login_changes()
     try:
         result = await func(*args, **kwargs)
     except AlexapyLoginCloseRequested:
         _LOGGER.debug(
             "%s.%s: Ignoring attempt to access Alexa after HA shutdown",
             func.__module__[func.__module__.find(".") + 1:],
             func.__name__,
         )
         return None
     except AlexapyLoginError as ex:
         _LOGGER.debug(
             "%s.%s: detected bad login: %s",
             func.__module__[func.__module__.find(".") + 1:],
             func.__name__,
             EXCEPTION_TEMPLATE.format(type(ex).__name__, ex.args),
         )
         instance = args[0]
         if hasattr(instance, "_login"):
             login = instance._login
             email = login.email
             hass = instance.hass if instance.hass else None
             if hass and ("configurator" not in
                          (hass.data[DATA_ALEXAMEDIA]["accounts"][email])
                          or not (hass.data[DATA_ALEXAMEDIA]["accounts"]
                                  [email]["configurator"])):
                 config_entry = hass.data[DATA_ALEXAMEDIA]["accounts"][
                     email]["config_entry"]
                 setup_alexa = hass.data[DATA_ALEXAMEDIA]["accounts"][
                     email]["setup_alexa"]
                 test_login_status = hass.data[DATA_ALEXAMEDIA]["accounts"][
                     email]["test_login_status"]
                 _LOGGER.debug(
                     "%s: Alexa API disconnected; attempting to relogin",
                     hide_email(email),
                 )
                 if login.status:
                     await login.reset()
                     await login.login()
                     await test_login_status(hass, config_entry, login,
                                             setup_alexa)
         return None
     return result
 async def async_step_start_proxy(self, user_input=None):
     """Start proxy for login."""
     _LOGGER.debug(
         "Starting proxy for %s - %s", hide_email(self.login.email), self.login.url,
     )
     await self.proxy.start_proxy()
     self._cancel_proxy_listener = async_call_later(
         self.hass, 600, lambda _: self._cancel_proxy(),
     )
     self.hass.http.register_view(AlexaMediaAuthorizationCallbackView)
     callback_url = (
         f"{self.config['hass_url']}{AUTH_CALLBACK_PATH}?flow_id={self.flow_id}"
     )
     proxy_url = f"{self.proxy.access_url()}?config_flow_id={self.flow_id}&callback_url={callback_url}"
     if self.login.lastreq:
         proxy_url = f"{self.proxy.access_url()}/resume?config_flow_id={self.flow_id}&callback_url={callback_url}"
     return self.async_external_step(step_id="check_proxy", url=proxy_url)
    def __init__(self, login, media_players=None) -> None:
        # pylint: disable=unexpected-keyword-arg
        """Initialize the Alexa device."""
        super().__init__(None, login)
        _LOGGER.debug("%s: Initiating alarm control panel", hide_email(login.email))
        # AlexaAPI requires a AlexaClient object, need to clean this up
        self._available = None
        self._assumed_state = None

        # Guard info
        self._appliance_id = None
        self._guard_entity_id = None
        self._friendly_name = "Alexa Guard"
        self._state = None
        self._should_poll = False
        self._attrs: Dict[Text, Text] = {}
        self._media_players = {} or media_players
Пример #28
0
 def check_login_changes(self):
     """Update Login object if it has changed."""
     # _LOGGER.debug("Checking if Login object has changed")
     try:
         login = self.hass.data[DATA_ALEXAMEDIA]["accounts"][self.email]["login_obj"]
     except (AttributeError, KeyError):
         return
     # _LOGGER.debug("Login object %s closed status: %s", login, login.session.closed)
     # _LOGGER.debug(
     #     "Alexaapi %s closed status: %s",
     #     self.alexa_api,
     #     self.alexa_api._session.closed,
     # )
     if self.alexa_api.update_login(login):
         _LOGGER.debug("Login object has changed; updating")
         self._login = login
         self.email = login.email
         self.account = hide_email(login.email)
Пример #29
0
 async def wrapper(*args, **kwargs) -> Any:
     try:
         result = await func(*args, **kwargs)
     except AlexapyLoginError as ex:  # pylint: disable=broad-except
         template = "An exception of type {0} occurred." " Arguments:\n{1!r}"
         message = template.format(type(ex).__name__, ex.args)
         _LOGGER.debug(
             "%s.%s: detected bad login: %s",
             func.__module__[func.__module__.find(".") + 1 :],
             func.__name__,
             message,
         )
         instance = args[0]
         if hasattr(instance, "_login"):
             login = instance._login
             email = login.email
             hass = instance.hass if instance.hass else None
             if hass and (
                 "configurator"
                 not in (hass.data[DATA_ALEXAMEDIA]["accounts"][email])
                 or not (
                     hass.data[DATA_ALEXAMEDIA]["accounts"][email]["configurator"]
                 )
             ):
                 config_entry = hass.data[DATA_ALEXAMEDIA]["accounts"][email][
                     "config_entry"
                 ]
                 setup_alexa = hass.data[DATA_ALEXAMEDIA]["accounts"][email][
                     "setup_alexa"
                 ]
                 test_login_status = hass.data[DATA_ALEXAMEDIA]["accounts"][email][
                     "test_login_status"
                 ]
                 _LOGGER.debug(
                     "%s: Alexa API disconnected; attempting to relogin",
                     hide_email(email),
                 )
                 if login.status and not await test_login_status(
                     hass, config_entry, login, setup_alexa
                 ):
                     login.status = {}
                     await login.login()
         return None
     return result
Пример #30
0
 async def relogin(event=None) -> None:
     """Relogin to Alexa."""
     for email, _ in hass.data[DATA_ALEXAMEDIA]["accounts"].items():
         if hide_email(email) == event.data.get("email"):
             _LOGGER.debug("Received relogin request: %s", event)
             email = account.get(CONF_EMAIL)
             login_obj = hass.data[DATA_ALEXAMEDIA]["accounts"][email].get(
                 "login_obj")
             if login_obj is None:
                 login_obj = AlexaLogin(url, email, password,
                                        hass.config.path,
                                        account.get(CONF_DEBUG))
                 hass.data[DATA_ALEXAMEDIA]["accounts"][email][
                     "login_obj"] = login_obj
             await login_obj.reset()
             # await login_obj.login()
             if await test_login_status(hass, config_entry, login_obj):
                 await setup_alexa(hass, config_entry, login_obj)
             break