async def async_step_node_pro(self, user_input=None):
        """Handle the initialization of the integration with a Node/Pro."""
        if not user_input:
            return self.async_show_form(step_id="node_pro",
                                        data_schema=self.node_pro_schema)

        await self._async_set_unique_id(user_input[CONF_IP_ADDRESS])

        websession = aiohttp_client.async_get_clientsession(self.hass)
        client = Client(websession)

        try:
            await client.node.from_samba(user_input[CONF_IP_ADDRESS],
                                         user_input[CONF_PASSWORD])
        except NodeProError as err:
            LOGGER.error("Error connecting to Node/Pro unit: %s", err)
            return self.async_show_form(
                step_id="node_pro",
                data_schema=self.node_pro_schema,
                errors={CONF_IP_ADDRESS: "unable_to_connect"},
            )

        return self.async_create_entry(
            title=f"Node/Pro ({user_input[CONF_IP_ADDRESS]})",
            data={
                **user_input, CONF_INTEGRATION_TYPE: INTEGRATION_TYPE_NODE_PRO
            },
        )
    async def async_step_user(self, user_input=None):
        """Handle the start of the config flow."""
        if not user_input:
            return await self._show_form()

        geo_id = async_get_geography_id(user_input)
        await self._async_set_unique_id(geo_id)

        websession = aiohttp_client.async_get_clientsession(self.hass)
        client = Client(websession, api_key=user_input[CONF_API_KEY])

        # If this is the first (and only the first) time we've seen this API key, check
        # that it's valid:
        checked_keys = self.hass.data.setdefault("airvisual_checked_api_keys",
                                                 set())
        check_keys_lock = self.hass.data.setdefault(
            "airvisual_checked_api_keys_lock", asyncio.Lock())

        async with check_keys_lock:
            if user_input[CONF_API_KEY] not in checked_keys:
                try:
                    await client.api.nearest_city()
                except InvalidKeyError:
                    return await self._show_form(
                        errors={CONF_API_KEY: "invalid_api_key"})

                checked_keys.add(user_input[CONF_API_KEY])
                return self.async_create_entry(title=f"Cloud API ({geo_id})",
                                               data=user_input)
Exemple #3
0
async def async_setup_platform(
        hass, config, async_add_entities, discovery_info=None):
    """Configure the platform and add the sensors."""
    from pyairvisual import Client

    city = config.get(CONF_CITY)
    state = config.get(CONF_STATE)
    country = config.get(CONF_COUNTRY)

    latitude = config.get(CONF_LATITUDE, hass.config.latitude)
    longitude = config.get(CONF_LONGITUDE, hass.config.longitude)

    websession = aiohttp_client.async_get_clientsession(hass)

    if city and state and country:
        _LOGGER.debug(
            "Using city, state, and country: %s, %s, %s", city, state, country)
        location_id = ','.join((city, state, country))
        data = AirVisualData(
            Client(config[CONF_API_KEY], websession),
            city=city,
            state=state,
            country=country,
            show_on_map=config[CONF_SHOW_ON_MAP],
            scan_interval=config[CONF_SCAN_INTERVAL])
    else:
        _LOGGER.debug(
            "Using latitude and longitude: %s, %s", latitude, longitude)
        location_id = ','.join((str(latitude), str(longitude)))
        data = AirVisualData(
            Client(config[CONF_API_KEY], websession),
            latitude=latitude,
            longitude=longitude,
            show_on_map=config[CONF_SHOW_ON_MAP],
            scan_interval=config[CONF_SCAN_INTERVAL])

    await data.async_update()

    sensors = []
    for locale in config[CONF_MONITORED_CONDITIONS]:
        for kind, name, icon, unit in SENSORS:
            sensors.append(
                AirVisualSensor(
                    data, kind, name, icon, unit, locale, location_id))

    async_add_entities(sensors, True)
