diff --git a/homeassistant/components/command_line/sensor.py b/homeassistant/components/command_line/sensor.py index 2ccbdbc4785..f04320b159e 100644 --- a/homeassistant/components/command_line/sensor.py +++ b/homeassistant/components/command_line/sensor.py @@ -16,13 +16,12 @@ from homeassistant.components.sensor import ( PLATFORM_SCHEMA, STATE_CLASSES_SCHEMA, SensorDeviceClass, - SensorEntity, - SensorStateClass, ) from homeassistant.components.sensor.helpers import async_parse_date_datetime from homeassistant.const import ( CONF_COMMAND, CONF_DEVICE_CLASS, + CONF_ICON, CONF_NAME, CONF_SCAN_INTERVAL, CONF_UNIQUE_ID, @@ -36,7 +35,11 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.event import async_track_time_interval from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue from homeassistant.helpers.template import Template -from homeassistant.helpers.template_entity import ManualTriggerEntity +from homeassistant.helpers.template_entity import ( + CONF_AVAILABILITY, + CONF_PICTURE, + ManualTriggerSensorEntity, +) from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.util import dt as dt_util @@ -47,6 +50,16 @@ CONF_JSON_ATTRIBUTES = "json_attributes" DEFAULT_NAME = "Command Sensor" +TRIGGER_ENTITY_OPTIONS = ( + CONF_AVAILABILITY, + CONF_DEVICE_CLASS, + CONF_ICON, + CONF_PICTURE, + CONF_UNIQUE_ID, + CONF_STATE_CLASS, + CONF_UNIT_OF_MEASUREMENT, +) + SCAN_INTERVAL = timedelta(seconds=60) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( @@ -87,30 +100,25 @@ async def async_setup_platform( name: str = sensor_config[CONF_NAME] command: str = sensor_config[CONF_COMMAND] - unit: str | None = sensor_config.get(CONF_UNIT_OF_MEASUREMENT) value_template: Template | None = sensor_config.get(CONF_VALUE_TEMPLATE) command_timeout: int = sensor_config[CONF_COMMAND_TIMEOUT] - unique_id: str | None = sensor_config.get(CONF_UNIQUE_ID) if value_template is not None: value_template.hass = hass json_attributes: list[str] | None = sensor_config.get(CONF_JSON_ATTRIBUTES) scan_interval: timedelta = sensor_config.get(CONF_SCAN_INTERVAL, SCAN_INTERVAL) - state_class: SensorStateClass | None = sensor_config.get(CONF_STATE_CLASS) data = CommandSensorData(hass, command, command_timeout) - trigger_entity_config = { - CONF_UNIQUE_ID: unique_id, - CONF_NAME: Template(name, hass), - CONF_DEVICE_CLASS: sensor_config.get(CONF_DEVICE_CLASS), - } + trigger_entity_config = {CONF_NAME: Template(name, hass)} + for key in TRIGGER_ENTITY_OPTIONS: + if key not in sensor_config: + continue + trigger_entity_config[key] = sensor_config[key] async_add_entities( [ CommandSensor( data, trigger_entity_config, - unit, - state_class, value_template, json_attributes, scan_interval, @@ -119,7 +127,7 @@ async def async_setup_platform( ) -class CommandSensor(ManualTriggerEntity, SensorEntity): +class CommandSensor(ManualTriggerSensorEntity): """Representation of a sensor that is using shell commands.""" _attr_should_poll = False @@ -128,8 +136,6 @@ class CommandSensor(ManualTriggerEntity, SensorEntity): self, data: CommandSensorData, config: ConfigType, - unit_of_measurement: str | None, - state_class: SensorStateClass | None, value_template: Template | None, json_attributes: list[str] | None, scan_interval: timedelta, @@ -141,8 +147,6 @@ class CommandSensor(ManualTriggerEntity, SensorEntity): self._json_attributes = json_attributes self._attr_native_value = None self._value_template = value_template - self._attr_native_unit_of_measurement = unit_of_measurement - self._attr_state_class = state_class self._scan_interval = scan_interval self._process_updates: asyncio.Lock | None = None diff --git a/homeassistant/components/rest/sensor.py b/homeassistant/components/rest/sensor.py index f7743a853ad..63a9d6f210c 100644 --- a/homeassistant/components/rest/sensor.py +++ b/homeassistant/components/rest/sensor.py @@ -12,7 +12,6 @@ from homeassistant.components.sensor import ( DOMAIN as SENSOR_DOMAIN, PLATFORM_SCHEMA, SensorDeviceClass, - SensorEntity, ) from homeassistant.components.sensor.helpers import async_parse_date_datetime from homeassistant.const import ( @@ -118,7 +117,7 @@ async def async_setup_platform( ) -class RestSensor(ManualTriggerSensorEntity, RestEntity, SensorEntity): +class RestSensor(ManualTriggerSensorEntity, RestEntity): """Implementation of a REST sensor.""" def __init__( diff --git a/homeassistant/components/scrape/sensor.py b/homeassistant/components/scrape/sensor.py index 7cd7e2197ab..2763d034804 100644 --- a/homeassistant/components/scrape/sensor.py +++ b/homeassistant/components/scrape/sensor.py @@ -6,11 +6,7 @@ from typing import Any, cast import voluptuous as vol -from homeassistant.components.sensor import ( - CONF_STATE_CLASS, - SensorDeviceClass, - SensorEntity, -) +from homeassistant.components.sensor import CONF_STATE_CLASS, SensorDeviceClass from homeassistant.components.sensor.helpers import async_parse_date_datetime from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( @@ -32,6 +28,7 @@ from homeassistant.helpers.template_entity import ( CONF_PICTURE, TEMPLATE_SENSOR_BASE_SCHEMA, ManualTriggerEntity, + ManualTriggerSensorEntity, ) from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.helpers.update_coordinator import CoordinatorEntity @@ -41,6 +38,16 @@ from .coordinator import ScrapeCoordinator _LOGGER = logging.getLogger(__name__) +TRIGGER_ENTITY_OPTIONS = ( + CONF_AVAILABILITY, + CONF_DEVICE_CLASS, + CONF_ICON, + CONF_PICTURE, + CONF_UNIQUE_ID, + CONF_STATE_CLASS, + CONF_UNIT_OF_MEASUREMENT, +) + async def async_setup_platform( hass: HomeAssistant, @@ -63,25 +70,17 @@ async def async_setup_platform( if value_template is not None: value_template.hass = hass - trigger_entity_config = { - CONF_NAME: sensor_config[CONF_NAME], - CONF_DEVICE_CLASS: sensor_config.get(CONF_DEVICE_CLASS), - CONF_UNIQUE_ID: sensor_config.get(CONF_UNIQUE_ID), - } - if available := sensor_config.get(CONF_AVAILABILITY): - trigger_entity_config[CONF_AVAILABILITY] = available - if icon := sensor_config.get(CONF_ICON): - trigger_entity_config[CONF_ICON] = icon - if picture := sensor_config.get(CONF_PICTURE): - trigger_entity_config[CONF_PICTURE] = picture + trigger_entity_config = {CONF_NAME: sensor_config[CONF_NAME]} + for key in TRIGGER_ENTITY_OPTIONS: + if key not in sensor_config: + continue + trigger_entity_config[key] = sensor_config[key] entities.append( ScrapeSensor( hass, coordinator, trigger_entity_config, - sensor_config.get(CONF_UNIT_OF_MEASUREMENT), - sensor_config.get(CONF_STATE_CLASS), sensor_config[CONF_SELECT], sensor_config.get(CONF_ATTRIBUTE), sensor_config[CONF_INDEX], @@ -113,19 +112,17 @@ async def async_setup_entry( Template(value_string, hass) if value_string is not None else None ) - trigger_entity_config = { - CONF_NAME: name, - CONF_DEVICE_CLASS: sensor_config.get(CONF_DEVICE_CLASS), - CONF_UNIQUE_ID: sensor_config[CONF_UNIQUE_ID], - } + trigger_entity_config = {CONF_NAME: name} + for key in TRIGGER_ENTITY_OPTIONS: + if key not in sensor_config: + continue + trigger_entity_config[key] = sensor_config[key] entities.append( ScrapeSensor( hass, coordinator, trigger_entity_config, - sensor_config.get(CONF_UNIT_OF_MEASUREMENT), - sensor_config.get(CONF_STATE_CLASS), sensor_config[CONF_SELECT], sensor_config.get(CONF_ATTRIBUTE), sensor_config[CONF_INDEX], @@ -137,9 +134,7 @@ async def async_setup_entry( async_add_entities(entities) -class ScrapeSensor( - CoordinatorEntity[ScrapeCoordinator], ManualTriggerEntity, SensorEntity -): +class ScrapeSensor(CoordinatorEntity[ScrapeCoordinator], ManualTriggerSensorEntity): """Representation of a web scrape sensor.""" def __init__( @@ -147,8 +142,6 @@ class ScrapeSensor( hass: HomeAssistant, coordinator: ScrapeCoordinator, trigger_entity_config: ConfigType, - unit_of_measurement: str | None, - state_class: str | None, select: str, attr: str | None, index: int, @@ -157,9 +150,7 @@ class ScrapeSensor( ) -> None: """Initialize a web scrape sensor.""" CoordinatorEntity.__init__(self, coordinator) - ManualTriggerEntity.__init__(self, hass, trigger_entity_config) - self._attr_native_unit_of_measurement = unit_of_measurement - self._attr_state_class = state_class + ManualTriggerSensorEntity.__init__(self, hass, trigger_entity_config) self._select = select self._attr = attr self._index = index diff --git a/homeassistant/components/sql/sensor.py b/homeassistant/components/sql/sensor.py index f750b364106..0b32b10f972 100644 --- a/homeassistant/components/sql/sensor.py +++ b/homeassistant/components/sql/sensor.py @@ -19,12 +19,7 @@ from homeassistant.components.recorder import ( SupportedDialect, get_instance, ) -from homeassistant.components.sensor import ( - CONF_STATE_CLASS, - SensorDeviceClass, - SensorEntity, - SensorStateClass, -) +from homeassistant.components.sensor import CONF_STATE_CLASS from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( CONF_DEVICE_CLASS, @@ -44,7 +39,7 @@ from homeassistant.helpers.template import Template from homeassistant.helpers.template_entity import ( CONF_AVAILABILITY, CONF_PICTURE, - ManualTriggerEntity, + ManualTriggerSensorEntity, ) from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType @@ -56,6 +51,16 @@ _LOGGER = logging.getLogger(__name__) _SQL_LAMBDA_CACHE: LRUCache = LRUCache(1000) +TRIGGER_ENTITY_OPTIONS = ( + CONF_AVAILABILITY, + CONF_DEVICE_CLASS, + CONF_ICON, + CONF_PICTURE, + CONF_UNIQUE_ID, + CONF_STATE_CLASS, + CONF_UNIT_OF_MEASUREMENT, +) + async def async_setup_platform( hass: HomeAssistant, @@ -69,43 +74,29 @@ async def async_setup_platform( name: Template = conf[CONF_NAME] query_str: str = conf[CONF_QUERY] - unit: str | None = conf.get(CONF_UNIT_OF_MEASUREMENT) value_template: Template | None = conf.get(CONF_VALUE_TEMPLATE) column_name: str = conf[CONF_COLUMN_NAME] unique_id: str | None = conf.get(CONF_UNIQUE_ID) db_url: str = resolve_db_url(hass, conf.get(CONF_DB_URL)) - device_class: SensorDeviceClass | None = conf.get(CONF_DEVICE_CLASS) - state_class: SensorStateClass | None = conf.get(CONF_STATE_CLASS) - availability: Template | None = conf.get(CONF_AVAILABILITY) - icon: Template | None = conf.get(CONF_ICON) - picture: Template | None = conf.get(CONF_PICTURE) if value_template is not None: value_template.hass = hass - trigger_entity_config = { - CONF_NAME: name, - CONF_DEVICE_CLASS: device_class, - CONF_UNIQUE_ID: unique_id, - } - if availability: - trigger_entity_config[CONF_AVAILABILITY] = availability - if icon: - trigger_entity_config[CONF_ICON] = icon - if picture: - trigger_entity_config[CONF_PICTURE] = picture + trigger_entity_config = {CONF_NAME: name} + for key in TRIGGER_ENTITY_OPTIONS: + if key not in conf: + continue + trigger_entity_config[key] = conf[key] await async_setup_sensor( hass, trigger_entity_config, query_str, column_name, - unit, value_template, unique_id, db_url, True, - state_class, async_add_entities, ) @@ -118,11 +109,8 @@ async def async_setup_entry( db_url: str = resolve_db_url(hass, entry.options.get(CONF_DB_URL)) name: str = entry.options[CONF_NAME] query_str: str = entry.options[CONF_QUERY] - unit: str | None = entry.options.get(CONF_UNIT_OF_MEASUREMENT) template: str | None = entry.options.get(CONF_VALUE_TEMPLATE) column_name: str = entry.options[CONF_COLUMN_NAME] - device_class: SensorDeviceClass | None = entry.options.get(CONF_DEVICE_CLASS, None) - state_class: SensorStateClass | None = entry.options.get(CONF_STATE_CLASS, None) value_template: Template | None = None if template is not None: @@ -135,23 +123,21 @@ async def async_setup_entry( value_template.hass = hass name_template = Template(name, hass) - trigger_entity_config = { - CONF_NAME: name_template, - CONF_DEVICE_CLASS: device_class, - CONF_UNIQUE_ID: entry.entry_id, - } + trigger_entity_config = {CONF_NAME: name_template} + for key in TRIGGER_ENTITY_OPTIONS: + if key not in entry.options: + continue + trigger_entity_config[key] = entry.options[key] await async_setup_sensor( hass, trigger_entity_config, query_str, column_name, - unit, value_template, entry.entry_id, db_url, False, - state_class, async_add_entities, ) @@ -191,12 +177,10 @@ async def async_setup_sensor( trigger_entity_config: ConfigType, query_str: str, column_name: str, - unit: str | None, value_template: Template | None, unique_id: str | None, db_url: str, yaml: bool, - state_class: SensorStateClass | None, async_add_entities: AddEntitiesCallback, ) -> None: """Set up the SQL sensor.""" @@ -274,10 +258,8 @@ async def async_setup_sensor( sessmaker, query_str, column_name, - unit, value_template, yaml, - state_class, use_database_executor, ) ], @@ -317,7 +299,7 @@ def _generate_lambda_stmt(query: str) -> StatementLambdaElement: return lambda_stmt(lambda: text, lambda_cache=_SQL_LAMBDA_CACHE) -class SQLSensor(ManualTriggerEntity, SensorEntity): +class SQLSensor(ManualTriggerSensorEntity): """Representation of an SQL sensor.""" def __init__( @@ -326,17 +308,13 @@ class SQLSensor(ManualTriggerEntity, SensorEntity): sessmaker: scoped_session, query: str, column: str, - unit: str | None, value_template: Template | None, yaml: bool, - state_class: SensorStateClass | None, use_database_executor: bool, ) -> None: """Initialize the SQL sensor.""" super().__init__(self.hass, trigger_entity_config) self._query = query - self._attr_native_unit_of_measurement = unit - self._attr_state_class = state_class self._template = value_template self._column_name = column self.sessionmaker = sessmaker diff --git a/homeassistant/helpers/template_entity.py b/homeassistant/helpers/template_entity.py index 07e68152d64..70a0ee1d16c 100644 --- a/homeassistant/helpers/template_entity.py +++ b/homeassistant/helpers/template_entity.py @@ -486,7 +486,7 @@ class TriggerBaseEntity(Entity): def __init__( self, hass: HomeAssistant, - config: dict, + config: ConfigType, ) -> None: """Initialize the entity.""" self.hass = hass @@ -623,7 +623,7 @@ class ManualTriggerEntity(TriggerBaseEntity): def __init__( self, hass: HomeAssistant, - config: dict, + config: ConfigType, ) -> None: """Initialize the entity.""" TriggerBaseEntity.__init__(self, hass, config) @@ -655,13 +655,13 @@ class ManualTriggerEntity(TriggerBaseEntity): self._render_templates(variables) -class ManualTriggerSensorEntity(ManualTriggerEntity): +class ManualTriggerSensorEntity(ManualTriggerEntity, SensorEntity): """Template entity based on manual trigger data for sensor.""" def __init__( self, hass: HomeAssistant, - config: dict, + config: ConfigType, ) -> None: """Initialize the sensor entity.""" ManualTriggerEntity.__init__(self, hass, config)