From f0ec1235b1f65e985393ddeaea1df439849e3612 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Fri, 5 Jan 2024 09:32:22 +0100 Subject: [PATCH] Remove naming warnings and work-a-rounds for incorrectly configured MQTT entities (#107188) * Remove naming warnings for MQTT entities * Remove unused const --- homeassistant/components/mqtt/client.py | 25 ---------- homeassistant/components/mqtt/mixins.py | 54 +++------------------- homeassistant/components/mqtt/models.py | 1 - homeassistant/components/mqtt/strings.json | 8 ---- tests/components/mqtt/test_mixins.py | 29 ++++-------- 5 files changed, 15 insertions(+), 102 deletions(-) diff --git a/homeassistant/components/mqtt/client.py b/homeassistant/components/mqtt/client.py index c87d4c9244a..e9ef92ddbf8 100644 --- a/homeassistant/components/mqtt/client.py +++ b/homeassistant/components/mqtt/client.py @@ -35,7 +35,6 @@ from homeassistant.core import ( ) from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.dispatcher import dispatcher_send -from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue from homeassistant.helpers.typing import ConfigType from homeassistant.loader import bind_hass from homeassistant.util import dt as dt_util @@ -94,10 +93,6 @@ SUBSCRIBE_COOLDOWN = 0.1 UNSUBSCRIBE_COOLDOWN = 0.1 TIMEOUT_ACK = 10 -MQTT_ENTRIES_NAMING_BLOG_URL = ( - "https://developers.home-assistant.io/blog/2023-057-21-change-naming-mqtt-entities/" -) - SubscribePayloadType = str | bytes # Only bytes if encoding is None @@ -425,7 +420,6 @@ class MQTT: @callback def ha_started(_: Event) -> None: - self.register_naming_issues() self._ha_started.set() self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, ha_started) @@ -438,25 +432,6 @@ class MQTT: hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_stop_mqtt) ) - def register_naming_issues(self) -> None: - """Register issues with MQTT entity naming.""" - mqtt_data = get_mqtt_data(self.hass) - for issue_key, items in mqtt_data.issues.items(): - config_list = "\n".join([f"- {item}" for item in items]) - async_create_issue( - self.hass, - DOMAIN, - issue_key, - breaks_in_ha_version="2024.2.0", - is_fixable=False, - translation_key=issue_key, - translation_placeholders={ - "config": config_list, - }, - learn_more_url=MQTT_ENTRIES_NAMING_BLOG_URL, - severity=IssueSeverity.WARNING, - ) - def start( self, mqtt_data: MqttData, diff --git a/homeassistant/components/mqtt/mixins.py b/homeassistant/components/mqtt/mixins.py index 8047af17050..1cb12930b5a 100644 --- a/homeassistant/components/mqtt/mixins.py +++ b/homeassistant/components/mqtt/mixins.py @@ -1158,7 +1158,6 @@ class MqttEntity( _attr_should_poll = False _default_name: str | None _entity_id_format: str - _issue_key: str | None def __init__( self, @@ -1196,7 +1195,6 @@ class MqttEntity( @final async def async_added_to_hass(self) -> None: """Subscribe to MQTT events.""" - self.collect_issues() await super().async_added_to_hass() self._prepare_subscribe_topics() await self._subscribe_topics() @@ -1269,7 +1267,6 @@ class MqttEntity( def _set_entity_name(self, config: ConfigType) -> None: """Help setting the entity name if needed.""" - self._issue_key = None entity_name: str | None | UndefinedType = config.get(CONF_NAME, UNDEFINED) # Only set _attr_name if it is needed if entity_name is not UNDEFINED: @@ -1282,50 +1279,13 @@ class MqttEntity( # don't set the name attribute and derive # the name from the device_class delattr(self, "_attr_name") - if CONF_DEVICE in config: - device_name: str - if CONF_NAME not in config[CONF_DEVICE]: - _LOGGER.info( - "MQTT device information always needs to include a name, got %s, " - "if device information is shared between multiple entities, the device " - "name must be included in each entity's device configuration", - config, - ) - elif (device_name := config[CONF_DEVICE][CONF_NAME]) == entity_name: - self._attr_name = None - if not self._discovery: - self._issue_key = "entity_name_is_device_name_yaml" - _LOGGER.warning( - "MQTT device name is equal to entity name in your config %s, " - "this is not expected. Please correct your configuration. " - "The entity name will be set to `null`", - config, - ) - elif isinstance(entity_name, str) and entity_name.startswith(device_name): - self._attr_name = ( - new_entity_name := entity_name[len(device_name) :].lstrip() - ) - if device_name[:1].isupper(): - # Ensure a capital if the device name first char is a capital - new_entity_name = new_entity_name[:1].upper() + new_entity_name[1:] - if not self._discovery: - self._issue_key = "entity_name_startswith_device_name_yaml" - _LOGGER.warning( - "MQTT entity name starts with the device name in your config %s, " - "this is not expected. Please correct your configuration. " - "The device name prefix will be stripped off the entity name " - "and becomes '%s'", - config, - new_entity_name, - ) - - def collect_issues(self) -> None: - """Process issues for MQTT entities.""" - if self._issue_key is None: - return - mqtt_data = get_mqtt_data(self.hass) - issues = mqtt_data.issues.setdefault(self._issue_key, set()) - issues.add(self.entity_id) + if CONF_DEVICE in config and CONF_NAME not in config[CONF_DEVICE]: + _LOGGER.info( + "MQTT device information always needs to include a name, got %s, " + "if device information is shared between multiple entities, the device " + "name must be included in each entity's device configuration", + config, + ) def _setup_common_attributes_from_config(self, config: ConfigType) -> None: """(Re)Setup the common attributes for the entity.""" diff --git a/homeassistant/components/mqtt/models.py b/homeassistant/components/mqtt/models.py index 63b8d537170..0d009cf356b 100644 --- a/homeassistant/components/mqtt/models.py +++ b/homeassistant/components/mqtt/models.py @@ -339,7 +339,6 @@ class MqttData: ) discovery_unsubscribe: list[CALLBACK_TYPE] = field(default_factory=list) integration_unsubscribe: dict[str, CALLBACK_TYPE] = field(default_factory=dict) - issues: dict[str, set[str]] = field(default_factory=dict) last_discovery: float = 0.0 reload_dispatchers: list[CALLBACK_TYPE] = field(default_factory=list) reload_handlers: dict[str, CALLBACK_TYPE] = field(default_factory=dict) diff --git a/homeassistant/components/mqtt/strings.json b/homeassistant/components/mqtt/strings.json index 3194806a221..5cd7676115b 100644 --- a/homeassistant/components/mqtt/strings.json +++ b/homeassistant/components/mqtt/strings.json @@ -8,14 +8,6 @@ "title": "MQTT vacuum entities with legacy schema added through MQTT discovery", "description": "MQTT vacuum entities that use the legacy schema are deprecated, please adjust your devices to use the correct schema and restart Home Assistant to fix this issue." }, - "entity_name_is_device_name_yaml": { - "title": "Manual configured MQTT entities with a name that is equal to the device name", - "description": "Some MQTT entities have an entity name equal to the device name. This is not expected. The entity name is set to `null` as a work-a-round to avoid a duplicate name. Please update your configuration and restart Home Assistant to fix this issue.\n\nList of affected entities:\n\n{config}" - }, - "entity_name_startswith_device_name_yaml": { - "title": "Manual configured MQTT entities with a name that starts with the device name", - "description": "Some MQTT entities have an entity name that starts with the device name. This is not expected. To avoid a duplicate name the device name prefix is stripped off the entity name as a work-a-round. Please update your configuration and restart Home Assistant to fix this issue. \n\nList of affected entities:\n\n{config}" - }, "deprecated_climate_aux_property": { "title": "MQTT entities with auxiliary heat support found", "description": "Entity `{entity_id}` has auxiliary heat support enabled, which has been deprecated for MQTT climate devices. Please adjust your configuration and remove deprecated config options from your configuration and restart Home Assistant to fix this issue." diff --git a/tests/components/mqtt/test_mixins.py b/tests/components/mqtt/test_mixins.py index 7a625a2f5f6..3c25d419cfe 100644 --- a/tests/components/mqtt/test_mixins.py +++ b/tests/components/mqtt/test_mixins.py @@ -89,7 +89,6 @@ async def test_availability_with_shared_state_topic( "friendly_name", "device_name", "assert_log", - "issue_events", ), [ ( # default_entity_name_without_device_name @@ -106,7 +105,6 @@ async def test_availability_with_shared_state_topic( DEFAULT_SENSOR_NAME, None, True, - 0, ), ( # default_entity_name_with_device_name { @@ -122,7 +120,6 @@ async def test_availability_with_shared_state_topic( "Test MQTT Sensor", "Test", False, - 0, ), ( # name_follows_device_class { @@ -139,7 +136,6 @@ async def test_availability_with_shared_state_topic( "Test Humidity", "Test", False, - 0, ), ( # name_follows_device_class_without_device_name { @@ -156,7 +152,6 @@ async def test_availability_with_shared_state_topic( "Humidity", None, True, - 0, ), ( # name_overrides_device_class { @@ -174,7 +169,6 @@ async def test_availability_with_shared_state_topic( "Test MySensor", "Test", False, - 0, ), ( # name_set_no_device_name_set { @@ -192,7 +186,6 @@ async def test_availability_with_shared_state_topic( "MySensor", None, True, - 0, ), ( # none_entity_name_with_device_name { @@ -210,7 +203,6 @@ async def test_availability_with_shared_state_topic( "Test", "Test", False, - 0, ), ( # none_entity_name_without_device_name { @@ -228,7 +220,6 @@ async def test_availability_with_shared_state_topic( "mqtt veryunique", None, True, - 0, ), ( # entity_name_and_device_name_the_same { @@ -245,11 +236,10 @@ async def test_availability_with_shared_state_topic( } } }, - "sensor.hello_world", - "Hello world", + "sensor.hello_world_hello_world", + "Hello world Hello world", "Hello world", False, - 1, ), ( # entity_name_startswith_device_name1 { @@ -266,11 +256,10 @@ async def test_availability_with_shared_state_topic( } } }, - "sensor.world_automation", - "World automation", + "sensor.world_world_automation", + "World World automation", "World", False, - 1, ), ( # entity_name_startswith_device_name2 { @@ -287,11 +276,10 @@ async def test_availability_with_shared_state_topic( } } }, - "sensor.world_automation", - "world automation", + "sensor.world_world_automation", + "world world automation", "world", False, - 1, ), ], ids=[ @@ -320,7 +308,6 @@ async def test_default_entity_and_device_name( friendly_name: str, device_name: str | None, assert_log: bool, - issue_events: int, ) -> None: """Test device name setup with and without a device_class set. @@ -349,8 +336,8 @@ async def test_default_entity_and_device_name( "MQTT device information always needs to include a name" in caplog.text ) is assert_log - # Assert that an issues ware registered - assert len(events) == issue_events + # Assert that no issues ware registered + assert len(events) == 0 @patch("homeassistant.components.mqtt.PLATFORMS", [Platform.BINARY_SENSOR])