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_unique_id = f"{device.device_uuid}-{description.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:
self._attr_unit_of_measurement = device.humidity_unit
self._attr_native_unit_of_measurement = device.humidity_unit
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
def state(self):
def native_value(self):
"""Return the state of the sensor."""
if self.entity_description.key == CONST.TEMP_STATUS_KEY:
return self._device.temp

View File

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

View File

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

View File

@ -82,12 +82,12 @@ class AdGuardHomeSensor(AdGuardHomeDeviceEntity, SensorEntity):
)
@property
def state(self) -> str | None:
def native_value(self) -> str | None:
"""Return the state of the sensor."""
return self._state
@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 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):
"""Initialize AdsSensor entity."""
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._factor = factor
@ -64,6 +64,6 @@ class AdsSensor(AdsEntity, SensorEntity):
)
@property
def state(self) -> StateType:
def native_value(self) -> StateType:
"""Return the state of the device."""
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):
"""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):
"""Initialize the Advantage Air timer control."""
@ -58,7 +58,7 @@ class AdvantageAirTimeTo(AdvantageAirEntity, SensorEntity):
)
@property
def state(self):
def native_value(self):
"""Return the current value."""
return self._ac[self._time_key]
@ -78,7 +78,7 @@ class AdvantageAirTimeTo(AdvantageAirEntity, SensorEntity):
class AdvantageAirZoneVent(AdvantageAirEntity, SensorEntity):
"""Representation of Advantage Air Zone Vent Sensor."""
_attr_unit_of_measurement = PERCENTAGE
_attr_native_unit_of_measurement = PERCENTAGE
_attr_state_class = STATE_CLASS_MEASUREMENT
def __init__(self, instance, ac_key, zone_key):
@ -90,7 +90,7 @@ class AdvantageAirZoneVent(AdvantageAirEntity, SensorEntity):
)
@property
def state(self):
def native_value(self):
"""Return the current value of the air vent."""
if self._zone["state"] == ADVANTAGE_AIR_STATE_OPEN:
return self._zone["value"]
@ -107,7 +107,7 @@ class AdvantageAirZoneVent(AdvantageAirEntity, SensorEntity):
class AdvantageAirZoneSignal(AdvantageAirEntity, SensorEntity):
"""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
def __init__(self, instance, ac_key, zone_key):
@ -119,7 +119,7 @@ class AdvantageAirZoneSignal(AdvantageAirEntity, SensorEntity):
)
@property
def state(self):
def native_value(self):
"""Return the current value of the wireless signal."""
return self._zone["rssi"]
@ -140,7 +140,7 @@ class AdvantageAirZoneSignal(AdvantageAirEntity, SensorEntity):
class AdvantageAirZoneTemp(AdvantageAirEntity, SensorEntity):
"""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_icon = "mdi:thermometer"
_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_unique_id = self._unique_id
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):
@ -106,7 +106,7 @@ class AemetSensor(AbstractAemetSensor):
self._weather_coordinator = weather_coordinator
@property
def state(self):
def native_value(self):
"""Return the state of the device."""
return self._weather_coordinator.data.get(self._sensor_type)
@ -134,7 +134,7 @@ class AemetForecastSensor(AbstractAemetSensor):
)
@property
def state(self):
def native_value(self):
"""Return the state of the device."""
forecast = None
forecasts = self._weather_coordinator.data.get(

View File

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

View File

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

View File

@ -84,7 +84,7 @@ class AirlySensor(CoordinatorEntity, SensorEntity):
self.entity_description = description
@property
def state(self) -> StateType:
def native_value(self) -> StateType:
"""Return the state."""
state = self.coordinator.data[self.entity_description.key]
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_icon = SENSOR_TYPES[self.kind][ATTR_ICON]
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()}"
@property
def state(self):
def native_value(self):
"""Return the state."""
self._state = self.coordinator.data[self.kind]
return self._state

View File

@ -212,7 +212,7 @@ class AirVisualGeographySensor(AirVisualEntity, SensorEntity):
self._attr_icon = icon
self._attr_name = f"{GEOGRAPHY_SENSOR_LOCALES[locale]} {name}"
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._kind = kind
self._locale = locale
@ -232,16 +232,16 @@ class AirVisualGeographySensor(AirVisualEntity, SensorEntity):
if self._kind == SENSOR_KIND_LEVEL:
aqi = data[f"aqi{self._locale}"]
[(self._attr_state, self._attr_icon)] = [
[(self._attr_native_value, self._attr_icon)] = [
(name, icon)
for (floor, ceiling), (name, icon) in POLLUTANT_LEVELS.items()
if floor <= aqi <= ceiling
]
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:
symbol = data[f"main{self._locale}"]
self._attr_state = symbol
self._attr_native_value = symbol
self._attr_extra_state_attributes.update(
{
ATTR_POLLUTANT_SYMBOL: symbol,
@ -298,7 +298,7 @@ class AirVisualNodeProSensor(AirVisualEntity, SensorEntity):
f"{coordinator.data['settings']['node_name']} Node/Pro: {name}"
)
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
@property
@ -320,24 +320,30 @@ class AirVisualNodeProSensor(AirVisualEntity, SensorEntity):
"""Update the entity from the latest data."""
if self._kind == SENSOR_KIND_AQI:
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:
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:
self._attr_state = self.coordinator.data["status"]["battery"]
self._attr_native_value = self.coordinator.data["status"]["battery"]
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:
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:
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:
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:
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:
self._attr_state = self.coordinator.data["measurements"].get(
self._attr_native_value = self.coordinator.data["measurements"].get(
"temperature_C"
)
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):
if self._attr_state != message.text:
self._attr_state = message.text
if self._attr_native_value != message.text:
self._attr_native_value = message.text
self.schedule_update_ha_state()

View File

@ -112,7 +112,7 @@ class AlphaVantageSensor(SensorEntity):
self._symbol = symbol[CONF_SYMBOL]
self._attr_name = symbol.get(CONF_NAME, self._symbol)
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"))
def update(self):
@ -120,7 +120,7 @@ class AlphaVantageSensor(SensorEntity):
_LOGGER.debug("Requesting new data for symbol %s", self._symbol)
all_values, _ = self._timeseries.get_intraday(self._symbol)
values = next(iter(all_values.values()))
self._attr_state = values["1. open"]
self._attr_native_value = values["1. open"]
self._attr_extra_state_attributes = (
{
ATTR_ATTRIBUTION: ATTRIBUTION,
@ -148,7 +148,7 @@ class AlphaVantageForeignExchange(SensorEntity):
else f"{self._to_currency}/{self._from_currency}"
)
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):
"""Get the latest data and updates the states."""
@ -160,7 +160,7 @@ class AlphaVantageForeignExchange(SensorEntity):
values, _ = self._foreign_exchange.get_currency_exchange_rate(
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 = (
{
ATTR_ATTRIBUTION: ATTRIBUTION,

View File

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

View File

@ -66,7 +66,7 @@ class AmbeeSensorEntity(CoordinatorEntity, SensorEntity):
}
@property
def state(self) -> StateType:
def native_value(self) -> StateType:
"""Return the state of the sensor."""
value = getattr(self.coordinator.data, self.entity_description.key)
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
)
self._attr_unit_of_measurement = unit
self._attr_native_unit_of_measurement = unit
@callback
def update_from_latest_data(self) -> None:
@ -75,10 +75,10 @@ class AmbientWeatherSensor(AmbientWeatherEntity, SensorEntity):
].get(TYPE_SOLARRADIATION)
if w_m2_brightness_val is None:
self._attr_state = None
self._attr_native_value = None
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:
self._attr_state = self._ambient.stations[self._mac_address][
self._attr_native_value = self._ambient.stations[self._mac_address][
ATTR_LAST_DATA
].get(self._sensor_type)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -138,7 +138,7 @@ class ArwnSensor(SensorEntity):
# This mqtt topic for the sensor which is its uid
self._attr_unique_id = topic
self._state_key = state_key
self._attr_unit_of_measurement = units
self._attr_native_unit_of_measurement = units
self._attr_icon = icon
self._attr_device_class = device_class
@ -147,5 +147,5 @@ class ArwnSensor(SensorEntity):
ev = {}
ev.update(event)
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()

View File

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

View File

@ -49,10 +49,12 @@ class AtagSensor(AtagEntity, SensorEntity):
PERCENTAGE,
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
def state(self):
def native_value(self):
"""Return the state of the sensor."""
return self.coordinator.data.report[self._id].state

View File

@ -258,10 +258,10 @@ class AtomeSensor(SensorEntity):
if sensor_type == LIVE_TYPE:
self._attr_device_class = DEVICE_CLASS_POWER
self._attr_unit_of_measurement = POWER_WATT
self._attr_native_unit_of_measurement = POWER_WATT
else:
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):
"""Update device state."""
@ -269,13 +269,13 @@ class AtomeSensor(SensorEntity):
update_function()
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 = {
"subscribed_power": self._data.subscribed_power,
"is_connected": self._data.is_connected,
}
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(
getattr(self._data, f"{self._sensor_type}_last_reset")
)

View File

@ -146,7 +146,7 @@ class AugustOperatorSensor(AugustEntityMixin, RestoreEntity, SensorEntity):
self._attr_available = True
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_keypad = lock_activity.operated_keypad
self._operated_autorelock = lock_activity.operated_autorelock
@ -208,7 +208,7 @@ class AugustBatterySensor(AugustEntityMixin, SensorEntity):
"""Representation of an August sensor."""
_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):
"""Initialize the sensor."""
@ -223,8 +223,8 @@ class AugustBatterySensor(AugustEntityMixin, SensorEntity):
def _update_from_data(self):
"""Get the latest state of the sensor."""
state_provider = SENSOR_TYPES_BATTERY[self._sensor_type]["state_provider"]
self._attr_state = state_provider(self._detail)
self._attr_available = self._attr_state is not None
self._attr_native_value = state_provider(self._detail)
self._attr_available = self._attr_native_value is not None
@property
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):
"""Implementation of an aurora sensor."""
_attr_unit_of_measurement = PERCENTAGE
_attr_native_unit_of_measurement = PERCENTAGE
@property
def state(self):
def native_value(self):
"""Return % chance the aurora is visible."""
return self.coordinator.data

View File

@ -51,7 +51,7 @@ class AuroraABBSolarPVMonitorSensor(SensorEntity):
"""Representation of a Sensor."""
_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
def __init__(self, client, name, typename):
@ -68,7 +68,7 @@ class AuroraABBSolarPVMonitorSensor(SensorEntity):
self.client.connect()
# read ADC channel 3 (grid power output)
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:
# aurorapy does not have different exceptions (yet) for dealing
# with timeout vs other comms errors.
@ -82,7 +82,7 @@ class AuroraABBSolarPVMonitorSensor(SensorEntity):
_LOGGER.debug("No response from inverter (could be dark)")
else:
raise error
self._attr_state = None
self._attr_native_value = None
finally:
if self.client.serline.isOpen():
self.client.close()

View File

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

View File

@ -71,7 +71,7 @@ class AzureDevOpsSensor(AzureDevOpsDeviceEntity, SensorEntity):
unit_of_measurement: str = "",
) -> None:
"""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.organization = organization
self.project = project
@ -107,7 +107,7 @@ class AzureDevOpsLatestBuildSensor(AzureDevOpsSensor):
_LOGGER.warning(exception)
self._attr_available = False
return False
self._attr_state = build.build_number
self._attr_native_value = build.build_number
self._attr_extra_state_attributes = {
"definition_id": build.definition.id,
"definition_name": build.definition.name,

View File

@ -94,7 +94,7 @@ class BboxUptimeSensor(SensorEntity):
def __init__(self, bbox_data, sensor_type, name):
"""Initialize the sensor."""
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.bbox_data = bbox_data
@ -104,7 +104,7 @@ class BboxUptimeSensor(SensorEntity):
uptime = utcnow() - timedelta(
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):
@ -116,7 +116,7 @@ class BboxSensor(SensorEntity):
"""Initialize the sensor."""
self.type = sensor_type
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.bbox_data = bbox_data
@ -124,19 +124,25 @@ class BboxSensor(SensorEntity):
"""Get the latest data from Bbox and update the state."""
self.bbox_data.update()
if self.type == "down_max_bandwidth":
self._attr_state = round(
self._attr_native_value = round(
self.bbox_data.data["rx"]["maxBandwidth"] / 1000, 2
)
elif self.type == "up_max_bandwidth":
self._attr_state = round(
self._attr_native_value = round(
self.bbox_data.data["tx"]["maxBandwidth"] / 1000, 2
)
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":
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":
self._attr_state = self.bbox_data.router_infos["device"]["numberofboots"]
self._attr_native_value = self.bbox_data.router_infos["device"][
"numberofboots"
]
class BboxData:

View File

@ -63,17 +63,17 @@ class BeewiSmartclimSensor(SensorEntity):
self._poller = poller
self._attr_name = name
self._device = device
self._attr_unit_of_measurement = unit
self._attr_native_unit_of_measurement = unit
self._attr_device_class = self._device
self._attr_unique_id = f"{mac}_{device}"
def update(self):
"""Fetch new state data from the poller."""
self._poller.update_sensor()
self._attr_state = None
self._attr_native_value = None
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:
self._attr_state = self._poller.get_humidity()
self._attr_native_value = self._poller.get_humidity()
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):
"""Initialize the sensor."""
self._attr_name = name
self._attr_unit_of_measurement = unit
self._attr_native_unit_of_measurement = unit
self._multiplier = multiplier
self.bh1750_sensor = bh1750_sensor
@ -109,7 +109,7 @@ class BH1750Sensor(SensorEntity):
"""Get the latest data from the BH1750 and update the states."""
await self.hass.async_add_executor_job(self.bh1750_sensor.update)
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)
)
else:

