Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for Ecobee sensors."""
2 
3 from __future__ import annotations
4 
5 from dataclasses import dataclass
6 
7 from pyecobee.const import ECOBEE_STATE_CALIBRATING, ECOBEE_STATE_UNKNOWN
8 
10  SensorDeviceClass,
11  SensorEntity,
12  SensorEntityDescription,
13  SensorStateClass,
14 )
15 from homeassistant.config_entries import ConfigEntry
16 from homeassistant.const import (
17  CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
18  CONCENTRATION_PARTS_PER_MILLION,
19  PERCENTAGE,
20  UnitOfTemperature,
21 )
22 from homeassistant.core import HomeAssistant
23 from homeassistant.helpers.device_registry import DeviceInfo
24 from homeassistant.helpers.entity_platform import AddEntitiesCallback
25 
26 from .const import DOMAIN, ECOBEE_MODEL_TO_NAME, MANUFACTURER
27 
28 
29 @dataclass(frozen=True, kw_only=True)
31  """Represent the ecobee sensor entity description."""
32 
33  runtime_key: str | None
34 
35 
36 SENSOR_TYPES: tuple[EcobeeSensorEntityDescription, ...] = (
38  key="temperature",
39  native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
40  device_class=SensorDeviceClass.TEMPERATURE,
41  state_class=SensorStateClass.MEASUREMENT,
42  runtime_key=None,
43  ),
45  key="humidity",
46  native_unit_of_measurement=PERCENTAGE,
47  device_class=SensorDeviceClass.HUMIDITY,
48  state_class=SensorStateClass.MEASUREMENT,
49  runtime_key=None,
50  ),
52  key="co2PPM",
53  native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
54  device_class=SensorDeviceClass.CO2,
55  state_class=SensorStateClass.MEASUREMENT,
56  runtime_key="actualCO2",
57  ),
59  key="vocPPM",
60  device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
61  native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
62  state_class=SensorStateClass.MEASUREMENT,
63  runtime_key="actualVOC",
64  ),
66  key="airQuality",
67  device_class=SensorDeviceClass.AQI,
68  state_class=SensorStateClass.MEASUREMENT,
69  runtime_key="actualAQScore",
70  ),
71 )
72 
73 
75  hass: HomeAssistant,
76  config_entry: ConfigEntry,
77  async_add_entities: AddEntitiesCallback,
78 ) -> None:
79  """Set up ecobee sensors."""
80  data = hass.data[DOMAIN]
81  entities = [
82  EcobeeSensor(data, sensor["name"], index, description)
83  for index in range(len(data.ecobee.thermostats))
84  for sensor in data.ecobee.get_remote_sensors(index)
85  for item in sensor["capability"]
86  for description in SENSOR_TYPES
87  if description.key == item["type"]
88  ]
89 
90  async_add_entities(entities, True)
91 
92 
94  """Representation of an Ecobee sensor."""
95 
96  _attr_has_entity_name = True
97 
98  entity_description: EcobeeSensorEntityDescription
99 
100  def __init__(
101  self,
102  data,
103  sensor_name,
104  sensor_index,
105  description: EcobeeSensorEntityDescription,
106  ) -> None:
107  """Initialize the sensor."""
108  self.entity_descriptionentity_description = description
109  self.datadata = data
110  self.sensor_namesensor_name = sensor_name
111  self.indexindex = sensor_index
112  self._state_state = None
113 
114  @property
115  def unique_id(self) -> str | None:
116  """Return a unique identifier for this sensor."""
117  for sensor in self.datadata.ecobee.get_remote_sensors(self.indexindex):
118  if sensor["name"] == self.sensor_namesensor_name:
119  if "code" in sensor:
120  return f"{sensor['code']}-{self.device_class}"
121  thermostat = self.datadata.ecobee.get_thermostat(self.indexindex)
122  return f"{thermostat['identifier']}-{sensor['id']}-{self.device_class}"
123  return None
124 
125  @property
126  def device_info(self) -> DeviceInfo | None:
127  """Return device information for this sensor."""
128  identifier = None
129  model = None
130  for sensor in self.datadata.ecobee.get_remote_sensors(self.indexindex):
131  if sensor["name"] != self.sensor_namesensor_name:
132  continue
133  if "code" in sensor:
134  identifier = sensor["code"]
135  model = "ecobee Room Sensor"
136  else:
137  thermostat = self.datadata.ecobee.get_thermostat(self.indexindex)
138  identifier = thermostat["identifier"]
139  try:
140  model = (
141  f"{ECOBEE_MODEL_TO_NAME[thermostat['modelNumber']]} Thermostat"
142  )
143  except KeyError:
144  # Ecobee model is not in our list
145  model = None
146  break
147 
148  if identifier is not None and model is not None:
149  return DeviceInfo(
150  identifiers={(DOMAIN, identifier)},
151  manufacturer=MANUFACTURER,
152  model=model,
153  name=self.sensor_namesensor_name,
154  )
155  return None
156 
157  @property
158  def available(self) -> bool:
159  """Return true if device is available."""
160  thermostat = self.datadata.ecobee.get_thermostat(self.indexindex)
161  return thermostat["runtime"]["connected"]
162 
163  @property
164  def native_value(self):
165  """Return the state of the sensor."""
166  if self._state_state in (
167  ECOBEE_STATE_CALIBRATING,
168  ECOBEE_STATE_UNKNOWN,
169  "unknown",
170  ):
171  return None
172 
173  if self.entity_descriptionentity_description.key == "temperature":
174  return float(self._state_state) / 10
175 
176  return self._state_state
177 
178  async def async_update(self) -> None:
179  """Get the latest state of the sensor."""
180  await self.datadata.update()
181  for sensor in self.datadata.ecobee.get_remote_sensors(self.indexindex):
182  if sensor["name"] != self.sensor_namesensor_name:
183  continue
184  for item in sensor["capability"]:
185  if item["type"] != self.entity_descriptionentity_description.key:
186  continue
187  if self.entity_descriptionentity_description.runtime_key is None:
188  self._state_state = item["value"]
189  else:
190  thermostat = self.datadata.ecobee.get_thermostat(self.indexindex)
191  self._state_state = thermostat["runtime"][
192  self.entity_descriptionentity_description.runtime_key
193  ]
194  break
None __init__(self, data, sensor_name, sensor_index, EcobeeSensorEntityDescription description)
Definition: sensor.py:106
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:78
IssData update(pyiss.ISS iss)
Definition: __init__.py:33