Example #1
0
async def async_setup_entry(hass, config_entry):
    """Set up Tesla as config entry."""
    # pylint: disable=too-many-locals
    hass.data.setdefault(DOMAIN, {})
    config = config_entry.data
    # Because users can have multiple accounts, we always create a new session so they have separate cookies
    async_client = httpx.AsyncClient(headers={USER_AGENT: SERVER_SOFTWARE},
                                     timeout=60)
    email = config_entry.title
    if not hass.data[DOMAIN]:
        async_setup_services(hass)
    if email in hass.data[DOMAIN] and CONF_SCAN_INTERVAL in hass.data[DOMAIN][
            email]:
        scan_interval = hass.data[DOMAIN][email][CONF_SCAN_INTERVAL]
        hass.config_entries.async_update_entry(
            config_entry, options={CONF_SCAN_INTERVAL: scan_interval})
        hass.data[DOMAIN].pop(email)
    try:
        controller = TeslaAPI(
            async_client,
            email=config.get(CONF_USERNAME),
            refresh_token=config[CONF_TOKEN],
            access_token=config[CONF_ACCESS_TOKEN],
            expiration=config.get(CONF_EXPIRATION, 0),
            auth_domain=config.get(CONF_DOMAIN, AUTH_DOMAIN),
            update_interval=config_entry.options.get(CONF_SCAN_INTERVAL,
                                                     DEFAULT_SCAN_INTERVAL),
            polling_policy=config_entry.options.get(CONF_POLLING_POLICY,
                                                    DEFAULT_POLLING_POLICY),
        )
        result = await controller.connect(
            wake_if_asleep=config_entry.options.get(CONF_WAKE_ON_START,
                                                    DEFAULT_WAKE_ON_START))
        refresh_token = result["refresh_token"]
        access_token = result["access_token"]
        expiration = result["expiration"]
    except IncompleteCredentials as ex:
        await async_client.aclose()
        raise ConfigEntryAuthFailed from ex
    except httpx.ConnectTimeout as ex:
        await async_client.aclose()
        raise ConfigEntryNotReady from ex
    except TeslaException as ex:
        await async_client.aclose()
        if ex.code == HTTPStatus.UNAUTHORIZED:
            raise ConfigEntryAuthFailed from ex
        if ex.message in [
                "VEHICLE_UNAVAILABLE",
                "TOO_MANY_REQUESTS",
                "SERVICE_MAINTENANCE",
                "UPSTREAM_TIMEOUT",
        ]:
            raise ConfigEntryNotReady(
                f"Temporarily unable to communicate with Tesla API: {ex.message}"
            ) from ex
        _LOGGER.error("Unable to communicate with Tesla API: %s", ex.message)
        return False

    async def _async_close_client(*_):
        await async_client.aclose()

    @callback
    def _async_create_close_task():
        asyncio.create_task(_async_close_client())

    config_entry.async_on_unload(
        hass.bus.async_listen_once(EVENT_HOMEASSISTANT_CLOSE,
                                   _async_close_client))
    config_entry.async_on_unload(_async_create_close_task)

    _async_save_tokens(hass, config_entry, access_token, refresh_token,
                       expiration)
    coordinator = TeslaDataUpdateCoordinator(hass,
                                             config_entry=config_entry,
                                             controller=controller)
    # Fetch initial data so we have data when entities subscribe
    entry_data = hass.data[DOMAIN][config_entry.entry_id] = {
        "coordinator": coordinator,
        "devices": defaultdict(list),
        DATA_LISTENER: [config_entry.add_update_listener(update_listener)],
    }
    _LOGGER.debug("Connected to the Tesla API")

    await coordinator.async_config_entry_first_refresh()

    all_devices = controller.get_homeassistant_components()

    if not all_devices:
        return False

    for device in all_devices:
        entry_data["devices"][device.hass_type].append(device)

    hass.config_entries.async_setup_platforms(config_entry, PLATFORMS)

    return True