View File

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

View File

@ -37,7 +37,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
class BizkaibusSensor(SensorEntity):
"""The class for handling the data."""
_attr_unit_of_measurement = TIME_MINUTES
_attr_native_unit_of_measurement = TIME_MINUTES
def __init__(self, data, name):
"""Initialize the sensor."""
@ -48,7 +48,7 @@ class BizkaibusSensor(SensorEntity):
"""Get the latest data from the webservice."""
self.data.update()
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:

View File

@ -20,10 +20,10 @@ class BleBoxSensorEntity(BleBoxEntity, SensorEntity):
def __init__(self, feature):
"""Initialize a BleBox sensor 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]
@property
def state(self):
def native_value(self):
"""Return the state."""
return self._feature.current

View File

@ -44,7 +44,7 @@ class BlinkSensor(SensorEntity):
self._attr_device_class = device_class
self.data = data
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._sensor_key = (
"temperature_calibrated" if sensor_type == "temperature" else sensor_type
@ -54,9 +54,9 @@ class BlinkSensor(SensorEntity):
"""Retrieve sensor data from the camera."""
self.data.refresh()
try:
self._attr_state = self._camera.attributes[self._sensor_key]
self._attr_native_value = self._camera.attributes[self._sensor_key]
except KeyError:
self._attr_state = None
self._attr_native_value = None
_LOGGER.error(
"%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_icon = ICON
_attr_unit_of_measurement = "BTC"
_attr_native_unit_of_measurement = "BTC"
def __init__(self, name, addresses):
"""Initialize the sensor."""
@ -57,4 +57,4 @@ class BlockchainSensor(SensorEntity):
def update(self):
"""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._attr_name = f"{device['DeviceName']} {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:
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
def device_class(self):
@ -99,6 +103,6 @@ class BloomSkySensor(SensorEntity):
"""Request an update from the BloomSky API."""
self._bloomsky.refresh_devices()
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
)

View File

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

View File

@ -327,25 +327,27 @@ class BME680Sensor(SensorEntity):
self.bme680_client = bme680_client
self.temp_unit = temp_unit
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]
async def async_update(self):
"""Get the latest data from the BME680 and update the states."""
await self.hass.async_add_executor_job(self.bme680_client.update)
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:
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:
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:
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:
self._attr_state = int(
self._attr_native_value = int(
round(self.bme680_client.sensor_data.gas_resistance, 0)
)
elif self.type == SENSOR_AQ:
aq_score = self.bme680_client.sensor_data.air_quality
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."""
self._bmp280 = bmp280
self._attr_name = name
self._attr_unit_of_measurement = unit_of_measurement
self._attr_native_unit_of_measurement = unit_of_measurement
class Bmp280TemperatureSensor(Bmp280Sensor):
@ -94,7 +94,7 @@ class Bmp280TemperatureSensor(Bmp280Sensor):
def update(self):
"""Fetch new state data for the sensor."""
try:
self._attr_state = round(self._bmp280.temperature, 1)
self._attr_native_value = round(self._bmp280.temperature, 1)
if not self.available:
_LOGGER.warning("Communication restored with temperature sensor")
self._attr_available = True
@ -119,7 +119,7 @@ class Bmp280PressureSensor(Bmp280Sensor):
def update(self):
"""Fetch new state data for the sensor."""
try:
self._attr_state = round(self._bmp280.pressure)
self._attr_native_value = round(self._bmp280.pressure)
if not self.available:
_LOGGER.warning("Communication restored with pressure sensor")
self._attr_available = True

View File

@ -516,7 +516,7 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, SensorEntity):
self._attr_device_class = attribute_info.get(
attribute, [None, None, None, None]
)[1]
self._attr_unit_of_measurement = attribute_info.get(
self._attr_native_unit_of_measurement = attribute_info.get(
attribute, [None, None, None, None]
)[2]
@ -525,24 +525,24 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, SensorEntity):
_LOGGER.debug("Updating %s", self._vehicle.name)
vehicle_state = self._vehicle.state
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:
value = getattr(vehicle_state, self._attribute)
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:
value = getattr(vehicle_state, self._attribute)
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:
self._attr_state = getattr(vehicle_state, self._attribute)
self._attr_native_value = getattr(vehicle_state, self._attribute)
elif self._service == SERVICE_LAST_TRIP:
vehicle_last_trip = self._vehicle.state.last_trip
if self._attribute == "date_utc":
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:
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:
vehicle_all_trips = self._vehicle.state.all_trips
for attribute in (
@ -555,13 +555,13 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, SensorEntity):
if self._attribute.startswith(f"{attribute}_"):
attr = getattr(vehicle_all_trips, attribute)
sub_attr = self._attribute.replace(f"{attribute}_", "")
self._attr_state = getattr(attr, sub_attr)
self._attr_native_value = getattr(attr, sub_attr)
return
if self._attribute == "reset_date_utc":
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:
self._attr_state = getattr(vehicle_all_trips, self._attribute)
self._attr_native_value = getattr(vehicle_all_trips, self._attribute)
vehicle_state = self._vehicle.state
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."""
_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:
"""Initialize an SHC temperature reporting sensor."""
@ -156,7 +156,7 @@ class TemperatureSensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_temperature"
@property
def state(self):
def native_value(self):
"""Return the state of the sensor."""
return self._device.temperature
@ -165,7 +165,7 @@ class HumiditySensor(SHCEntity, SensorEntity):
"""Representation of an SHC humidity reporting sensor."""
_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:
"""Initialize an SHC humidity reporting sensor."""
@ -174,7 +174,7 @@ class HumiditySensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_humidity"
@property
def state(self):
def native_value(self):
"""Return the state of the sensor."""
return self._device.humidity
@ -183,7 +183,7 @@ class PuritySensor(SHCEntity, SensorEntity):
"""Representation of an SHC purity reporting sensor."""
_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:
"""Initialize an SHC purity reporting sensor."""
@ -192,7 +192,7 @@ class PuritySensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_purity"
@property
def state(self):
def native_value(self):
"""Return the state of the sensor."""
return self._device.purity
@ -207,7 +207,7 @@ class AirQualitySensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_airquality"
@property
def state(self):
def native_value(self):
"""Return the state of the sensor."""
return self._device.combined_rating.name
@ -229,7 +229,7 @@ class TemperatureRatingSensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_temperature_rating"
@property
def state(self):
def native_value(self):
"""Return the state of the sensor."""
return self._device.temperature_rating.name
@ -244,7 +244,7 @@ class HumidityRatingSensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_humidity_rating"
@property
def state(self):
def native_value(self):
"""Return the state of the sensor."""
return self._device.humidity_rating.name
@ -259,7 +259,7 @@ class PurityRatingSensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_purity_rating"
@property
def state(self):
def native_value(self):
"""Return the state of the sensor."""
return self._device.purity_rating.name
@ -268,7 +268,7 @@ class PowerSensor(SHCEntity, SensorEntity):
"""Representation of an SHC power reporting sensor."""
_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:
"""Initialize an SHC power reporting sensor."""
@ -277,7 +277,7 @@ class PowerSensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_power"
@property
def state(self):
def native_value(self):
"""Return the state of the sensor."""
return self._device.powerconsumption
@ -286,7 +286,7 @@ class EnergySensor(SHCEntity, SensorEntity):
"""Representation of an SHC energy reporting sensor."""
_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:
"""Initialize an SHC energy reporting sensor."""
@ -295,7 +295,7 @@ class EnergySensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{self._device.serial}_energy"
@property
def state(self):
def native_value(self):
"""Return the state of the sensor."""
return self._device.energyconsumption / 1000.0
@ -304,7 +304,7 @@ class ValveTappetSensor(SHCEntity, SensorEntity):
"""Representation of an SHC valve tappet reporting sensor."""
_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:
"""Initialize an SHC valve tappet reporting sensor."""
@ -313,7 +313,7 @@ class ValveTappetSensor(SHCEntity, SensorEntity):
self._attr_unique_id = f"{device.serial}_valvetappet"
@property
def state(self):
def native_value(self):
"""Return the state of the sensor."""
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_name = f"{device.name} {SENSOR_TYPES[monitored_condition][0]}"
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_unit_of_measurement = SENSOR_TYPES[monitored_condition][1]
self._attr_native_unit_of_measurement = SENSOR_TYPES[monitored_condition][1]
def _update_state(self, data):
"""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,
icon="mdi:file-document-outline",
name=ATTR_PAGE_COUNTER.replace("_", " ").title(),
unit_of_measurement=UNIT_PAGES,
native_unit_of_measurement=UNIT_PAGES,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_BW_COUNTER,
icon="mdi:file-document-outline",
name=ATTR_BW_COUNTER.replace("_", " ").title(),
unit_of_measurement=UNIT_PAGES,
native_unit_of_measurement=UNIT_PAGES,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_COLOR_COUNTER,
icon="mdi:file-document-outline",
name=ATTR_COLOR_COUNTER.replace("_", " ").title(),
unit_of_measurement=UNIT_PAGES,
native_unit_of_measurement=UNIT_PAGES,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_DUPLEX_COUNTER,
icon="mdi:file-document-outline",
name=ATTR_DUPLEX_COUNTER.replace("_", " ").title(),
unit_of_measurement=UNIT_PAGES,
native_unit_of_measurement=UNIT_PAGES,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_DRUM_REMAINING_LIFE,
icon="mdi:chart-donut",
name=ATTR_DRUM_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_BLACK_DRUM_REMAINING_LIFE,
icon="mdi:chart-donut",
name=ATTR_BLACK_DRUM_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_CYAN_DRUM_REMAINING_LIFE,
icon="mdi:chart-donut",
name=ATTR_CYAN_DRUM_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_MAGENTA_DRUM_REMAINING_LIFE,
icon="mdi:chart-donut",
name=ATTR_MAGENTA_DRUM_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_YELLOW_DRUM_REMAINING_LIFE,
icon="mdi:chart-donut",
name=ATTR_YELLOW_DRUM_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_BELT_UNIT_REMAINING_LIFE,
icon="mdi:current-ac",
name=ATTR_BELT_UNIT_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_FUSER_REMAINING_LIFE,
icon="mdi:water-outline",
name=ATTR_FUSER_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_LASER_REMAINING_LIFE,
icon="mdi:spotlight-beam",
name=ATTR_LASER_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_PF_KIT_1_REMAINING_LIFE,
icon="mdi:printer-3d",
name=ATTR_PF_KIT_1_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_PF_KIT_MP_REMAINING_LIFE,
icon="mdi:printer-3d",
name=ATTR_PF_KIT_MP_REMAINING_LIFE.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_BLACK_TONER_REMAINING,
icon="mdi:printer-3d-nozzle",
name=ATTR_BLACK_TONER_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_CYAN_TONER_REMAINING,
icon="mdi:printer-3d-nozzle",
name=ATTR_CYAN_TONER_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_MAGENTA_TONER_REMAINING,
icon="mdi:printer-3d-nozzle",
name=ATTR_MAGENTA_TONER_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_YELLOW_TONER_REMAINING,
icon="mdi:printer-3d-nozzle",
name=ATTR_YELLOW_TONER_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_BLACK_INK_REMAINING,
icon="mdi:printer-3d-nozzle",
name=ATTR_BLACK_INK_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_CYAN_INK_REMAINING,
icon="mdi:printer-3d-nozzle",
name=ATTR_CYAN_INK_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_MAGENTA_INK_REMAINING,
icon="mdi:printer-3d-nozzle",
name=ATTR_MAGENTA_INK_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_YELLOW_INK_REMAINING,
icon="mdi:printer-3d-nozzle",
name=ATTR_YELLOW_INK_REMAINING.replace("_", " ").title(),
unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=PERCENTAGE,
state_class=STATE_CLASS_MEASUREMENT,
),
SensorEntityDescription(

View File

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

View File

@ -103,4 +103,4 @@ class BrottsplatskartanSensor(SensorEntity):
ATTR_ATTRIBUTION: brottsplatskartan.ATTRIBUTION
}
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_icon = SENSOR_TYPES[sensor_type][2]
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._attr_unique_id = "{:2.6f}{:2.6f}{}".format(
coordinates[CONF_LATITUDE], coordinates[CONF_LONGITUDE], sensor_type
@ -438,7 +438,7 @@ class BrSensor(SensorEntity):
img = condition.get(IMAGE)
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
return True
return False
@ -446,9 +446,11 @@ class BrSensor(SensorEntity):
if self.type.startswith(WINDSPEED):
# hass wants windspeeds in km/h not m/s, so convert:
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:
self._attr_state = round(self.state * 3.6, 1)
self._attr_native_value = round(self.state * 3.6, 1)
return True
except IndexError:
_LOGGER.warning("No forecast for fcday=%s", fcday)
@ -456,7 +458,7 @@ class BrSensor(SensorEntity):
# update all other sensors
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
except IndexError:
_LOGGER.warning("No forecast for fcday=%s", fcday)
@ -480,7 +482,7 @@ class BrSensor(SensorEntity):
img = condition.get(IMAGE)
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
return True
@ -490,25 +492,27 @@ class BrSensor(SensorEntity):
# update nested precipitation forecast sensors
nested = data.get(PRECIPITATION_FORECAST)
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
if self.type in [WINDSPEED, WINDGUST]:
# 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:
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
if self.type == VISIBILITY:
# 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:
self._attr_state = round(self.state / 1000, 1)
self._attr_native_value = round(self.state / 1000, 1)
return True
# 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):
result = {ATTR_ATTRIBUTION: data.get(ATTRIBUTION)}
if self._timeframe is not None:

View File

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

View File

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

View File

@ -265,7 +265,7 @@ class CityBikesNetwork:
class CityBikesStation(SensorEntity):
"""CityBikes API Sensor."""
_attr_unit_of_measurement = "bikes"
_attr_native_unit_of_measurement = "bikes"
_attr_icon = "mdi:bike"
def __init__(self, network, station_id, entity_id):
@ -281,7 +281,7 @@ class CityBikesStation(SensorEntity):
station_data = station
break
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 = (
{
ATTR_ATTRIBUTION: CITYBIKES_ATTRIBUTION,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -107,7 +107,7 @@ class CompensationSensor(SensorEntity):
return False
@property
def state(self):
def native_value(self):
"""Return the state of the sensor."""
return self._state
@ -123,7 +123,7 @@ class CompensationSensor(SensorEntity):
return ret
@property
def unit_of_measurement(self):
def native_unit_of_measurement(self):
"""Return the unit the value is expressed in."""
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):
"""Sensor representing corona virus data."""
_attr_unit_of_measurement = "people"
_attr_native_unit_of_measurement = "people"
def __init__(self, coordinator, country, info_type):
"""Initialize coronavirus sensor."""
@ -53,7 +53,7 @@ class CoronavirusSensor(CoordinatorEntity, SensorEntity):
)
@property
def state(self):
def native_value(self):
"""State of the sensor."""
if self.country == OPTION_WORLDWIDE:
sum_cases = 0

View File

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

View File

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

View File

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

View File

@ -2,6 +2,7 @@
from __future__ import annotations
from collections.abc import Mapping
from contextlib import suppress
from dataclasses import dataclass
from datetime import datetime, timedelta
import logging
@ -26,6 +27,8 @@ from homeassistant.const import (
DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_TIMESTAMP,
DEVICE_CLASS_VOLTAGE,
TEMP_CELSIUS,
TEMP_FAHRENHEIT,
)
from homeassistant.core import HomeAssistant
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_component import EntityComponent
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers.typing import ConfigType, StateType
_LOGGER: Final = logging.getLogger(__name__)
@ -102,14 +105,18 @@ class SensorEntityDescription(EntityDescription):
state_class: str | None = None
last_reset: datetime | None = None
native_unit_of_measurement: str | None = None
class SensorEntity(Entity):
"""Base class for sensor entities."""
entity_description: SensorEntityDescription
_attr_state_class: str | 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
def state_class(self) -> str | None:
@ -145,3 +152,94 @@ class SensorEntity(Entity):
return {ATTR_LAST_RESET: last_reset.isoformat()}
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:
self._slow_reported = True
extra = ""
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"
)
report_issue = self._suggest_report_issue()
_LOGGER.warning(
"Updating state for %s (%s) took %.3f seconds. %s",
"Updating state for %s (%s) took %.3f seconds. Please %s",
self.entity_id,
type(self),
end - start,
extra,
report_issue,
)
# Overwrite properties that have been set in the config file.
@ -858,6 +846,23 @@ class Entity(ABC):
if self.parallel_updates:
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
class ToggleEntityDescription(EntityDescription):

View File

@ -19,53 +19,55 @@ def _get_named_tuple(input_dict):
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:
data = {}
sensor_entry = next(
sensor_entry for sensor_entry in SENSOR_TYPES if sensor_entry.key == sensor_type
)
sensor_entry.name = name
return arlo.ArloSensor(data, sensor_entry)
sensor = arlo.ArloSensor(data, sensor_entry)
sensor.hass = hass
return sensor
@pytest.fixture()
def default_sensor():
def default_sensor(hass):
"""Create an ArloSensor with default values."""
return _get_sensor()
return _get_sensor(hass)
@pytest.fixture()
def battery_sensor():
def battery_sensor(hass):
"""Create an ArloSensor with battery data."""
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()
def temperature_sensor():
def temperature_sensor(hass):
"""Create a temperature ArloSensor."""
return _get_sensor("Temperature", "temperature")
return _get_sensor(hass, "Temperature", "temperature")
@pytest.fixture()
def humidity_sensor():
def humidity_sensor(hass):
"""Create a humidity ArloSensor."""
return _get_sensor("Humidity", "humidity")
return _get_sensor(hass, "Humidity", "humidity")
@pytest.fixture()
def cameras_sensor():
def cameras_sensor(hass):
"""Create a total cameras ArloSensor."""
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()
def captured_sensor():
def captured_sensor(hass):
"""Create a captured today ArloSensor."""
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:
@ -88,14 +90,6 @@ def platform_setup():
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()
def mock_dispatch():
"""Mock the dispatcher connect method."""
@ -145,14 +139,14 @@ def test_sensor_name(default_sensor):
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."""
await sensor_with_hass_data.async_added_to_hass()
await default_sensor.async_added_to_hass()
assert len(mock_dispatch.mock_calls) == 1
kall = mock_dispatch.call_args
args, kwargs = kall
assert len(args) == 3
assert args[0] == sensor_with_hass_data.hass
assert args[0] == default_sensor.hass
assert args[1] == "arlo_update"
assert not kwargs
@ -197,22 +191,22 @@ def test_update_captured_today(captured_sensor):
assert captured_sensor.state == 5
def _test_attributes(sensor_type):
def _test_attributes(hass, sensor_type):
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
assert attrs.get(ATTR_ATTRIBUTION) == "Data provided by arlo.netgear.com"
assert attrs.get("brand") == "Netgear Arlo"
assert attrs.get("model") == "TEST123"
def test_state_attributes():
def test_state_attributes(hass):
"""Test attributes for camera sensor types."""
_test_attributes("battery_level")
_test_attributes("signal_strength")
_test_attributes("temperature")
_test_attributes("humidity")
_test_attributes("air_quality")
_test_attributes(hass, "battery_level")
_test_attributes(hass, "signal_strength")
_test_attributes(hass, "temperature")
_test_attributes(hass, "humidity")
_test_attributes(hass, "air_quality")
def test_attributes_total_cameras(cameras_sensor):
@ -223,17 +217,17 @@ def test_attributes_total_cameras(cameras_sensor):
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})
sensor = _get_sensor("test", sensor_type, data)
sensor = _get_sensor(hass, "test", sensor_type, data)
sensor.update()
assert sensor.state == value
def test_update():
def test_update(hass):
"""Test update method for direct transcription sensor types."""
_test_update("battery_level", "battery_level", 100)
_test_update("signal_strength", "signal_strength", 100)
_test_update("temperature", "ambient_temperature", 21.4)
_test_update("humidity", "ambient_humidity", 45.1)
_test_update("air_quality", "ambient_air_quality", 14.2)
_test_update(hass, "battery_level", "battery_level", 100)
_test_update(hass, "signal_strength", "signal_strength", 100)
_test_update(hass, "temperature", "ambient_temperature", 21.4)
_test_update(hass, "humidity", "ambient_humidity", 45.1)
_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()))
class MockSensor(MockEntity):
class MockSensor(MockEntity, sensor.SensorEntity):
"""Mock Sensor class."""
@property
@ -70,6 +70,11 @@ class MockSensor(MockEntity):
return self._handle("device_class")
@property
def unit_of_measurement(self):
"""Return the unit_of_measurement of this sensor."""
return self._handle("unit_of_measurement")
def native_unit_of_measurement(self):
"""Return the native unit_of_measurement of this sensor."""
return self._handle("native_unit_of_measurement")
@property
def native_value(self):
"""Return the native value of this sensor."""
return self._handle("native_value")