Move temperature conversions to sensor base class (1/8) (#48261)

* Move temperature conversions to entity base class (1/8)

* Update integrations a-c

* Leave old temperature conversion until all integrations are migrated

* tweak

* Use contextlib.suppress

* Remove the MeasurableUnitEntity mixin

* Address comments, add tests

* Fix f-string

* Drop deprecation warning from base entity class

* Update with _attr-shorthand

* Fix rebase mistakes

* Fix additional rebase mistakes

* Only report temperature conversion once

* Fix additional rebase mistakes

* Format homeassistant/components/bbox/sensor.py

* Fix check for overidden _attr_state

* Remove test workarounds from implementation

* Remove useless None-check

* Tweaks

* Migrate new sensors a-c

* Update climacell

* Push deprecation of temperature conversion forward

* Override __repr__ in SensorEntity

* Include native_value in SensorEntity attributes

* Pylint

* Black

* Black

* Fix rebase mistakes

* black

* Fix rebase mistakes

* Revert changes in august/sensor.py

* Revert handling of unit converted restored state

* Apply code review suggestion

* Fix arlo test
This commit is contained in:
Erik Montnemery 2021-08-11 10:45:05 +02:00 committed by GitHub
parent 930c1dbe9b
commit 4e07ab1b32
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
71 changed files with 516 additions and 360 deletions

View file

@ -61,14 +61,14 @@ class AbodeSensor(AbodeDevice, SensorEntity):
self._attr_name = f"{device.name} {description.name}" self._attr_name = f"{device.name} {description.name}"
self._attr_unique_id = f"{device.device_uuid}-{description.key}" self._attr_unique_id = f"{device.device_uuid}-{description.key}"
if description.key == CONST.TEMP_STATUS_KEY: if description.key == CONST.TEMP_STATUS_KEY:
self._attr_unit_of_measurement = device.temp_unit self._attr_native_unit_of_measurement = device.temp_unit
elif description.key == CONST.HUMI_STATUS_KEY: elif description.key == CONST.HUMI_STATUS_KEY:
self._attr_unit_of_measurement = device.humidity_unit self._attr_native_unit_of_measurement = device.humidity_unit
elif description.key == CONST.LUX_STATUS_KEY: elif description.key == CONST.LUX_STATUS_KEY:
self._attr_unit_of_measurement = device.lux_unit self._attr_native_unit_of_measurement = device.lux_unit
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
if self.entity_description.key == CONST.TEMP_STATUS_KEY: if self.entity_description.key == CONST.TEMP_STATUS_KEY:
return self._device.temp return self._device.temp

View file

@ -88,10 +88,10 @@ class AccuWeatherSensor(CoordinatorEntity, SensorEntity):
) )
if coordinator.is_metric: if coordinator.is_metric:
self._unit_system = API_METRIC self._unit_system = API_METRIC
self._attr_unit_of_measurement = description.unit_metric self._attr_native_unit_of_measurement = description.unit_metric
else: else:
self._unit_system = API_IMPERIAL self._unit_system = API_IMPERIAL
self._attr_unit_of_measurement = description.unit_imperial self._attr_native_unit_of_measurement = description.unit_imperial
self._attr_device_info = { self._attr_device_info = {
"identifiers": {(DOMAIN, coordinator.location_key)}, "identifiers": {(DOMAIN, coordinator.location_key)},
"name": NAME, "name": NAME,
@ -101,7 +101,7 @@ class AccuWeatherSensor(CoordinatorEntity, SensorEntity):
self.forecast_day = forecast_day self.forecast_day = forecast_day
@property @property
def state(self) -> StateType: def native_value(self) -> StateType:
"""Return the state.""" """Return the state."""
if self.forecast_day is not None: if self.forecast_day is not None:
if self.entity_description.device_class == DEVICE_CLASS_TEMPERATURE: if self.entity_description.device_class == DEVICE_CLASS_TEMPERATURE:

View file

@ -42,6 +42,6 @@ class AcmedaBattery(AcmedaBase, SensorEntity):
return f"{super().name} Battery" return f"{super().name} Battery"
@property @property
def state(self): def native_value(self):
"""Return the state of the device.""" """Return the state of the device."""
return self.roller.battery return self.roller.battery

View file

@ -82,12 +82,12 @@ class AdGuardHomeSensor(AdGuardHomeDeviceEntity, SensorEntity):
) )
@property @property
def state(self) -> str | None: def native_value(self) -> str | None:
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._state return self._state
@property @property
def unit_of_measurement(self) -> str | None: def native_unit_of_measurement(self) -> str | None:
"""Return the unit this state is expressed in.""" """Return the unit this state is expressed in."""
return self._unit_of_measurement return self._unit_of_measurement

View file

@ -50,7 +50,7 @@ class AdsSensor(AdsEntity, SensorEntity):
def __init__(self, ads_hub, ads_var, ads_type, name, unit_of_measurement, factor): def __init__(self, ads_hub, ads_var, ads_type, name, unit_of_measurement, factor):
"""Initialize AdsSensor entity.""" """Initialize AdsSensor entity."""
super().__init__(ads_hub, name, ads_var) super().__init__(ads_hub, name, ads_var)
self._attr_unit_of_measurement = unit_of_measurement self._attr_native_unit_of_measurement = unit_of_measurement
self._ads_type = ads_type self._ads_type = ads_type
self._factor = factor self._factor = factor
@ -64,6 +64,6 @@ class AdsSensor(AdsEntity, SensorEntity):
) )
@property @property
def state(self) -> StateType: def native_value(self) -> StateType:
"""Return the state of the device.""" """Return the state of the device."""
return self._state_dict[STATE_KEY_STATE] return self._state_dict[STATE_KEY_STATE]

View file

@ -45,7 +45,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class AdvantageAirTimeTo(AdvantageAirEntity, SensorEntity): class AdvantageAirTimeTo(AdvantageAirEntity, SensorEntity):
"""Representation of Advantage Air timer control.""" """Representation of Advantage Air timer control."""
_attr_unit_of_measurement = ADVANTAGE_AIR_SET_COUNTDOWN_UNIT _attr_native_unit_of_measurement = ADVANTAGE_AIR_SET_COUNTDOWN_UNIT
def __init__(self, instance, ac_key, action): def __init__(self, instance, ac_key, action):
"""Initialize the Advantage Air timer control.""" """Initialize the Advantage Air timer control."""
@ -58,7 +58,7 @@ class AdvantageAirTimeTo(AdvantageAirEntity, SensorEntity):
) )
@property @property
def state(self): def native_value(self):
"""Return the current value.""" """Return the current value."""
return self._ac[self._time_key] return self._ac[self._time_key]
@ -78,7 +78,7 @@ class AdvantageAirTimeTo(AdvantageAirEntity, SensorEntity):
class AdvantageAirZoneVent(AdvantageAirEntity, SensorEntity): class AdvantageAirZoneVent(AdvantageAirEntity, SensorEntity):
"""Representation of Advantage Air Zone Vent Sensor.""" """Representation of Advantage Air Zone Vent Sensor."""
_attr_unit_of_measurement = PERCENTAGE _attr_native_unit_of_measurement = PERCENTAGE
_attr_state_class = STATE_CLASS_MEASUREMENT _attr_state_class = STATE_CLASS_MEASUREMENT
def __init__(self, instance, ac_key, zone_key): def __init__(self, instance, ac_key, zone_key):
@ -90,7 +90,7 @@ class AdvantageAirZoneVent(AdvantageAirEntity, SensorEntity):
) )
@property @property
def state(self): def native_value(self):
"""Return the current value of the air vent.""" """Return the current value of the air vent."""
if self._zone["state"] == ADVANTAGE_AIR_STATE_OPEN: if self._zone["state"] == ADVANTAGE_AIR_STATE_OPEN:
return self._zone["value"] return self._zone["value"]
@ -107,7 +107,7 @@ class AdvantageAirZoneVent(AdvantageAirEntity, SensorEntity):
class AdvantageAirZoneSignal(AdvantageAirEntity, SensorEntity): class AdvantageAirZoneSignal(AdvantageAirEntity, SensorEntity):
"""Representation of Advantage Air Zone wireless signal sensor.""" """Representation of Advantage Air Zone wireless signal sensor."""
_attr_unit_of_measurement = PERCENTAGE _attr_native_unit_of_measurement = PERCENTAGE
_attr_state_class = STATE_CLASS_MEASUREMENT _attr_state_class = STATE_CLASS_MEASUREMENT
def __init__(self, instance, ac_key, zone_key): def __init__(self, instance, ac_key, zone_key):
@ -119,7 +119,7 @@ class AdvantageAirZoneSignal(AdvantageAirEntity, SensorEntity):
) )
@property @property
def state(self): def native_value(self):
"""Return the current value of the wireless signal.""" """Return the current value of the wireless signal."""
return self._zone["rssi"] return self._zone["rssi"]
@ -140,7 +140,7 @@ class AdvantageAirZoneSignal(AdvantageAirEntity, SensorEntity):
class AdvantageAirZoneTemp(AdvantageAirEntity, SensorEntity): class AdvantageAirZoneTemp(AdvantageAirEntity, SensorEntity):
"""Representation of Advantage Air Zone wireless signal sensor.""" """Representation of Advantage Air Zone wireless signal sensor."""
_attr_unit_of_measurement = TEMP_CELSIUS _attr_native_unit_of_measurement = TEMP_CELSIUS
_attr_state_class = STATE_CLASS_MEASUREMENT _attr_state_class = STATE_CLASS_MEASUREMENT
_attr_icon = "mdi:thermometer" _attr_icon = "mdi:thermometer"
_attr_entity_registry_enabled_default = False _attr_entity_registry_enabled_default = False

View file