Example #2
0
async def async_setup_entry(hass, config_entry):
    """Set up Tesla as config entry."""
    hass.data.setdefault(DOMAIN, {})
    config = config_entry.data
    websession = aiohttp_client.async_get_clientsession(hass)
    email = config_entry.title
    if email in hass.data[DOMAIN] and CONF_SCAN_INTERVAL in hass.data[DOMAIN][
            email]:
        scan_interval = hass.data[DOMAIN][email][CONF_SCAN_INTERVAL]
        hass.config_entries.async_update_entry(
            config_entry, options={CONF_SCAN_INTERVAL: scan_interval})
        hass.data[DOMAIN].pop(email)
    try:
        controller = TeslaAPI(
            websession,
            email=config.get(CONF_USERNAME),
            password=config.get(CONF_PASSWORD),
            refresh_token=config[CONF_TOKEN],
            access_token=config[CONF_ACCESS_TOKEN],
            update_interval=config_entry.options.get(CONF_SCAN_INTERVAL,
                                                     DEFAULT_SCAN_INTERVAL),
        )
        (refresh_token, access_token) = await controller.connect(
            wake_if_asleep=config_entry.options.get(CONF_WAKE_ON_START,
                                                    DEFAULT_WAKE_ON_START))
    except IncompleteCredentials:
        _async_start_reauth(hass, config_entry)
        return False
    except TeslaException as ex:
        if ex.code == HTTP_UNAUTHORIZED:
            _async_start_reauth(hass, config_entry)
        _LOGGER.error("Unable to communicate with Tesla API: %s", ex.message)
        return False
    _async_save_tokens(hass, config_entry, access_token, refresh_token)
    coordinator = TeslaDataUpdateCoordinator(hass,
                                             config_entry=config_entry,
                                             controller=controller)
    # Fetch initial data so we have data when entities subscribe
    entry_data = hass.data[DOMAIN][config_entry.entry_id] = {
        "coordinator": coordinator,
        "devices": defaultdict(list),
        DATA_LISTENER: [config_entry.add_update_listener(update_listener)],
    }
    _LOGGER.debug("Connected to the Tesla API")

    await coordinator.async_refresh()
    if not coordinator.last_update_success:
        raise ConfigEntryNotReady

    all_devices = controller.get_homeassistant_components()

    if not all_devices:
        return False

    for device in all_devices:
        entry_data["devices"][device.hass_type].append(device)

    for platform in PLATFORMS:
        _LOGGER.debug("Loading %s", platform)
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(
                config_entry, platform))
    return True
Example #3
0
async def async_setup_entry(opp, config_entry):
    """Set up Tesla as config entry."""
    opp.data.setdefault(DOMAIN, {})
    config = config_entry.data
    # Because users can have multiple accounts, we always create a new session so they have separate cookies
    async_client = httpx.AsyncClient(headers={USER_AGENT: SERVER_SOFTWARE},
                                     timeout=60)
    email = config_entry.title
    if email in opp.data[DOMAIN] and CONF_SCAN_INTERVAL in opp.data[DOMAIN][
            email]:
        scan_interval = opp.data[DOMAIN][email][CONF_SCAN_INTERVAL]
        opp.config_entries.async_update_entry(
            config_entry, options={CONF_SCAN_INTERVAL: scan_interval})
        opp.data[DOMAIN].pop(email)
    try:
        controller = TeslaAPI(
            async_client,
            email=config.get(CONF_USERNAME),
            password=config.get(CONF_PASSWORD),
            refresh_token=config[CONF_TOKEN],
            access_token=config[CONF_ACCESS_TOKEN],
            expiration=config.get(CONF_EXPIRATION, 0),
            update_interval=config_entry.options.get(CONF_SCAN_INTERVAL,
                                                     DEFAULT_SCAN_INTERVAL),
        )
        result = await controller.connect(
            wake_if_asleep=config_entry.options.get(CONF_WAKE_ON_START,
                                                    DEFAULT_WAKE_ON_START))
        refresh_token = result["refresh_token"]
        access_token = result["access_token"]
    except IncompleteCredentials as ex:
        await async_client.aclose()
        raise ConfigEntryAuthFailed from ex
    except httpx.ConnectTimeout as ex:
        await async_client.aclose()
        raise ConfigEntryNotReady from ex
    except TeslaException as ex:
        await async_client.aclose()
        if ex.code == HTTP_UNAUTHORIZED:
            raise ConfigEntryAuthFailed from ex
        _LOGGER.error("Unable to communicate with Tesla API: %s", ex.message)
        return False

    async def _async_close_client(*_):
        await async_client.aclose()

    @callback
    def _async_create_close_task():
        asyncio.create_task(_async_close_client())

    config_entry.async_on_unload(
        opp.bus.async_listen_once(EVENT_OPENPEERPOWER_CLOSE,
                                  _async_close_client))
    config_entry.async_on_unload(_async_create_close_task)

    _async_save_tokens(opp, config_entry, access_token, refresh_token)
    coordinator = TeslaDataUpdateCoordinator(opp,
                                             config_entry=config_entry,
                                             controller=controller)
    # Fetch initial data so we have data when entities subscribe
    entry_data = opp.data[DOMAIN][config_entry.entry_id] = {
        "coordinator": coordinator,
        "devices": defaultdict(list),
        DATA_LISTENER: [config_entry.add_update_listener(update_listener)],
    }
    _LOGGER.debug("Connected to the Tesla API")

    await coordinator.async_config_entry_first_refresh()

    all_devices = controller.get_homeassistant_components()

    if not all_devices:
        return False

    for device in all_devices:
        entry_data["devices"][device.opp_type].append(device)

    opp.config_entries.async_setup_platforms(config_entry, PLATFORMS)

    return True