Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for gauges from flood monitoring API."""
2 
3 from typing import Any
4 
5 from homeassistant.components.sensor import SensorEntity, SensorStateClass
6 from homeassistant.config_entries import ConfigEntry
7 from homeassistant.const import UnitOfLength
8 from homeassistant.core import HomeAssistant, callback
9 from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
10 from homeassistant.helpers.entity_platform import AddEntitiesCallback
12  CoordinatorEntity,
13  DataUpdateCoordinator,
14 )
15 
16 from .const import DOMAIN
17 
18 UNIT_MAPPING = {
19  "http://qudt.org/1.1/vocab/unit#Meter": UnitOfLength.METERS,
20 }
21 
22 
24  hass: HomeAssistant,
25  config_entry: ConfigEntry,
26  async_add_entities: AddEntitiesCallback,
27 ) -> None:
28  """Set up UK Flood Monitoring Sensors."""
29  coordinator: DataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
30  created_entities: set[str] = set()
31 
32  @callback
33  def _async_create_new_entities():
34  """Create new entities."""
35  if not coordinator.last_update_success:
36  return
37  measures: dict[str, dict[str, Any]] = coordinator.data["measures"]
38  entities: list[Measurement] = []
39  # Look to see if payload contains new measures
40  for key, data in measures.items():
41  if key in created_entities:
42  continue
43 
44  if "latestReading" not in data:
45  # Don't create a sensor entity for a gauge that isn't available
46  continue
47 
48  entities.append(Measurement(coordinator, key))
49  created_entities.add(key)
50 
51  async_add_entities(entities)
52 
53  _async_create_new_entities()
54 
55  # Subscribe to the coordinator to create new entities
56  # when the coordinator updates
57  config_entry.async_on_unload(
58  coordinator.async_add_listener(_async_create_new_entities)
59  )
60 
61 
63  """A gauge at a flood monitoring station."""
64 
65  _attr_attribution = (
66  "This uses Environment Agency flood and river level data "
67  "from the real-time data API"
68  )
69  _attr_state_class = SensorStateClass.MEASUREMENT
70  _attr_has_entity_name = True
71  _attr_name = None
72 
73  def __init__(self, coordinator, key):
74  """Initialise the gauge with a data instance and station."""
75  super().__init__(coordinator)
76  self.keykey = key
77  self._attr_unique_id_attr_unique_id = key
78 
79  @property
80  def station_name(self):
81  """Return the station name for the measure."""
82  return self.coordinator.data["label"]
83 
84  @property
85  def station_id(self):
86  """Return the station id for the measure."""
87  return self.coordinator.data["measures"][self.keykey]["stationReference"]
88 
89  @property
90  def qualifier(self):
91  """Return the qualifier for the station."""
92  return self.coordinator.data["measures"][self.keykey]["qualifier"]
93 
94  @property
95  def parameter_name(self):
96  """Return the parameter name for the station."""
97  return self.coordinator.data["measures"][self.keykey]["parameterName"]
98 
99  @property
100  def device_info(self):
101  """Return the device info."""
102  return DeviceInfo(
103  entry_type=DeviceEntryType.SERVICE,
104  identifiers={(DOMAIN, "measure-id", self.station_idstation_id)},
105  manufacturer="https://environment.data.gov.uk/",
106  model=self.parameter_nameparameter_name,
107  name=f"{self.station_name} {self.parameter_name} {self.qualifier}",
108  )
109 
110  @property
111  def available(self) -> bool:
112  """Return True if entity is available."""
113  if not self.coordinator.last_update_success:
114  return False
115 
116  # If sensor goes offline it will no longer contain a reading
117  if "latestReading" not in self.coordinator.data["measures"][self.keykey]:
118  return False
119 
120  # Sometimes lastestReading key is present but actually a URL rather than a piece of data
121  # This is usually because the sensor has been archived
122  if not isinstance(
123  self.coordinator.data["measures"][self.keykey]["latestReading"], dict
124  ):
125  return False
126 
127  return True
128 
129  @property
131  """Return units for the sensor."""
132  measure = self.coordinator.data["measures"][self.keykey]
133  if "unit" not in measure:
134  return None
135  return UNIT_MAPPING.get(measure["unit"], measure["unitName"])
136 
137  @property
138  def native_value(self):
139  """Return the current sensor value."""
140  return self.coordinator.data["measures"][self.keykey]["latestReading"]["value"]
def __init__(self, coordinator, key)
Definition: sensor.py:73
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:27