@ -85,7 +85,7 @@ class AbstractAemetSensor(CoordinatorEntity, SensorEntity):
self._attr_name = f"{self._name} {self._sensor_name}" self._attr_name = f"{self._name} {self._sensor_name}"
self._attr_unique_id = self._unique_id self._attr_unique_id = self._unique_id
self._attr_device_class = sensor_configuration.get(SENSOR_DEVICE_CLASS) self._attr_device_class = sensor_configuration.get(SENSOR_DEVICE_CLASS)
self._attr_unit_of_measurement = sensor_configuration.get(SENSOR_UNIT) self._attr_native_unit_of_measurement = sensor_configuration.get(SENSOR_UNIT)
class AemetSensor(AbstractAemetSensor): class AemetSensor(AbstractAemetSensor):
@ -106,7 +106,7 @@ class AemetSensor(AbstractAemetSensor):
self._weather_coordinator = weather_coordinator self._weather_coordinator = weather_coordinator
@property @property
def state(self): def native_value(self):
"""Return the state of the device.""" """Return the state of the device."""
return self._weather_coordinator.data.get(self._sensor_type) return self._weather_coordinator.data.get(self._sensor_type)
@ -134,7 +134,7 @@ class AemetForecastSensor(AbstractAemetSensor):
) )
@property @property
def state(self): def native_value(self):
"""Return the state of the device.""" """Return the state of the device."""
forecast = None forecast = None
forecasts = self._weather_coordinator.data.get( forecasts = self._weather_coordinator.data.get(

View file

@ -109,7 +109,7 @@ async def async_setup_platform(
class AfterShipSensor(SensorEntity): class AfterShipSensor(SensorEntity):
"""Representation of a AfterShip sensor.""" """Representation of a AfterShip sensor."""
_attr_unit_of_measurement: str = "packages" _attr_native_unit_of_measurement: str = "packages"
_attr_icon: str = ICON _attr_icon: str = ICON
def __init__(self, aftership: Tracking, name: str) -> None: def __init__(self, aftership: Tracking, name: str) -> None:
@ -120,7 +120,7 @@ class AfterShipSensor(SensorEntity):
self._attr_name = name self._attr_name = name
@property @property
def state(self) -> int | None: def native_value(self) -> int | None:
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._state return self._state

View file

@ -50,34 +50,34 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
AirlySensorEntityDescription( AirlySensorEntityDescription(
key=ATTR_API_CAQI, key=ATTR_API_CAQI,
name=ATTR_API_CAQI, name=ATTR_API_CAQI,
unit_of_measurement="CAQI", native_unit_of_measurement="CAQI",
), ),
AirlySensorEntityDescription( AirlySensorEntityDescription(
key=ATTR_API_PM1, key=ATTR_API_PM1,
icon="mdi:blur", icon="mdi:blur",
name=ATTR_API_PM1, name=ATTR_API_PM1,
unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
AirlySensorEntityDescription( AirlySensorEntityDescription(
key=ATTR_API_PM25, key=ATTR_API_PM25,
icon="mdi:blur", icon="mdi:blur",
name="PM2.5", name="PM2.5",
unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
AirlySensorEntityDescription( AirlySensorEntityDescription(
key=ATTR_API_PM10, key=ATTR_API_PM10,
icon="mdi:blur", icon="mdi:blur",
name=ATTR_API_PM10, name=ATTR_API_PM10,
unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
AirlySensorEntityDescription( AirlySensorEntityDescription(
key=ATTR_API_HUMIDITY, key=ATTR_API_HUMIDITY,
device_class=DEVICE_CLASS_HUMIDITY, device_class=DEVICE_CLASS_HUMIDITY,
name=ATTR_API_HUMIDITY.capitalize(), name=ATTR_API_HUMIDITY.capitalize(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
value=lambda value: round(value, 1), value=lambda value: round(value, 1),
), ),
@ -85,14 +85,14 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
key=ATTR_API_PRESSURE, key=ATTR_API_PRESSURE,
device_class=DEVICE_CLASS_PRESSURE, device_class=DEVICE_CLASS_PRESSURE,
name=ATTR_API_PRESSURE.capitalize(), name=ATTR_API_PRESSURE.capitalize(),
unit_of_measurement=PRESSURE_HPA, native_unit_of_measurement=PRESSURE_HPA,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
AirlySensorEntityDescription( AirlySensorEntityDescription(
key=ATTR_API_TEMPERATURE, key=ATTR_API_TEMPERATURE,
device_class=DEVICE_CLASS_TEMPERATURE, device_class=DEVICE_CLASS_TEMPERATURE,
name=ATTR_API_TEMPERATURE.capitalize(), name=ATTR_API_TEMPERATURE.capitalize(),
unit_of_measurement=TEMP_CELSIUS, native_unit_of_measurement=TEMP_CELSIUS,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
value=lambda value: round(value, 1), value=lambda value: round(value, 1),
), ),

View file

@ -84,7 +84,7 @@ class AirlySensor(CoordinatorEntity, SensorEntity):
self.entity_description = description self.entity_description = description
@property @property
def state(self) -> StateType: def native_value(self) -> StateType:
"""Return the state.""" """Return the state."""
state = self.coordinator.data[self.entity_description.key] state = self.coordinator.data[self.entity_description.key]
return cast(StateType, self.entity_description.value(state)) return cast(StateType, self.entity_description.value(state))

View file

@ -72,11 +72,11 @@ class AirNowSensor(CoordinatorEntity, SensorEntity):
self._attr_name = f"AirNow {SENSOR_TYPES[self.kind][ATTR_LABEL]}" self._attr_name = f"AirNow {SENSOR_TYPES[self.kind][ATTR_LABEL]}"
self._attr_icon = SENSOR_TYPES[self.kind][ATTR_ICON] self._attr_icon = SENSOR_TYPES[self.kind][ATTR_ICON]
self._attr_device_class = SENSOR_TYPES[self.kind][ATTR_DEVICE_CLASS] self._attr_device_class = SENSOR_TYPES[self.kind][ATTR_DEVICE_CLASS]
self._attr_unit_of_measurement = SENSOR_TYPES[self.kind][ATTR_UNIT] self._attr_native_unit_of_measurement = SENSOR_TYPES[self.kind][ATTR_UNIT]
self._attr_unique_id = f"{self.coordinator.latitude}-{self.coordinator.longitude}-{self.kind.lower()}" self._attr_unique_id = f"{self.coordinator.latitude}-{self.coordinator.longitude}-{self.kind.lower()}"
@property @property
def state(self): def native_value(self):
"""Return the state.""" """Return the state."""
self._state = self.coordinator.data[self.kind] self._state = self.coordinator.data[self.kind]
return self._state return self._state

View file

@ -212,7 +212,7 @@ class AirVisualGeographySensor(AirVisualEntity, SensorEntity):
self._attr_icon = icon self._attr_icon = icon
self._attr_name = f"{GEOGRAPHY_SENSOR_LOCALES[locale]} {name}" self._attr_name = f"{GEOGRAPHY_SENSOR_LOCALES[locale]} {name}"
self._attr_unique_id = f"{config_entry.unique_id}_{locale}_{kind}" self._attr_unique_id = f"{config_entry.unique_id}_{locale}_{kind}"
self._attr_unit_of_measurement = unit self._attr_native_unit_of_measurement = unit
self._config_entry = config_entry self._config_entry = config_entry
self._kind = kind self._kind = kind
self._locale = locale self._locale = locale
@ -232,16 +232,16 @@ class AirVisualGeographySensor(AirVisualEntity, SensorEntity):
if self._kind == SENSOR_KIND_LEVEL: if self._kind == SENSOR_KIND_LEVEL:
aqi = data[f"aqi{self._locale}"] aqi = data[f"aqi{self._locale}"]
[(self._attr_state, self._attr_icon)] = [ [(self._attr_native_value, self._attr_icon)] = [
(name, icon) (name, icon)
for (floor, ceiling), (name, icon) in POLLUTANT_LEVELS.items() for (floor, ceiling), (name, icon) in POLLUTANT_LEVELS.items()
if floor <= aqi <= ceiling if floor <= aqi <= ceiling
] ]
elif self._kind == SENSOR_KIND_AQI: elif self._kind == SENSOR_KIND_AQI:
self._attr_state = data[f"aqi{self._locale}"] self._attr_native_value = data[f"aqi{self._locale}"]
elif self._kind == SENSOR_KIND_POLLUTANT: elif self._kind == SENSOR_KIND_POLLUTANT:
symbol = data[f"main{self._locale}"] symbol = data[f"main{self._locale}"]
self._attr_state = symbol self._attr_native_value = symbol
self._attr_extra_state_attributes.update( self._attr_extra_state_attributes.update(
{ {
ATTR_POLLUTANT_SYMBOL: symbol, ATTR_POLLUTANT_SYMBOL: symbol,
@ -298,7 +298,7 @@ class AirVisualNodeProSensor(AirVisualEntity, SensorEntity):
f"{coordinator.data['settings']['node_name']} Node/Pro: {name}" f"{coordinator.data['settings']['node_name']} Node/Pro: {name}"
) )
self._attr_unique_id = f"{coordinator.data['serial_number']}_{kind}" self._attr_unique_id = f"{coordinator.data['serial_number']}_{kind}"
self._attr_unit_of_measurement = unit self._attr_native_unit_of_measurement = unit
self._kind = kind self._kind = kind
@property @property
@ -320,24 +320,30 @@ class AirVisualNodeProSensor(AirVisualEntity, SensorEntity):
"""Update the entity from the latest data.""" """Update the entity from the latest data."""
if self._kind == SENSOR_KIND_AQI: if self._kind == SENSOR_KIND_AQI:
if self.coordinator.data["settings"]["is_aqi_usa"]: if self.coordinator.data["settings"]["is_aqi_usa"]:
self._attr_state = self.coordinator.data["measurements"]["aqi_us"] self._attr_native_value = self.coordinator.data["measurements"][
"aqi_us"
]
else: else:
self._attr_state = self.coordinator.data["measurements"]["aqi_cn"] self._attr_native_value = self.coordinator.data["measurements"][
"aqi_cn"
]
elif self._kind == SENSOR_KIND_BATTERY_LEVEL: elif self._kind == SENSOR_KIND_BATTERY_LEVEL:
self._attr_state = self.coordinator.data["status"]["battery"] self._attr_native_value = self.coordinator.data["status"]["battery"]
elif self._kind == SENSOR_KIND_CO2: elif self._kind == SENSOR_KIND_CO2:
self._attr_state = self.coordinator.data["measurements"].get("co2") self._attr_native_value = self.coordinator.data["measurements"].get("co2")
elif self._kind == SENSOR_KIND_HUMIDITY: elif self._kind == SENSOR_KIND_HUMIDITY:
self._attr_state = self.coordinator.data["measurements"].get("humidity") self._attr_native_value = self.coordinator.data["measurements"].get(
"humidity"
)
elif self._kind == SENSOR_KIND_PM_0_1: elif self._kind == SENSOR_KIND_PM_0_1:
self._attr_state = self.coordinator.data["measurements"].get("pm0_1") self._attr_native_value = self.coordinator.data["measurements"].get("pm0_1")
elif self._kind == SENSOR_KIND_PM_1_0: elif self._kind == SENSOR_KIND_PM_1_0:
self._attr_state = self.coordinator.data["measurements"].get("pm1_0") self._attr_native_value = self.coordinator.data["measurements"].get("pm1_0")
elif self._kind == SENSOR_KIND_PM_2_5: elif self._kind == SENSOR_KIND_PM_2_5:
self._attr_state = self.coordinator.data["measurements"].get("pm2_5") self._attr_native_value = self.coordinator.data["measurements"].get("pm2_5")
elif self._kind == SENSOR_KIND_TEMPERATURE: elif self._kind == SENSOR_KIND_TEMPERATURE:
self._attr_state = self.coordinator.data["measurements"].get( self._attr_native_value = self.coordinator.data["measurements"].get(
"temperature_C" "temperature_C"
) )
elif self._kind == SENSOR_KIND_VOC: elif self._kind == SENSOR_KIND_VOC:
self._attr_state = self.coordinator.data["measurements"].get("voc") self._attr_native_value = self.coordinator.data["measurements"].get("voc")

View file

@ -32,6 +32,6 @@ class AlarmDecoderSensor(SensorEntity):
) )
def _message_callback(self, message): def _message_callback(self, message):
if self._attr_state != message.text: if self._attr_native_value != message.text:
self._attr_state = message.text self._attr_native_value = message.text
self.schedule_update_ha_state() self.schedule_update_ha_state()

View file

@ -112,7 +112,7 @@ class AlphaVantageSensor(SensorEntity):
self._symbol = symbol[CONF_SYMBOL] self._symbol = symbol[CONF_SYMBOL]
self._attr_name = symbol.get(CONF_NAME, self._symbol) self._attr_name = symbol.get(CONF_NAME, self._symbol)
self._timeseries = timeseries self._timeseries = timeseries
self._attr_unit_of_measurement = symbol.get(CONF_CURRENCY, self._symbol) self._attr_native_unit_of_measurement = symbol.get(CONF_CURRENCY, self._symbol)
self._attr_icon = ICONS.get(symbol.get(CONF_CURRENCY, "USD")) self._attr_icon = ICONS.get(symbol.get(CONF_CURRENCY, "USD"))
def update(self): def update(self):
@ -120,7 +120,7 @@ class AlphaVantageSensor(SensorEntity):
_LOGGER.debug("Requesting new data for symbol %s", self._symbol) _LOGGER.debug("Requesting new data for symbol %s", self._symbol)
all_values, _ = self._timeseries.get_intraday(self._symbol) all_values, _ = self._timeseries.get_intraday(self._symbol)
values = next(iter(all_values.values())) values = next(iter(all_values.values()))
self._attr_state = values["1. open"] self._attr_native_value = values["1. open"]
self._attr_extra_state_attributes = ( self._attr_extra_state_attributes = (
{ {
ATTR_ATTRIBUTION: ATTRIBUTION, ATTR_ATTRIBUTION: ATTRIBUTION,
@ -148,7 +148,7 @@ class AlphaVantageForeignExchange(SensorEntity):
else f"{self._to_currency}/{self._from_currency}" else f"{self._to_currency}/{self._from_currency}"
) )
self._attr_icon = ICONS.get(self._from_currency, "USD") self._attr_icon = ICONS.get(self._from_currency, "USD")
self._attr_unit_of_measurement = self._to_currency self._attr_native_unit_of_measurement = self._to_currency
def update(self): def update(self):
"""Get the latest data and updates the states.""" """Get the latest data and updates the states."""
@ -160,7 +160,7 @@ class AlphaVantageForeignExchange(SensorEntity):
values, _ = self._foreign_exchange.get_currency_exchange_rate( values, _ = self._foreign_exchange.get_currency_exchange_rate(
from_currency=self._from_currency, to_currency=self._to_currency from_currency=self._from_currency, to_currency=self._to_currency
) )
self._attr_state = round(float(values["5. Exchange Rate"]), 4) self._attr_native_value = round(float(values["5. Exchange Rate"]), 4)
self._attr_extra_state_attributes = ( self._attr_extra_state_attributes = (
{ {
ATTR_ATTRIBUTION: ATTRIBUTION, ATTR_ATTRIBUTION: ATTRIBUTION,

View file

@ -39,38 +39,38 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
SensorEntityDescription( SensorEntityDescription(
key="particulate_matter_2_5", key="particulate_matter_2_5",
name="Particulate Matter < 2.5 μm", name="Particulate Matter < 2.5 μm",
unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key="particulate_matter_10", key="particulate_matter_10",
name="Particulate Matter < 10 μm", name="Particulate Matter < 10 μm",
unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key="sulphur_dioxide", key="sulphur_dioxide",
name="Sulphur Dioxide (SO2)", name="Sulphur Dioxide (SO2)",
unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION, native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key="nitrogen_dioxide", key="nitrogen_dioxide",
name="Nitrogen Dioxide (NO2)", name="Nitrogen Dioxide (NO2)",
unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION, native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key="ozone", key="ozone",
name="Ozone", name="Ozone",
unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION, native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key="carbon_monoxide", key="carbon_monoxide",
name="Carbon Monoxide (CO)", name="Carbon Monoxide (CO)",
device_class=DEVICE_CLASS_CO, device_class=DEVICE_CLASS_CO,
unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION, native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -85,21 +85,21 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Grass Pollen", name="Grass Pollen",
icon="mdi:grass", icon="mdi:grass",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
), ),
SensorEntityDescription( SensorEntityDescription(
key="tree", key="tree",
name="Tree Pollen", name="Tree Pollen",
icon="mdi:tree", icon="mdi:tree",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
), ),
SensorEntityDescription( SensorEntityDescription(
key="weed", key="weed",
name="Weed Pollen", name="Weed Pollen",
icon="mdi:sprout", icon="mdi:sprout",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
), ),
SensorEntityDescription( SensorEntityDescription(
key="grass_risk", key="grass_risk",
@ -124,7 +124,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Poaceae Grass Pollen", name="Poaceae Grass Pollen",
icon="mdi:grass", icon="mdi:grass",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -132,7 +132,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Alder Tree Pollen", name="Alder Tree Pollen",
icon="mdi:tree", icon="mdi:tree",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -140,7 +140,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Birch Tree Pollen", name="Birch Tree Pollen",
icon="mdi:tree", icon="mdi:tree",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -148,7 +148,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Cypress Tree Pollen", name="Cypress Tree Pollen",
icon="mdi:tree", icon="mdi:tree",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -156,7 +156,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Elm Tree Pollen", name="Elm Tree Pollen",
icon="mdi:tree", icon="mdi:tree",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -164,7 +164,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Hazel Tree Pollen", name="Hazel Tree Pollen",
icon="mdi:tree", icon="mdi:tree",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -172,7 +172,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Oak Tree Pollen", name="Oak Tree Pollen",
icon="mdi:tree", icon="mdi:tree",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -180,7 +180,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Pine Tree Pollen", name="Pine Tree Pollen",
icon="mdi:tree", icon="mdi:tree",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -188,7 +188,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Plane Tree Pollen", name="Plane Tree Pollen",
icon="mdi:tree", icon="mdi:tree",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -196,7 +196,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Poplar Tree Pollen", name="Poplar Tree Pollen",
icon="mdi:tree", icon="mdi:tree",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -204,7 +204,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Chenopod Weed Pollen", name="Chenopod Weed Pollen",
icon="mdi:sprout", icon="mdi:sprout",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -212,7 +212,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Mugwort Weed Pollen", name="Mugwort Weed Pollen",
icon="mdi:sprout", icon="mdi:sprout",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -220,7 +220,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Nettle Weed Pollen", name="Nettle Weed Pollen",
icon="mdi:sprout", icon="mdi:sprout",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( SensorEntityDescription(
@ -228,7 +228,7 @@ SENSORS: dict[str, list[SensorEntityDescription]] = {
name="Ragweed Weed Pollen", name="Ragweed Weed Pollen",
icon="mdi:sprout", icon="mdi:sprout",
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER, native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
], ],

View file

@ -66,7 +66,7 @@ class AmbeeSensorEntity(CoordinatorEntity, SensorEntity):
} }
@property @property
def state(self) -> StateType: def native_value(self) -> StateType:
"""Return the state of the sensor.""" """Return the state of the sensor."""
value = getattr(self.coordinator.data, self.entity_description.key) value = getattr(self.coordinator.data, self.entity_description.key)
if isinstance(value, str): if isinstance(value, str):

View file

@ -61,7 +61,7 @@ class AmbientWeatherSensor(AmbientWeatherEntity, SensorEntity):
ambient, mac_address, station_name, sensor_type, sensor_name, device_class ambient, mac_address, station_name, sensor_type, sensor_name, device_class
) )
self._attr_unit_of_measurement = unit self._attr_native_unit_of_measurement = unit
@callback @callback
def update_from_latest_data(self) -> None: def update_from_latest_data(self) -> None:
@ -75,10 +75,10 @@ class AmbientWeatherSensor(AmbientWeatherEntity, SensorEntity):
].get(TYPE_SOLARRADIATION) ].get(TYPE_SOLARRADIATION)
if w_m2_brightness_val is None: if w_m2_brightness_val is None:
self._attr_state = None self._attr_native_value = None
else: else:
self._attr_state = round(float(w_m2_brightness_val) / 0.0079) self._attr_native_value = round(float(w_m2_brightness_val) / 0.0079)
else: else:
self._attr_state = self._ambient.stations[self._mac_address][ self._attr_native_value = self._ambient.stations[self._mac_address][
ATTR_LAST_DATA ATTR_LAST_DATA
].get(self._sensor_type) ].get(self._sensor_type)

View file

@ -61,7 +61,7 @@ class AmcrestSensor(SensorEntity):
return self._name return self._name
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._state return self._state
@ -76,7 +76,7 @@ class AmcrestSensor(SensorEntity):
return self._icon return self._icon
@property @property
def unit_of_measurement(self): def native_unit_of_measurement(self):
"""Return the units of measurement.""" """Return the units of measurement."""
return self._unit_of_measurement return self._unit_of_measurement

View file

@ -50,12 +50,12 @@ class IPWebcamSensor(AndroidIPCamEntity, SensorEntity):
return self._name return self._name
@property @property
def unit_of_measurement(self): def native_unit_of_measurement(self):
"""Return the unit the value is expressed in.""" """Return the unit the value is expressed in."""
return self._unit return self._unit
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._state return self._state

View file

@ -165,16 +165,16 @@ class APCUPSdSensor(SensorEntity):
self.type = sensor_type self.type = sensor_type
self._attr_name = SENSOR_PREFIX + SENSOR_TYPES[sensor_type][0] self._attr_name = SENSOR_PREFIX + SENSOR_TYPES[sensor_type][0]
self._attr_icon = SENSOR_TYPES[self.type][2] self._attr_icon = SENSOR_TYPES[self.type][2]
self._attr_unit_of_measurement = SENSOR_TYPES[sensor_type][1] self._attr_native_unit_of_measurement = SENSOR_TYPES[sensor_type][1]
self._attr_device_class = SENSOR_TYPES[sensor_type][3] self._attr_device_class = SENSOR_TYPES[sensor_type][3]
def update(self): def update(self):
"""Get the latest status and use it to update our sensor state.""" """Get the latest status and use it to update our sensor state."""
if self.type.upper() not in self._data.status: if self.type.upper() not in self._data.status:
self._attr_state = None self._attr_native_value = None
else: else:
self._attr_state, inferred_unit = infer_unit( self._attr_native_value, inferred_unit = infer_unit(
self._data.status[self.type.upper()] self._data.status[self.type.upper()]
) )
if not self._attr_unit_of_measurement: if not self._attr_native_unit_of_measurement:
self._attr_unit_of_measurement = inferred_unit self._attr_native_unit_of_measurement = inferred_unit

View file

@ -92,11 +92,11 @@ class AquaLogicSensor(SensorEntity):
panel = self._processor.panel panel = self._processor.panel
if panel is not None: if panel is not None:
if panel.is_metric: if panel.is_metric:
self._attr_unit_of_measurement = SENSOR_TYPES[self._type][1][0] self._attr_native_unit_of_measurement = SENSOR_TYPES[self._type][1][0]
else: else:
self._attr_unit_of_measurement = SENSOR_TYPES[self._type][1][1] self._attr_native_unit_of_measurement = SENSOR_TYPES[self._type][1][1]
self._attr_state = getattr(panel, self._type) self._attr_native_value = getattr(panel, self._type)
self.async_write_ha_state() self.async_write_ha_state()
else: else:
self._attr_unit_of_measurement = None self._attr_native_unit_of_measurement = None

View file

@ -42,4 +42,4 @@ class ArduinoSensor(SensorEntity):
def update(self): def update(self):
"""Get the latest value from the pin.""" """Get the latest value from the pin."""
self._attr_state = self._board.get_analog_inputs()[self._pin][1] self._attr_native_value = self._board.get_analog_inputs()[self._pin][1]

View file

@ -141,7 +141,7 @@ class ArestSensor(SensorEntity):
self.arest = arest self.arest = arest
self._attr_name = f"{location.title()} {name.title()}" self._attr_name = f"{location.title()} {name.title()}"
self._variable = variable self._variable = variable
self._attr_unit_of_measurement = unit_of_measurement self._attr_native_unit_of_measurement = unit_of_measurement
self._renderer = renderer self._renderer = renderer
if pin is not None: if pin is not None:
@ -155,9 +155,9 @@ class ArestSensor(SensorEntity):
self._attr_available = self.arest.available self._attr_available = self.arest.available
values = self.arest.data values = self.arest.data
if "error" in values: if "error" in values:
self._attr_state = values["error"] self._attr_native_value = values["error"]
else: else:
self._attr_state = self._renderer( self._attr_native_value = self._renderer(
values.get("value", values.get(self._variable, None)) values.get("value", values.get(self._variable, None))
) )

View file

@ -127,7 +127,7 @@ class ArloSensor(SensorEntity):
self.async_schedule_update_ha_state(True) self.async_schedule_update_ha_state(True)
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._state return self._state

View file

@ -138,7 +138,7 @@ class ArwnSensor(SensorEntity):
# This mqtt topic for the sensor which is its uid # This mqtt topic for the sensor which is its uid
self._attr_unique_id = topic self._attr_unique_id = topic
self._state_key = state_key self._state_key = state_key
self._attr_unit_of_measurement = units self._attr_native_unit_of_measurement = units
self._attr_icon = icon self._attr_icon = icon
self._attr_device_class = device_class self._attr_device_class = device_class
@ -147,5 +147,5 @@ class ArwnSensor(SensorEntity):
ev = {} ev = {}
ev.update(event) ev.update(event)
self._attr_extra_state_attributes = ev self._attr_extra_state_attributes = ev
self._attr_state = ev.get(self._state_key, None) self._attr_native_value = ev.get(self._state_key, None)
self.async_write_ha_state() self.async_write_ha_state()

View file

@ -48,13 +48,13 @@ CONNECTION_SENSORS: tuple[AsusWrtSensorEntityDescription, ...] = (
key=SENSORS_CONNECTED_DEVICE[0], key=SENSORS_CONNECTED_DEVICE[0],
name="Devices Connected", name="Devices Connected",
icon="mdi:router-network", icon="mdi:router-network",
unit_of_measurement=UNIT_DEVICES, native_unit_of_measurement=UNIT_DEVICES,
), ),
AsusWrtSensorEntityDescription( AsusWrtSensorEntityDescription(
key=SENSORS_RATES[0], key=SENSORS_RATES[0],
name="Download Speed", name="Download Speed",
icon="mdi:download-network", icon="mdi:download-network",
unit_of_measurement=DATA_RATE_MEGABITS_PER_SECOND, native_unit_of_measurement=DATA_RATE_MEGABITS_PER_SECOND,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
factor=125000, factor=125000,
), ),
@ -62,7 +62,7 @@ CONNECTION_SENSORS: tuple[AsusWrtSensorEntityDescription, ...] = (
key=SENSORS_RATES[1], key=SENSORS_RATES[1],
name="Upload Speed", name="Upload Speed",
icon="mdi:upload-network", icon="mdi:upload-network",
unit_of_measurement=DATA_RATE_MEGABITS_PER_SECOND, native_unit_of_measurement=DATA_RATE_MEGABITS_PER_SECOND,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
factor=125000, factor=125000,
), ),
@ -70,7 +70,7 @@ CONNECTION_SENSORS: tuple[AsusWrtSensorEntityDescription, ...] = (
key=SENSORS_BYTES[0], key=SENSORS_BYTES[0],
name="Download", name="Download",
icon="mdi:download", icon="mdi:download",
unit_of_measurement=DATA_GIGABYTES, native_unit_of_measurement=DATA_GIGABYTES,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
factor=1000000000, factor=1000000000,
), ),
@ -78,7 +78,7 @@ CONNECTION_SENSORS: tuple[AsusWrtSensorEntityDescription, ...] = (
key=SENSORS_BYTES[1], key=SENSORS_BYTES[1],
name="Upload", name="Upload",
icon="mdi:upload", icon="mdi:upload",
unit_of_measurement=DATA_GIGABYTES, native_unit_of_measurement=DATA_GIGABYTES,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
factor=1000000000, factor=1000000000,
), ),
@ -150,11 +150,11 @@ class AsusWrtSensor(CoordinatorEntity, SensorEntity):
self._attr_unique_id = f"{DOMAIN} {self.name}" self._attr_unique_id = f"{DOMAIN} {self.name}"
self._attr_state_class = STATE_CLASS_MEASUREMENT self._attr_state_class = STATE_CLASS_MEASUREMENT
if description.unit_of_measurement == DATA_GIGABYTES: if description.native_unit_of_measurement == DATA_GIGABYTES:
self._attr_last_reset = dt_util.utc_from_timestamp(0) self._attr_last_reset = dt_util.utc_from_timestamp(0)
@property @property
def state(self) -> str: def native_value(self) -> str:
"""Return current state.""" """Return current state."""
descr = self.entity_description descr = self.entity_description
state = self.coordinator.data.get(descr.key) state = self.coordinator.data.get(descr.key)

View file

@ -49,10 +49,12 @@ class AtagSensor(AtagEntity, SensorEntity):
PERCENTAGE, PERCENTAGE,
TIME_HOURS, TIME_HOURS,
): ):
self._attr_unit_of_measurement = coordinator.data.report[self._id].measure self._attr_native_unit_of_measurement = coordinator.data.report[
self._id
].measure
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self.coordinator.data.report[self._id].state return self.coordinator.data.report[self._id].state

View file

@ -258,10 +258,10 @@ class AtomeSensor(SensorEntity):
if sensor_type == LIVE_TYPE: if sensor_type == LIVE_TYPE:
self._attr_device_class = DEVICE_CLASS_POWER self._attr_device_class = DEVICE_CLASS_POWER
self._attr_unit_of_measurement = POWER_WATT self._attr_native_unit_of_measurement = POWER_WATT
else: else:
self._attr_device_class = DEVICE_CLASS_ENERGY self._attr_device_class = DEVICE_CLASS_ENERGY
self._attr_unit_of_measurement = ENERGY_KILO_WATT_HOUR self._attr_native_unit_of_measurement = ENERGY_KILO_WATT_HOUR
def update(self): def update(self):
"""Update device state.""" """Update device state."""
@ -269,13 +269,13 @@ class AtomeSensor(SensorEntity):
update_function() update_function()
if self._sensor_type == LIVE_TYPE: if self._sensor_type == LIVE_TYPE:
self._attr_state = self._data.live_power self._attr_native_value = self._data.live_power
self._attr_extra_state_attributes = { self._attr_extra_state_attributes = {
"subscribed_power": self._data.subscribed_power, "subscribed_power": self._data.subscribed_power,
"is_connected": self._data.is_connected, "is_connected": self._data.is_connected,
} }
else: else:
self._attr_state = getattr(self._data, f"{self._sensor_type}_usage") self._attr_native_value = getattr(self._data, f"{self._sensor_type}_usage")
self._attr_last_reset = dt_util.as_utc( self._attr_last_reset = dt_util.as_utc(
getattr(self._data, f"{self._sensor_type}_last_reset") getattr(self._data, f"{self._sensor_type}_last_reset")
) )

View file

@ -146,7 +146,7 @@ class AugustOperatorSensor(AugustEntityMixin, RestoreEntity, SensorEntity):
self._attr_available = True self._attr_available = True
if lock_activity is not None: if lock_activity is not None:
self._attr_state = lock_activity.operated_by self._attr_native_value = lock_activity.operated_by
self._operated_remote = lock_activity.operated_remote self._operated_remote = lock_activity.operated_remote
self._operated_keypad = lock_activity.operated_keypad self._operated_keypad = lock_activity.operated_keypad
self._operated_autorelock = lock_activity.operated_autorelock self._operated_autorelock = lock_activity.operated_autorelock
@ -208,7 +208,7 @@ class AugustBatterySensor(AugustEntityMixin, SensorEntity):
"""Representation of an August sensor.""" """Representation of an August sensor."""
_attr_device_class = DEVICE_CLASS_BATTERY _attr_device_class = DEVICE_CLASS_BATTERY
_attr_unit_of_measurement = PERCENTAGE _attr_native_unit_of_measurement = PERCENTAGE
def __init__(self, data, sensor_type, device, old_device): def __init__(self, data, sensor_type, device, old_device):
"""Initialize the sensor.""" """Initialize the sensor."""
@ -223,8 +223,8 @@ class AugustBatterySensor(AugustEntityMixin, SensorEntity):
def _update_from_data(self): def _update_from_data(self):
"""Get the latest state of the sensor.""" """Get the latest state of the sensor."""
state_provider = SENSOR_TYPES_BATTERY[self._sensor_type]["state_provider"] state_provider = SENSOR_TYPES_BATTERY[self._sensor_type]["state_provider"]
self._attr_state = state_provider(self._detail) self._attr_native_value = state_provider(self._detail)
self._attr_available = self._attr_state is not None self._attr_available = self._attr_native_value is not None
@property @property
def old_unique_id(self) -> str: def old_unique_id(self) -> str:

View file

@ -22,9 +22,9 @@ async def async_setup_entry(hass, entry, async_add_entries):
class AuroraSensor(AuroraEntity, SensorEntity): class AuroraSensor(AuroraEntity, SensorEntity):
"""Implementation of an aurora sensor.""" """Implementation of an aurora sensor."""
_attr_unit_of_measurement = PERCENTAGE _attr_native_unit_of_measurement = PERCENTAGE
@property @property
def state(self): def native_value(self):
"""Return % chance the aurora is visible.""" """Return % chance the aurora is visible."""
return self.coordinator.data return self.coordinator.data

View file

@ -51,7 +51,7 @@ class AuroraABBSolarPVMonitorSensor(SensorEntity):
"""Representation of a Sensor.""" """Representation of a Sensor."""
_attr_state_class = STATE_CLASS_MEASUREMENT _attr_state_class = STATE_CLASS_MEASUREMENT
_attr_unit_of_measurement = POWER_WATT _attr_native_unit_of_measurement = POWER_WATT
_attr_device_class = DEVICE_CLASS_POWER _attr_device_class = DEVICE_CLASS_POWER
def __init__(self, client, name, typename): def __init__(self, client, name, typename):
@ -68,7 +68,7 @@ class AuroraABBSolarPVMonitorSensor(SensorEntity):
self.client.connect() self.client.connect()
# read ADC channel 3 (grid power output) # read ADC channel 3 (grid power output)
power_watts = self.client.measure(3, True) power_watts = self.client.measure(3, True)
self._attr_state = round(power_watts, 1) self._attr_native_value = round(power_watts, 1)
except AuroraError as error: except AuroraError as error:
# aurorapy does not have different exceptions (yet) for dealing # aurorapy does not have different exceptions (yet) for dealing
# with timeout vs other comms errors. # with timeout vs other comms errors.
@ -82,7 +82,7 @@ class AuroraABBSolarPVMonitorSensor(SensorEntity):
_LOGGER.debug("No response from inverter (could be dark)") _LOGGER.debug("No response from inverter (could be dark)")
else: else:
raise error raise error
self._attr_state = None self._attr_native_value = None
finally: finally:
if self.client.serline.isOpen(): if self.client.serline.isOpen():
self.client.close() self.client.close()

View file

@ -144,7 +144,7 @@ class AwairSensor(CoordinatorEntity, SensorEntity):
return False return False
@property @property
def state(self) -> float: def native_value(self) -> float:
"""Return the state, rounding off to reasonable values.""" """Return the state, rounding off to reasonable values."""
state: float state: float
@ -175,7 +175,7 @@ class AwairSensor(CoordinatorEntity, SensorEntity):
return SENSOR_TYPES[self._kind][ATTR_DEVICE_CLASS] return SENSOR_TYPES[self._kind][ATTR_DEVICE_CLASS]
@property @property
def unit_of_measurement(self) -> str: def native_unit_of_measurement(self) -> str:
"""Return the unit the value is expressed in.""" """Return the unit the value is expressed in."""
return SENSOR_TYPES[self._kind][ATTR_UNIT] return SENSOR_TYPES[self._kind][ATTR_UNIT]

View file

@ -71,7 +71,7 @@ class AzureDevOpsSensor(AzureDevOpsDeviceEntity, SensorEntity):
unit_of_measurement: str = "", unit_of_measurement: str = "",
) -> None: ) -> None:
"""Initialize Azure DevOps sensor.""" """Initialize Azure DevOps sensor."""
self._attr_unit_of_measurement = unit_of_measurement self._attr_native_unit_of_measurement = unit_of_measurement
self.client = client self.client = client
self.organization = organization self.organization = organization
self.project = project self.project = project
@ -107,7 +107,7 @@ class AzureDevOpsLatestBuildSensor(AzureDevOpsSensor):
_LOGGER.warning(exception) _LOGGER.warning(exception)
self._attr_available = False self._attr_available = False
return False return False
self._attr_state = build.build_number self._attr_native_value = build.build_number
self._attr_extra_state_attributes = { self._attr_extra_state_attributes = {
"definition_id": build.definition.id, "definition_id": build.definition.id,
"definition_name": build.definition.name, "definition_name": build.definition.name,

View file

@ -94,7 +94,7 @@ class BboxUptimeSensor(SensorEntity):
def __init__(self, bbox_data, sensor_type, name): def __init__(self, bbox_data, sensor_type, name):
"""Initialize the sensor.""" """Initialize the sensor."""
self._attr_name = f"{name} {SENSOR_TYPES[sensor_type][0]}" self._attr_name = f"{name} {SENSOR_TYPES[sensor_type][0]}"
self._unit_of_measurement = SENSOR_TYPES[sensor_type][1] self._attr_native_unit_of_measurement = SENSOR_TYPES[sensor_type][1]
self._attr_icon = SENSOR_TYPES[sensor_type][2] self._attr_icon = SENSOR_TYPES[sensor_type][2]
self.bbox_data = bbox_data self.bbox_data = bbox_data
@ -104,7 +104,7 @@ class BboxUptimeSensor(SensorEntity):
uptime = utcnow() - timedelta( uptime = utcnow() - timedelta(
seconds=self.bbox_data.router_infos["device"]["uptime"] seconds=self.bbox_data.router_infos["device"]["uptime"]
) )
self._attr_state = uptime.replace(microsecond=0).isoformat() self._attr_native_value = uptime.replace(microsecond=0).isoformat()
class BboxSensor(SensorEntity): class BboxSensor(SensorEntity):
@ -116,7 +116,7 @@ class BboxSensor(SensorEntity):
"""Initialize the sensor.""" """Initialize the sensor."""
self.type = sensor_type self.type = sensor_type
self._attr_name = f"{name} {SENSOR_TYPES[sensor_type][0]}" self._attr_name = f"{name} {SENSOR_TYPES[sensor_type][0]}"
self._attr_unit_of_measurement = SENSOR_TYPES[sensor_type][1] self._attr_native_unit_of_measurement = SENSOR_TYPES[sensor_type][1]
self._attr_icon = SENSOR_TYPES[sensor_type][2] self._attr_icon = SENSOR_TYPES[sensor_type][2]
self.bbox_data = bbox_data self.bbox_data = bbox_data
@ -124,19 +124,25 @@ class BboxSensor(SensorEntity):
"""Get the latest data from Bbox and update the state.""" """Get the latest data from Bbox and update the state."""
self.bbox_data.update() self.bbox_data.update()
if self.type == "down_max_bandwidth": if self.type == "down_max_bandwidth":
self._attr_state = round( self._attr_native_value = round(
self.bbox_data.data["rx"]["maxBandwidth"] / 1000, 2 self.bbox_data.data["rx"]["maxBandwidth"] / 1000, 2
) )
elif self.type == "up_max_bandwidth": elif self.type == "up_max_bandwidth":
self._attr_state = round( self._attr_native_value = round(
self.bbox_data.data["tx"]["maxBandwidth"] / 1000, 2 self.bbox_data.data["tx"]["maxBandwidth"] / 1000, 2
) )
elif self.type == "current_down_bandwidth": elif self.type == "current_down_bandwidth":
self._attr_state = round(self.bbox_data.data["rx"]["bandwidth"] / 1000, 2) self._attr_native_value = round(
self.bbox_data.data["rx"]["bandwidth"] / 1000, 2
)
elif self.type == "current_up_bandwidth": elif self.type == "current_up_bandwidth":
self._attr_state = round(self.bbox_data.data["tx"]["bandwidth"] / 1000, 2) self._attr_native_value = round(
self.bbox_data.data["tx"]["bandwidth"] / 1000, 2
)
elif self.type == "number_of_reboots": elif self.type == "number_of_reboots":
self._attr_state = self.bbox_data.router_infos["device"]["numberofboots"] self._attr_native_value = self.bbox_data.router_infos["device"][
"numberofboots"
]
class BboxData: class BboxData:

View file

@ -63,17 +63,17 @@ class BeewiSmartclimSensor(SensorEntity):
self._poller = poller self._poller = poller
self._attr_name = name self._attr_name = name
self._device = device self._device = device
self._attr_unit_of_measurement = unit self._attr_native_unit_of_measurement = unit
self._attr_device_class = self._device self._attr_device_class = self._device
self._attr_unique_id = f"{mac}_{device}" self._attr_unique_id = f"{mac}_{device}"
def update(self): def update(self):
"""Fetch new state data from the poller.""" """Fetch new state data from the poller."""
self._poller.update_sensor() self._poller.update_sensor()
self._attr_state = None self._attr_native_value = None
if self._device == DEVICE_CLASS_TEMPERATURE: if self._device == DEVICE_CLASS_TEMPERATURE:
self._attr_state = self._poller.get_temperature() self._attr_native_value = self._poller.get_temperature()
if self._device == DEVICE_CLASS_HUMIDITY: if self._device == DEVICE_CLASS_HUMIDITY:
self._attr_state = self._poller.get_humidity() self._attr_native_value = self._poller.get_humidity()
if self._device == DEVICE_CLASS_BATTERY: if self._device == DEVICE_CLASS_BATTERY:
self._attr_state = self._poller.get_battery() self._attr_native_value = self._poller.get_battery()

View file

@ -101,7 +101,7 @@ class BH1750Sensor(SensorEntity):
def __init__(self, bh1750_sensor, name, unit, multiplier=1.0): def __init__(self, bh1750_sensor, name, unit, multiplier=1.0):
"""Initialize the sensor.""" """Initialize the sensor."""
self._attr_name = name self._attr_name = name
self._attr_unit_of_measurement = unit self._attr_native_unit_of_measurement = unit
self._multiplier = multiplier self._multiplier = multiplier
self.bh1750_sensor = bh1750_sensor self.bh1750_sensor = bh1750_sensor
@ -109,7 +109,7 @@ class BH1750Sensor(SensorEntity):
"""Get the latest data from the BH1750 and update the states.""" """Get the latest data from the BH1750 and update the states."""
await self.hass.async_add_executor_job(self.bh1750_sensor.update) await self.hass.async_add_executor_job(self.bh1750_sensor.update)
if self.bh1750_sensor.sample_ok and self.bh1750_sensor.light_level >= 0: if self.bh1750_sensor.sample_ok and self.bh1750_sensor.light_level >= 0:
self._attr_state = int( self._attr_native_value = int(
round(self.bh1750_sensor.light_level * self._multiplier) round(self.bh1750_sensor.light_level * self._multiplier)
) )
else: else:

View file

@ -39,22 +39,22 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription( SensorEntityDescription(
key="trade_volume_btc", key="trade_volume_btc",
name="Trade volume", name="Trade volume",
unit_of_measurement="BTC", native_unit_of_measurement="BTC",
), ),
SensorEntityDescription( SensorEntityDescription(
key="miners_revenue_usd", key="miners_revenue_usd",
name="Miners revenue", name="Miners revenue",
unit_of_measurement="USD", native_unit_of_measurement="USD",
), ),
SensorEntityDescription( SensorEntityDescription(
key="btc_mined", key="btc_mined",
name="Mined", name="Mined",
unit_of_measurement="BTC", native_unit_of_measurement="BTC",
), ),
SensorEntityDescription( SensorEntityDescription(
key="trade_volume_usd", key="trade_volume_usd",
name="Trade volume", name="Trade volume",
unit_of_measurement="USD", native_unit_of_measurement="USD",
), ),
SensorEntityDescription( SensorEntityDescription(
key="difficulty", key="difficulty",
@ -63,7 +63,7 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription( SensorEntityDescription(
key="minutes_between_blocks", key="minutes_between_blocks",
name="Time between Blocks", name="Time between Blocks",
unit_of_measurement=TIME_MINUTES, native_unit_of_measurement=TIME_MINUTES,
), ),
SensorEntityDescription( SensorEntityDescription(
key="number_of_transactions", key="number_of_transactions",
@ -72,7 +72,7 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription( SensorEntityDescription(
key="hash_rate", key="hash_rate",
name="Hash rate", name="Hash rate",
unit_of_measurement=f"PH/{TIME_SECONDS}", native_unit_of_measurement=f"PH/{TIME_SECONDS}",
), ),
SensorEntityDescription( SensorEntityDescription(
key="timestamp", key="timestamp",
@ -89,22 +89,22 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription( SensorEntityDescription(
key="total_fees_btc", key="total_fees_btc",
name="Total fees", name="Total fees",
unit_of_measurement="BTC", native_unit_of_measurement="BTC",
), ),
SensorEntityDescription( SensorEntityDescription(
key="total_btc_sent", key="total_btc_sent",
name="Total sent", name="Total sent",
unit_of_measurement="BTC", native_unit_of_measurement="BTC",
), ),
SensorEntityDescription( SensorEntityDescription(
key="estimated_btc_sent", key="estimated_btc_sent",
name="Estimated sent", name="Estimated sent",
unit_of_measurement="BTC", native_unit_of_measurement="BTC",
), ),
SensorEntityDescription( SensorEntityDescription(
key="total_btc", key="total_btc",
name="Total", name="Total",
unit_of_measurement="BTC", native_unit_of_measurement="BTC",
), ),
SensorEntityDescription( SensorEntityDescription(
key="total_blocks", key="total_blocks",
@ -117,17 +117,17 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription( SensorEntityDescription(
key="estimated_transaction_volume_usd", key="estimated_transaction_volume_usd",
name="Est. Transaction volume", name="Est. Transaction volume",
unit_of_measurement="USD", native_unit_of_measurement="USD",
), ),
SensorEntityDescription( SensorEntityDescription(
key="miners_revenue_btc", key="miners_revenue_btc",
name="Miners revenue", name="Miners revenue",
unit_of_measurement="BTC", native_unit_of_measurement="BTC",
), ),
SensorEntityDescription( SensorEntityDescription(
key="market_price_usd", key="market_price_usd",
name="Market price", name="Market price",
unit_of_measurement="USD", native_unit_of_measurement="USD",
), ),
) )
@ -182,48 +182,48 @@ class BitcoinSensor(SensorEntity):
sensor_type = self.entity_description.key sensor_type = self.entity_description.key
if sensor_type == "exchangerate": if sensor_type == "exchangerate":
self._attr_state = ticker[self._currency].p15min self._attr_native_value = ticker[self._currency].p15min
self._attr_unit_of_measurement = self._currency self._attr_native_unit_of_measurement = self._currency
elif sensor_type == "trade_volume_btc": elif sensor_type == "trade_volume_btc":
self._attr_state = f"{stats.trade_volume_btc:.1f}" self._attr_native_value = f"{stats.trade_volume_btc:.1f}"
elif sensor_type == "miners_revenue_usd": elif sensor_type == "miners_revenue_usd":
self._attr_state = f"{stats.miners_revenue_usd:.0f}" self._attr_native_value = f"{stats.miners_revenue_usd:.0f}"
elif sensor_type == "btc_mined": elif sensor_type == "btc_mined":
self._attr_state = str(stats.btc_mined * 0.00000001) self._attr_native_value = str(stats.btc_mined * 0.00000001)
elif sensor_type == "trade_volume_usd": elif sensor_type == "trade_volume_usd":
self._attr_state = f"{stats.trade_volume_usd:.1f}" self._attr_native_value = f"{stats.trade_volume_usd:.1f}"
elif sensor_type == "difficulty": elif sensor_type == "difficulty":
self._attr_state = f"{stats.difficulty:.0f}" self._attr_native_value = f"{stats.difficulty:.0f}"
elif sensor_type == "minutes_between_blocks": elif sensor_type == "minutes_between_blocks":
self._attr_state = f"{stats.minutes_between_blocks:.2f}" self._attr_native_value = f"{stats.minutes_between_blocks:.2f}"
elif sensor_type == "number_of_transactions": elif sensor_type == "number_of_transactions":
self._attr_state = str(stats.number_of_transactions) self._attr_native_value = str(stats.number_of_transactions)
elif sensor_type == "hash_rate": elif sensor_type == "hash_rate":
self._attr_state = f"{stats.hash_rate * 0.000001:.1f}" self._attr_native_value = f"{stats.hash_rate * 0.000001:.1f}"
elif sensor_type == "timestamp": elif sensor_type == "timestamp":
self._attr_state = stats.timestamp self._attr_native_value = stats.timestamp
elif sensor_type == "mined_blocks": elif sensor_type == "mined_blocks":
self._attr_state = str(stats.mined_blocks) self._attr_native_value = str(stats.mined_blocks)
elif sensor_type == "blocks_size": elif sensor_type == "blocks_size":
self._attr_state = f"{stats.blocks_size:.1f}" self._attr_native_value = f"{stats.blocks_size:.1f}"
elif sensor_type == "total_fees_btc": elif sensor_type == "total_fees_btc":
self._attr_state = f"{stats.total_fees_btc * 0.00000001:.2f}" self._attr_native_value = f"{stats.total_fees_btc * 0.00000001:.2f}"
elif sensor_type == "total_btc_sent": elif sensor_type == "total_btc_sent":
self._attr_state = f"{stats.total_btc_sent * 0.00000001:.2f}" self._attr_native_value = f"{stats.total_btc_sent * 0.00000001:.2f}"
elif sensor_type == "estimated_btc_sent": elif sensor_type == "estimated_btc_sent":
self._attr_state = f"{stats.estimated_btc_sent * 0.00000001:.2f}" self._attr_native_value = f"{stats.estimated_btc_sent * 0.00000001:.2f}"
elif sensor_type == "total_btc": elif sensor_type == "total_btc":
self._attr_state = f"{stats.total_btc * 0.00000001:.2f}" self._attr_native_value = f"{stats.total_btc * 0.00000001:.2f}"
elif sensor_type == "total_blocks": elif sensor_type == "total_blocks":
self._attr_state = f"{stats.total_blocks:.0f}" self._attr_native_value = f"{stats.total_blocks:.0f}"
elif sensor_type == "next_retarget": elif sensor_type == "next_retarget":
self._attr_state = f"{stats.next_retarget:.2f}" self._attr_native_value = f"{stats.next_retarget:.2f}"
elif sensor_type == "estimated_transaction_volume_usd": elif sensor_type == "estimated_transaction_volume_usd":
self._attr_state = f"{stats.estimated_transaction_volume_usd:.2f}" self._attr_native_value = f"{stats.estimated_transaction_volume_usd:.2f}"
elif sensor_type == "miners_revenue_btc": elif sensor_type == "miners_revenue_btc":
self._attr_state = f"{stats.miners_revenue_btc * 0.00000001:.1f}" self._attr_native_value = f"{stats.miners_revenue_btc * 0.00000001:.1f}"
elif sensor_type == "market_price_usd": elif sensor_type == "market_price_usd":
self._attr_state = f"{stats.market_price_usd:.2f}" self._attr_native_value = f"{stats.market_price_usd:.2f}"
class BitcoinData: class BitcoinData:

View file

@ -37,7 +37,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
class BizkaibusSensor(SensorEntity): class BizkaibusSensor(SensorEntity):
"""The class for handling the data.""" """The class for handling the data."""
_attr_unit_of_measurement = TIME_MINUTES _attr_native_unit_of_measurement = TIME_MINUTES
def __init__(self, data, name): def __init__(self, data, name):
"""Initialize the sensor.""" """Initialize the sensor."""
@ -48,7 +48,7 @@ class BizkaibusSensor(SensorEntity):
"""Get the latest data from the webservice.""" """Get the latest data from the webservice."""
self.data.update() self.data.update()
with suppress(TypeError): with suppress(TypeError):
self._attr_state = self.data.info[0][ATTR_DUE_IN] self._attr_native_value = self.data.info[0][ATTR_DUE_IN]
class Bizkaibus: class Bizkaibus:

View file

@ -20,10 +20,10 @@ class BleBoxSensorEntity(BleBoxEntity, SensorEntity):
def __init__(self, feature): def __init__(self, feature):
"""Initialize a BleBox sensor feature.""" """Initialize a BleBox sensor feature."""
super().__init__(feature) super().__init__(feature)
self._attr_unit_of_measurement = BLEBOX_TO_UNIT_MAP[feature.unit] self._attr_native_unit_of_measurement = BLEBOX_TO_UNIT_MAP[feature.unit]
self._attr_device_class = BLEBOX_TO_HASS_DEVICE_CLASSES[feature.device_class] self._attr_device_class = BLEBOX_TO_HASS_DEVICE_CLASSES[feature.device_class]
@property @property
def state(self): def native_value(self):
"""Return the state.""" """Return the state."""
return self._feature.current return self._feature.current

View file

@ -44,7 +44,7 @@ class BlinkSensor(SensorEntity):
self._attr_device_class = device_class self._attr_device_class = device_class
self.data = data self.data = data
self._camera = data.cameras[camera] self._camera = data.cameras[camera]
self._attr_unit_of_measurement = units self._attr_native_unit_of_measurement = units
self._attr_unique_id = f"{self._camera.serial}-{sensor_type}" self._attr_unique_id = f"{self._camera.serial}-{sensor_type}"
self._sensor_key = ( self._sensor_key = (
"temperature_calibrated" if sensor_type == "temperature" else sensor_type "temperature_calibrated" if sensor_type == "temperature" else sensor_type
@ -54,9 +54,9 @@ class BlinkSensor(SensorEntity):
"""Retrieve sensor data from the camera.""" """Retrieve sensor data from the camera."""
self.data.refresh() self.data.refresh()
try: try:
self._attr_state = self._camera.attributes[self._sensor_key] self._attr_native_value = self._camera.attributes[self._sensor_key]
except KeyError: except KeyError:
self._attr_state = None self._attr_native_value = None
_LOGGER.error( _LOGGER.error(
"%s not a valid camera attribute. Did the API change?", self._sensor_key "%s not a valid camera attribute. Did the API change?", self._sensor_key
) )

View file

@ -48,7 +48,7 @@ class BlockchainSensor(SensorEntity):
_attr_extra_state_attributes = {ATTR_ATTRIBUTION: ATTRIBUTION} _attr_extra_state_attributes = {ATTR_ATTRIBUTION: ATTRIBUTION}
_attr_icon = ICON _attr_icon = ICON
_attr_unit_of_measurement = "BTC" _attr_native_unit_of_measurement = "BTC"
def __init__(self, name, addresses): def __init__(self, name, addresses):
"""Initialize the sensor.""" """Initialize the sensor."""
@ -57,4 +57,4 @@ class BlockchainSensor(SensorEntity):
def update(self): def update(self):
"""Get the latest state of the sensor.""" """Get the latest state of the sensor."""
self._attr_state = get_balance(self.addresses) self._attr_native_value = get_balance(self.addresses)

View file

@ -86,9 +86,13 @@ class BloomSkySensor(SensorEntity):
self._sensor_name = sensor_name self._sensor_name = sensor_name
self._attr_name = f"{device['DeviceName']} {sensor_name}" self._attr_name = f"{device['DeviceName']} {sensor_name}"
self._attr_unique_id = f"{self._device_id}-{sensor_name}" self._attr_unique_id = f"{self._device_id}-{sensor_name}"
self._attr_unit_of_measurement = SENSOR_UNITS_IMPERIAL.get(sensor_name, None) self._attr_native_unit_of_measurement = SENSOR_UNITS_IMPERIAL.get(
sensor_name, None
)
if self._bloomsky.is_metric: if self._bloomsky.is_metric:
self._attr_unit_of_measurement = SENSOR_UNITS_METRIC.get(sensor_name, None) self._attr_native_unit_of_measurement = SENSOR_UNITS_METRIC.get(
sensor_name, None
)
@property @property
def device_class(self): def device_class(self):
@ -99,6 +103,6 @@ class BloomSkySensor(SensorEntity):
"""Request an update from the BloomSky API.""" """Request an update from the BloomSky API."""
self._bloomsky.refresh_devices() self._bloomsky.refresh_devices()
state = self._bloomsky.devices[self._device_id]["Data"][self._sensor_name] state = self._bloomsky.devices[self._device_id]["Data"][self._sensor_name]
self._attr_state = ( self._attr_native_value = (
f"{state:.2f}" if self._sensor_name in FORMAT_NUMBERS else state f"{state:.2f}" if self._sensor_name in FORMAT_NUMBERS else state
) )

View file

@ -127,11 +127,11 @@ class BME280Sensor(CoordinatorEntity, SensorEntity):
self._attr_name = f"{name} {SENSOR_TYPES[sensor_type][0]}" self._attr_name = f"{name} {SENSOR_TYPES[sensor_type][0]}"
self.temp_unit = temp_unit self.temp_unit = temp_unit
self.type = sensor_type self.type = sensor_type
self._attr_unit_of_measurement = SENSOR_TYPES[sensor_type][1] self._attr_native_unit_of_measurement = SENSOR_TYPES[sensor_type][1]
self._attr_device_class = SENSOR_TYPES[sensor_type][2] self._attr_device_class = SENSOR_TYPES[sensor_type][2]
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
if self.type == SENSOR_TEMP: if self.type == SENSOR_TEMP:
temperature = round(self.coordinator.data.temperature, 1) temperature = round(self.coordinator.data.temperature, 1)

View file

@ -327,25 +327,27 @@ class BME680Sensor(SensorEntity):
self.bme680_client = bme680_client self.bme680_client = bme680_client
self.temp_unit = temp_unit self.temp_unit = temp_unit
self.type = sensor_type self.type = sensor_type
self._attr_unit_of_measurement = SENSOR_TYPES[sensor_type][1] self._attr_native_unit_of_measurement = SENSOR_TYPES[sensor_type][1]
self._attr_device_class = SENSOR_TYPES[sensor_type][2] self._attr_device_class = SENSOR_TYPES[sensor_type][2]
async def async_update(self): async def async_update(self):
"""Get the latest data from the BME680 and update the states.""" """Get the latest data from the BME680 and update the states."""
await self.hass.async_add_executor_job(self.bme680_client.update) await self.hass.async_add_executor_job(self.bme680_client.update)
if self.type == SENSOR_TEMP: if self.type == SENSOR_TEMP:
self._attr_state = round(self.bme680_client.sensor_data.temperature, 1) self._attr_native_value = round(
self.bme680_client.sensor_data.temperature, 1
)
if self.temp_unit == TEMP_FAHRENHEIT: if self.temp_unit == TEMP_FAHRENHEIT:
self._attr_state = round(celsius_to_fahrenheit(self.state), 1) self._attr_native_value = round(celsius_to_fahrenheit(self.state), 1)
elif self.type == SENSOR_HUMID: elif self.type == SENSOR_HUMID:
self._attr_state = round(self.bme680_client.sensor_data.humidity, 1) self._attr_native_value = round(self.bme680_client.sensor_data.humidity, 1)
elif self.type == SENSOR_PRESS: elif self.type == SENSOR_PRESS:
self._attr_state = round(self.bme680_client.sensor_data.pressure, 1) self._attr_native_value = round(self.bme680_client.sensor_data.pressure, 1)
elif self.type == SENSOR_GAS: elif self.type == SENSOR_GAS:
self._attr_state = int( self._attr_native_value = int(
round(self.bme680_client.sensor_data.gas_resistance, 0) round(self.bme680_client.sensor_data.gas_resistance, 0)
) )
elif self.type == SENSOR_AQ: elif self.type == SENSOR_AQ:
aq_score = self.bme680_client.sensor_data.air_quality aq_score = self.bme680_client.sensor_data.air_quality
if aq_score is not None: if aq_score is not None:
self._attr_state = round(aq_score, 1) self._attr_native_value = round(aq_score, 1)

View file

@ -78,7 +78,7 @@ class Bmp280Sensor(SensorEntity):
"""Initialize the sensor.""" """Initialize the sensor."""
self._bmp280 = bmp280 self._bmp280 = bmp280
self._attr_name = name self._attr_name = name
self._attr_unit_of_measurement = unit_of_measurement self._attr_native_unit_of_measurement = unit_of_measurement
class Bmp280TemperatureSensor(Bmp280Sensor): class Bmp280TemperatureSensor(Bmp280Sensor):
@ -94,7 +94,7 @@ class Bmp280TemperatureSensor(Bmp280Sensor):
def update(self): def update(self):
"""Fetch new state data for the sensor.""" """Fetch new state data for the sensor."""
try: try:
self._attr_state = round(self._bmp280.temperature, 1) self._attr_native_value = round(self._bmp280.temperature, 1)
if not self.available: if not self.available:
_LOGGER.warning("Communication restored with temperature sensor") _LOGGER.warning("Communication restored with temperature sensor")
self._attr_available = True self._attr_available = True
@ -119,7 +119,7 @@ class Bmp280PressureSensor(Bmp280Sensor):
def update(self): def update(self):
"""Fetch new state data for the sensor.""" """Fetch new state data for the sensor."""
try: try:
self._attr_state = round(self._bmp280.pressure) self._attr_native_value = round(self._bmp280.pressure)
if not self.available: if not self.available:
_LOGGER.warning("Communication restored with pressure sensor") _LOGGER.warning("Communication restored with pressure sensor")
self._attr_available = True self._attr_available = True

View file

@ -516,7 +516,7 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, SensorEntity):
self._attr_device_class = attribute_info.get( self._attr_device_class = attribute_info.get(
attribute, [None, None, None, None] attribute, [None, None, None, None]
)[1] )[1]
self._attr_unit_of_measurement = attribute_info.get( self._attr_native_unit_of_measurement = attribute_info.get(
attribute, [None, None, None, None] attribute, [None, None, None, None]
)[2] )[2]
@ -525,24 +525,24 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, SensorEntity):
_LOGGER.debug("Updating %s", self._vehicle.name) _LOGGER.debug("Updating %s", self._vehicle.name)
vehicle_state = self._vehicle.state vehicle_state = self._vehicle.state
if self._attribute == "charging_status": if self._attribute == "charging_status":
self._attr_state = getattr(vehicle_state, self._attribute).value self._attr_native_value = getattr(vehicle_state, self._attribute).value
elif self.unit_of_measurement == VOLUME_GALLONS: elif self.unit_of_measurement == VOLUME_GALLONS:
value = getattr(vehicle_state, self._attribute) value = getattr(vehicle_state, self._attribute)
value_converted = self.hass.config.units.volume(value, VOLUME_LITERS) value_converted = self.hass.config.units.volume(value, VOLUME_LITERS)
self._attr_state = round(value_converted) self._attr_native_value = round(value_converted)
elif self.unit_of_measurement == LENGTH_MILES: elif self.unit_of_measurement == LENGTH_MILES:
value = getattr(vehicle_state, self._attribute) value = getattr(vehicle_state, self._attribute)
value_converted = self.hass.config.units.length(value, LENGTH_KILOMETERS) value_converted = self.hass.config.units.length(value, LENGTH_KILOMETERS)
self._attr_state = round(value_converted) self._attr_native_value = round(value_converted)
elif self._service is None: elif self._service is None:
self._attr_state = getattr(vehicle_state, self._attribute) self._attr_native_value = getattr(vehicle_state, self._attribute)
elif self._service == SERVICE_LAST_TRIP: elif self._service == SERVICE_LAST_TRIP:
vehicle_last_trip = self._vehicle.state.last_trip vehicle_last_trip = self._vehicle.state.last_trip
if self._attribute == "date_utc": if self._attribute == "date_utc":
date_str = getattr(vehicle_last_trip, "date") date_str = getattr(vehicle_last_trip, "date")
self._attr_state = dt_util.parse_datetime(date_str).isoformat() self._attr_native_value = dt_util.parse_datetime(date_str).isoformat()
else: else:
self._attr_state = getattr(vehicle_last_trip, self._attribute) self._attr_native_value = getattr(vehicle_last_trip, self._attribute)
elif self._service == SERVICE_ALL_TRIPS: elif self._service == SERVICE_ALL_TRIPS:
vehicle_all_trips = self._vehicle.state.all_trips vehicle_all_trips = self._vehicle.state.all_trips
for attribute in ( for attribute in (
@ -555,13 +555,13 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, SensorEntity):
if self._attribute.startswith(f"{attribute}_"): if self._attribute.startswith(f"{attribute}_"):
attr = getattr(vehicle_all_trips, attribute) attr = getattr(vehicle_all_trips, attribute)
sub_attr = self._attribute.replace(f"{attribute}_", "") sub_attr = self._attribute.replace(f"{attribute}_", "")
self._attr_state = getattr(attr, sub_attr) self._attr_native_value = getattr(attr, sub_attr)
return return
if self._attribute == "reset_date_utc": if self._attribute == "reset_date_utc":
date_str = getattr(vehicle_all_trips, "reset_date") date_str = getattr(vehicle_all_trips, "reset_date")
self._attr_state = dt_util.parse_datetime(date_str).isoformat() self._attr_native_value = dt_util.parse_datetime(date_str).isoformat()
else: else:
self._attr_state = getattr(vehicle_all_trips, self._attribute) self._attr_native_value = getattr(vehicle_all_trips, self._attribute)
vehicle_state = self._vehicle.state vehicle_state = self._vehicle.state
charging_state = vehicle_state.charging_status in [ChargingState.CHARGING] charging_state = vehicle_state.charging_status in [ChargingState.CHARGING]

View file

@ -147,7 +147,7 @@ class TemperatureSensor(SHCEntity, SensorEntity):
"""Representation of an SHC temperature reporting sensor.""" """Representation of an SHC temperature reporting sensor."""
_attr_device_class = DEVICE_CLASS_TEMPERATURE _attr_device_class = DEVICE_CLASS_TEMPERATURE
_attr_unit_of_measurement = TEMP_CELSIUS _attr_native_unit_of_measurement = TEMP_CELSIUS
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None: def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC temperature reporting sensor.""" """Initialize an SHC temperature reporting sensor."""
@ -156,7 +156,7 @@ class TemperatureSensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_temperature" self._attr_unique_id = f"{device.serial}_temperature"
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._device.temperature return self._device.temperature
@ -165,7 +165,7 @@ class HumiditySensor(SHCEntity, SensorEntity):
"""Representation of an SHC humidity reporting sensor.""" """Representation of an SHC humidity reporting sensor."""
_attr_device_class = DEVICE_CLASS_HUMIDITY _attr_device_class = DEVICE_CLASS_HUMIDITY
_attr_unit_of_measurement = PERCENTAGE _attr_native_unit_of_measurement = PERCENTAGE
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None: def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC humidity reporting sensor.""" """Initialize an SHC humidity reporting sensor."""
@ -174,7 +174,7 @@ class HumiditySensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_humidity" self._attr_unique_id = f"{device.serial}_humidity"
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._device.humidity return self._device.humidity
@ -183,7 +183,7 @@ class PuritySensor(SHCEntity, SensorEntity):
"""Representation of an SHC purity reporting sensor.""" """Representation of an SHC purity reporting sensor."""
_attr_icon = "mdi:molecule-co2" _attr_icon = "mdi:molecule-co2"
_attr_unit_of_measurement = CONCENTRATION_PARTS_PER_MILLION _attr_native_unit_of_measurement = CONCENTRATION_PARTS_PER_MILLION
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None: def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC purity reporting sensor.""" """Initialize an SHC purity reporting sensor."""
@ -192,7 +192,7 @@ class PuritySensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_purity" self._attr_unique_id = f"{device.serial}_purity"
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._device.purity return self._device.purity
@ -207,7 +207,7 @@ class AirQualitySensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_airquality" self._attr_unique_id = f"{device.serial}_airquality"
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._device.combined_rating.name return self._device.combined_rating.name
@ -229,7 +229,7 @@ class TemperatureRatingSensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_temperature_rating" self._attr_unique_id = f"{device.serial}_temperature_rating"
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._device.temperature_rating.name return self._device.temperature_rating.name
@ -244,7 +244,7 @@ class HumidityRatingSensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_humidity_rating" self._attr_unique_id = f"{device.serial}_humidity_rating"
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._device.humidity_rating.name return self._device.humidity_rating.name
@ -259,7 +259,7 @@ class PurityRatingSensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_purity_rating" self._attr_unique_id = f"{device.serial}_purity_rating"
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._device.purity_rating.name return self._device.purity_rating.name
@ -268,7 +268,7 @@ class PowerSensor(SHCEntity, SensorEntity):
"""Representation of an SHC power reporting sensor.""" """Representation of an SHC power reporting sensor."""
_attr_device_class = DEVICE_CLASS_POWER _attr_device_class = DEVICE_CLASS_POWER
_attr_unit_of_measurement = POWER_WATT _attr_native_unit_of_measurement = POWER_WATT
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None: def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC power reporting sensor.""" """Initialize an SHC power reporting sensor."""
@ -277,7 +277,7 @@ class PowerSensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_power" self._attr_unique_id = f"{device.serial}_power"
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._device.powerconsumption return self._device.powerconsumption
@ -286,7 +286,7 @@ class EnergySensor(SHCEntity, SensorEntity):
"""Representation of an SHC energy reporting sensor.""" """Representation of an SHC energy reporting sensor."""
_attr_device_class = DEVICE_CLASS_ENERGY _attr_device_class = DEVICE_CLASS_ENERGY
_attr_unit_of_measurement = ENERGY_KILO_WATT_HOUR _attr_native_unit_of_measurement = ENERGY_KILO_WATT_HOUR
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None: def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC energy reporting sensor.""" """Initialize an SHC energy reporting sensor."""
@ -295,7 +295,7 @@ class EnergySensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{self._device.serial}_energy" self._attr_unique_id = f"{self._device.serial}_energy"
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._device.energyconsumption / 1000.0 return self._device.energyconsumption / 1000.0
@ -304,7 +304,7 @@ class ValveTappetSensor(SHCEntity, SensorEntity):
"""Representation of an SHC valve tappet reporting sensor.""" """Representation of an SHC valve tappet reporting sensor."""
_attr_icon = "mdi:gauge" _attr_icon = "mdi:gauge"
_attr_unit_of_measurement = PERCENTAGE _attr_native_unit_of_measurement = PERCENTAGE
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None: def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC valve tappet reporting sensor.""" """Initialize an SHC valve tappet reporting sensor."""
@ -313,7 +313,7 @@ class ValveTappetSensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_valvetappet" self._attr_unique_id = f"{device.serial}_valvetappet"
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._device.position return self._device.position

View file

@ -91,10 +91,10 @@ class BroadlinkSensor(BroadlinkEntity, SensorEntity):
self._attr_device_class = SENSOR_TYPES[monitored_condition][2] self._attr_device_class = SENSOR_TYPES[monitored_condition][2]
self._attr_name = f"{device.name} {SENSOR_TYPES[monitored_condition][0]}" self._attr_name = f"{device.name} {SENSOR_TYPES[monitored_condition][0]}"
self._attr_state_class = SENSOR_TYPES[monitored_condition][3] self._attr_state_class = SENSOR_TYPES[monitored_condition][3]
self._attr_state = self._coordinator.data[monitored_condition] self._attr_native_value = self._coordinator.data[monitored_condition]
self._attr_unique_id = f"{device.unique_id}-{monitored_condition}" self._attr_unique_id = f"{device.unique_id}-{monitored_condition}"
self._attr_unit_of_measurement = SENSOR_TYPES[monitored_condition][1] self._attr_native_unit_of_measurement = SENSOR_TYPES[monitored_condition][1]
def _update_state(self, data): def _update_state(self, data):
"""Update the state of the entity.""" """Update the state of the entity."""
self._attr_state = data[self._monitored_condition] self._attr_native_value = data[self._monitored_condition]

View file

@ -87,154 +87,154 @@ SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = (
key=ATTR_PAGE_COUNTER, key=ATTR_PAGE_COUNTER,
icon="mdi:file-document-outline", icon="mdi:file-document-outline",
name=ATTR_PAGE_COUNTER.replace("_", " ").title(), name=ATTR_PAGE_COUNTER.replace("_", " ").title(),
unit_of_measurement=UNIT_PAGES, native_unit_of_measurement=UNIT_PAGES,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_BW_COUNTER, key=ATTR_BW_COUNTER,
icon="mdi:file-document-outline", icon="mdi:file-document-outline",
name=ATTR_BW_COUNTER.replace("_", " ").title(), name=ATTR_BW_COUNTER.replace("_", " ").title(),
unit_of_measurement=UNIT_PAGES, native_unit_of_measurement=UNIT_PAGES,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_COLOR_COUNTER, key=ATTR_COLOR_COUNTER,
icon="mdi:file-document-outline", icon="mdi:file-document-outline",
name=ATTR_COLOR_COUNTER.replace("_", " ").title(), name=ATTR_COLOR_COUNTER.replace("_", " ").title(),
unit_of_measurement=UNIT_PAGES, native_unit_of_measurement=UNIT_PAGES,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_DUPLEX_COUNTER, key=ATTR_DUPLEX_COUNTER,
icon="mdi:file-document-outline", icon="mdi:file-document-outline",
name=ATTR_DUPLEX_COUNTER.replace("_", " ").title(), name=ATTR_DUPLEX_COUNTER.replace("_", " ").title(),
unit_of_measurement=UNIT_PAGES, native_unit_of_measurement=UNIT_PAGES,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_DRUM_REMAINING_LIFE, key=ATTR_DRUM_REMAINING_LIFE,
icon="mdi:chart-donut", icon="mdi:chart-donut",
name=ATTR_DRUM_REMAINING_LIFE.replace("_", " ").title(), name=ATTR_DRUM_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_BLACK_DRUM_REMAINING_LIFE, key=ATTR_BLACK_DRUM_REMAINING_LIFE,
icon="mdi:chart-donut", icon="mdi:chart-donut",
name=ATTR_BLACK_DRUM_REMAINING_LIFE.replace("_", " ").title(), name=ATTR_BLACK_DRUM_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_CYAN_DRUM_REMAINING_LIFE, key=ATTR_CYAN_DRUM_REMAINING_LIFE,
icon="mdi:chart-donut", icon="mdi:chart-donut",
name=ATTR_CYAN_DRUM_REMAINING_LIFE.replace("_", " ").title(), name=ATTR_CYAN_DRUM_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_MAGENTA_DRUM_REMAINING_LIFE, key=ATTR_MAGENTA_DRUM_REMAINING_LIFE,
icon="mdi:chart-donut", icon="mdi:chart-donut",
name=ATTR_MAGENTA_DRUM_REMAINING_LIFE.replace("_", " ").title(), name=ATTR_MAGENTA_DRUM_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_YELLOW_DRUM_REMAINING_LIFE, key=ATTR_YELLOW_DRUM_REMAINING_LIFE,
icon="mdi:chart-donut", icon="mdi:chart-donut",
name=ATTR_YELLOW_DRUM_REMAINING_LIFE.replace("_", " ").title(), name=ATTR_YELLOW_DRUM_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_BELT_UNIT_REMAINING_LIFE, key=ATTR_BELT_UNIT_REMAINING_LIFE,
icon="mdi:current-ac", icon="mdi:current-ac",
name=ATTR_BELT_UNIT_REMAINING_LIFE.replace("_", " ").title(), name=ATTR_BELT_UNIT_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_FUSER_REMAINING_LIFE, key=ATTR_FUSER_REMAINING_LIFE,
icon="mdi:water-outline", icon="mdi:water-outline",
name=ATTR_FUSER_REMAINING_LIFE.replace("_", " ").title(), name=ATTR_FUSER_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_LASER_REMAINING_LIFE, key=ATTR_LASER_REMAINING_LIFE,
icon="mdi:spotlight-beam", icon="mdi:spotlight-beam",
name=ATTR_LASER_REMAINING_LIFE.replace("_", " ").title(), name=ATTR_LASER_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_PF_KIT_1_REMAINING_LIFE, key=ATTR_PF_KIT_1_REMAINING_LIFE,
icon="mdi:printer-3d", icon="mdi:printer-3d",
name=ATTR_PF_KIT_1_REMAINING_LIFE.replace("_", " ").title(), name=ATTR_PF_KIT_1_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_PF_KIT_MP_REMAINING_LIFE, key=ATTR_PF_KIT_MP_REMAINING_LIFE,
icon="mdi:printer-3d", icon="mdi:printer-3d",
name=ATTR_PF_KIT_MP_REMAINING_LIFE.replace("_", " ").title(), name=ATTR_PF_KIT_MP_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_BLACK_TONER_REMAINING, key=ATTR_BLACK_TONER_REMAINING,
icon="mdi:printer-3d-nozzle", icon="mdi:printer-3d-nozzle",
name=ATTR_BLACK_TONER_REMAINING.replace("_", " ").title(), name=ATTR_BLACK_TONER_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_CYAN_TONER_REMAINING, key=ATTR_CYAN_TONER_REMAINING,
icon="mdi:printer-3d-nozzle", icon="mdi:printer-3d-nozzle",
name=ATTR_CYAN_TONER_REMAINING.replace("_", " ").title(), name=ATTR_CYAN_TONER_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_MAGENTA_TONER_REMAINING, key=ATTR_MAGENTA_TONER_REMAINING,
icon="mdi:printer-3d-nozzle", icon="mdi:printer-3d-nozzle",
name=ATTR_MAGENTA_TONER_REMAINING.replace("_", " ").title(), name=ATTR_MAGENTA_TONER_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_YELLOW_TONER_REMAINING, key=ATTR_YELLOW_TONER_REMAINING,
icon="mdi:printer-3d-nozzle", icon="mdi:printer-3d-nozzle",
name=ATTR_YELLOW_TONER_REMAINING.replace("_", " ").title(), name=ATTR_YELLOW_TONER_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_BLACK_INK_REMAINING, key=ATTR_BLACK_INK_REMAINING,
icon="mdi:printer-3d-nozzle", icon="mdi:printer-3d-nozzle",
name=ATTR_BLACK_INK_REMAINING.replace("_", " ").title(), name=ATTR_BLACK_INK_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_CYAN_INK_REMAINING, key=ATTR_CYAN_INK_REMAINING,
icon="mdi:printer-3d-nozzle", icon="mdi:printer-3d-nozzle",
name=ATTR_CYAN_INK_REMAINING.replace("_", " ").title(), name=ATTR_CYAN_INK_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_MAGENTA_INK_REMAINING, key=ATTR_MAGENTA_INK_REMAINING,
icon="mdi:printer-3d-nozzle", icon="mdi:printer-3d-nozzle",
name=ATTR_MAGENTA_INK_REMAINING.replace("_", " ").title(), name=ATTR_MAGENTA_INK_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
key=ATTR_YELLOW_INK_REMAINING, key=ATTR_YELLOW_INK_REMAINING,
icon="mdi:printer-3d-nozzle", icon="mdi:printer-3d-nozzle",
name=ATTR_YELLOW_INK_REMAINING.replace("_", " ").title(), name=ATTR_YELLOW_INK_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(

View file

@ -64,7 +64,7 @@ class BrotherPrinterSensor(CoordinatorEntity, SensorEntity):
self.entity_description = description self.entity_description = description
@property @property
def state(self) -> StateType: def native_value(self) -> StateType:
"""Return the state.""" """Return the state."""
if self.entity_description.key == ATTR_UPTIME: if self.entity_description.key == ATTR_UPTIME:
return cast( return cast(

View file

@ -103,4 +103,4 @@ class BrottsplatskartanSensor(SensorEntity):
ATTR_ATTRIBUTION: brottsplatskartan.ATTRIBUTION ATTR_ATTRIBUTION: brottsplatskartan.ATTRIBUTION
} }
self._attr_extra_state_attributes.update(incident_counts) self._attr_extra_state_attributes.update(incident_counts)
self._attr_state = len(incidents) self._attr_native_value = len(incidents)

View file

@ -364,7 +364,7 @@ class BrSensor(SensorEntity):
self._attr_name = f"{client_name} {SENSOR_TYPES[sensor_type][0]}" self._attr_name = f"{client_name} {SENSOR_TYPES[sensor_type][0]}"
self._attr_icon = SENSOR_TYPES[sensor_type][2] self._attr_icon = SENSOR_TYPES[sensor_type][2]
self.type = sensor_type self.type = sensor_type
self._attr_unit_of_measurement = SENSOR_TYPES[sensor_type][1] self._attr_native_unit_of_measurement = SENSOR_TYPES[sensor_type][1]
self._measured = None self._measured = None
self._attr_unique_id = "{:2.6f}{:2.6f}{}".format( self._attr_unique_id = "{:2.6f}{:2.6f}{}".format(
coordinates[CONF_LATITUDE], coordinates[CONF_LONGITUDE], sensor_type coordinates[CONF_LATITUDE], coordinates[CONF_LONGITUDE], sensor_type
@ -438,7 +438,7 @@ class BrSensor(SensorEntity):
img = condition.get(IMAGE) img = condition.get(IMAGE)
if new_state != self.state or img != self.entity_picture: if new_state != self.state or img != self.entity_picture:
self._attr_state = new_state self._attr_native_value = new_state
self._attr_entity_picture = img self._attr_entity_picture = img
return True return True
return False return False
@ -446,9 +446,11 @@ class BrSensor(SensorEntity):
if self.type.startswith(WINDSPEED): if self.type.startswith(WINDSPEED):
# hass wants windspeeds in km/h not m/s, so convert: # hass wants windspeeds in km/h not m/s, so convert:
try: try:
self._attr_state = data.get(FORECAST)[fcday].get(self.type[:-3]) self._attr_native_value = data.get(FORECAST)[fcday].get(
self.type[:-3]
)
if self.state is not None: if self.state is not None:
self._attr_state = round(self.state * 3.6, 1) self._attr_native_value = round(self.state * 3.6, 1)
return True return True
except IndexError: except IndexError:
_LOGGER.warning("No forecast for fcday=%s", fcday) _LOGGER.warning("No forecast for fcday=%s", fcday)
@ -456,7 +458,7 @@ class BrSensor(SensorEntity):
# update all other sensors # update all other sensors
try: try:
self._attr_state = data.get(FORECAST)[fcday].get(self.type[:-3]) self._attr_native_value = data.get(FORECAST)[fcday].get(self.type[:-3])
return True return True
except IndexError: except IndexError:
_LOGGER.warning("No forecast for fcday=%s", fcday) _LOGGER.warning("No forecast for fcday=%s", fcday)
@ -480,7 +482,7 @@ class BrSensor(SensorEntity):
img = condition.get(IMAGE) img = condition.get(IMAGE)
if new_state != self.state or img != self.entity_picture: if new_state != self.state or img != self.entity_picture:
self._attr_state = new_state self._attr_native_value = new_state
self._attr_entity_picture = img self._attr_entity_picture = img
return True return True
@ -490,25 +492,27 @@ class BrSensor(SensorEntity):
# update nested precipitation forecast sensors # update nested precipitation forecast sensors
nested = data.get(PRECIPITATION_FORECAST) nested = data.get(PRECIPITATION_FORECAST)
self._timeframe = nested.get(TIMEFRAME) self._timeframe = nested.get(TIMEFRAME)
self._attr_state = nested.get(self.type[len(PRECIPITATION_FORECAST) + 1 :]) self._attr_native_value = nested.get(
self.type[len(PRECIPITATION_FORECAST) + 1 :]
)
return True return True
if self.type in [WINDSPEED, WINDGUST]: if self.type in [WINDSPEED, WINDGUST]:
# hass wants windspeeds in km/h not m/s, so convert: # hass wants windspeeds in km/h not m/s, so convert:
self._attr_state = data.get(self.type) self._attr_native_value = data.get(self.type)
if self.state is not None: if self.state is not None:
self._attr_state = round(data.get(self.type) * 3.6, 1) self._attr_native_value = round(data.get(self.type) * 3.6, 1)
return True return True
if self.type == VISIBILITY: if self.type == VISIBILITY:
# hass wants visibility in km (not m), so convert: # hass wants visibility in km (not m), so convert:
self._attr_state = data.get(self.type) self._attr_native_value = data.get(self.type)
if self.state is not None: if self.state is not None:
self._attr_state = round(self.state / 1000, 1) self._attr_native_value = round(self.state / 1000, 1)
return True return True
# update all other sensors # update all other sensors
self._attr_state = data.get(self.type) self._attr_native_value = data.get(self.type)
if self.type.startswith(PRECIPITATION_FORECAST): if self.type.startswith(PRECIPITATION_FORECAST):
result = {ATTR_ATTRIBUTION: data.get(ATTRIBUTION)} result = {ATTR_ATTRIBUTION: data.get(ATTRIBUTION)}
if self._timeframe is not None: if self._timeframe is not None:

View file

@ -144,7 +144,7 @@ class CanarySensor(CoordinatorEntity, SensorEntity):
return None return None
@property @property
def state(self) -> float | None: def native_value(self) -> float | None:
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self.reading return self.reading

View file

@ -85,7 +85,7 @@ class SSLCertificateTimestamp(CertExpiryEntity, SensorEntity):
self._attr_unique_id = f"{coordinator.host}:{coordinator.port}-timestamp" self._attr_unique_id = f"{coordinator.host}:{coordinator.port}-timestamp"
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
if self.coordinator.data: if self.coordinator.data:
return self.coordinator.data.isoformat() return self.coordinator.data.isoformat()

View file

@ -265,7 +265,7 @@ class CityBikesNetwork:
class CityBikesStation(SensorEntity): class CityBikesStation(SensorEntity):
"""CityBikes API Sensor.""" """CityBikes API Sensor."""
_attr_unit_of_measurement = "bikes" _attr_native_unit_of_measurement = "bikes"
_attr_icon = "mdi:bike" _attr_icon = "mdi:bike"
def __init__(self, network, station_id, entity_id): def __init__(self, network, station_id, entity_id):
@ -281,7 +281,7 @@ class CityBikesStation(SensorEntity):
station_data = station station_data = station
break break
self._attr_name = station_data.get(ATTR_NAME) self._attr_name = station_data.get(ATTR_NAME)
self._attr_state = station_data.get(ATTR_FREE_BIKES) self._attr_native_value = station_data.get(ATTR_FREE_BIKES)
self._attr_extra_state_attributes = ( self._attr_extra_state_attributes = (
{ {
ATTR_ATTRIBUTION: CITYBIKES_ATTRIBUTION, ATTR_ATTRIBUTION: CITYBIKES_ATTRIBUTION,

View file

@ -68,7 +68,7 @@ class BaseClimaCellSensorEntity(ClimaCellEntity, SensorEntity):
f"{self._config_entry.unique_id}_{slugify(description.name)}" f"{self._config_entry.unique_id}_{slugify(description.name)}"
) )
self._attr_extra_state_attributes = {ATTR_ATTRIBUTION: self.attribution} self._attr_extra_state_attributes = {ATTR_ATTRIBUTION: self.attribution}
self._attr_unit_of_measurement = ( self._attr_native_unit_of_measurement = (
description.unit_metric description.unit_metric
if hass.config.units.is_metric if hass.config.units.is_metric
else description.unit_imperial else description.unit_imperial
@ -80,7 +80,7 @@ class BaseClimaCellSensorEntity(ClimaCellEntity, SensorEntity):
"""Return the raw state.""" """Return the raw state."""
@property @property
def state(self) -> str | int | float | None: def native_value(self) -> str | int | float | None:
"""Return the state.""" """Return the state."""
state = self._state state = self._state
if ( if (

View file

@ -123,12 +123,12 @@ class CO2Sensor(update_coordinator.CoordinatorEntity[CO2SignalResponse], SensorE
) )
@property @property
def state(self) -> StateType: def native_value(self) -> StateType:
"""Return sensor state.""" """Return sensor state."""
return round(self.coordinator.data["data"][self._description.key], 2) # type: ignore[misc] return round(self.coordinator.data["data"][self._description.key], 2) # type: ignore[misc]
@property @property
def unit_of_measurement(self) -> str | None: def native_unit_of_measurement(self) -> str | None:
"""Return the unit of measurement.""" """Return the unit of measurement."""
if self._description.unit_of_measurement: if self._description.unit_of_measurement:
return self._description.unit_of_measurement return self._description.unit_of_measurement

View file

@ -116,12 +116,12 @@ class AccountSensor(SensorEntity):
return self._id return self._id
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._state return self._state
@property @property
def unit_of_measurement(self): def native_unit_of_measurement(self):
"""Return the unit of measurement this sensor expresses itself in.""" """Return the unit of measurement this sensor expresses itself in."""
return self._unit_of_measurement return self._unit_of_measurement
@ -181,12 +181,12 @@ class ExchangeRateSensor(SensorEntity):
return self._id return self._id
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._state return self._state
@property @property
def unit_of_measurement(self): def native_unit_of_measurement(self):
"""Return the unit of measurement this sensor expresses itself in.""" """Return the unit of measurement this sensor expresses itself in."""
return self._unit_of_measurement return self._unit_of_measurement

View file

@ -86,12 +86,12 @@ class ComedHourlyPricingSensor(SensorEntity):
return self._name return self._name
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._state return self._state
@property @property
def unit_of_measurement(self): def native_unit_of_measurement(self):
"""Return the unit of measurement of this entity, if any.""" """Return the unit of measurement of this entity, if any."""
return self._unit_of_measurement return self._unit_of_measurement

View file

@ -297,7 +297,7 @@ class ComfoConnectSensor(SensorEntity):
self.schedule_update_ha_state() self.schedule_update_ha_state()
@property @property
def state(self): def native_value(self):
"""Return the state of the entity.""" """Return the state of the entity."""
try: try:
return self._ccb.data[self._sensor_id] return self._ccb.data[self._sensor_id]
@ -325,7 +325,7 @@ class ComfoConnectSensor(SensorEntity):
return SENSOR_TYPES[self._sensor_type][ATTR_ICON] return SENSOR_TYPES[self._sensor_type][ATTR_ICON]
@property @property
def unit_of_measurement(self): def native_unit_of_measurement(self):
"""Return the unit of measurement of this entity.""" """Return the unit of measurement of this entity."""
return SENSOR_TYPES[self._sensor_type][ATTR_UNIT] return SENSOR_TYPES[self._sensor_type][ATTR_UNIT]

View file

@ -84,12 +84,12 @@ class CommandSensor(SensorEntity):
return self._name return self._name
@property @property
def unit_of_measurement(self): def native_unit_of_measurement(self):
"""Return the unit the value is expressed in.""" """Return the unit the value is expressed in."""
return self._unit_of_measurement return self._unit_of_measurement
@property @property
def state(self): def native_value(self):
"""Return the state of the device.""" """Return the state of the device."""
return self._state return self._state

View file

@ -107,7 +107,7 @@ class CompensationSensor(SensorEntity):
return False return False
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._state return self._state
@ -123,7 +123,7 @@ class CompensationSensor(SensorEntity):
return ret return ret
@property @property
def unit_of_measurement(self): def native_unit_of_measurement(self):
"""Return the unit the value is expressed in.""" """Return the unit the value is expressed in."""
return self._unit_of_measurement return self._unit_of_measurement

View file

@ -27,7 +27,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class CoronavirusSensor(CoordinatorEntity, SensorEntity): class CoronavirusSensor(CoordinatorEntity, SensorEntity):
"""Sensor representing corona virus data.""" """Sensor representing corona virus data."""
_attr_unit_of_measurement = "people" _attr_native_unit_of_measurement = "people"
def __init__(self, coordinator, country, info_type): def __init__(self, coordinator, country, info_type):
"""Initialize coronavirus sensor.""" """Initialize coronavirus sensor."""
@ -53,7 +53,7 @@ class CoronavirusSensor(CoordinatorEntity, SensorEntity):
) )
@property @property
def state(self): def native_value(self):
"""State of the sensor.""" """State of the sensor."""
if self.country == OPTION_WORLDWIDE: if self.country == OPTION_WORLDWIDE:
sum_cases = 0 sum_cases = 0

View file

@ -43,12 +43,12 @@ class CpuSpeedSensor(SensorEntity):
return self._name return self._name
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._state return self._state
@property @property
def unit_of_measurement(self): def native_unit_of_measurement(self):
"""Return the unit the value is expressed in.""" """Return the unit the value is expressed in."""
return FREQUENCY_GIGAHERTZ return FREQUENCY_GIGAHERTZ

View file

@ -111,7 +111,7 @@ class CupsSensor(SensorEntity):
return self._name return self._name
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
if self._printer is None: if self._printer is None:
return None return None
@ -183,7 +183,7 @@ class IPPSensor(SensorEntity):
return self._available return self._available
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
if self._attributes is None: if self._attributes is None:
return None return None
@ -257,7 +257,7 @@ class MarkerSensor(SensorEntity):
return ICON_MARKER return ICON_MARKER
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
if self._attributes is None: if self._attributes is None:
return None return None
@ -265,7 +265,7 @@ class MarkerSensor(SensorEntity):
return self._attributes[self._printer]["marker-levels"][self._index] return self._attributes[self._printer]["marker-levels"][self._index]
@property @property
def unit_of_measurement(self): def native_unit_of_measurement(self):
"""Return the unit of measurement.""" """Return the unit of measurement."""
return PERCENTAGE return PERCENTAGE

View file

@ -65,7 +65,7 @@ class CurrencylayerSensor(SensorEntity):
self._state = None self._state = None
@property @property
def unit_of_measurement(self): def native_unit_of_measurement(self):
"""Return the unit of measurement of this entity, if any.""" """Return the unit of measurement of this entity, if any."""
return self._quote return self._quote
@ -80,7 +80,7 @@ class CurrencylayerSensor(SensorEntity):
return ICON return ICON
@property @property
def state(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._state return self._state

View file

@ -2,6 +2,7 @@
from __future__ import annotations from __future__ import annotations
from collections.abc import Mapping from collections.abc import Mapping
from contextlib import suppress
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime, timedelta from datetime import datetime, timedelta
import logging import logging
@ -26,6 +27,8 @@ from homeassistant.const import (
DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_TIMESTAMP, DEVICE_CLASS_TIMESTAMP,
DEVICE_CLASS_VOLTAGE, DEVICE_CLASS_VOLTAGE,
TEMP_CELSIUS,
TEMP_FAHRENHEIT,
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.config_validation import ( # noqa: F401 from homeassistant.helpers.config_validation import ( # noqa: F401
@ -34,7 +37,7 @@ from homeassistant.helpers.config_validation import ( # noqa: F401
) )
from homeassistant.helpers.entity import Entity, EntityDescription from homeassistant.helpers.entity import Entity, EntityDescription
from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType, StateType
_LOGGER: Final = logging.getLogger(__name__) _LOGGER: Final = logging.getLogger(__name__)
@ -102,14 +105,18 @@ class SensorEntityDescription(EntityDescription):
state_class: str | None = None state_class: str | None = None
last_reset: datetime | None = None last_reset: datetime | None = None
native_unit_of_measurement: str | None = None
class SensorEntity(Entity): class SensorEntity(Entity):
"""Base class for sensor entities.""" """Base class for sensor entities."""
entity_description: SensorEntityDescription entity_description: SensorEntityDescription
_attr_state_class: str | None
_attr_last_reset: datetime | None _attr_last_reset: datetime | None
_attr_native_unit_of_measurement: str | None
_attr_native_value: StateType = None
_attr_state_class: str | None
_temperature_conversion_reported = False
@property @property
def state_class(self) -> str | None: def state_class(self) -> str | None:
@ -145,3 +152,94 @@ class SensorEntity(Entity):
return {ATTR_LAST_RESET: last_reset.isoformat()} return {ATTR_LAST_RESET: last_reset.isoformat()}
return None return None
@property
def native_value(self) -> StateType:
"""Return the value reported by the sensor."""
return self._attr_native_value
@property
def native_unit_of_measurement(self) -> str | None:
"""Return the unit of measurement of the sensor, if any."""
if hasattr(self, "_attr_native_unit_of_measurement"):
return self._attr_native_unit_of_measurement
if hasattr(self, "entity_description"):
return self.entity_description.native_unit_of_measurement
return None
@property
def unit_of_measurement(self) -> str | None:
"""Return the unit of measurement of the entity, after unit conversion."""
if (
hasattr(self, "_attr_unit_of_measurement")
and self._attr_unit_of_measurement is not None
):
return self._attr_unit_of_measurement
if (
hasattr(self, "entity_description")
and self.entity_description.unit_of_measurement is not None
):
return self.entity_description.unit_of_measurement
native_unit_of_measurement = self.native_unit_of_measurement
if native_unit_of_measurement in (TEMP_CELSIUS, TEMP_FAHRENHEIT):
return self.hass.config.units.temperature_unit
return native_unit_of_measurement
@property
def state(self) -> Any:
"""Return the state of the sensor and perform unit conversions, if needed."""
# Test if _attr_state has been set in this instance
if "_attr_state" in self.__dict__:
return self._attr_state
unit_of_measurement = self.native_unit_of_measurement
value = self.native_value
units = self.hass.config.units
if (
value is not None
and unit_of_measurement in (TEMP_CELSIUS, TEMP_FAHRENHEIT)
and unit_of_measurement != units.temperature_unit
):
if (
self.device_class != DEVICE_CLASS_TEMPERATURE
and not self._temperature_conversion_reported
):
self._temperature_conversion_reported = True
report_issue = self._suggest_report_issue()
_LOGGER.warning(
"Entity %s (%s) with device_class %s reports a temperature in "
"%s which will be converted to %s. Temperature conversion for "
"entities without correct device_class is deprecated and will"
" be removed from Home Assistant Core 2022.3. Please update "
"your configuration if device_class is manually configured, "
"otherwise %s",
self.entity_id,
type(self),
self.device_class,
unit_of_measurement,
units.temperature_unit,
report_issue,
)
value_s = str(value)
prec = len(value_s) - value_s.index(".") - 1 if "." in value_s else 0
# Suppress ValueError (Could not convert sensor_value to float)
with suppress(ValueError):
temp = units.temperature(float(value), unit_of_measurement)
value = str(round(temp) if prec == 0 else round(temp, prec))
return value
def __repr__(self) -> str:
"""Return the representation.
Entity.__repr__ includes the state in the generated string, this fails if we're
called before self.hass is set.
"""
if not self.hass:
return f"<Entity {self.name}>"
return super().__repr__()

View file

@ -539,25 +539,13 @@ class Entity(ABC):
if end - start > 0.4 and not self._slow_reported: if end - start > 0.4 and not self._slow_reported:
self._slow_reported = True self._slow_reported = True
extra = "" report_issue = self._suggest_report_issue()
if "custom_components" in type(self).__module__:
extra = "Please report it to the custom component author."
else:
extra = (
"Please create a bug report at "
"https://github.com/home-assistant/core/issues?q=is%3Aopen+is%3Aissue"
)
if self.platform:
extra += (
f"+label%3A%22integration%3A+{self.platform.platform_name}%22"
)
_LOGGER.warning( _LOGGER.warning(
"Updating state for %s (%s) took %.3f seconds. %s", "Updating state for %s (%s) took %.3f seconds. Please %s",
self.entity_id, self.entity_id,
type(self), type(self),
end - start, end - start,
extra, report_issue,
) )
# Overwrite properties that have been set in the config file. # Overwrite properties that have been set in the config file.
@ -858,6 +846,23 @@ class Entity(ABC):
if self.parallel_updates: if self.parallel_updates:
self.parallel_updates.release() self.parallel_updates.release()
def _suggest_report_issue(self) -> str:
"""Suggest to report an issue."""
report_issue = ""
if "custom_components" in type(self).__module__:
report_issue = "report it to the custom component author."
else:
report_issue = (
"create a bug report at "
"https://github.com/home-assistant/core/issues?q=is%3Aopen+is%3Aissue"
)
if self.platform:
report_issue += (
f"+label%3A%22integration%3A+{self.platform.platform_name}%22"
)
return report_issue
@dataclass @dataclass
class ToggleEntityDescription(EntityDescription): class ToggleEntityDescription(EntityDescription):

View file

@ -19,53 +19,55 @@ def _get_named_tuple(input_dict):
return namedtuple("Struct", input_dict.keys())(*input_dict.values()) return namedtuple("Struct", input_dict.keys())(*input_dict.values())
def _get_sensor(name="Last", sensor_type="last_capture", data=None): def _get_sensor(hass, name="Last", sensor_type="last_capture", data=None):
if data is None: if data is None:
data = {} data = {}
sensor_entry = next( sensor_entry = next(
sensor_entry for sensor_entry in SENSOR_TYPES if sensor_entry.key == sensor_type sensor_entry for sensor_entry in SENSOR_TYPES if sensor_entry.key == sensor_type
) )
sensor_entry.name = name sensor_entry.name = name
return arlo.ArloSensor(data, sensor_entry) sensor = arlo.ArloSensor(data, sensor_entry)
sensor.hass = hass
return sensor
@pytest.fixture() @pytest.fixture()
def default_sensor(): def default_sensor(hass):
"""Create an ArloSensor with default values.""" """Create an ArloSensor with default values."""
return _get_sensor() return _get_sensor(hass)
@pytest.fixture() @pytest.fixture()
def battery_sensor(): def battery_sensor(hass):
"""Create an ArloSensor with battery data.""" """Create an ArloSensor with battery data."""
data = _get_named_tuple({"battery_level": 50}) data = _get_named_tuple({"battery_level": 50})
return _get_sensor("Battery Level", "battery_level", data) return _get_sensor(hass, "Battery Level", "battery_level", data)
@pytest.fixture() @pytest.fixture()
def temperature_sensor(): def temperature_sensor(hass):
"""Create a temperature ArloSensor.""" """Create a temperature ArloSensor."""
return _get_sensor("Temperature", "temperature") return _get_sensor(hass, "Temperature", "temperature")
@pytest.fixture() @pytest.fixture()
def humidity_sensor(): def humidity_sensor(hass):
"""Create a humidity ArloSensor.""" """Create a humidity ArloSensor."""
return _get_sensor("Humidity", "humidity") return _get_sensor(hass, "Humidity", "humidity")
@pytest.fixture() @pytest.fixture()
def cameras_sensor(): def cameras_sensor(hass):
"""Create a total cameras ArloSensor.""" """Create a total cameras ArloSensor."""
data = _get_named_tuple({"cameras": [0, 0]}) data = _get_named_tuple({"cameras": [0, 0]})
return _get_sensor("Arlo Cameras", "total_cameras", data) return _get_sensor(hass, "Arlo Cameras", "total_cameras", data)
@pytest.fixture() @pytest.fixture()
def captured_sensor(): def captured_sensor(hass):
"""Create a captured today ArloSensor.""" """Create a captured today ArloSensor."""
data = _get_named_tuple({"captured_today": [0, 0, 0, 0, 0]}) data = _get_named_tuple({"captured_today": [0, 0, 0, 0, 0]})
return _get_sensor("Captured Today", "captured_today", data) return _get_sensor(hass, "Captured Today", "captured_today", data)
class PlatformSetupFixture: class PlatformSetupFixture:
@ -88,14 +90,6 @@ def platform_setup():
return PlatformSetupFixture() return PlatformSetupFixture()
@pytest.fixture()
def sensor_with_hass_data(default_sensor, hass):
"""Create a sensor with async_dispatcher_connected mocked."""
hass.data = {}
default_sensor.hass = hass
return default_sensor
@pytest.fixture() @pytest.fixture()
def mock_dispatch(): def mock_dispatch():
"""Mock the dispatcher connect method.""" """Mock the dispatcher connect method."""
@ -145,14 +139,14 @@ def test_sensor_name(default_sensor):
assert default_sensor.name == "Last" assert default_sensor.name == "Last"
async def test_async_added_to_hass(sensor_with_hass_data, mock_dispatch): async def test_async_added_to_hass(default_sensor, mock_dispatch):
"""Test dispatcher called when added.""" """Test dispatcher called when added."""
await sensor_with_hass_data.async_added_to_hass() await default_sensor.async_added_to_hass()
assert len(mock_dispatch.mock_calls) == 1 assert len(mock_dispatch.mock_calls) == 1
kall = mock_dispatch.call_args kall = mock_dispatch.call_args
args, kwargs = kall args, kwargs = kall
assert len(args) == 3 assert len(args) == 3
assert args[0] == sensor_with_hass_data.hass assert args[0] == default_sensor.hass
assert args[1] == "arlo_update" assert args[1] == "arlo_update"
assert not kwargs assert not kwargs
@ -197,22 +191,22 @@ def test_update_captured_today(captured_sensor):
assert captured_sensor.state == 5 assert captured_sensor.state == 5
def _test_attributes(sensor_type): def _test_attributes(hass, sensor_type):
data = _get_named_tuple({"model_id": "TEST123"}) data = _get_named_tuple({"model_id": "TEST123"})
sensor = _get_sensor("test", sensor_type, data) sensor = _get_sensor(hass, "test", sensor_type, data)
attrs = sensor.extra_state_attributes attrs = sensor.extra_state_attributes
assert attrs.get(ATTR_ATTRIBUTION) == "Data provided by arlo.netgear.com" assert attrs.get(ATTR_ATTRIBUTION) == "Data provided by arlo.netgear.com"
assert attrs.get("brand") == "Netgear Arlo" assert attrs.get("brand") == "Netgear Arlo"
assert attrs.get("model") == "TEST123" assert attrs.get("model") == "TEST123"
def test_state_attributes(): def test_state_attributes(hass):
"""Test attributes for camera sensor types.""" """Test attributes for camera sensor types."""
_test_attributes("battery_level") _test_attributes(hass, "battery_level")
_test_attributes("signal_strength") _test_attributes(hass, "signal_strength")
_test_attributes("temperature") _test_attributes(hass, "temperature")
_test_attributes("humidity") _test_attributes(hass, "humidity")
_test_attributes("air_quality") _test_attributes(hass, "air_quality")
def test_attributes_total_cameras(cameras_sensor): def test_attributes_total_cameras(cameras_sensor):
@ -223,17 +217,17 @@ def test_attributes_total_cameras(cameras_sensor):
assert attrs.get("model") is None assert attrs.get("model") is None
def _test_update(sensor_type, key, value): def _test_update(hass, sensor_type, key, value):
data = _get_named_tuple({key: value}) data = _get_named_tuple({key: value})
sensor = _get_sensor("test", sensor_type, data) sensor = _get_sensor(hass, "test", sensor_type, data)
sensor.update() sensor.update()
assert sensor.state == value assert sensor.state == value
def test_update(): def test_update(hass):
"""Test update method for direct transcription sensor types.""" """Test update method for direct transcription sensor types."""
_test_update("battery_level", "battery_level", 100) _test_update(hass, "battery_level", "battery_level", 100)
_test_update("signal_strength", "signal_strength", 100) _test_update(hass, "signal_strength", "signal_strength", 100)
_test_update("temperature", "ambient_temperature", 21.4) _test_update(hass, "temperature", "ambient_temperature", 21.4)
_test_update("humidity", "ambient_humidity", 45.1) _test_update(hass, "humidity", "ambient_humidity", 45.1)
_test_update("air_quality", "ambient_air_quality", 14.2) _test_update(hass, "air_quality", "ambient_air_quality", 14.2)

View file

@ -0,0 +1,30 @@
"""The test for sensor device automation."""
from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT, TEMP_CELSIUS, TEMP_FAHRENHEIT
from homeassistant.setup import async_setup_component
async def test_deprecated_temperature_conversion(
hass, caplog, enable_custom_integrations
):
"""Test warning on deprecated temperature conversion."""
platform = getattr(hass.components, "test.sensor")
platform.init(empty=True)
platform.ENTITIES["0"] = platform.MockSensor(
name="Test", native_value="0.0", native_unit_of_measurement=TEMP_FAHRENHEIT
)
entity0 = platform.ENTITIES["0"]
assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}})
await hass.async_block_till_done()
state = hass.states.get(entity0.entity_id)
assert state.state == "-17.8"
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == TEMP_CELSIUS
assert (
"Entity sensor.test (<class 'custom_components.test.sensor.MockSensor'>) "
"with device_class None reports a temperature in °F which will be converted to "
"°C. Temperature conversion for entities without correct device_class is "
"deprecated and will be removed from Home Assistant Core 2022.3. Please update "
"your configuration if device_class is manually configured, otherwise report it "
"to the custom component author."
) in caplog.text

View file

@ -61,7 +61,7 @@ async def async_setup_platform(
async_add_entities_callback(list(ENTITIES.values())) async_add_entities_callback(list(ENTITIES.values()))
class MockSensor(MockEntity): class MockSensor(MockEntity, sensor.SensorEntity):
"""Mock Sensor class.""" """Mock Sensor class."""
@property @property
@ -70,6 +70,11 @@ class MockSensor(MockEntity):
return self._handle("device_class") return self._handle("device_class")
@property @property
def unit_of_measurement(self): def native_unit_of_measurement(self):
"""Return the unit_of_measurement of this sensor.""" """Return the native unit_of_measurement of this sensor."""
return self._handle("unit_of_measurement") return self._handle("native_unit_of_measurement")
@property
def native_value(self):
"""Return the native value of this sensor."""
return self._handle("native_value")