async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the Luftdaten sensor.""" from luftdaten import Luftdaten name = config.get(CONF_NAME) show_on_map = config.get(CONF_SHOW_ON_MAP) sensor_id = config.get(CONF_SENSORID) session = async_get_clientsession(hass) luftdaten = LuftdatenData(Luftdaten(sensor_id, hass.loop, session)) await luftdaten.async_update() if luftdaten.data is None: _LOGGER.error("Sensor is not available: %s", sensor_id) return devices = [] for variable in config[CONF_MONITORED_CONDITIONS]: if luftdaten.data.values[variable] is None: _LOGGER.warning( "It might be that sensor %s is not providing " "measurements for %s", sensor_id, variable) devices.append( LuftdatenSensor(luftdaten, name, variable, sensor_id, show_on_map)) async_add_entities(devices)
async def async_setup_entry(hass, config_entry): """Set up Luftdaten as config entry.""" from luftdaten import Luftdaten from luftdaten.exceptions import LuftdatenError session = async_get_clientsession(hass) try: luftdaten = LuftDatenData( Luftdaten(config_entry.data[CONF_SENSOR_ID], hass.loop, session), config_entry.data.get(CONF_SENSORS, {}).get(CONF_MONITORED_CONDITIONS, list(SENSORS))) await luftdaten.async_update() hass.data[DOMAIN][DATA_LUFTDATEN_CLIENT][config_entry.entry_id] = \ luftdaten except LuftdatenError: raise ConfigEntryNotReady hass.async_create_task( hass.config_entries.async_forward_entry_setup(config_entry, 'sensor')) async def refresh_sensors(event_time): """Refresh Luftdaten data.""" await luftdaten.async_update() async_dispatcher_send(hass, TOPIC_UPDATE) hass.data[DOMAIN][DATA_LUFTDATEN_LISTENER][ config_entry.entry_id] = async_track_time_interval( hass, refresh_sensors, hass.data[DOMAIN].get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)) return True
async def async_step_user(self, user_input=None): """Handle the start of the config flow.""" if not user_input: return self._show_form() sensor_id = user_input[CONF_SENSOR_ID] if sensor_id in configured_sensors(self.hass): return self._show_form({CONF_SENSOR_ID: "sensor_exists"}) session = aiohttp_client.async_get_clientsession(self.hass) luftdaten = Luftdaten(user_input[CONF_SENSOR_ID], self.hass.loop, session) try: await luftdaten.get_data() valid = await luftdaten.validate_sensor() except LuftdatenConnectionError: return self._show_form({CONF_SENSOR_ID: "communication_error"}) if not valid: return self._show_form({CONF_SENSOR_ID: "invalid_sensor"}) available_sensors = [ x for x in luftdaten.values if luftdaten.values[x] is not None ] if available_sensors: user_input.update( {CONF_SENSORS: {CONF_MONITORED_CONDITIONS: available_sensors}} ) scan_interval = user_input.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) user_input.update({CONF_SCAN_INTERVAL: scan_interval.seconds}) return self.async_create_entry(title=str(sensor_id), data=user_input)
async def async_step_user(self, user_input=None): """Handle the start of the config flow.""" from luftdaten import Luftdaten, exceptions if not user_input: return self._show_form() sensor_id = user_input[CONF_SENSOR_ID] if sensor_id in configured_sensors(self.hass): return self._show_form({CONF_SENSOR_ID: 'sensor_exists'}) session = aiohttp_client.async_get_clientsession(self.hass) luftdaten = Luftdaten( user_input[CONF_SENSOR_ID], self.hass.loop, session) try: await luftdaten.get_data() valid = await luftdaten.validate_sensor() except exceptions.LuftdatenConnectionError: return self._show_form( {CONF_SENSOR_ID: 'communication_error'}) if not valid: return self._show_form({CONF_SENSOR_ID: 'invalid_sensor'}) scan_interval = user_input.get( CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) user_input.update({CONF_SCAN_INTERVAL: scan_interval.seconds}) return self.async_create_entry(title=str(sensor_id), data=user_input)
async def async_step_user(self, user_input=None): """Handle the start of the config flow.""" if not user_input: return self._show_form() await self.async_set_unique_id(str(user_input[CONF_SENSOR_ID])) self._abort_if_unique_id_configured() luftdaten = Luftdaten(user_input[CONF_SENSOR_ID]) try: await luftdaten.get_data() valid = await luftdaten.validate_sensor() except LuftdatenConnectionError: return self._show_form({CONF_SENSOR_ID: "cannot_connect"}) if not valid: return self._show_form({CONF_SENSOR_ID: "invalid_sensor"}) available_sensors = [ x for x, x_values in luftdaten.values.items() if x_values is not None ] if available_sensors: user_input.update( {CONF_SENSORS: {CONF_MONITORED_CONDITIONS: available_sensors}} ) scan_interval = user_input.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) user_input.update({CONF_SCAN_INTERVAL: scan_interval.total_seconds()}) return self.async_create_entry( title=str(user_input[CONF_SENSOR_ID]), data=user_input )
async def test_sensor_values(httpx_mock: HTTPXMock): """Test the sensor values.""" httpx_mock.add_response(json=RESPONSE_VALID) client = Luftdaten(SENSOR_ID) await client.get_data() assert client.values == {"temperature": 10.5, "humidity": 79.3}
async def test_meta(httpx_mock: HTTPXMock): """Test the meta information.""" httpx_mock.add_response(json=RESPONSE_VALID) client = Luftdaten(SENSOR_ID) await client.get_data() assert client.meta["sensor_id"] == 1 assert client.meta["latitude"] == 48.792 assert client.meta["longitude"] == 9.164 assert client.meta["altitude"] == 326.9
async def test_timeout(httpx_mock: HTTPXMock): """Test if the connection is hitting the timeout.""" def raise_timeout(request): """Set the timeout for the requests.""" raise httpx.ReadTimeout( f"Unable to read within {request.extensions['timeout']}", request=request) httpx_mock.add_callback(raise_timeout) with pytest.raises(httpx.ReadTimeout): client = Luftdaten(SENSOR_ID) await client.get_data()
async def async_setup_entry(hass, config_entry): """Set up Luftdaten as config entry.""" from luftdaten import Luftdaten from luftdaten.exceptions import LuftdatenError if not isinstance(config_entry.data[CONF_SENSOR_ID], int): _async_fixup_sensor_id(hass, config_entry, config_entry.data[CONF_SENSOR_ID]) if ( config_entry.data[CONF_SENSOR_ID] in duplicate_stations(hass) and config_entry.source == SOURCE_IMPORT ): _LOGGER.warning( "Removing duplicate sensors for station %s", config_entry.data[CONF_SENSOR_ID], ) hass.async_create_task(hass.config_entries.async_remove(config_entry.entry_id)) return False session = async_get_clientsession(hass) try: luftdaten = LuftDatenData( Luftdaten(config_entry.data[CONF_SENSOR_ID], hass.loop, session), config_entry.data.get(CONF_SENSORS, {}).get( CONF_MONITORED_CONDITIONS, list(SENSORS) ), ) await luftdaten.async_update() hass.data[DOMAIN][DATA_LUFTDATEN_CLIENT][config_entry.entry_id] = luftdaten except LuftdatenError: raise ConfigEntryNotReady hass.async_create_task( hass.config_entries.async_forward_entry_setup(config_entry, "sensor") ) async def refresh_sensors(event_time): """Refresh Luftdaten data.""" await luftdaten.async_update() async_dispatcher_send(hass, TOPIC_UPDATE) hass.data[DOMAIN][DATA_LUFTDATEN_LISTENER][ config_entry.entry_id ] = async_track_time_interval( hass, refresh_sensors, hass.data[DOMAIN].get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL), ) return True
async def main(): """Sample code to retrieve the data.""" async with aiohttp.ClientSession() as session: data = Luftdaten(SENSOR_ID, loop, session) await data.get_data() if not await data.validate_sensor(): print("Station is not available:", data.sensor_id) return if data.values and data.meta: # Print the sensor values print("Sensor values:", data.values) # Print the coordinates fo the sensor print("Location:", data.meta['latitude'], data.meta['longitude'])
async def async_setup_entry(hass, config_entry): """Set up Luftdaten as config entry.""" hass.data.setdefault( DOMAIN, { DATA_LUFTDATEN_CLIENT: {}, DATA_LUFTDATEN_LISTENER: {}, }, ) # For backwards compat, set unique ID if config_entry.unique_id is None: hass.config_entries.async_update_entry( config_entry, unique_id=config_entry.data[CONF_SENSOR_ID]) try: luftdaten = LuftDatenData( Luftdaten(config_entry.data[CONF_SENSOR_ID]), config_entry.data.get(CONF_SENSORS, {}).get(CONF_MONITORED_CONDITIONS, SENSOR_KEYS), ) await luftdaten.async_update() hass.data[DOMAIN][DATA_LUFTDATEN_CLIENT][ config_entry.entry_id] = luftdaten except LuftdatenError as err: raise ConfigEntryNotReady from err hass.config_entries.async_setup_platforms(config_entry, PLATFORMS) async def refresh_sensors(event_time): """Refresh Luftdaten data.""" await luftdaten.async_update() async_dispatcher_send(hass, TOPIC_UPDATE) hass.data[DOMAIN][DATA_LUFTDATEN_LISTENER][ config_entry.entry_id] = async_track_time_interval( hass, refresh_sensors, hass.data[DOMAIN].get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL), ) return True
async def main(): """Sample code to retrieve the data.""" data = Luftdaten(SENSOR_ID) await data.get_data() if not await data.validate_sensor(): print("Station is not available:", data.sensor_id) return if data.values and data.meta: # Print the sensor values print("Sensor values:", data.values) # Print the coordinates fo the sensor print( "Location:", data.meta["latitude"], data.meta["longitude"], data.meta["altitude"], )
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Sensor.Community as config entry.""" # For backwards compat, set unique ID if entry.unique_id is None: hass.config_entries.async_update_entry(entry, unique_id=str( entry.data[CONF_SENSOR_ID])) sensor_community = Luftdaten(entry.data[CONF_SENSOR_ID]) async def async_update() -> dict[str, float | int]: """Update sensor/binary sensor data.""" try: await sensor_community.get_data() except LuftdatenError as err: raise UpdateFailed( "Unable to retrieve data from Sensor.Community") from err if not sensor_community.values: raise UpdateFailed( "Did not receive sensor data from Sensor.Community") data: dict[str, float | int] = sensor_community.values data.update(sensor_community.meta) return data coordinator: DataUpdateCoordinator[dict[str, Any]] = DataUpdateCoordinator( hass, _LOGGER, name=f"{DOMAIN}_{sensor_community.sensor_id}", update_interval=DEFAULT_SCAN_INTERVAL, update_method=async_update, ) await coordinator.async_config_entry_first_refresh() hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator hass.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def async_step_user( self, user_input: dict[str, Any] | None = None ) -> FlowResult: """Handle the start of the config flow.""" if user_input is None: return self._show_form() await self.async_set_unique_id(str(user_input[CONF_SENSOR_ID])) self._abort_if_unique_id_configured() sensor_community = Luftdaten(user_input[CONF_SENSOR_ID]) try: await sensor_community.get_data() valid = await sensor_community.validate_sensor() except LuftdatenConnectionError: return self._show_form({CONF_SENSOR_ID: "cannot_connect"}) if not valid: return self._show_form({CONF_SENSOR_ID: "invalid_sensor"}) return self.async_create_entry( title=str(user_input[CONF_SENSOR_ID]), data=user_input )