Skip to content

Commit c27a67d

Browse files
authored
Do not add integration config entry to source device (home-assistant#148730)
1 parent 3ae9ea3 commit c27a67d

File tree

4 files changed

+216
-33
lines changed

4 files changed

+216
-33
lines changed

homeassistant/components/integration/__init__.py

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,29 @@
22

33
from __future__ import annotations
44

5+
import logging
6+
57
from homeassistant.config_entries import ConfigEntry
68
from homeassistant.const import Platform
79
from homeassistant.core import HomeAssistant
810
from homeassistant.helpers.device import (
911
async_entity_id_to_device_id,
1012
async_remove_stale_devices_links_keep_entity_device,
1113
)
12-
from homeassistant.helpers.helper_integration import async_handle_source_entity_changes
14+
from homeassistant.helpers.helper_integration import (
15+
async_handle_source_entity_changes,
16+
async_remove_helper_config_entry_from_source_device,
17+
)
1318

1419
from .const import CONF_SOURCE_SENSOR
1520

21+
_LOGGER = logging.getLogger(__name__)
22+
1623

1724
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
1825
"""Set up Integration from a config entry."""
1926

27+
# This can be removed in HA Core 2026.2
2028
async_remove_stale_devices_links_keep_entity_device(
2129
hass,
2230
entry.entry_id,
@@ -29,20 +37,16 @@ def set_source_entity_id_or_uuid(source_entity_id: str) -> None:
2937
options={**entry.options, CONF_SOURCE_SENSOR: source_entity_id},
3038
)
3139

32-
async def source_entity_removed() -> None:
33-
# The source entity has been removed, we need to clean the device links.
34-
async_remove_stale_devices_links_keep_entity_device(hass, entry.entry_id, None)
35-
3640
entry.async_on_unload(
3741
async_handle_source_entity_changes(
3842
hass,
43+
add_helper_config_entry_to_device=False,
3944
helper_config_entry_id=entry.entry_id,
4045
set_source_entity_id_or_uuid=set_source_entity_id_or_uuid,
4146
source_device_id=async_entity_id_to_device_id(
4247
hass, entry.options[CONF_SOURCE_SENSOR]
4348
),
4449
source_entity_id_or_uuid=entry.options[CONF_SOURCE_SENSOR],
45-
source_entity_removed=source_entity_removed,
4650
)
4751
)
4852

@@ -51,6 +55,40 @@ async def source_entity_removed() -> None:
5155
return True
5256

5357

58+
async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
59+
"""Migrate old entry."""
60+
_LOGGER.debug(
61+
"Migrating from version %s.%s", config_entry.version, config_entry.minor_version
62+
)
63+
64+
if config_entry.version > 1:
65+
# This means the user has downgraded from a future version
66+
return False
67+
if config_entry.version == 1:
68+
options = {**config_entry.options}
69+
if config_entry.minor_version < 2:
70+
# Remove the integration config entry from the source device
71+
if source_device_id := async_entity_id_to_device_id(
72+
hass, options[CONF_SOURCE_SENSOR]
73+
):
74+
async_remove_helper_config_entry_from_source_device(
75+
hass,
76+
helper_config_entry_id=config_entry.entry_id,
77+
source_device_id=source_device_id,
78+
)
79+
hass.config_entries.async_update_entry(
80+
config_entry, options=options, minor_version=2
81+
)
82+
83+
_LOGGER.debug(
84+
"Migration to version %s.%s successful",
85+
config_entry.version,
86+
config_entry.minor_version,
87+
)
88+
89+
return True
90+
91+
5492
async def config_entry_update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
5593
"""Update listener, called when the config entry options are changed."""
5694
# Remove device link for entry, the source device may have changed.

homeassistant/components/integration/config_flow.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ async def _get_config_schema(handler: SchemaCommonFlowHandler) -> vol.Schema:
147147
class ConfigFlowHandler(SchemaConfigFlowHandler, domain=DOMAIN):
148148
"""Handle a config or options flow for Integration."""
149149

150+
MINOR_VERSION = 2
151+
150152
config_flow = CONFIG_FLOW
151153
options_flow = OPTIONS_FLOW
152154

homeassistant/components/integration/sensor.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@
4040
callback,
4141
)
4242
from homeassistant.helpers import config_validation as cv, entity_registry as er
43-
from homeassistant.helpers.device import async_device_info_to_link_from_entity
44-
from homeassistant.helpers.device_registry import DeviceInfo
43+
from homeassistant.helpers.device import async_entity_id_to_device
4544
from homeassistant.helpers.entity_platform import (
4645
AddConfigEntryEntitiesCallback,
4746
AddEntitiesCallback,
@@ -246,11 +245,6 @@ async def async_setup_entry(
246245
registry, config_entry.options[CONF_SOURCE_SENSOR]
247246
)
248247

249-
device_info = async_device_info_to_link_from_entity(
250-
hass,
251-
source_entity_id,
252-
)
253-
254248
if (unit_prefix := config_entry.options.get(CONF_UNIT_PREFIX)) == "none":
255249
# Before we had support for optional selectors, "none" was used for selecting nothing
256250
unit_prefix = None
@@ -265,14 +259,14 @@ async def async_setup_entry(
265259
round_digits = int(round_digits)
266260

267261
integral = IntegrationSensor(
262+
hass,
268263
integration_method=config_entry.options[CONF_METHOD],
269264
name=config_entry.title,
270265
round_digits=round_digits,
271266
source_entity=source_entity_id,
272267
unique_id=config_entry.entry_id,
273268
unit_prefix=unit_prefix,
274269
unit_time=config_entry.options[CONF_UNIT_TIME],
275-
device_info=device_info,
276270
max_sub_interval=max_sub_interval,
277271
)
278272

@@ -287,6 +281,7 @@ async def async_setup_platform(
287281
) -> None:
288282
"""Set up the integration sensor."""
289283
integral = IntegrationSensor(
284+
hass,
290285
integration_method=config[CONF_METHOD],
291286
name=config.get(CONF_NAME),
292287
round_digits=config.get(CONF_ROUND_DIGITS),
@@ -308,6 +303,7 @@ class IntegrationSensor(RestoreSensor):
308303

309304
def __init__(
310305
self,
306+
hass: HomeAssistant,
311307
*,
312308
integration_method: str,
313309
name: str | None,
@@ -317,7 +313,6 @@ def __init__(
317313
unit_prefix: str | None,
318314
unit_time: UnitOfTime,
319315
max_sub_interval: timedelta | None,
320-
device_info: DeviceInfo | None = None,
321316
) -> None:
322317
"""Initialize the integration sensor."""
323318
self._attr_unique_id = unique_id
@@ -335,7 +330,10 @@ def __init__(
335330
self._attr_icon = "mdi:chart-histogram"
336331
self._source_entity: str = source_entity
337332
self._last_valid_state: Decimal | None = None
338-
self._attr_device_info = device_info
333+
self.device_entry = async_entity_id_to_device(
334+
hass,
335+
source_entity,
336+
)
339337
self._max_sub_interval: timedelta | None = (
340338
None # disable time based integration
341339
if max_sub_interval is None or max_sub_interval.total_seconds() == 0

0 commit comments

Comments
 (0)