Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions homeassistant/components/mqtt/abbreviations.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"curr_hum_tpl": "current_humidity_template",
"curr_temp_t": "current_temperature_topic",
"curr_temp_tpl": "current_temperature_template",
"def_ent_id": "default_entity_id",
"dev": "device",
"dev_cla": "device_class",
"dir_cmd_t": "direction_command_topic",
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/mqtt/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
CONF_CODE_TRIGGER_REQUIRED = "code_trigger_required"
CONF_COMMAND_TEMPLATE = "command_template"
CONF_COMMAND_TOPIC = "command_topic"
CONF_DEFAULT_ENTITY_ID = "default_entity_id"
CONF_DISCOVERY_PREFIX = "discovery_prefix"
CONF_ENCODING = "encoding"
CONF_JSON_ATTRS_TOPIC = "json_attributes_topic"
Expand Down
59 changes: 56 additions & 3 deletions homeassistant/components/mqtt/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
CONF_MODEL_ID,
CONF_NAME,
CONF_UNIQUE_ID,
CONF_URL,
CONF_VALUE_TEMPLATE,
)
from homeassistant.core import Event, HassJobType, HomeAssistant, callback
Expand Down Expand Up @@ -74,6 +75,7 @@
CONF_AVAILABILITY_TOPIC,
CONF_CONFIGURATION_URL,
CONF_CONNECTIONS,
CONF_DEFAULT_ENTITY_ID,
CONF_ENABLED_BY_DEFAULT,
CONF_ENCODING,
CONF_ENTITY_PICTURE,
Expand All @@ -83,6 +85,7 @@
CONF_JSON_ATTRS_TOPIC,
CONF_MANUFACTURER,
CONF_OBJECT_ID,
CONF_ORIGIN,
CONF_PAYLOAD_AVAILABLE,
CONF_PAYLOAD_NOT_AVAILABLE,
CONF_QOS,
Expand Down Expand Up @@ -1406,12 +1409,62 @@ def __init__(
ensure_via_device_exists(self.hass, self.device_info, self._config_entry)

def _init_entity_id(self) -> None:
"""Set entity_id from object_id if defined in config."""
if CONF_OBJECT_ID not in self._config:
"""Set entity_id from default_entity_id if defined in config."""
object_id: str
default_entity_id: str | None
# Setting the default entity_id through the CONF_OBJECT_ID is deprecated
# Support will be removed with HA Core 2026.4
if (
CONF_DEFAULT_ENTITY_ID not in self._config
and CONF_OBJECT_ID not in self._config
):
return
if (default_entity_id := self._config.get(CONF_DEFAULT_ENTITY_ID)) is None:
object_id = self._config[CONF_OBJECT_ID]
else:
_, _, object_id = default_entity_id.partition(".")
self.entity_id = async_generate_entity_id(
self._entity_id_format, self._config[CONF_OBJECT_ID], None, self.hass
self._entity_id_format, object_id, None, self.hass
)
if CONF_OBJECT_ID in self._config:
domain = self.entity_id.split(".")[0]
if not self._discovery:
async_create_issue(
self.hass,
DOMAIN,
self.entity_id,
issue_domain=DOMAIN,
is_fixable=False,
breaks_in_ha_version="2026.4",
severity=IssueSeverity.WARNING,
learn_more_url=f"{learn_more_url(domain)}#default_enity_id",
translation_placeholders={
"entity_id": self.entity_id,
"object_id": self._config[CONF_OBJECT_ID],
"domain": domain,
},
translation_key="deprecated_object_id",
)
else:
if CONF_ORIGIN in self._config:
origin_name = self._config[CONF_ORIGIN][CONF_NAME]
url = self._config[CONF_ORIGIN].get(CONF_URL)
origin = f"[{origin_name}]({url})" if url else origin_name
else:
origin = "the integration"
_LOGGER.warning(
"The configuration for entity %s uses the deprecated option "
"`object_id` to set the default entity id. Replace the "
'`"object_id": "%s"` option with `"default_entity_id": '
'"%s"` in your published discovery configuration to fix this '
"issue, or contact the maintainer of %s that published this config "
"to fix this. This will stop working in Home Assistant Core 2026.4",
self.entity_id,
self._config[CONF_OBJECT_ID],
f"{domain}.{self._config[CONF_OBJECT_ID]}",
origin,
)

if self.unique_id is None:
return
# Check for previous deleted entities
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/mqtt/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
CONF_COMPONENTS,
CONF_CONFIGURATION_URL,
CONF_CONNECTIONS,
CONF_DEFAULT_ENTITY_ID,
CONF_DEPRECATED_VIA_HUB,
CONF_ENABLED_BY_DEFAULT,
CONF_ENCODING,
Expand Down Expand Up @@ -180,6 +181,7 @@ def validate_device_has_at_least_one_identifier(value: ConfigType) -> ConfigType
vol.Optional(CONF_ICON): cv.icon,
vol.Optional(CONF_JSON_ATTRS_TOPIC): valid_subscribe_topic,
vol.Optional(CONF_JSON_ATTRS_TEMPLATE): cv.template,
vol.Optional(CONF_DEFAULT_ENTITY_ID): cv.string,
vol.Optional(CONF_OBJECT_ID): cv.string,
vol.Optional(CONF_UNIQUE_ID): cv.string,
}
Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/mqtt/strings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{
"issues": {
"deprecated_object_id": {
"title": "Deprecated option object_id used",
"description": "Entity {entity_id} uses the `object_id` option which deprecated. To fix the issue, replace the `object_id: {object_id}` option with `default_entity_id: {domain}.{object_id}` in your \"configuration.yaml\", and restart Home Assistant."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"is" missing -> "… which is deprecated. …"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

},
"deprecated_vacuum_battery_feature": {
"title": "Deprecated battery feature used",
"description": "Vacuum entity {entity_id} implements the battery feature which is deprecated. This will stop working in Home Assistant 2026.2. Implement a separate entity for the battery state instead. To fix the issue, remove the `battery` feature from the configured supported features, and restart Home Assistant."
Expand Down
2 changes: 1 addition & 1 deletion tests/components/mqtt/test_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
button.DOMAIN: {
"command_topic": "command-topic",
"name": "test",
"object_id": "test_button",
"default_entity_id": "button.test_button",
"payload_press": "beer press",
"qos": "2",
}
Expand Down
52 changes: 47 additions & 5 deletions tests/components/mqtt/test_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -1473,6 +1473,48 @@ async def test_discover_alarm_control_panel(
"Hello World 19",
"device_tracker",
),
(
"homeassistant/binary_sensor/object/bla/config",
'{ "name": "Hello World 2", "obj_id": "hello_id", '
'"o": {"name": "X2mqtt"}, "state_topic": "test-topic" }',
"binary_sensor.hello_id",
"Hello World 2",
"binary_sensor",
),
(
"homeassistant/button/object/bla/config",
'{ "name": "Hello World button", "obj_id": "hello_id", '
'"o": {"name": "X2mqtt", "url": "https://example.com/x2mqtt"}, '
'"command_topic": "test-topic" }',
"button.hello_id",
"Hello World button",
"button",
),
(
"homeassistant/alarm_control_panel/object/bla/config",
'{ "name": "Hello World 1", "def_ent_id": "alarm_control_panel.hello_id", '
'"state_topic": "test-topic", "command_topic": "test-topic" }',
"alarm_control_panel.hello_id",
"Hello World 1",
"alarm_control_panel",
),
(
"homeassistant/binary_sensor/object/bla/config",
'{ "name": "Hello World 2", "def_ent_id": "binary_sensor.hello_id", '
'"o": {"name": "X2mqtt"}, "state_topic": "test-topic" }',
"binary_sensor.hello_id",
"Hello World 2",
"binary_sensor",
),
(
"homeassistant/button/object/bla/config",
'{ "name": "Hello World button", "def_ent_id": "button.hello_id", '
'"o": {"name": "X2mqtt", "url": "https://example.com/x2mqtt"}, '
'"command_topic": "test-topic" }',
"button.hello_id",
"Hello World button",
"button",
),
],
)
async def test_discovery_with_object_id(
Expand All @@ -1496,20 +1538,20 @@ async def test_discovery_with_object_id(
assert (domain, "object bla") in hass.data["mqtt"].discovery_already_discovered


async def test_discovery_with_object_id_for_previous_deleted_entity(
async def test_discovery_with_default_entity_id_for_previous_deleted_entity(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
) -> None:
"""Test discovering an MQTT entity with object_id and unique_id."""
"""Test discovering an MQTT entity with default_entity_id and unique_id."""

topic = "homeassistant/sensor/object/bla/config"
config = (
'{ "name": "Hello World 11", "unique_id": "very_unique", '
'"obj_id": "hello_id", "state_topic": "test-topic" }'
'"def_ent_id": "sensor.hello_id", "state_topic": "test-topic" }'
)
new_config = (
'{ "name": "Hello World 11", "unique_id": "very_unique", '
'"obj_id": "updated_hello_id", "state_topic": "test-topic" }'
'"def_ent_id": "sensor.updated_hello_id", "state_topic": "test-topic" }'
)
initial_entity_id = "sensor.hello_id"
new_entity_id = "sensor.updated_hello_id"
Expand All @@ -1531,7 +1573,7 @@ async def test_discovery_with_object_id_for_previous_deleted_entity(
await hass.async_block_till_done()
assert (domain, "object bla") not in hass.data["mqtt"].discovery_already_discovered

# Rediscover with new object_id
# Rediscover with new default_entity_id
async_fire_mqtt_message(hass, topic, new_config)
await hass.async_block_till_done()

Expand Down
40 changes: 37 additions & 3 deletions tests/components/mqtt/test_mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ async def test_name_attribute_is_set_or_not(
hass,
"homeassistant/binary_sensor/bla/config",
'{ "name": "Gate", "state_topic": "test-topic", "device_class": "door", '
'"object_id": "gate",'
'"default_entity_id": "binary_sensor.gate",'
'"device": {"identifiers": "very_unique", "name": "xyz_door_sensor"}'
"}",
)
Expand All @@ -384,7 +384,7 @@ async def test_name_attribute_is_set_or_not(
hass,
"homeassistant/binary_sensor/bla/config",
'{ "state_topic": "test-topic", "device_class": "door", '
'"object_id": "gate",'
'"default_entity_id": "binary_sensor.gate",'
'"device": {"identifiers": "very_unique", "name": "xyz_door_sensor"}'
"}",
)
Expand All @@ -400,7 +400,7 @@ async def test_name_attribute_is_set_or_not(
hass,
"homeassistant/binary_sensor/bla/config",
'{ "name": null, "state_topic": "test-topic", "device_class": "door", '
'"object_id": "gate",'
'"default_entity_id": "binary_sensor.gate",'
'"device": {"identifiers": "very_unique", "name": "xyz_door_sensor"}'
"}",
)
Expand Down Expand Up @@ -468,6 +468,40 @@ async def test_value_template_fails(
)


@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
sensor.DOMAIN: {
"name": "test",
"state_topic": "test-topic",
"object_id": "test",
}
}
},
],
)
async def test_deprecated_option_object_id_is_used_in_yaml(
hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator
) -> None:
"""Test issue registry in case the deprecated option object_id was used in YAML."""
await mqtt_mock_entry()
await hass.async_block_till_done()

state = hass.states.get("sensor.test")
assert state is not None

issue_registry = ir.async_get(hass)
issue = issue_registry.async_get_issue(mqtt.DOMAIN, "sensor.test")
assert issue is not None
assert issue.translation_placeholders == {
"entity_id": "sensor.test",
"object_id": "test",
"domain": "sensor",
}


@pytest.mark.parametrize(
"mqtt_config_subentries_data",
[
Expand Down
2 changes: 1 addition & 1 deletion tests/components/mqtt/test_notify.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
notify.DOMAIN: {
"command_topic": "command-topic",
"name": "test",
"object_id": "test_notify",
"default_entity_id": "notify.test_notify",
"qos": "2",
}
}
Expand Down