1 """Sensor for checking the status of London air."""
3 from __future__
import annotations
5 from datetime
import timedelta
6 from http
import HTTPStatus
10 import voluptuous
as vol
13 PLATFORM_SCHEMA
as SENSOR_PLATFORM_SCHEMA,
22 _LOGGER = logging.getLogger(__name__)
24 CONF_LOCATIONS =
"locations"
29 "Barking and Dagenham",
45 "Kensington and Chelsea",
59 URL =
"http://api.erg.kcl.ac.uk/AirQuality/Hourly/MonitoringIndex/GroupName=London/Json"
61 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
63 vol.Optional(CONF_LOCATIONS, default=AUTHORITIES): vol.All(
64 cv.ensure_list, [vol.In(AUTHORITIES)]
73 add_entities: AddEntitiesCallback,
74 discovery_info: DiscoveryInfoType |
None =
None,
76 """Set up the London Air sensor."""
84 """Get the latest data for all authorities."""
87 """Initialize the AirData object."""
91 @Throttle(SCAN_INTERVAL)
93 """Get the latest data from TFL."""
94 response = requests.get(URL, timeout=10)
95 if response.status_code != HTTPStatus.OK:
96 _LOGGER.warning(
"Invalid response from API")
102 """Single authority air sensor."""
104 ICON =
"mdi:cloud-outline"
107 """Initialize the sensor."""
116 """Return the name of the sensor."""
117 return self.
_name_name
121 """Return the state of the sensor."""
126 """Return the dict of sites data."""
131 """Icon to use in the frontend, if any."""
136 """Return other details about the sensor state."""
138 attrs[
"updated"] = self.
_updated_updated
144 """Update the sensor."""
145 sites_status: list = []
151 site[
"pollutants_status"]
153 if site[
"pollutants_status"] !=
"no_species_data"
157 self.
_state_state =
max(set(sites_status), key=sites_status.count)
163 """Iterate over list of species at each site."""
164 parsed_species_data = []
166 for species
in species_data:
167 if species[
"@AirQualityBand"] !=
"No data":
169 species_dict[
"description"] = species[
"@SpeciesDescription"]
170 species_dict[
"code"] = species[
"@SpeciesCode"]
171 species_dict[
"quality"] = species[
"@AirQualityBand"]
172 species_dict[
"index"] = species[
"@AirQualityIndex"]
173 species_dict[
"summary"] = (
174 f
"{species_dict['code']} is {species_dict['quality']}"
176 parsed_species_data.append(species_dict)
177 quality_list.append(species_dict[
"quality"])
178 return parsed_species_data, quality_list
182 """Iterate over all sites at an authority."""
184 for site
in entry_sites_data:
188 site_data[
"updated"] = site[
"@BulletinDate"]
189 site_data[
"latitude"] = site[
"@Latitude"]
190 site_data[
"longitude"] = site[
"@Longitude"]
191 site_data[
"site_code"] = site[
"@SiteCode"]
192 site_data[
"site_name"] = site[
"@SiteName"].split(
"-")[-1].lstrip()
193 site_data[
"site_type"] = site[
"@SiteType"]
195 if isinstance(site[
"Species"], dict):
196 species_data = [site[
"Species"]]
198 species_data = site[
"Species"]
200 parsed_species_data, quality_list =
parse_species(species_data)
202 if not parsed_species_data:
203 parsed_species_data.append(
"no_species_data")
204 site_data[
"pollutants"] = parsed_species_data
207 site_data[
"pollutants_status"] =
max(
208 set(quality_list), key=quality_list.count
210 site_data[
"number_of_pollutants"] = len(quality_list)
212 site_data[
"pollutants_status"] =
"no_species_data"
213 site_data[
"number_of_pollutants"] = 0
215 authority_data.append(site_data)
216 return authority_data
220 """Parse return dict or list of data from API."""
221 data = dict.fromkeys(AUTHORITIES)
222 for authority
in AUTHORITIES:
223 for entry
in response[
"HourlyAirQualityIndex"][
"LocalAuthority"]:
224 if entry[
"@LocalAuthorityName"] == authority:
225 entry_sites_data = []
227 if isinstance(entry[
"Site"], dict):
228 entry_sites_data = [entry[
"Site"]]
230 entry_sites_data = entry[
"Site"]
232 data[authority] =
parse_site(entry_sites_data)
def extra_state_attributes(self)
def __init__(self, name, api_data)
def add_entities(account, async_add_entities, tracked)
def parse_species(species_data)
def parse_site(entry_sites_data)
def parse_api_response(response)
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)