Exemple #4
0
async def async_setup_entry(hass, config_entry):
    """Set up AirVisual as config entry."""
    websession = aiohttp_client.async_get_clientsession(hass)

    if CONF_API_KEY in config_entry.data:
        _standardize_geography_config_entry(hass, config_entry)
        airvisual = AirVisualGeographyData(
            hass,
            Client(websession, api_key=config_entry.data[CONF_API_KEY]),
            config_entry,
        )

        # Only geography-based entries have options:
        config_entry.add_update_listener(async_update_options)
    else:
        _standardize_node_pro_config_entry(hass, config_entry)
        airvisual = AirVisualNodeProData(hass, Client(websession),
                                         config_entry)

    await airvisual.async_update()

    hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id] = airvisual

    for component in PLATFORMS:
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(
                config_entry, component))

    async def refresh(event_time):
        """Refresh data from AirVisual."""
        await airvisual.async_update()

    hass.data[DOMAIN][DATA_LISTENER][
        config_entry.entry_id] = async_track_time_interval(
            hass, refresh, airvisual.scan_interval)

    return True
Exemple #5
0
    async def async_step_geography(self, user_input=None):
        """Handle the initialization of the integration via the cloud API."""
        if not user_input:
            return self.async_show_form(step_id="geography",
                                        data_schema=self.geography_schema)

        geo_id = async_get_geography_id(user_input)
        await self._async_set_unique_id(geo_id)
        self._abort_if_unique_id_configured()

        # Find older config entries without unique ID:
        for entry in self._async_current_entries():
            if entry.version != 1:
                continue

            if any(geo_id == async_get_geography_id(geography)
                   for geography in entry.data[CONF_GEOGRAPHIES]):
                return self.async_abort(reason="already_configured")

        websession = aiohttp_client.async_get_clientsession(self.hass)
        client = Client(session=websession, api_key=user_input[CONF_API_KEY])

        # If this is the first (and only the first) time we've seen this API key, check
        # that it's valid:
        checked_keys = self.hass.data.setdefault("airvisual_checked_api_keys",
                                                 set())
        check_keys_lock = self.hass.data.setdefault(
            "airvisual_checked_api_keys_lock", asyncio.Lock())

        async with check_keys_lock:
            if user_input[CONF_API_KEY] not in checked_keys:
                try:
                    await client.api.nearest_city()
                except InvalidKeyError:
                    return self.async_show_form(
                        step_id="geography",
                        data_schema=self.geography_schema,
                        errors={CONF_API_KEY: "invalid_api_key"},
                    )

                checked_keys.add(user_input[CONF_API_KEY])

            return self.async_create_entry(
                title=f"Cloud API ({geo_id})",
                data={
                    **user_input, CONF_INTEGRATION_TYPE:
                    INTEGRATION_TYPE_GEOGRAPHY
                },
            )
Exemple #6
0
async def async_setup_entry(hass, config_entry):
    """Set up AirVisual as config entry."""
    entry_updates = {}
    if not config_entry.unique_id:
        # If the config entry doesn't already have a unique ID, set one:
        entry_updates["unique_id"] = config_entry.data[CONF_API_KEY]
    if not config_entry.options:
        # If the config entry doesn't already have any options set, set defaults:
        entry_updates["options"] = DEFAULT_OPTIONS

    if entry_updates:
        hass.config_entries.async_update_entry(config_entry, **entry_updates)

    websession = aiohttp_client.async_get_clientsession(hass)

    hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id] = AirVisualData(
        hass, Client(websession, api_key=config_entry.data[CONF_API_KEY]),
        config_entry)

    try:
        await hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id
                                             ].async_update()
    except InvalidKeyError:
        _LOGGER.error("Invalid API key provided")
        raise ConfigEntryNotReady

    hass.async_create_task(
        hass.config_entries.async_forward_entry_setup(config_entry, "sensor"))

    async def refresh(event_time):
        """Refresh data from AirVisual."""
        await hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id
                                             ].async_update()

    hass.data[DOMAIN][DATA_LISTENER][
        config_entry.entry_id] = async_track_time_interval(
            hass, refresh, DEFAULT_SCAN_INTERVAL)

    config_entry.add_update_listener(async_update_options)

    return True
