Move entity category to entity details - remove service to action

This commit is contained in:
jbouwh
2025-06-18 15:11:24 +00:00
parent 1417f31929
commit 0d1234ac8f
2 changed files with 38 additions and 36 deletions

View File

@@ -439,6 +439,15 @@ BINARY_SENSOR_DEVICE_CLASS_SELECTOR = SelectSelector(
sort=True, sort=True,
) )
) )
SENSOR_ENTITY_CATEGORY_SELECTOR = SelectSelector(
SelectSelectorConfig(
options=[EntityCategory.DIAGNOSTIC.value],
mode=SelectSelectorMode.DROPDOWN,
translation_key=CONF_ENTITY_CATEGORY,
sort=True,
)
)
BUTTON_DEVICE_CLASS_SELECTOR = SelectSelector( BUTTON_DEVICE_CLASS_SELECTOR = SelectSelector(
SelectSelectorConfig( SelectSelectorConfig(
options=[device_class.value for device_class in ButtonDeviceClass], options=[device_class.value for device_class in ButtonDeviceClass],
@@ -613,18 +622,6 @@ def validate_fan_platform_config(config: dict[str, Any]) -> dict[str, str]:
return errors return errors
@callback
def validate_binary_sensor_platform_config(
config: dict[str, Any],
) -> dict[str, str]:
"""Validate the binary sensor sensor entity_category."""
errors: dict[str, str] = {}
if config.get(CONF_ENTITY_CATEGORY) == EntityCategory.CONFIG:
errors[CONF_ENTITY_CATEGORY] = "sensor_entity_category_must_not_be_config"
return errors
@callback @callback
def validate_sensor_platform_config( def validate_sensor_platform_config(
config: dict[str, Any], config: dict[str, Any],
@@ -670,9 +667,6 @@ def validate_sensor_platform_config(
): ):
errors[CONF_UNIT_OF_MEASUREMENT] = "invalid_uom_for_state_class" errors[CONF_UNIT_OF_MEASUREMENT] = "invalid_uom_for_state_class"
if config.get(CONF_ENTITY_CATEGORY) == EntityCategory.CONFIG:
errors[CONF_ENTITY_CATEGORY] = "sensor_entity_category_must_not_be_config"
return errors return errors
@@ -755,14 +749,17 @@ COMMON_ENTITY_FIELDS: dict[str, PlatformField] = {
exclude_from_reconfig=True, exclude_from_reconfig=True,
default=None, default=None,
), ),
CONF_ENTITY_PICTURE: PlatformField(
selector=TEXT_SELECTOR, required=False, validator=cv.url, error="invalid_url"
),
}
SHARED_PLATFORM_ENTITY_FIELDS: dict[str, PlatformField] = {
CONF_ENTITY_CATEGORY: PlatformField( CONF_ENTITY_CATEGORY: PlatformField(
selector=ENTITY_CATEGORY_SELECTOR, selector=ENTITY_CATEGORY_SELECTOR,
required=False, required=False,
default=None, default=None,
), ),
CONF_ENTITY_PICTURE: PlatformField(
selector=TEXT_SELECTOR, required=False, validator=cv.url, error="invalid_url"
),
} }
PLATFORM_ENTITY_FIELDS: dict[str, dict[str, PlatformField]] = { PLATFORM_ENTITY_FIELDS: dict[str, dict[str, PlatformField]] = {
@@ -771,6 +768,11 @@ PLATFORM_ENTITY_FIELDS: dict[str, dict[str, PlatformField]] = {
selector=BINARY_SENSOR_DEVICE_CLASS_SELECTOR, selector=BINARY_SENSOR_DEVICE_CLASS_SELECTOR,
required=False, required=False,
), ),
CONF_ENTITY_CATEGORY: PlatformField(
selector=SENSOR_ENTITY_CATEGORY_SELECTOR,
required=False,
default=None,
),
}, },
Platform.BUTTON.value: { Platform.BUTTON.value: {
CONF_DEVICE_CLASS: PlatformField( CONF_DEVICE_CLASS: PlatformField(
@@ -834,6 +836,11 @@ PLATFORM_ENTITY_FIELDS: dict[str, dict[str, PlatformField]] = {
required=False, required=False,
conditions=({"device_class": "enum"},), conditions=({"device_class": "enum"},),
), ),
CONF_ENTITY_CATEGORY: PlatformField(
selector=SENSOR_ENTITY_CATEGORY_SELECTOR,
required=False,
default=None,
),
}, },
Platform.SWITCH.value: { Platform.SWITCH.value: {
CONF_DEVICE_CLASS: PlatformField( CONF_DEVICE_CLASS: PlatformField(
@@ -1885,7 +1892,7 @@ ENTITY_CONFIG_VALIDATOR: dict[
str, str,
Callable[[dict[str, Any]], dict[str, str]] | None, Callable[[dict[str, Any]], dict[str, str]] | None,
] = { ] = {
Platform.BINARY_SENSOR.value: validate_binary_sensor_platform_config, Platform.BINARY_SENSOR.value: None,
Platform.BUTTON.value: None, Platform.BUTTON.value: None,
Platform.COVER.value: validate_cover_platform_config, Platform.COVER.value: validate_cover_platform_config,
Platform.FAN.value: validate_fan_platform_config, Platform.FAN.value: validate_fan_platform_config,
@@ -2025,12 +2032,13 @@ def validate_user_input(
) )
if config_validator is not None: if config_validator is not None:
if TYPE_CHECKING:
assert component_data is not None
errors |= config_validator( errors |= config_validator(
merged_user_input calculate_merged_config(
if component_data is None
else calculate_merged_config(
merged_user_input, data_schema_fields, component_data merged_user_input, data_schema_fields, component_data
) ),
) )
return merged_user_input, errors return merged_user_input, errors
@@ -2780,16 +2788,8 @@ class MQTTSubentryFlowHandler(ConfigSubentryFlow):
entity_name_label = f" ({name})" if name is not None else "" entity_name_label = f" ({name})" if name is not None else ""
data_schema = data_schema_from_fields(data_schema_fields, reconfig=reconfig) data_schema = data_schema_from_fields(data_schema_fields, reconfig=reconfig)
if user_input is not None: if user_input is not None:
platform: str = (
user_input[CONF_PLATFORM]
if component_data is None
else component_data[CONF_PLATFORM]
)
merged_user_input, errors = validate_user_input( merged_user_input, errors = validate_user_input(
user_input, user_input, data_schema_fields, component_data=component_data
data_schema_fields,
component_data=component_data,
config_validator=ENTITY_CONFIG_VALIDATOR[platform],
) )
if not errors: if not errors:
if self._component_id is None: if self._component_id is None:
@@ -2871,7 +2871,9 @@ class MQTTSubentryFlowHandler(ConfigSubentryFlow):
assert self._component_id is not None assert self._component_id is not None
component_data = self._subentry_data["components"][self._component_id] component_data = self._subentry_data["components"][self._component_id]
platform = component_data[CONF_PLATFORM] platform = component_data[CONF_PLATFORM]
data_schema_fields = PLATFORM_ENTITY_FIELDS[platform] data_schema_fields = (
SHARED_PLATFORM_ENTITY_FIELDS | PLATFORM_ENTITY_FIELDS[platform]
)
errors: dict[str, str] = {} errors: dict[str, str] = {}
data_schema = data_schema_from_fields( data_schema = data_schema_from_fields(
@@ -2977,6 +2979,7 @@ class MQTTSubentryFlowHandler(ConfigSubentryFlow):
platform = component_data[CONF_PLATFORM] platform = component_data[CONF_PLATFORM]
platform_fields: dict[str, PlatformField] = ( platform_fields: dict[str, PlatformField] = (
COMMON_ENTITY_FIELDS COMMON_ENTITY_FIELDS
| SHARED_PLATFORM_ENTITY_FIELDS
| PLATFORM_ENTITY_FIELDS[platform] | PLATFORM_ENTITY_FIELDS[platform]
| PLATFORM_MQTT_FIELDS[platform] | PLATFORM_MQTT_FIELDS[platform]
) )

View File

@@ -181,13 +181,11 @@
"data": { "data": {
"platform": "Type of entity", "platform": "Type of entity",
"name": "Entity name", "name": "Entity name",
"entity_category": "Entity category",
"entity_picture": "Entity picture" "entity_picture": "Entity picture"
}, },
"data_description": { "data_description": {
"platform": "The type of the entity to configure.", "platform": "The type of the entity to configure.",
"name": "The name of the entity. Leave empty to set it to `None` to [mark it as main feature of the MQTT device](https://www.home-assistant.io/integrations/mqtt/#naming-of-mqtt-entities).", "name": "The name of the entity. Leave empty to set it to `None` to [mark it as main feature of the MQTT device](https://www.home-assistant.io/integrations/mqtt/#naming-of-mqtt-entities).",
"entity_category": "The category of the entity to configure. Leave empty to [mark it as a main feature of the MQTT device](https://developers.home-assistant.io/docs/core/entity/#registry-properties). An entity with a category will not be exposed to cloud, Alexa, or Google Assistant components, nor included in indirect service calls to devices or areas.",
"entity_picture": "An URL to a picture to be assigned." "entity_picture": "An URL to a picture to be assigned."
} }
}, },
@@ -216,6 +214,7 @@
"description": "Please configure specific details for {platform} entity \"{entity}\":", "description": "Please configure specific details for {platform} entity \"{entity}\":",
"data": { "data": {
"device_class": "Device class", "device_class": "Device class",
"entity_category": "Entity category",
"fan_feature_speed": "Speed support", "fan_feature_speed": "Speed support",
"fan_feature_preset_modes": "Preset modes support", "fan_feature_preset_modes": "Preset modes support",
"fan_feature_oscillation": "Oscillation support", "fan_feature_oscillation": "Oscillation support",
@@ -228,6 +227,7 @@
}, },
"data_description": { "data_description": {
"device_class": "The Device class of the {platform} entity. [Learn more.]({url}#device_class)", "device_class": "The Device class of the {platform} entity. [Learn more.]({url}#device_class)",
"entity_category": "Allow marking an entity as device configuration or diagnostics. An entity with a category will not be exposed to cloud, Alexa, or Google Assistant components, nor included in indirect action calls to devices or areas. Sensor entities cannot be assigned a device configiuration class. [Learn more.](https://developers.home-assistant.io/docs/core/entity/#registry-properties)",
"fan_feature_speed": "The fan supports multiple speeds.", "fan_feature_speed": "The fan supports multiple speeds.",
"fan_feature_preset_modes": "The fan supports preset modes.", "fan_feature_preset_modes": "The fan supports preset modes.",
"fan_feature_oscillation": "The fan supports oscillation.", "fan_feature_oscillation": "The fan supports oscillation.",
@@ -653,7 +653,6 @@
"options_not_allowed_with_state_class_or_uom": "The 'Options' setting is not allowed when state class or unit of measurement are used", "options_not_allowed_with_state_class_or_uom": "The 'Options' setting is not allowed when state class or unit of measurement are used",
"options_device_class_enum": "The 'Options' setting must be used with the Enumeration device class. If you continue, the existing options will be reset", "options_device_class_enum": "The 'Options' setting must be used with the Enumeration device class. If you continue, the existing options will be reset",
"options_with_enum_device_class": "Configure options for the enumeration sensor", "options_with_enum_device_class": "Configure options for the enumeration sensor",
"sensor_entity_category_must_not_be_config": "Sensor entities can not be categorized as configurable",
"uom_required_for_device_class": "The selected device class requires a unit" "uom_required_for_device_class": "The selected device class requires a unit"
} }
} }