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 dbc38cd

Browse files
autinerdjoostlek
andauthored
Add switch platform to eheimdigital (home-assistant#142412)
* Add switch platform to eheimdigital * docstring fixes * Review * Review --------- Co-authored-by: Joostlek <joostlek@outlook.com>
1 parent 102d55e commit dbc38cd

File tree

5 files changed

+232
-0
lines changed

5 files changed

+232
-0
lines changed

‎homeassistant/components/eheimdigital/__init__.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Platform.LIGHT,
1515
Platform.NUMBER,
1616
Platform.SENSOR,
17+
Platform.SWITCH,
1718
Platform.TIME,
1819
]
1920

‎homeassistant/components/eheimdigital/icons.json‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@
3131
}
3232
}
3333
},
34+
"switch": {
35+
"filter_active": {
36+
"default": "mdi:pump",
37+
"state": {
38+
"off": "mdi:pump-off"
39+
}
40+
}
41+
},
3442
"time": {
3543
"day_start_time": {
3644
"default": "mdi:weather-sunny"
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
"""EHEIM Digital switches."""
2+
3+
from typing import Any, override
4+
5+
from eheimdigital.classic_vario import EheimDigitalClassicVario
6+
from eheimdigital.device import EheimDigitalDevice
7+
8+
from homeassistant.components.switch import SwitchEntity
9+
from homeassistant.core import HomeAssistant
10+
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
11+
12+
from .coordinator import EheimDigitalConfigEntry, EheimDigitalUpdateCoordinator
13+
from .entity import EheimDigitalEntity
14+
15+
# Coordinator is used to centralize the data updates
16+
PARALLEL_UPDATES = 0
17+
18+
19+
async def async_setup_entry(
20+
hass: HomeAssistant,
21+
entry: EheimDigitalConfigEntry,
22+
async_add_entities: AddConfigEntryEntitiesCallback,
23+
) -> None:
24+
"""Set up the callbacks for the coordinator so switches can be added as devices are found."""
25+
coordinator = entry.runtime_data
26+
27+
def async_setup_device_entities(
28+
device_address: dict[str, EheimDigitalDevice],
29+
) -> None:
30+
"""Set up the switch entities for one or multiple devices."""
31+
entities: list[SwitchEntity] = []
32+
for device in device_address.values():
33+
if isinstance(device, EheimDigitalClassicVario):
34+
entities.append(EheimDigitalClassicVarioSwitch(coordinator, device)) # noqa: PERF401
35+
36+
async_add_entities(entities)
37+
38+
coordinator.add_platform_callback(async_setup_device_entities)
39+
async_setup_device_entities(coordinator.hub.devices)
40+
41+
42+
class EheimDigitalClassicVarioSwitch(
43+
EheimDigitalEntity[EheimDigitalClassicVario], SwitchEntity
44+
):
45+
"""Represent an EHEIM Digital classicVARIO switch entity."""
46+
47+
_attr_translation_key = "filter_active"
48+
_attr_name = None
49+
50+
def __init__(
51+
self,
52+
coordinator: EheimDigitalUpdateCoordinator,
53+
device: EheimDigitalClassicVario,
54+
) -> None:
55+
"""Initialize an EHEIM Digital classicVARIO switch entity."""
56+
super().__init__(coordinator, device)
57+
self._attr_unique_id = device.mac_address
58+
self._async_update_attrs()
59+
60+
@override
61+
async def async_turn_off(self, **kwargs: Any) -> None:
62+
await self._device.set_active(active=False)
63+
64+
@override
65+
async def async_turn_on(self, **kwargs: Any) -> None:
66+
await self._device.set_active(active=True)
67+
68+
@override
69+
def _async_update_attrs(self) -> None:
70+
self._attr_is_on = self._device.is_active
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# serializer version: 1
2+
# name: test_setup_classic_vario[switch.mock_classicvario-entry]
3+
EntityRegistryEntrySnapshot({
4+
'aliases': set({
5+
}),
6+
'area_id': None,
7+
'capabilities': None,
8+
'config_entry_id': <ANY>,
9+
'config_subentry_id': <ANY>,
10+
'device_class': None,
11+
'device_id': <ANY>,
12+
'disabled_by': None,
13+
'domain': 'switch',
14+
'entity_category': None,
15+
'entity_id': 'switch.mock_classicvario',
16+
'has_entity_name': True,
17+
'hidden_by': None,
18+
'icon': None,
19+
'id': <ANY>,
20+
'labels': set({
21+
}),
22+
'name': None,
23+
'options': dict({
24+
}),
25+
'original_device_class': None,
26+
'original_icon': None,
27+
'original_name': None,
28+
'platform': 'eheimdigital',
29+
'previous_unique_id': None,
30+
'supported_features': 0,
31+
'translation_key': 'filter_active',
32+
'unique_id': '00:00:00:00:00:03',
33+
'unit_of_measurement': None,
34+
})
35+
# ---
36+
# name: test_setup_classic_vario[switch.mock_classicvario-state]
37+
StateSnapshot({
38+
'attributes': ReadOnlyDict({
39+
'friendly_name': 'Mock classicVARIO',
40+
}),
41+
'context': <ANY>,
42+
'entity_id': 'switch.mock_classicvario',
43+
'last_changed': <ANY>,
44+
'last_reported': <ANY>,
45+
'last_updated': <ANY>,
46+
'state': 'on',
47+
})
48+
# ---
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
"""Tests for the switch module."""
2+
3+
from unittest.mock import AsyncMock, MagicMock, patch
4+
5+
from eheimdigital.types import EheimDeviceType
6+
import pytest
7+
from syrupy.assertion import SnapshotAssertion
8+
9+
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
10+
from homeassistant.const import (
11+
ATTR_ENTITY_ID,
12+
SERVICE_TURN_OFF,
13+
SERVICE_TURN_ON,
14+
STATE_OFF,
15+
STATE_ON,
16+
Platform,
17+
)
18+
from homeassistant.core import HomeAssistant
19+
from homeassistant.helpers import entity_registry as er
20+
21+
from .conftest import init_integration
22+
23+
from tests.common import MockConfigEntry, snapshot_platform
24+
25+
26+
@pytest.mark.usefixtures("classic_vario_mock")
27+
async def test_setup_classic_vario(
28+
hass: HomeAssistant,
29+
eheimdigital_hub_mock: MagicMock,
30+
mock_config_entry: MockConfigEntry,
31+
entity_registry: er.EntityRegistry,
32+
snapshot: SnapshotAssertion,
33+
) -> None:
34+
"""Test switch platform setup for the filter."""
35+
mock_config_entry.add_to_hass(hass)
36+
37+
with (
38+
patch("homeassistant.components.eheimdigital.PLATFORMS", [Platform.SWITCH]),
39+
patch(
40+
"homeassistant.components.eheimdigital.coordinator.asyncio.Event",
41+
new=AsyncMock,
42+
),
43+
):
44+
await hass.config_entries.async_setup(mock_config_entry.entry_id)
45+
46+
await eheimdigital_hub_mock.call_args.kwargs["device_found_callback"](
47+
"00:00:00:00:00:03", EheimDeviceType.VERSION_EHEIM_CLASSIC_VARIO
48+
)
49+
await hass.async_block_till_done()
50+
51+
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
52+
53+
54+
@pytest.mark.parametrize(
55+
("service", "active"), [(SERVICE_TURN_OFF, False), (SERVICE_TURN_ON, True)]
56+
)
57+
async def test_turn_on_off(
58+
hass: HomeAssistant,
59+
eheimdigital_hub_mock: MagicMock,
60+
mock_config_entry: MockConfigEntry,
61+
classic_vario_mock: MagicMock,
62+
service: str,
63+
active: bool,
64+
) -> None:
65+
"""Test turning on/off the switch."""
66+
await init_integration(hass, mock_config_entry)
67+
68+
await eheimdigital_hub_mock.call_args.kwargs["device_found_callback"](
69+
"00:00:00:00:00:03", EheimDeviceType.VERSION_EHEIM_CLASSIC_VARIO
70+
)
71+
await hass.async_block_till_done()
72+
73+
await hass.services.async_call(
74+
SWITCH_DOMAIN,
75+
service,
76+
{ATTR_ENTITY_ID: "switch.mock_classicvario"},
77+
blocking=True,
78+
)
79+
80+
classic_vario_mock.set_active.assert_awaited_once_with(active=active)
81+
82+
83+
async def test_state_update(
84+
hass: HomeAssistant,
85+
eheimdigital_hub_mock: MagicMock,
86+
mock_config_entry: MockConfigEntry,
87+
classic_vario_mock: MagicMock,
88+
) -> None:
89+
"""Test the switch state update."""
90+
await init_integration(hass, mock_config_entry)
91+
92+
await eheimdigital_hub_mock.call_args.kwargs["device_found_callback"](
93+
"00:00:00:00:00:03", EheimDeviceType.VERSION_EHEIM_CLASSIC_VARIO
94+
)
95+
await hass.async_block_till_done()
96+
97+
assert (state := hass.states.get("switch.mock_classicvario"))
98+
assert state.state == STATE_ON
99+
100+
classic_vario_mock.is_active = False
101+
102+
await eheimdigital_hub_mock.call_args.kwargs["receive_callback"]()
103+
104+
assert (state := hass.states.get("switch.mock_classicvario"))
105+
assert state.state == STATE_OFF

0 commit comments

Comments
(0)

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