hass-core/homeassistant/components/mobile_app/sensor.py
Erik Montnemery d1afcd773f
Revert "Cache entity properties that are never expected to change in the base class" ()
Revert "Cache entity properties that are never expected to change in the base class ()"

This reverts commit 042776ebb8.
2023-09-15 11:25:24 +02:00

134 lines
4.7 KiB
Python

"""Sensor platform for mobile_app."""
from __future__ import annotations
from datetime import date, datetime
from typing import Any
from homeassistant.components.sensor import RestoreSensor, SensorDeviceClass
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_WEBHOOK_ID, STATE_UNKNOWN, UnitOfTemperature
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.util import dt as dt_util
from .const import (
ATTR_SENSOR_ATTRIBUTES,
ATTR_SENSOR_DEVICE_CLASS,
ATTR_SENSOR_ENTITY_CATEGORY,
ATTR_SENSOR_ICON,
ATTR_SENSOR_NAME,
ATTR_SENSOR_STATE,
ATTR_SENSOR_STATE_CLASS,
ATTR_SENSOR_TYPE,
ATTR_SENSOR_TYPE_SENSOR as ENTITY_TYPE,
ATTR_SENSOR_UNIQUE_ID,
ATTR_SENSOR_UOM,
DOMAIN,
)
from .entity import MobileAppEntity
from .webhook import _extract_sensor_unique_id
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up mobile app sensor from a config entry."""
entities = []
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
entity_registry = er.async_get(hass)
entries = er.async_entries_for_config_entry(entity_registry, config_entry.entry_id)
for entry in entries:
if entry.domain != ENTITY_TYPE or entry.disabled_by:
continue
config: dict[str, Any] = {
ATTR_SENSOR_ATTRIBUTES: {},
ATTR_SENSOR_DEVICE_CLASS: entry.device_class or entry.original_device_class,
ATTR_SENSOR_ICON: entry.original_icon,
ATTR_SENSOR_NAME: entry.original_name,
ATTR_SENSOR_STATE: None,
ATTR_SENSOR_TYPE: entry.domain,
ATTR_SENSOR_UNIQUE_ID: entry.unique_id,
ATTR_SENSOR_UOM: entry.unit_of_measurement,
ATTR_SENSOR_ENTITY_CATEGORY: entry.entity_category,
}
entities.append(MobileAppSensor(config, config_entry))
async_add_entities(entities)
@callback
def handle_sensor_registration(data):
if data[CONF_WEBHOOK_ID] != webhook_id:
return
async_add_entities([MobileAppSensor(data, config_entry)])
async_dispatcher_connect(
hass,
f"{DOMAIN}_{ENTITY_TYPE}_register",
handle_sensor_registration,
)
class MobileAppSensor(MobileAppEntity, RestoreSensor):
"""Representation of an mobile app sensor."""
async def async_restore_last_state(self, last_state):
"""Restore previous state."""
await super().async_restore_last_state(last_state)
if not (last_sensor_data := await self.async_get_last_sensor_data()):
# Workaround to handle migration to RestoreSensor, can be removed
# in HA Core 2023.4
self._config[ATTR_SENSOR_STATE] = None
webhook_id = self._entry.data[CONF_WEBHOOK_ID]
sensor_unique_id = _extract_sensor_unique_id(webhook_id, self.unique_id)
if (
self.device_class == SensorDeviceClass.TEMPERATURE
and sensor_unique_id == "battery_temperature"
):
self._config[ATTR_SENSOR_UOM] = UnitOfTemperature.CELSIUS
return
self._config[ATTR_SENSOR_STATE] = last_sensor_data.native_value
self._config[ATTR_SENSOR_UOM] = last_sensor_data.native_unit_of_measurement
@property
def native_value(self) -> StateType | date | datetime:
"""Return the state of the sensor."""
if (state := self._config[ATTR_SENSOR_STATE]) in (None, STATE_UNKNOWN):
return None
if (
self.device_class
in (
SensorDeviceClass.DATE,
SensorDeviceClass.TIMESTAMP,
)
# Only parse strings: if the sensor's state is restored, the state is a
# native date or datetime, not str
and isinstance(state, str)
and (timestamp := dt_util.parse_datetime(state)) is not None
):
if self.device_class == SensorDeviceClass.DATE:
return timestamp.date()
return timestamp
return state
@property
def native_unit_of_measurement(self) -> str | None:
"""Return the unit of measurement this sensor expresses itself in."""
return self._config.get(ATTR_SENSOR_UOM)
@property
def state_class(self) -> str | None:
"""Return state class."""
return self._config.get(ATTR_SENSOR_STATE_CLASS)