async def async_setup_entry(hass, config_entry):
    """Set up AirVisual as config entry."""
    websession = aiohttp_client.async_get_clientsession(hass)

    if CONF_API_KEY in config_entry.data:
        _standardize_geography_config_entry(hass, config_entry)

        client = Client(api_key=config_entry.data[CONF_API_KEY],
                        session=websession)

        update_interval = async_get_cloud_api_update_interval(
            hass, config_entry.data[CONF_API_KEY])

        async def async_update_data():
            """Get new data from the API."""
            if CONF_CITY in config_entry.data:
                api_coro = client.api.city(
                    config_entry.data[CONF_CITY],
                    config_entry.data[CONF_STATE],
                    config_entry.data[CONF_COUNTRY],
                )
            else:
                api_coro = client.api.nearest_city(
                    config_entry.data[CONF_LATITUDE],
                    config_entry.data[CONF_LONGITUDE],
                )

            try:
                return await api_coro
            except AirVisualError as err:
                raise UpdateFailed(f"Error while retrieving data: {err}")

        coordinator = DataUpdateCoordinator(
            hass,
            LOGGER,
            name="geography data",
            update_interval=update_interval,
            update_method=async_update_data,
        )

        # Ensure any other, existing config entries that use this API key are updated
        # with the new scan interval:
        async_reset_coordinator_update_intervals(hass, update_interval)

        # Only geography-based entries have options:
        config_entry.add_update_listener(async_update_options)
    else:
        _standardize_node_pro_config_entry(hass, config_entry)

        client = Client(session=websession)

        async def async_update_data():
            """Get new data from the API."""
            try:
                return await client.node.from_samba(
                    config_entry.data[CONF_IP_ADDRESS],
                    config_entry.data[CONF_PASSWORD],
                    include_history=False,
                    include_trends=False,
                )
            except NodeProError as err:
                raise UpdateFailed(f"Error while retrieving data: {err}")

        coordinator = DataUpdateCoordinator(
            hass,
            LOGGER,
            name="Node/Pro data",
            update_interval=DEFAULT_NODE_PRO_SCAN_INTERVAL,
            update_method=async_update_data,
        )

    await coordinator.async_refresh()

    hass.data[DOMAIN][DATA_COORDINATOR][config_entry.entry_id] = coordinator

    for component in PLATFORMS:
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(
                config_entry, component))

    return True
Exemple #8
0
async def async_setup_entry(hass, config_entry):
    """Set up AirVisual as config entry."""
    websession = aiohttp_client.async_get_clientsession(hass)

    if CONF_API_KEY in config_entry.data:
        _standardize_geography_config_entry(hass, config_entry)

        client = Client(api_key=config_entry.data[CONF_API_KEY], session=websession)

        async def async_update_data():
            """Get new data from the API."""
            if CONF_CITY in config_entry.data:
                api_coro = client.api.city(
                    config_entry.data[CONF_CITY],
                    config_entry.data[CONF_STATE],
                    config_entry.data[CONF_COUNTRY],
                )
            else:
                api_coro = client.api.nearest_city(
                    config_entry.data[CONF_LATITUDE], config_entry.data[CONF_LONGITUDE],
                )

            try:
                return await api_coro
            except AirVisualError as err:
                raise UpdateFailed(f"Error while retrieving data: {err}")

        coordinator = DataUpdateCoordinator(
            hass,
            LOGGER,
            name=async_get_geography_id(config_entry.data),
            # We give a placeholder update interval in order to create the coordinator;
            # then, below, we use the coordinator's presence (along with any other
            # coordinators using the same API key) to calculate an actual, leveled
            # update interval:
            update_interval=timedelta(minutes=5),
            update_method=async_update_data,
        )

        hass.data[DOMAIN][DATA_COORDINATOR][config_entry.entry_id] = coordinator
        async_sync_geo_coordinator_update_intervals(
            hass, config_entry.data[CONF_API_KEY]
        )

        # Only geography-based entries have options:
        config_entry.add_update_listener(async_update_options)
    else:
        _standardize_node_pro_config_entry(hass, config_entry)

        client = Client(session=websession)

        async def async_update_data():
            """Get new data from the API."""
            try:
                return await client.node.from_samba(
                    config_entry.data[CONF_IP_ADDRESS],
                    config_entry.data[CONF_PASSWORD],
                    include_history=False,
                    include_trends=False,
                )
            except NodeProError as err:
                raise UpdateFailed(f"Error while retrieving data: {err}")

        coordinator = DataUpdateCoordinator(
            hass,
            LOGGER,
            name="Node/Pro data",
            update_interval=DEFAULT_NODE_PRO_UPDATE_INTERVAL,
            update_method=async_update_data,
        )

        hass.data[DOMAIN][DATA_COORDINATOR][config_entry.entry_id] = coordinator

    await coordinator.async_refresh()

    for component in PLATFORMS:
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(config_entry, component)
        )

    return True