Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit cde5961

Browse files
Refactor eheimdigital platform async_setup_entry (home-assistant#136745)
1 parent d83c335 commit cde5961

File tree

5 files changed

+148
-24
lines changed

5 files changed

+148
-24
lines changed

‎homeassistant/components/eheimdigital/climate.py‎

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import Any
44

5+
from eheimdigital.device import EheimDigitalDevice
56
from eheimdigital.heater import EheimDigitalHeater
67
from eheimdigital.types import EheimDigitalClientError, HeaterMode, HeaterUnit
78

@@ -39,17 +40,23 @@ async def async_setup_entry(
3940
"""Set up the callbacks for the coordinator so climate entities can be added as devices are found."""
4041
coordinator = entry.runtime_data
4142

42-
async def async_setup_device_entities(device_address: str) -> None:
43-
"""Set up the light entities for a device."""
44-
device = coordinator.hub.devices[device_address]
43+
def async_setup_device_entities(
44+
device_address: str | dict[str, EheimDigitalDevice],
45+
) -> None:
46+
"""Set up the climate entities for one or multiple devices."""
47+
entities: list[EheimDigitalHeaterClimate] = []
48+
if isinstance(device_address, str):
49+
device_address = {device_address: coordinator.hub.devices[device_address]}
50+
for device in device_address.values():
51+
if isinstance(device, EheimDigitalHeater):
52+
entities.append(EheimDigitalHeaterClimate(coordinator, device))
53+
coordinator.known_devices.add(device.mac_address)
4554

46-
if isinstance(device, EheimDigitalHeater):
47-
async_add_entities([EheimDigitalHeaterClimate(coordinator, device)])
55+
async_add_entities(entities)
4856

4957
coordinator.add_platform_callback(async_setup_device_entities)
5058

51-
for device_address in entry.runtime_data.hub.devices:
52-
await async_setup_device_entities(device_address)
59+
async_setup_device_entities(coordinator.hub.devices)
5360

5461

5562
class EheimDigitalHeaterClimate(EheimDigitalEntity[EheimDigitalHeater], ClimateEntity):

‎homeassistant/components/eheimdigital/coordinator.py‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
from __future__ import annotations
44

5-
from collections.abc import Callable, Coroutine
6-
from typing import Any
5+
from collections.abc import Callable
76

87
from aiohttp import ClientError
98
from eheimdigital.device import EheimDigitalDevice
@@ -19,7 +18,9 @@
1918

2019
from .const import DOMAIN, LOGGER
2120

22-
type AsyncSetupDeviceEntitiesCallback = Callable[[str], Coroutine[Any, Any, None]]
21+
type AsyncSetupDeviceEntitiesCallback = Callable[
22+
[str | dict[str, EheimDigitalDevice]], None
23+
]
2324

2425

2526
class EheimDigitalUpdateCoordinator(
@@ -61,7 +62,7 @@ async def _async_device_found(
6162

6263
if device_address not in self.known_devices:
6364
for platform_callback in self.platform_callbacks:
64-
awaitplatform_callback(device_address)
65+
platform_callback(device_address)
6566

6667
async def _async_receive_callback(self) -> None:
6768
self.async_set_updated_data(self.hub.devices)

‎homeassistant/components/eheimdigital/light.py‎

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from typing import Any
44

55
from eheimdigital.classic_led_ctrl import EheimDigitalClassicLEDControl
6+
from eheimdigital.device import EheimDigitalDevice
67
from eheimdigital.types import EheimDigitalClientError, LightMode
78

89
from homeassistant.components.light import (
@@ -37,24 +38,28 @@ async def async_setup_entry(
3738
"""Set up the callbacks for the coordinator so lights can be added as devices are found."""
3839
coordinator = entry.runtime_data
3940

40-
async def async_setup_device_entities(device_address: str) -> None:
41-
"""Set up the light entities for a device."""
42-
device = coordinator.hub.devices[device_address]
41+
def async_setup_device_entities(
42+
device_address: str | dict[str, EheimDigitalDevice],
43+
) -> None:
44+
"""Set up the light entities for one or multiple devices."""
4345
entities: list[EheimDigitalClassicLEDControlLight] = []
46+
if isinstance(device_address, str):
47+
device_address = {device_address: coordinator.hub.devices[device_address]}
48+
for device in device_address.values():
49+
if isinstance(device, EheimDigitalClassicLEDControl):
50+
for channel in range(2):
51+
if len(device.tankconfig[channel]) > 0:
52+
entities.append(
53+
EheimDigitalClassicLEDControlLight(
54+
coordinator, device, channel
55+
)
56+
)
57+
coordinator.known_devices.add(device.mac_address)
4458

45-
if isinstance(device, EheimDigitalClassicLEDControl):
46-
for channel in range(2):
47-
if len(device.tankconfig[channel]) > 0:
48-
entities.append(
49-
EheimDigitalClassicLEDControlLight(coordinator, device, channel)
50-
)
51-
coordinator.known_devices.add(device.mac_address)
5259
async_add_entities(entities)
5360

5461
coordinator.add_platform_callback(async_setup_device_entities)
55-
56-
for device_address in entry.runtime_data.hub.devices:
57-
await async_setup_device_entities(device_address)
62+
async_setup_device_entities(coordinator.hub.devices)
5863

5964

6065
class EheimDigitalClassicLEDControlLight(

‎tests/components/eheimdigital/snapshots/test_climate.ambr‎

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,80 @@
11
# serializer version: 1
2+
# name: test_dynamic_new_devices[climate.mock_heater_none-entry]
3+
EntityRegistryEntrySnapshot({
4+
'aliases': set({
5+
}),
6+
'area_id': None,
7+
'capabilities': dict({
8+
'hvac_modes': list([
9+
<HVACMode.OFF: 'off'>,
10+
<HVACMode.AUTO: 'auto'>,
11+
]),
12+
'max_temp': 32,
13+
'min_temp': 18,
14+
'preset_modes': list([
15+
'none',
16+
'bio_mode',
17+
'smart_mode',
18+
]),
19+
'target_temp_step': 0.5,
20+
}),
21+
'config_entry_id': <ANY>,
22+
'device_class': None,
23+
'device_id': <ANY>,
24+
'disabled_by': None,
25+
'domain': 'climate',
26+
'entity_category': None,
27+
'entity_id': 'climate.mock_heater_none',
28+
'has_entity_name': True,
29+
'hidden_by': None,
30+
'icon': None,
31+
'id': <ANY>,
32+
'labels': set({
33+
}),
34+
'name': None,
35+
'options': dict({
36+
}),
37+
'original_device_class': None,
38+
'original_icon': None,
39+
'original_name': None,
40+
'platform': 'eheimdigital',
41+
'previous_unique_id': None,
42+
'supported_features': <ClimateEntityFeature: 401>,
43+
'translation_key': 'heater',
44+
'unique_id': '00:00:00:00:00:02',
45+
'unit_of_measurement': None,
46+
})
47+
# ---
48+
# name: test_dynamic_new_devices[climate.mock_heater_none-state]
49+
StateSnapshot({
50+
'attributes': ReadOnlyDict({
51+
'current_temperature': 24.2,
52+
'friendly_name': 'Mock Heater None',
53+
'hvac_action': <HVACAction.HEATING: 'heating'>,
54+
'hvac_modes': list([
55+
<HVACMode.OFF: 'off'>,
56+
<HVACMode.AUTO: 'auto'>,
57+
]),
58+
'max_temp': 32,
59+
'min_temp': 18,
60+
'preset_mode': 'none',
61+
'preset_modes': list([
62+
'none',
63+
'bio_mode',
64+
'smart_mode',
65+
]),
66+
'supported_features': <ClimateEntityFeature: 401>,
67+
'target_temp_step': 0.5,
68+
'temperature': 25.5,
69+
}),
70+
'context': <ANY>,
71+
'entity_id': 'climate.mock_heater_none',
72+
'last_changed': <ANY>,
73+
'last_reported': <ANY>,
74+
'last_updated': <ANY>,
75+
'state': 'auto',
76+
})
77+
# ---
278
# name: test_setup_heater[climate.mock_heater_none-entry]
379
EntityRegistryEntrySnapshot({
480
'aliases': set({

‎tests/components/eheimdigital/test_climate.py‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,41 @@ async def test_setup_heater(
5656
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
5757

5858

59+
async def test_dynamic_new_devices(
60+
hass: HomeAssistant,
61+
eheimdigital_hub_mock: MagicMock,
62+
heater_mock: MagicMock,
63+
entity_registry: er.EntityRegistry,
64+
snapshot: SnapshotAssertion,
65+
mock_config_entry: MockConfigEntry,
66+
) -> None:
67+
"""Test light platform setup with at first no devices and dynamically adding a device."""
68+
mock_config_entry.add_to_hass(hass)
69+
70+
eheimdigital_hub_mock.return_value.devices = {}
71+
72+
with patch("homeassistant.components.eheimdigital.PLATFORMS", [Platform.CLIMATE]):
73+
await hass.config_entries.async_setup(mock_config_entry.entry_id)
74+
75+
assert (
76+
len(
77+
entity_registry.entities.get_entries_for_config_entry_id(
78+
mock_config_entry.entry_id
79+
)
80+
)
81+
== 0
82+
)
83+
84+
eheimdigital_hub_mock.return_value.devices = {"00:00:00:00:00:02": heater_mock}
85+
86+
await eheimdigital_hub_mock.call_args.kwargs["device_found_callback"](
87+
"00:00:00:00:00:02", EheimDeviceType.VERSION_EHEIM_EXT_HEATER
88+
)
89+
await hass.async_block_till_done()
90+
91+
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
92+
93+
5994
@pytest.mark.parametrize(
6095
("preset_mode", "heater_mode"),
6196
[

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /