mirror of
https://github.com/home-assistant/core
synced 2024-08-28 03:36:46 +02:00
Remove naming warnings and work-a-rounds for incorrectly configured MQTT entities (#107188)
* Remove naming warnings for MQTT entities * Remove unused const
This commit is contained in:
parent
8c4a29c200
commit
f0ec1235b1
@ -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,
|
||||
|
@ -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."""
|
||||
|
@ -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)
|
||||
|
@ -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."
|
||||
|
@ -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])
|
||||
|
Loading…
Reference in New Issue
Block a user