diff --git a/homeassistant/components/ambient_station/__init__.py b/homeassistant/components/ambient_station/__init__.py index d719f9b3728..201f21c0f17 100644 --- a/homeassistant/components/ambient_station/__init__.py +++ b/homeassistant/components/ambient_station/__init__.py @@ -1,38 +1,17 @@ """Support for Ambient Weather Station Service.""" from __future__ import annotations +from typing import Any + from aioambient import Client from aioambient.errors import WebsocketError -from homeassistant.components.binary_sensor import ( - DEVICE_CLASS_CONNECTIVITY, - DOMAIN as BINARY_SENSOR, -) -from homeassistant.components.sensor import DOMAIN as SENSOR from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( ATTR_LOCATION, ATTR_NAME, - CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, - CONCENTRATION_PARTS_PER_MILLION, CONF_API_KEY, - DEGREE, - DEVICE_CLASS_BATTERY, - DEVICE_CLASS_CO2, - DEVICE_CLASS_HUMIDITY, - DEVICE_CLASS_ILLUMINANCE, - DEVICE_CLASS_PRESSURE, - DEVICE_CLASS_TEMPERATURE, - DEVICE_CLASS_TIMESTAMP, EVENT_HOMEASSISTANT_STOP, - IRRADIATION_WATTS_PER_SQUARE_METER, - LIGHT_LUX, - PERCENTAGE, - PRECIPITATION_INCHES, - PRECIPITATION_INCHES_PER_HOUR, - PRESSURE_INHG, - SPEED_MILES_PER_HOUR, - TEMP_FAHRENHEIT, ) from homeassistant.core import Event, HomeAssistant, callback from homeassistant.exceptions import ConfigEntryNotReady @@ -41,266 +20,43 @@ from homeassistant.helpers.dispatcher import ( async_dispatcher_connect, async_dispatcher_send, ) -from homeassistant.helpers.entity import Entity +from homeassistant.helpers.entity import Entity, EntityDescription from homeassistant.helpers.event import async_call_later from .const import ( ATTR_LAST_DATA, - ATTR_MONITORED_CONDITIONS, CONF_APP_KEY, DATA_CLIENT, DOMAIN, LOGGER, + TYPE_SOLARRADIATION, + TYPE_SOLARRADIATION_LX, ) -PLATFORMS = [BINARY_SENSOR, SENSOR] +PLATFORMS = ["binary_sensor", "sensor"] DATA_CONFIG = "config" DEFAULT_SOCKET_MIN_RETRY = 15 -TYPE_24HOURRAININ = "24hourrainin" -TYPE_BAROMABSIN = "baromabsin" -TYPE_BAROMRELIN = "baromrelin" -TYPE_BATT1 = "batt1" -TYPE_BATT10 = "batt10" -TYPE_BATT2 = "batt2" -TYPE_BATT3 = "batt3" -TYPE_BATT4 = "batt4" -TYPE_BATT5 = "batt5" -TYPE_BATT6 = "batt6" -TYPE_BATT7 = "batt7" -TYPE_BATT8 = "batt8" -TYPE_BATT9 = "batt9" -TYPE_BATT_CO2 = "batt_co2" -TYPE_BATTOUT = "battout" -TYPE_CO2 = "co2" -TYPE_DAILYRAININ = "dailyrainin" -TYPE_DEWPOINT = "dewPoint" -TYPE_EVENTRAININ = "eventrainin" -TYPE_FEELSLIKE = "feelsLike" -TYPE_HOURLYRAININ = "hourlyrainin" -TYPE_HUMIDITY = "humidity" -TYPE_HUMIDITY1 = "humidity1" -TYPE_HUMIDITY10 = "humidity10" -TYPE_HUMIDITY2 = "humidity2" -TYPE_HUMIDITY3 = "humidity3" -TYPE_HUMIDITY4 = "humidity4" -TYPE_HUMIDITY5 = "humidity5" -TYPE_HUMIDITY6 = "humidity6" -TYPE_HUMIDITY7 = "humidity7" -TYPE_HUMIDITY8 = "humidity8" -TYPE_HUMIDITY9 = "humidity9" -TYPE_HUMIDITYIN = "humidityin" -TYPE_LASTRAIN = "lastRain" -TYPE_MAXDAILYGUST = "maxdailygust" -TYPE_MONTHLYRAININ = "monthlyrainin" -TYPE_PM25 = "pm25" -TYPE_PM25_24H = "pm25_24h" -TYPE_PM25_BATT = "batt_25" -TYPE_PM25_IN = "pm25_in" -TYPE_PM25_IN_24H = "pm25_in_24h" -TYPE_PM25IN_BATT = "batt_25in" -TYPE_RELAY1 = "relay1" -TYPE_RELAY10 = "relay10" -TYPE_RELAY2 = "relay2" -TYPE_RELAY3 = "relay3" -TYPE_RELAY4 = "relay4" -TYPE_RELAY5 = "relay5" -TYPE_RELAY6 = "relay6" -TYPE_RELAY7 = "relay7" -TYPE_RELAY8 = "relay8" -TYPE_RELAY9 = "relay9" -TYPE_SOILHUM1 = "soilhum1" -TYPE_SOILHUM10 = "soilhum10" -TYPE_SOILHUM2 = "soilhum2" -TYPE_SOILHUM3 = "soilhum3" -TYPE_SOILHUM4 = "soilhum4" -TYPE_SOILHUM5 = "soilhum5" -TYPE_SOILHUM6 = "soilhum6" -TYPE_SOILHUM7 = "soilhum7" -TYPE_SOILHUM8 = "soilhum8" -TYPE_SOILHUM9 = "soilhum9" -TYPE_SOILTEMP1F = "soiltemp1f" -TYPE_SOILTEMP10F = "soiltemp10f" -TYPE_SOILTEMP2F = "soiltemp2f" -TYPE_SOILTEMP3F = "soiltemp3f" -TYPE_SOILTEMP4F = "soiltemp4f" -TYPE_SOILTEMP5F = "soiltemp5f" -TYPE_SOILTEMP6F = "soiltemp6f" -TYPE_SOILTEMP7F = "soiltemp7f" -TYPE_SOILTEMP8F = "soiltemp8f" -TYPE_SOILTEMP9F = "soiltemp9f" -TYPE_SOLARRADIATION = "solarradiation" -TYPE_SOLARRADIATION_LX = "solarradiation_lx" -TYPE_TEMP10F = "temp10f" -TYPE_TEMP1F = "temp1f" -TYPE_TEMP2F = "temp2f" -TYPE_TEMP3F = "temp3f" -TYPE_TEMP4F = "temp4f" -TYPE_TEMP5F = "temp5f" -TYPE_TEMP6F = "temp6f" -TYPE_TEMP7F = "temp7f" -TYPE_TEMP8F = "temp8f" -TYPE_TEMP9F = "temp9f" -TYPE_TEMPF = "tempf" -TYPE_TEMPINF = "tempinf" -TYPE_TOTALRAININ = "totalrainin" -TYPE_UV = "uv" -TYPE_WEEKLYRAININ = "weeklyrainin" -TYPE_WINDDIR = "winddir" -TYPE_WINDDIR_AVG10M = "winddir_avg10m" -TYPE_WINDDIR_AVG2M = "winddir_avg2m" -TYPE_WINDGUSTDIR = "windgustdir" -TYPE_WINDGUSTMPH = "windgustmph" -TYPE_WINDSPDMPH_AVG10M = "windspdmph_avg10m" -TYPE_WINDSPDMPH_AVG2M = "windspdmph_avg2m" -TYPE_WINDSPEEDMPH = "windspeedmph" -TYPE_YEARLYRAININ = "yearlyrainin" -SENSOR_TYPES = { - TYPE_24HOURRAININ: ("24 Hr Rain", PRECIPITATION_INCHES, SENSOR, None), - TYPE_BAROMABSIN: ("Abs Pressure", PRESSURE_INHG, SENSOR, DEVICE_CLASS_PRESSURE), - TYPE_BAROMRELIN: ("Rel Pressure", PRESSURE_INHG, SENSOR, DEVICE_CLASS_PRESSURE), - TYPE_BATT10: ("Battery 10", None, BINARY_SENSOR, DEVICE_CLASS_BATTERY), - TYPE_BATT1: ("Battery 1", None, BINARY_SENSOR, DEVICE_CLASS_BATTERY), - TYPE_BATT2: ("Battery 2", None, BINARY_SENSOR, DEVICE_CLASS_BATTERY), - TYPE_BATT3: ("Battery 3", None, BINARY_SENSOR, DEVICE_CLASS_BATTERY), - TYPE_BATT4: ("Battery 4", None, BINARY_SENSOR, DEVICE_CLASS_BATTERY), - TYPE_BATT5: ("Battery 5", None, BINARY_SENSOR, DEVICE_CLASS_BATTERY), - TYPE_BATT6: ("Battery 6", None, BINARY_SENSOR, DEVICE_CLASS_BATTERY), - TYPE_BATT7: ("Battery 7", None, BINARY_SENSOR, DEVICE_CLASS_BATTERY), - TYPE_BATT8: ("Battery 8", None, BINARY_SENSOR, DEVICE_CLASS_BATTERY), - TYPE_BATT9: ("Battery 9", None, BINARY_SENSOR, DEVICE_CLASS_BATTERY), - TYPE_BATTOUT: ("Battery", None, BINARY_SENSOR, DEVICE_CLASS_BATTERY), - TYPE_BATT_CO2: ("CO2 Battery", None, BINARY_SENSOR, DEVICE_CLASS_BATTERY), - TYPE_CO2: ("co2", CONCENTRATION_PARTS_PER_MILLION, SENSOR, DEVICE_CLASS_CO2), - TYPE_DAILYRAININ: ("Daily Rain", PRECIPITATION_INCHES, SENSOR, None), - TYPE_DEWPOINT: ("Dew Point", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_EVENTRAININ: ("Event Rain", PRECIPITATION_INCHES, SENSOR, None), - TYPE_FEELSLIKE: ("Feels Like", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_HOURLYRAININ: ( - "Hourly Rain Rate", - PRECIPITATION_INCHES_PER_HOUR, - SENSOR, - None, - ), - TYPE_HUMIDITY10: ("Humidity 10", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_HUMIDITY1: ("Humidity 1", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_HUMIDITY2: ("Humidity 2", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_HUMIDITY3: ("Humidity 3", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_HUMIDITY4: ("Humidity 4", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_HUMIDITY5: ("Humidity 5", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_HUMIDITY6: ("Humidity 6", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_HUMIDITY7: ("Humidity 7", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_HUMIDITY8: ("Humidity 8", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_HUMIDITY9: ("Humidity 9", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_HUMIDITY: ("Humidity", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_HUMIDITYIN: ("Humidity In", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_LASTRAIN: ("Last Rain", None, SENSOR, DEVICE_CLASS_TIMESTAMP), - TYPE_MAXDAILYGUST: ("Max Gust", SPEED_MILES_PER_HOUR, SENSOR, None), - TYPE_MONTHLYRAININ: ("Monthly Rain", PRECIPITATION_INCHES, SENSOR, None), - TYPE_PM25_24H: ( - "PM25 24h Avg", - CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, - SENSOR, - None, - ), - TYPE_PM25_BATT: ("PM25 Battery", None, BINARY_SENSOR, DEVICE_CLASS_BATTERY), - TYPE_PM25_IN: ( - "PM25 Indoor", - CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, - SENSOR, - None, - ), - TYPE_PM25_IN_24H: ( - "PM25 Indoor 24h Avg", - CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, - SENSOR, - None, - ), - TYPE_PM25: ("PM25", CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, SENSOR, None), - TYPE_PM25IN_BATT: ( - "PM25 Indoor Battery", - None, - BINARY_SENSOR, - DEVICE_CLASS_BATTERY, - ), - TYPE_RELAY10: ("Relay 10", None, BINARY_SENSOR, DEVICE_CLASS_CONNECTIVITY), - TYPE_RELAY1: ("Relay 1", None, BINARY_SENSOR, DEVICE_CLASS_CONNECTIVITY), - TYPE_RELAY2: ("Relay 2", None, BINARY_SENSOR, DEVICE_CLASS_CONNECTIVITY), - TYPE_RELAY3: ("Relay 3", None, BINARY_SENSOR, DEVICE_CLASS_CONNECTIVITY), - TYPE_RELAY4: ("Relay 4", None, BINARY_SENSOR, DEVICE_CLASS_CONNECTIVITY), - TYPE_RELAY5: ("Relay 5", None, BINARY_SENSOR, DEVICE_CLASS_CONNECTIVITY), - TYPE_RELAY6: ("Relay 6", None, BINARY_SENSOR, DEVICE_CLASS_CONNECTIVITY), - TYPE_RELAY7: ("Relay 7", None, BINARY_SENSOR, DEVICE_CLASS_CONNECTIVITY), - TYPE_RELAY8: ("Relay 8", None, BINARY_SENSOR, DEVICE_CLASS_CONNECTIVITY), - TYPE_RELAY9: ("Relay 9", None, BINARY_SENSOR, DEVICE_CLASS_CONNECTIVITY), - TYPE_SOILHUM10: ("Soil Humidity 10", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_SOILHUM1: ("Soil Humidity 1", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_SOILHUM2: ("Soil Humidity 2", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_SOILHUM3: ("Soil Humidity 3", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_SOILHUM4: ("Soil Humidity 4", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_SOILHUM5: ("Soil Humidity 5", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_SOILHUM6: ("Soil Humidity 6", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_SOILHUM7: ("Soil Humidity 7", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_SOILHUM8: ("Soil Humidity 8", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_SOILHUM9: ("Soil Humidity 9", PERCENTAGE, SENSOR, DEVICE_CLASS_HUMIDITY), - TYPE_SOILTEMP10F: ( - "Soil Temp 10", - TEMP_FAHRENHEIT, - SENSOR, - DEVICE_CLASS_TEMPERATURE, - ), - TYPE_SOILTEMP1F: ("Soil Temp 1", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_SOILTEMP2F: ("Soil Temp 2", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_SOILTEMP3F: ("Soil Temp 3", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_SOILTEMP4F: ("Soil Temp 4", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_SOILTEMP5F: ("Soil Temp 5", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_SOILTEMP6F: ("Soil Temp 6", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_SOILTEMP7F: ("Soil Temp 7", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_SOILTEMP8F: ("Soil Temp 8", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_SOILTEMP9F: ("Soil Temp 9", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_SOLARRADIATION: ( - "Solar Rad", - IRRADIATION_WATTS_PER_SQUARE_METER, - SENSOR, - None, - ), - TYPE_SOLARRADIATION_LX: ( - "Solar Rad (lx)", - LIGHT_LUX, - SENSOR, - DEVICE_CLASS_ILLUMINANCE, - ), - TYPE_TEMP10F: ("Temp 10", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_TEMP1F: ("Temp 1", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_TEMP2F: ("Temp 2", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_TEMP3F: ("Temp 3", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_TEMP4F: ("Temp 4", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_TEMP5F: ("Temp 5", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_TEMP6F: ("Temp 6", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_TEMP7F: ("Temp 7", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_TEMP8F: ("Temp 8", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_TEMP9F: ("Temp 9", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_TEMPF: ("Temp", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_TEMPINF: ("Inside Temp", TEMP_FAHRENHEIT, SENSOR, DEVICE_CLASS_TEMPERATURE), - TYPE_TOTALRAININ: ("Lifetime Rain", PRECIPITATION_INCHES, SENSOR, None), - TYPE_UV: ("uv", "Index", SENSOR, None), - TYPE_WEEKLYRAININ: ("Weekly Rain", PRECIPITATION_INCHES, SENSOR, None), - TYPE_WINDDIR: ("Wind Dir", DEGREE, SENSOR, None), - TYPE_WINDDIR_AVG10M: ("Wind Dir Avg 10m", DEGREE, SENSOR, None), - TYPE_WINDDIR_AVG2M: ("Wind Dir Avg 2m", SPEED_MILES_PER_HOUR, SENSOR, None), - TYPE_WINDGUSTDIR: ("Gust Dir", DEGREE, SENSOR, None), - TYPE_WINDGUSTMPH: ("Wind Gust", SPEED_MILES_PER_HOUR, SENSOR, None), - TYPE_WINDSPDMPH_AVG10M: ("Wind Avg 10m", SPEED_MILES_PER_HOUR, SENSOR, None), - TYPE_WINDSPDMPH_AVG2M: ("Wind Avg 2m", SPEED_MILES_PER_HOUR, SENSOR, None), - TYPE_WINDSPEEDMPH: ("Wind Speed", SPEED_MILES_PER_HOUR, SENSOR, None), - TYPE_YEARLYRAININ: ("Yearly Rain", PRECIPITATION_INCHES, SENSOR, None), -} - CONFIG_SCHEMA = cv.deprecated(DOMAIN) +@callback +def async_wm2_to_lx(value: float) -> int: + """Calculate illuminance (in lux).""" + return round(value / 0.0079) + + +@callback +def async_hydrate_station_data(data: dict[str, Any]) -> dict[str, Any]: + """Hydrate station data with addition or normalized data.""" + if (irradiation := data.get(TYPE_SOLARRADIATION)) is not None: + data[TYPE_SOLARRADIATION_LX] = async_wm2_to_lx(irradiation) + + return data + + async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Set up the Ambient PWS as config entry.""" hass.data.setdefault(DOMAIN, {DATA_CLIENT: {}}) @@ -405,13 +161,14 @@ class AmbientStation: def on_data(data: dict) -> None: """Define a handler to fire when the data is received.""" - mac_address = data["macAddress"] - if data != self.stations[mac_address][ATTR_LAST_DATA]: - LOGGER.debug("New data received: %s", data) - self.stations[mac_address][ATTR_LAST_DATA] = data - async_dispatcher_send( - self._hass, f"ambient_station_data_update_{mac_address}" - ) + mac = data["macAddress"] + + if data == self.stations[mac][ATTR_LAST_DATA]: + return + + LOGGER.debug("New data received: %s", data) + self.stations[mac][ATTR_LAST_DATA] = async_hydrate_station_data(data) + async_dispatcher_send(self._hass, f"ambient_station_data_update_{mac}") def on_disconnect() -> None: """Define a handler to fire when the websocket is disconnected.""" @@ -420,26 +177,19 @@ class AmbientStation: def on_subscribed(data: dict) -> None: """Define a handler to fire when the subscription is set.""" for station in data["devices"]: - if station["macAddress"] in self.stations: + mac = station["macAddress"] + + if mac in self.stations: continue + LOGGER.debug("New station subscription: %s", data) - # Only create entities based on the data coming through the socket. - # If the user is monitoring brightness (in W/m^2), make sure we also - # add a calculated sensor for the same data measured in lx: - monitored_conditions = [ - k for k in station["lastData"] if k in SENSOR_TYPES - ] - if TYPE_SOLARRADIATION in monitored_conditions: - monitored_conditions.append(TYPE_SOLARRADIATION_LX) - self.stations[station["macAddress"]] = { - ATTR_LAST_DATA: station["lastData"], + self.stations[mac] = { + ATTR_LAST_DATA: async_hydrate_station_data(station["lastData"]), ATTR_LOCATION: station.get("info", {}).get("location"), - ATTR_MONITORED_CONDITIONS: monitored_conditions, - ATTR_NAME: station.get("info", {}).get( - "name", station["macAddress"] - ), + ATTR_NAME: station.get("info", {}).get("name", mac), } + # If the websocket disconnects and reconnects, the on_subscribed # handler will get called again; in that case, we don't want to # attempt forward setup of the config entry (because it will have @@ -466,28 +216,26 @@ class AmbientStation: class AmbientWeatherEntity(Entity): """Define a base Ambient PWS entity.""" + _attr_should_poll = False + def __init__( self, ambient: AmbientStation, mac_address: str, station_name: str, - sensor_type: str, - sensor_name: str, - device_class: str | None, + description: EntityDescription, ) -> None: """Initialize the sensor.""" self._ambient = ambient - self._attr_device_class = device_class self._attr_device_info = { "identifiers": {(DOMAIN, mac_address)}, "name": station_name, "manufacturer": "Ambient Weather", } - self._attr_name = f"{station_name}_{sensor_name}" - self._attr_should_poll = False - self._attr_unique_id = f"{mac_address}_{sensor_type}" + self._attr_name = f"{station_name}_{description.name}" + self._attr_unique_id = f"{mac_address}_{description.key}" self._mac_address = mac_address - self._sensor_type = sensor_type + self.entity_description = description async def async_added_to_hass(self) -> None: """Register callbacks.""" @@ -495,18 +243,18 @@ class AmbientWeatherEntity(Entity): @callback def update() -> None: """Update the state.""" - if self._sensor_type == TYPE_SOLARRADIATION_LX: + if self.entity_description.key == TYPE_SOLARRADIATION_LX: self._attr_available = ( - self._ambient.stations[self._mac_address][ATTR_LAST_DATA].get( + self._ambient.stations[self._mac_address][ATTR_LAST_DATA][ TYPE_SOLARRADIATION - ) + ] is not None ) else: self._attr_available = ( - self._ambient.stations[self._mac_address][ATTR_LAST_DATA].get( - self._sensor_type - ) + self._ambient.stations[self._mac_address][ATTR_LAST_DATA][ + self.entity_description.key + ] is not None ) diff --git a/homeassistant/components/ambient_station/binary_sensor.py b/homeassistant/components/ambient_station/binary_sensor.py index 093a582791e..e513486fb85 100644 --- a/homeassistant/components/ambient_station/binary_sensor.py +++ b/homeassistant/components/ambient_station/binary_sensor.py @@ -1,34 +1,209 @@ """Support for Ambient Weather Station binary sensors.""" from __future__ import annotations +from dataclasses import dataclass +from typing import Literal + from homeassistant.components.binary_sensor import ( - DOMAIN as BINARY_SENSOR, + DEVICE_CLASS_BATTERY, + DEVICE_CLASS_CONNECTIVITY, BinarySensorEntity, + BinarySensorEntityDescription, ) from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_NAME from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import ( - SENSOR_TYPES, - TYPE_BATT1, - TYPE_BATT2, - TYPE_BATT3, - TYPE_BATT4, - TYPE_BATT5, - TYPE_BATT6, - TYPE_BATT7, - TYPE_BATT8, - TYPE_BATT9, - TYPE_BATT10, - TYPE_BATT_CO2, - TYPE_BATTOUT, - TYPE_PM25_BATT, - TYPE_PM25IN_BATT, - AmbientWeatherEntity, +from . import AmbientWeatherEntity +from .const import ATTR_LAST_DATA, DATA_CLIENT, DOMAIN + +TYPE_BATT1 = "batt1" +TYPE_BATT10 = "batt10" +TYPE_BATT2 = "batt2" +TYPE_BATT3 = "batt3" +TYPE_BATT4 = "batt4" +TYPE_BATT5 = "batt5" +TYPE_BATT6 = "batt6" +TYPE_BATT7 = "batt7" +TYPE_BATT8 = "batt8" +TYPE_BATT9 = "batt9" +TYPE_BATT_CO2 = "batt_co2" +TYPE_BATTOUT = "battout" +TYPE_PM25_BATT = "batt_25" +TYPE_PM25IN_BATT = "batt_25in" +TYPE_RELAY1 = "relay1" +TYPE_RELAY10 = "relay10" +TYPE_RELAY2 = "relay2" +TYPE_RELAY3 = "relay3" +TYPE_RELAY4 = "relay4" +TYPE_RELAY5 = "relay5" +TYPE_RELAY6 = "relay6" +TYPE_RELAY7 = "relay7" +TYPE_RELAY8 = "relay8" +TYPE_RELAY9 = "relay9" + + +@dataclass +class AmbientBinarySensorDescriptionMixin: + """Define an entity description mixin for binary sensors.""" + + on_state: Literal[0, 1] + + +@dataclass +class AmbientBinarySensorDescription( + BinarySensorEntityDescription, AmbientBinarySensorDescriptionMixin +): + """Describe an Ambient PWS binary sensor.""" + + +BINARY_SENSOR_DESCRIPTIONS = ( + AmbientBinarySensorDescription( + key=TYPE_BATTOUT, + name="Battery", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_BATT1, + name="Battery 1", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_BATT2, + name="Battery 2", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_BATT3, + name="Battery 3", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_BATT4, + name="Battery 4", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_BATT5, + name="Battery 5", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_BATT6, + name="Battery 6", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_BATT7, + name="Battery 7", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_BATT8, + name="Battery 8", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_BATT9, + name="Battery 9", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_BATT10, + name="Battery 10", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_BATT_CO2, + name="CO2 Battery", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_PM25IN_BATT, + name="PM25 Indoor Battery", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_PM25_BATT, + name="PM25 Battery", + device_class=DEVICE_CLASS_BATTERY, + on_state=0, + ), + AmbientBinarySensorDescription( + key=TYPE_RELAY1, + name="Relay 1", + device_class=DEVICE_CLASS_CONNECTIVITY, + on_state=1, + ), + AmbientBinarySensorDescription( + key=TYPE_RELAY2, + name="Relay 2", + device_class=DEVICE_CLASS_CONNECTIVITY, + on_state=1, + ), + AmbientBinarySensorDescription( + key=TYPE_RELAY3, + name="Relay 3", + device_class=DEVICE_CLASS_CONNECTIVITY, + on_state=1, + ), + AmbientBinarySensorDescription( + key=TYPE_RELAY4, + name="Relay 4", + device_class=DEVICE_CLASS_CONNECTIVITY, + on_state=1, + ), + AmbientBinarySensorDescription( + key=TYPE_RELAY5, + name="Relay 5", + device_class=DEVICE_CLASS_CONNECTIVITY, + on_state=1, + ), + AmbientBinarySensorDescription( + key=TYPE_RELAY6, + name="Relay 6", + device_class=DEVICE_CLASS_CONNECTIVITY, + on_state=1, + ), + AmbientBinarySensorDescription( + key=TYPE_RELAY7, + name="Relay 7", + device_class=DEVICE_CLASS_CONNECTIVITY, + on_state=1, + ), + AmbientBinarySensorDescription( + key=TYPE_RELAY8, + name="Relay 8", + device_class=DEVICE_CLASS_CONNECTIVITY, + on_state=1, + ), + AmbientBinarySensorDescription( + key=TYPE_RELAY9, + name="Relay 9", + device_class=DEVICE_CLASS_CONNECTIVITY, + on_state=1, + ), + AmbientBinarySensorDescription( + key=TYPE_RELAY10, + name="Relay 10", + device_class=DEVICE_CLASS_CONNECTIVITY, + on_state=1, + ), ) -from .const import ATTR_LAST_DATA, ATTR_MONITORED_CONDITIONS, DATA_CLIENT, DOMAIN async def async_setup_entry( @@ -37,51 +212,29 @@ async def async_setup_entry( """Set up Ambient PWS binary sensors based on a config entry.""" ambient = hass.data[DOMAIN][DATA_CLIENT][entry.entry_id] - binary_sensor_list = [] - for mac_address, station in ambient.stations.items(): - for condition in station[ATTR_MONITORED_CONDITIONS]: - name, _, kind, device_class = SENSOR_TYPES[condition] - if kind == BINARY_SENSOR: - binary_sensor_list.append( - AmbientWeatherBinarySensor( - ambient, - mac_address, - station[ATTR_NAME], - condition, - name, - device_class, - ) - ) - - async_add_entities(binary_sensor_list) + async_add_entities( + [ + AmbientWeatherBinarySensor( + ambient, mac_address, station[ATTR_NAME], description + ) + for mac_address, station in ambient.stations.items() + for description in BINARY_SENSOR_DESCRIPTIONS + if description.key in station[ATTR_LAST_DATA] + ] + ) class AmbientWeatherBinarySensor(AmbientWeatherEntity, BinarySensorEntity): """Define an Ambient binary sensor.""" + entity_description: AmbientBinarySensorDescription + @callback def update_from_latest_data(self) -> None: """Fetch new state data for the entity.""" - state = self._ambient.stations[self._mac_address][ATTR_LAST_DATA].get( - self._sensor_type + self._attr_is_on = ( + self._ambient.stations[self._mac_address][ATTR_LAST_DATA][ + self.entity_description.key + ] + == self.entity_description.on_state ) - - if self._sensor_type in ( - TYPE_BATT1, - TYPE_BATT10, - TYPE_BATT2, - TYPE_BATT3, - TYPE_BATT4, - TYPE_BATT5, - TYPE_BATT6, - TYPE_BATT7, - TYPE_BATT8, - TYPE_BATT9, - TYPE_BATT_CO2, - TYPE_BATTOUT, - TYPE_PM25_BATT, - TYPE_PM25IN_BATT, - ): - self._attr_is_on = state == 0 - else: - self._attr_is_on = state == 1 diff --git a/homeassistant/components/ambient_station/const.py b/homeassistant/components/ambient_station/const.py index 87b5ff61877..cf5c97be045 100644 --- a/homeassistant/components/ambient_station/const.py +++ b/homeassistant/components/ambient_station/const.py @@ -5,8 +5,10 @@ DOMAIN = "ambient_station" LOGGER = logging.getLogger(__package__) ATTR_LAST_DATA = "last_data" -ATTR_MONITORED_CONDITIONS = "monitored_conditions" CONF_APP_KEY = "app_key" DATA_CLIENT = "data_client" + +TYPE_SOLARRADIATION = "solarradiation" +TYPE_SOLARRADIATION_LX = "solarradiation_lx" diff --git a/homeassistant/components/ambient_station/sensor.py b/homeassistant/components/ambient_station/sensor.py index 935a53e9384..0a77f6c7dd6 100644 --- a/homeassistant/components/ambient_station/sensor.py +++ b/homeassistant/components/ambient_station/sensor.py @@ -1,20 +1,554 @@ """Support for Ambient Weather Station sensors.""" from __future__ import annotations -from homeassistant.components.sensor import DOMAIN as SENSOR, SensorEntity +from homeassistant.components.sensor import SensorEntity, SensorEntityDescription from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ATTR_NAME +from homeassistant.const import ( + ATTR_NAME, + CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + CONCENTRATION_PARTS_PER_MILLION, + DEGREE, + DEVICE_CLASS_CO2, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_ILLUMINANCE, + DEVICE_CLASS_PM25, + DEVICE_CLASS_PRESSURE, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_TIMESTAMP, + IRRADIATION_WATTS_PER_SQUARE_METER, + LIGHT_LUX, + PERCENTAGE, + PRECIPITATION_INCHES, + PRECIPITATION_INCHES_PER_HOUR, + PRESSURE_INHG, + SPEED_MILES_PER_HOUR, + TEMP_FAHRENHEIT, +) from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import ( - SENSOR_TYPES, - TYPE_SOLARRADIATION, - TYPE_SOLARRADIATION_LX, - AmbientStation, - AmbientWeatherEntity, +from . import TYPE_SOLARRADIATION, TYPE_SOLARRADIATION_LX, AmbientWeatherEntity +from .const import ATTR_LAST_DATA, DATA_CLIENT, DOMAIN + +TYPE_24HOURRAININ = "24hourrainin" +TYPE_BAROMABSIN = "baromabsin" +TYPE_BAROMRELIN = "baromrelin" +TYPE_CO2 = "co2" +TYPE_DAILYRAININ = "dailyrainin" +TYPE_DEWPOINT = "dewPoint" +TYPE_EVENTRAININ = "eventrainin" +TYPE_FEELSLIKE = "feelsLike" +TYPE_HOURLYRAININ = "hourlyrainin" +TYPE_HUMIDITY = "humidity" +TYPE_HUMIDITY1 = "humidity1" +TYPE_HUMIDITY10 = "humidity10" +TYPE_HUMIDITY2 = "humidity2" +TYPE_HUMIDITY3 = "humidity3" +TYPE_HUMIDITY4 = "humidity4" +TYPE_HUMIDITY5 = "humidity5" +TYPE_HUMIDITY6 = "humidity6" +TYPE_HUMIDITY7 = "humidity7" +TYPE_HUMIDITY8 = "humidity8" +TYPE_HUMIDITY9 = "humidity9" +TYPE_HUMIDITYIN = "humidityin" +TYPE_LASTRAIN = "lastRain" +TYPE_MAXDAILYGUST = "maxdailygust" +TYPE_MONTHLYRAININ = "monthlyrainin" +TYPE_PM25 = "pm25" +TYPE_PM25_24H = "pm25_24h" +TYPE_PM25_IN = "pm25_in" +TYPE_PM25_IN_24H = "pm25_in_24h" +TYPE_SOILHUM1 = "soilhum1" +TYPE_SOILHUM10 = "soilhum10" +TYPE_SOILHUM2 = "soilhum2" +TYPE_SOILHUM3 = "soilhum3" +TYPE_SOILHUM4 = "soilhum4" +TYPE_SOILHUM5 = "soilhum5" +TYPE_SOILHUM6 = "soilhum6" +TYPE_SOILHUM7 = "soilhum7" +TYPE_SOILHUM8 = "soilhum8" +TYPE_SOILHUM9 = "soilhum9" +TYPE_SOILTEMP1F = "soiltemp1f" +TYPE_SOILTEMP10F = "soiltemp10f" +TYPE_SOILTEMP2F = "soiltemp2f" +TYPE_SOILTEMP3F = "soiltemp3f" +TYPE_SOILTEMP4F = "soiltemp4f" +TYPE_SOILTEMP5F = "soiltemp5f" +TYPE_SOILTEMP6F = "soiltemp6f" +TYPE_SOILTEMP7F = "soiltemp7f" +TYPE_SOILTEMP8F = "soiltemp8f" +TYPE_SOILTEMP9F = "soiltemp9f" +TYPE_TEMP10F = "temp10f" +TYPE_TEMP1F = "temp1f" +TYPE_TEMP2F = "temp2f" +TYPE_TEMP3F = "temp3f" +TYPE_TEMP4F = "temp4f" +TYPE_TEMP5F = "temp5f" +TYPE_TEMP6F = "temp6f" +TYPE_TEMP7F = "temp7f" +TYPE_TEMP8F = "temp8f" +TYPE_TEMP9F = "temp9f" +TYPE_TEMPF = "tempf" +TYPE_TEMPINF = "tempinf" +TYPE_TOTALRAININ = "totalrainin" +TYPE_UV = "uv" +TYPE_WEEKLYRAININ = "weeklyrainin" +TYPE_WINDDIR = "winddir" +TYPE_WINDDIR_AVG10M = "winddir_avg10m" +TYPE_WINDDIR_AVG2M = "winddir_avg2m" +TYPE_WINDGUSTDIR = "windgustdir" +TYPE_WINDGUSTMPH = "windgustmph" +TYPE_WINDSPDMPH_AVG10M = "windspdmph_avg10m" +TYPE_WINDSPDMPH_AVG2M = "windspdmph_avg2m" +TYPE_WINDSPEEDMPH = "windspeedmph" +TYPE_YEARLYRAININ = "yearlyrainin" + +SENSOR_DESCRIPTIONS = ( + SensorEntityDescription( + key=TYPE_24HOURRAININ, + name="24 Hr Rain", + icon="mdi:water", + native_unit_of_measurement=PRECIPITATION_INCHES, + ), + SensorEntityDescription( + key=TYPE_BAROMABSIN, + name="Abs Pressure", + native_unit_of_measurement=PRESSURE_INHG, + device_class=DEVICE_CLASS_PRESSURE, + ), + SensorEntityDescription( + key=TYPE_BAROMRELIN, + name="Rel Pressure", + native_unit_of_measurement=PRESSURE_INHG, + device_class=DEVICE_CLASS_PRESSURE, + ), + SensorEntityDescription( + key=TYPE_CO2, + name="co2", + native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION, + device_class=DEVICE_CLASS_CO2, + ), + SensorEntityDescription( + key=TYPE_DAILYRAININ, + name="Daily Rain", + icon="mdi:water", + native_unit_of_measurement=PRECIPITATION_INCHES, + ), + SensorEntityDescription( + key=TYPE_DEWPOINT, + name="Dew Point", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_EVENTRAININ, + name="Event Rain", + icon="mdi:water", + native_unit_of_measurement=PRECIPITATION_INCHES, + ), + SensorEntityDescription( + key=TYPE_FEELSLIKE, + name="Feels Like", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_HOURLYRAININ, + name="Hourly Rain Rate", + icon="mdi:water", + native_unit_of_measurement=PRECIPITATION_INCHES_PER_HOUR, + ), + SensorEntityDescription( + key=TYPE_HUMIDITY10, + name="Humidity 10", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_HUMIDITY1, + name="Humidity 1", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_HUMIDITY2, + name="Humidity 2", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_HUMIDITY3, + name="Humidity 3", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_HUMIDITY4, + name="Humidity 4", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_HUMIDITY5, + name="Humidity 5", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_HUMIDITY6, + name="Humidity 6", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_HUMIDITY7, + name="Humidity 7", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_HUMIDITY8, + name="Humidity 8", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_HUMIDITY9, + name="Humidity 9", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_HUMIDITY, + name="Humidity", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_HUMIDITYIN, + name="Humidity In", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_LASTRAIN, + name="Last Rain", + icon="mdi:water", + device_class=DEVICE_CLASS_TIMESTAMP, + ), + SensorEntityDescription( + key=TYPE_MAXDAILYGUST, + name="Max Gust", + icon="mdi:weather-windy", + native_unit_of_measurement=SPEED_MILES_PER_HOUR, + ), + SensorEntityDescription( + key=TYPE_MONTHLYRAININ, + name="Monthly Rain", + icon="mdi:water", + native_unit_of_measurement=PRECIPITATION_INCHES, + ), + SensorEntityDescription( + key=TYPE_PM25_24H, + name="PM25 24h Avg", + native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + device_class=DEVICE_CLASS_PM25, + ), + SensorEntityDescription( + key=TYPE_PM25_IN, + name="PM25 Indoor", + native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + device_class=DEVICE_CLASS_PM25, + ), + SensorEntityDescription( + key=TYPE_PM25_IN_24H, + name="PM25 Indoor 24h Avg", + native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + device_class=DEVICE_CLASS_PM25, + ), + SensorEntityDescription( + key=TYPE_PM25, + name="PM25", + native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + device_class=DEVICE_CLASS_PM25, + ), + SensorEntityDescription( + key=TYPE_SOILHUM10, + name="Soil Humidity 10", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_SOILHUM1, + name="Soil Humidity 1", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_SOILHUM2, + name="Soil Humidity 2", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_SOILHUM3, + name="Soil Humidity 3", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_SOILHUM4, + name="Soil Humidity 4", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_SOILHUM5, + name="Soil Humidity 5", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_SOILHUM6, + name="Soil Humidity 6", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_SOILHUM7, + name="Soil Humidity 7", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_SOILHUM8, + name="Soil Humidity 8", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_SOILHUM9, + name="Soil Humidity 9", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=TYPE_SOILTEMP10F, + name="Soil Temp 10", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_SOILTEMP1F, + name="Soil Temp 1", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_SOILTEMP2F, + name="Soil Temp 2", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_SOILTEMP3F, + name="Soil Temp 3", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_SOILTEMP4F, + name="Soil Temp 4", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_SOILTEMP5F, + name="Soil Temp 5", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_SOILTEMP6F, + name="Soil Temp 6", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_SOILTEMP7F, + name="Soil Temp 7", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_SOILTEMP8F, + name="Soil Temp 8", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_SOILTEMP9F, + name="Soil Temp 9", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_SOLARRADIATION, + name="Solar Rad", + native_unit_of_measurement=IRRADIATION_WATTS_PER_SQUARE_METER, + device_class=DEVICE_CLASS_ILLUMINANCE, + ), + SensorEntityDescription( + key=TYPE_SOLARRADIATION_LX, + name="Solar Rad (lx)", + native_unit_of_measurement=LIGHT_LUX, + device_class=DEVICE_CLASS_ILLUMINANCE, + ), + SensorEntityDescription( + key=TYPE_TEMP10F, + name="Temp 10", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_TEMP1F, + name="Temp 1", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_TEMP2F, + name="Temp 2", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_TEMP3F, + name="Temp 3", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_TEMP4F, + name="Temp 4", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_TEMP5F, + name="Temp 5", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_TEMP6F, + name="Temp 6", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_TEMP7F, + name="Temp 7", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_TEMP8F, + name="Temp 8", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_TEMP9F, + name="Temp 9", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_TEMPF, + name="Temp", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_TEMPINF, + name="Inside Temp", + native_unit_of_measurement=TEMP_FAHRENHEIT, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=TYPE_TOTALRAININ, + name="Lifetime Rain", + icon="mdi:water", + native_unit_of_measurement=PRECIPITATION_INCHES, + ), + SensorEntityDescription( + key=TYPE_UV, + name="UV Index", + native_unit_of_measurement="Index", + device_class=DEVICE_CLASS_ILLUMINANCE, + ), + SensorEntityDescription( + key=TYPE_WEEKLYRAININ, + name="Weekly Rain", + icon="mdi:water", + native_unit_of_measurement=PRECIPITATION_INCHES, + ), + SensorEntityDescription( + key=TYPE_WINDDIR, + name="Wind Dir", + icon="mdi:weather-windy", + native_unit_of_measurement=DEGREE, + ), + SensorEntityDescription( + key=TYPE_WINDDIR_AVG10M, + name="Wind Dir Avg 10m", + icon="mdi:weather-windy", + native_unit_of_measurement=DEGREE, + ), + SensorEntityDescription( + key=TYPE_WINDDIR_AVG2M, + name="Wind Dir Avg 2m", + icon="mdi:weather-windy", + native_unit_of_measurement=SPEED_MILES_PER_HOUR, + ), + SensorEntityDescription( + key=TYPE_WINDGUSTDIR, + name="Gust Dir", + icon="mdi:weather-windy", + native_unit_of_measurement=DEGREE, + ), + SensorEntityDescription( + key=TYPE_WINDGUSTMPH, + name="Wind Gust", + icon="mdi:weather-windy", + native_unit_of_measurement=SPEED_MILES_PER_HOUR, + ), + SensorEntityDescription( + key=TYPE_WINDSPDMPH_AVG10M, + name="Wind Avg 10m", + icon="mdi:weather-windy", + native_unit_of_measurement=SPEED_MILES_PER_HOUR, + ), + SensorEntityDescription( + key=TYPE_WINDSPDMPH_AVG2M, + name="Wind Avg 2m", + icon="mdi:weather-windy", + native_unit_of_measurement=SPEED_MILES_PER_HOUR, + ), + SensorEntityDescription( + key=TYPE_WINDSPEEDMPH, + name="Wind Speed", + icon="mdi:weather-windy", + native_unit_of_measurement=SPEED_MILES_PER_HOUR, + ), + SensorEntityDescription( + key=TYPE_YEARLYRAININ, + name="Yearly Rain", + icon="mdi:water", + native_unit_of_measurement=PRECIPITATION_INCHES, + ), ) -from .const import ATTR_LAST_DATA, ATTR_MONITORED_CONDITIONS, DATA_CLIENT, DOMAIN async def async_setup_entry( @@ -23,62 +557,22 @@ async def async_setup_entry( """Set up Ambient PWS sensors based on a config entry.""" ambient = hass.data[DOMAIN][DATA_CLIENT][entry.entry_id] - sensor_list = [] - for mac_address, station in ambient.stations.items(): - for condition in station[ATTR_MONITORED_CONDITIONS]: - name, unit, kind, device_class = SENSOR_TYPES[condition] - if kind == SENSOR: - sensor_list.append( - AmbientWeatherSensor( - ambient, - mac_address, - station[ATTR_NAME], - condition, - name, - device_class, - unit, - ) - ) - - async_add_entities(sensor_list) + async_add_entities( + [ + AmbientWeatherSensor(ambient, mac_address, station[ATTR_NAME], description) + for mac_address, station in ambient.stations.items() + for description in SENSOR_DESCRIPTIONS + if description.key in station[ATTR_LAST_DATA] + ] + ) class AmbientWeatherSensor(AmbientWeatherEntity, SensorEntity): """Define an Ambient sensor.""" - def __init__( - self, - ambient: AmbientStation, - mac_address: str, - station_name: str, - sensor_type: str, - sensor_name: str, - device_class: str | None, - unit: str | None, - ) -> None: - """Initialize the sensor.""" - super().__init__( - ambient, mac_address, station_name, sensor_type, sensor_name, device_class - ) - - self._attr_native_unit_of_measurement = unit - @callback def update_from_latest_data(self) -> None: """Fetch new state data for the sensor.""" - if self._sensor_type == TYPE_SOLARRADIATION_LX: - # If the user requests the solarradiation_lx sensor, use the - # value of the solarradiation sensor and apply a very accurate - # approximation of converting sunlight W/m^2 to lx: - w_m2_brightness_val = self._ambient.stations[self._mac_address][ - ATTR_LAST_DATA - ].get(TYPE_SOLARRADIATION) - - if w_m2_brightness_val is None: - self._attr_native_value = None - else: - self._attr_native_value = round(float(w_m2_brightness_val) / 0.0079) - else: - self._attr_native_value = self._ambient.stations[self._mac_address][ - ATTR_LAST_DATA - ].get(self._sensor_type) + self._attr_native_value = self._ambient.stations[self._mac_address][ + ATTR_LAST_DATA + ][self.entity_description.key]