diff --git a/homeassistant/components/mqtt/config_flow.py b/homeassistant/components/mqtt/config_flow.py index 9ce10826250..15f3f647c84 100644 --- a/homeassistant/components/mqtt/config_flow.py +++ b/homeassistant/components/mqtt/config_flow.py @@ -439,6 +439,15 @@ BINARY_SENSOR_DEVICE_CLASS_SELECTOR = SelectSelector( 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( SelectSelectorConfig( 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 -@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 def validate_sensor_platform_config( config: dict[str, Any], @@ -670,9 +667,6 @@ def validate_sensor_platform_config( ): 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 @@ -755,14 +749,17 @@ COMMON_ENTITY_FIELDS: dict[str, PlatformField] = { exclude_from_reconfig=True, 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( selector=ENTITY_CATEGORY_SELECTOR, required=False, 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]] = { @@ -771,6 +768,11 @@ PLATFORM_ENTITY_FIELDS: dict[str, dict[str, PlatformField]] = { selector=BINARY_SENSOR_DEVICE_CLASS_SELECTOR, required=False, ), + CONF_ENTITY_CATEGORY: PlatformField( + selector=SENSOR_ENTITY_CATEGORY_SELECTOR, + required=False, + default=None, + ), }, Platform.BUTTON.value: { CONF_DEVICE_CLASS: PlatformField( @@ -834,6 +836,11 @@ PLATFORM_ENTITY_FIELDS: dict[str, dict[str, PlatformField]] = { required=False, conditions=({"device_class": "enum"},), ), + CONF_ENTITY_CATEGORY: PlatformField( + selector=SENSOR_ENTITY_CATEGORY_SELECTOR, + required=False, + default=None, + ), }, Platform.SWITCH.value: { CONF_DEVICE_CLASS: PlatformField( @@ -1885,7 +1892,7 @@ ENTITY_CONFIG_VALIDATOR: dict[ str, 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.COVER.value: validate_cover_platform_config, Platform.FAN.value: validate_fan_platform_config, @@ -2025,12 +2032,13 @@ def validate_user_input( ) if config_validator is not None: + if TYPE_CHECKING: + assert component_data is not None + errors |= config_validator( - merged_user_input - if component_data is None - else calculate_merged_config( + calculate_merged_config( merged_user_input, data_schema_fields, component_data - ) + ), ) return merged_user_input, errors @@ -2780,16 +2788,8 @@ class MQTTSubentryFlowHandler(ConfigSubentryFlow): entity_name_label = f" ({name})" if name is not None else "" data_schema = data_schema_from_fields(data_schema_fields, reconfig=reconfig) 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( - user_input, - data_schema_fields, - component_data=component_data, - config_validator=ENTITY_CONFIG_VALIDATOR[platform], + user_input, data_schema_fields, component_data=component_data ) if not errors: if self._component_id is None: @@ -2871,7 +2871,9 @@ class MQTTSubentryFlowHandler(ConfigSubentryFlow): assert self._component_id is not None component_data = self._subentry_data["components"][self._component_id] 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] = {} data_schema = data_schema_from_fields( @@ -2977,6 +2979,7 @@ class MQTTSubentryFlowHandler(ConfigSubentryFlow): platform = component_data[CONF_PLATFORM] platform_fields: dict[str, PlatformField] = ( COMMON_ENTITY_FIELDS + | SHARED_PLATFORM_ENTITY_FIELDS | PLATFORM_ENTITY_FIELDS[platform] | PLATFORM_MQTT_FIELDS[platform] ) diff --git a/homeassistant/components/mqtt/strings.json b/homeassistant/components/mqtt/strings.json index 8fcc429dfa2..a132fdc27d8 100644 --- a/homeassistant/components/mqtt/strings.json +++ b/homeassistant/components/mqtt/strings.json @@ -181,13 +181,11 @@ "data": { "platform": "Type of entity", "name": "Entity name", - "entity_category": "Entity category", "entity_picture": "Entity picture" }, "data_description": { "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).", - "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." } }, @@ -216,6 +214,7 @@ "description": "Please configure specific details for {platform} entity \"{entity}\":", "data": { "device_class": "Device class", + "entity_category": "Entity category", "fan_feature_speed": "Speed support", "fan_feature_preset_modes": "Preset modes support", "fan_feature_oscillation": "Oscillation support", @@ -228,6 +227,7 @@ }, "data_description": { "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_preset_modes": "The fan supports preset modes.", "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_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", - "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" } }