diff --git a/homeassistant/components/sensor/__init__.py b/homeassistant/components/sensor/__init__.py index 10bf976f012..0fa270bb03d 100644 --- a/homeassistant/components/sensor/__init__.py +++ b/homeassistant/components/sensor/__init__.py @@ -150,6 +150,28 @@ class SensorEntityDescription(EntityDescription): unit_of_measurement: None = None # Type override, use native_unit_of_measurement +def _numeric_state_expected( + device_class: SensorDeviceClass | None, + state_class: SensorStateClass | str | None, + native_unit_of_measurement: str | None, + suggested_display_precision: int | None, +) -> bool: + """Return true if the sensor must be numeric.""" + # Note: the order of the checks needs to be kept aligned + # with the checks in `state` property. + if device_class in NON_NUMERIC_DEVICE_CLASSES: + return False + if ( + state_class is not None + or native_unit_of_measurement is not None + or suggested_display_precision is not None + ): + return True + # Sensors with custom device classes will have the device class + # converted to None and are not considered numeric + return device_class is not None + + class SensorEntity(Entity): """Base class for sensor entities.""" @@ -284,20 +306,12 @@ class SensorEntity(Entity): @property def _numeric_state_expected(self) -> bool: """Return true if the sensor must be numeric.""" - # Note: the order of the checks needs to be kept aligned - # with the checks in `state` property. - device_class = try_parse_enum(SensorDeviceClass, self.device_class) - if device_class in NON_NUMERIC_DEVICE_CLASSES: - return False - if ( - self.state_class is not None - or self.native_unit_of_measurement is not None - or self.suggested_display_precision is not None - ): - return True - # Sensors with custom device classes will have the device class - # converted to None and are not considered numeric - return device_class is not None + return _numeric_state_expected( + try_parse_enum(SensorDeviceClass, self.device_class), + self.state_class, + self.native_unit_of_measurement, + self.suggested_display_precision, + ) @property def options(self) -> list[str] | None: @@ -377,10 +391,8 @@ class SensorEntity(Entity): def state_attributes(self) -> dict[str, Any] | None: """Return state attributes.""" if last_reset := self.last_reset: - if ( - self.state_class != SensorStateClass.TOTAL - and not self._last_reset_reported - ): + state_class = self.state_class + if state_class != SensorStateClass.TOTAL and not self._last_reset_reported: self._last_reset_reported = True report_issue = self._suggest_report_issue() # This should raise in Home Assistant Core 2022.5 @@ -393,11 +405,11 @@ class SensorEntity(Entity): ), self.entity_id, type(self), - self.state_class, + state_class, report_issue, ) - if self.state_class == SensorStateClass.TOTAL: + if state_class == SensorStateClass.TOTAL: return {ATTR_LAST_RESET: last_reset.isoformat()} return None @@ -470,9 +482,9 @@ class SensorEntity(Entity): native_unit_of_measurement = self.native_unit_of_measurement if ( - self.device_class == SensorDeviceClass.TEMPERATURE - and native_unit_of_measurement + native_unit_of_measurement in {UnitOfTemperature.CELSIUS, UnitOfTemperature.FAHRENHEIT} + and self.device_class == SensorDeviceClass.TEMPERATURE ): return self.hass.config.units.temperature_unit @@ -590,7 +602,9 @@ class SensorEntity(Entity): # If the sensor has neither a device class, a state class, a unit of measurement # nor a precision then there are no further checks or conversions - if not self._numeric_state_expected: + if not _numeric_state_expected( + device_class, state_class, native_unit_of_measurement, suggested_precision + ): return value # From here on a numerical value is expected