Skip to content

Commit 2377b13

Browse files
elupusfrenck
authored andcommitted
Handle binary coils with non default mappings in nibe heatpump (home-assistant#148354)
1 parent 186c4e7 commit 2377b13

File tree

10 files changed

+487
-8
lines changed

10 files changed

+487
-8
lines changed

homeassistant/components/nibe_heatpump/binary_sensor.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class BinarySensor(CoilEntity, BinarySensorEntity):
3939
def __init__(self, coordinator: CoilCoordinator, coil: Coil) -> None:
4040
"""Initialize entity."""
4141
super().__init__(coordinator, coil, ENTITY_ID_FORMAT)
42+
self._on_value = coil.get_mapping_for(1)
4243

4344
def _async_read_coil(self, data: CoilData) -> None:
44-
self._attr_is_on = data.value == "ON"
45+
self._attr_is_on = data.value == self._on_value

homeassistant/components/nibe_heatpump/switch.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,16 @@ class Switch(CoilEntity, SwitchEntity):
4141
def __init__(self, coordinator: CoilCoordinator, coil: Coil) -> None:
4242
"""Initialize entity."""
4343
super().__init__(coordinator, coil, ENTITY_ID_FORMAT)
44+
self._on_value = coil.get_mapping_for(1)
45+
self._off_value = coil.get_mapping_for(0)
4446

4547
def _async_read_coil(self, data: CoilData) -> None:
46-
self._attr_is_on = data.value == "ON"
48+
self._attr_is_on = data.value == self._on_value
4749

4850
async def async_turn_on(self, **kwargs: Any) -> None:
4951
"""Turn the entity on."""
50-
await self._async_write_coil("ON")
52+
await self._async_write_coil(self._on_value)
5153

5254
async def async_turn_off(self, **kwargs: Any) -> None:
5355
"""Turn the entity off."""
54-
await self._async_write_coil("OFF")
56+
await self._async_write_coil(self._off_value)

tests/components/nibe_heatpump/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
"connection_type": "nibegw",
2525
}
2626

27+
MOCK_UNIQUE_ID = "mock_entry_unique_id"
28+
2729

2830
class MockConnection(Connection):
2931
"""A mock connection class."""
@@ -59,7 +61,9 @@ def mock_coil_update(self, coil_id: int, value: float | str | None):
5961

6062
async def async_add_entry(hass: HomeAssistant, data: dict[str, Any]) -> MockConfigEntry:
6163
"""Add entry and get the coordinator."""
62-
entry = MockConfigEntry(domain=DOMAIN, title="Dummy", data=data)
64+
entry = MockConfigEntry(
65+
domain=DOMAIN, title="Dummy", data=data, unique_id=MOCK_UNIQUE_ID
66+
)
6367

6468
entry.add_to_hass(hass)
6569
await hass.config_entries.async_setup(entry.entry_id)
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# serializer version: 1
2+
# name: test_update[Model.F1255-49239-OFF][binary_sensor.eb101_installed_49239-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': 'binary_sensor',
14+
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
15+
'entity_id': 'binary_sensor.eb101_installed_49239',
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': 'EB101 Installed',
28+
'platform': 'nibe_heatpump',
29+
'previous_unique_id': None,
30+
'suggested_object_id': 'eb101_installed_49239',
31+
'supported_features': 0,
32+
'translation_key': None,
33+
'unique_id': 'mock_entry_unique_id-49239',
34+
'unit_of_measurement': None,
35+
})
36+
# ---
37+
# name: test_update[Model.F1255-49239-OFF][binary_sensor.eb101_installed_49239-state]
38+
StateSnapshot({
39+
'attributes': ReadOnlyDict({
40+
'friendly_name': 'F1255 EB101 Installed',
41+
}),
42+
'context': <ANY>,
43+
'entity_id': 'binary_sensor.eb101_installed_49239',
44+
'last_changed': <ANY>,
45+
'last_reported': <ANY>,
46+
'last_updated': <ANY>,
47+
'state': 'off',
48+
})
49+
# ---
50+
# name: test_update[Model.F1255-49239-ON][binary_sensor.eb101_installed_49239-entry]
51+
EntityRegistryEntrySnapshot({
52+
'aliases': set({
53+
}),
54+
'area_id': None,
55+
'capabilities': None,
56+
'config_entry_id': <ANY>,
57+
'config_subentry_id': <ANY>,
58+
'device_class': None,
59+
'device_id': <ANY>,
60+
'disabled_by': None,
61+
'domain': 'binary_sensor',
62+
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
63+
'entity_id': 'binary_sensor.eb101_installed_49239',
64+
'has_entity_name': True,
65+
'hidden_by': None,
66+
'icon': None,
67+
'id': <ANY>,
68+
'labels': set({
69+
}),
70+
'name': None,
71+
'options': dict({
72+
}),
73+
'original_device_class': None,
74+
'original_icon': None,
75+
'original_name': 'EB101 Installed',
76+
'platform': 'nibe_heatpump',
77+
'previous_unique_id': None,
78+
'suggested_object_id': 'eb101_installed_49239',
79+
'supported_features': 0,
80+
'translation_key': None,
81+
'unique_id': 'mock_entry_unique_id-49239',
82+
'unit_of_measurement': None,
83+
})
84+
# ---
85+
# name: test_update[Model.F1255-49239-ON][binary_sensor.eb101_installed_49239-state]
86+
StateSnapshot({
87+
'attributes': ReadOnlyDict({
88+
'friendly_name': 'F1255 EB101 Installed',
89+
}),
90+
'context': <ANY>,
91+
'entity_id': 'binary_sensor.eb101_installed_49239',
92+
'last_changed': <ANY>,
93+
'last_reported': <ANY>,
94+
'last_updated': <ANY>,
95+
'state': 'on',
96+
})
97+
# ---
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
# serializer version: 1
2+
# name: test_update[Model.F1255-48043-ACTIVE][switch.holiday_activated_48043-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': <EntityCategory.CONFIG: 'config'>,
15+
'entity_id': 'switch.holiday_activated_48043',
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': 'Holiday - Activated',
28+
'platform': 'nibe_heatpump',
29+
'previous_unique_id': None,
30+
'suggested_object_id': 'holiday_activated_48043',
31+
'supported_features': 0,
32+
'translation_key': None,
33+
'unique_id': 'mock_entry_unique_id-48043',
34+
'unit_of_measurement': None,
35+
})
36+
# ---
37+
# name: test_update[Model.F1255-48043-ACTIVE][switch.holiday_activated_48043-state]
38+
StateSnapshot({
39+
'attributes': ReadOnlyDict({
40+
'friendly_name': 'F1255 Holiday - Activated',
41+
}),
42+
'context': <ANY>,
43+
'entity_id': 'switch.holiday_activated_48043',
44+
'last_changed': <ANY>,
45+
'last_reported': <ANY>,
46+
'last_updated': <ANY>,
47+
'state': 'on',
48+
})
49+
# ---
50+
# name: test_update[Model.F1255-48043-INACTIVE][switch.holiday_activated_48043-entry]
51+
EntityRegistryEntrySnapshot({
52+
'aliases': set({
53+
}),
54+
'area_id': None,
55+
'capabilities': None,
56+
'config_entry_id': <ANY>,
57+
'config_subentry_id': <ANY>,
58+
'device_class': None,
59+
'device_id': <ANY>,
60+
'disabled_by': None,
61+
'domain': 'switch',
62+
'entity_category': <EntityCategory.CONFIG: 'config'>,
63+
'entity_id': 'switch.holiday_activated_48043',
64+
'has_entity_name': True,
65+
'hidden_by': None,
66+
'icon': None,
67+
'id': <ANY>,
68+
'labels': set({
69+
}),
70+
'name': None,
71+
'options': dict({
72+
}),
73+
'original_device_class': None,
74+
'original_icon': None,
75+
'original_name': 'Holiday - Activated',
76+
'platform': 'nibe_heatpump',
77+
'previous_unique_id': None,
78+
'suggested_object_id': 'holiday_activated_48043',
79+
'supported_features': 0,
80+
'translation_key': None,
81+
'unique_id': 'mock_entry_unique_id-48043',
82+
'unit_of_measurement': None,
83+
})
84+
# ---
85+
# name: test_update[Model.F1255-48043-INACTIVE][switch.holiday_activated_48043-state]
86+
StateSnapshot({
87+
'attributes': ReadOnlyDict({
88+
'friendly_name': 'F1255 Holiday - Activated',
89+
}),
90+
'context': <ANY>,
91+
'entity_id': 'switch.holiday_activated_48043',
92+
'last_changed': <ANY>,
93+
'last_reported': <ANY>,
94+
'last_updated': <ANY>,
95+
'state': 'off',
96+
})
97+
# ---
98+
# name: test_update[Model.F1255-48071-OFF][switch.flm_1_accessory_48071-entry]
99+
EntityRegistryEntrySnapshot({
100+
'aliases': set({
101+
}),
102+
'area_id': None,
103+
'capabilities': None,
104+
'config_entry_id': <ANY>,
105+
'config_subentry_id': <ANY>,
106+
'device_class': None,
107+
'device_id': <ANY>,
108+
'disabled_by': None,
109+
'domain': 'switch',
110+
'entity_category': <EntityCategory.CONFIG: 'config'>,
111+
'entity_id': 'switch.flm_1_accessory_48071',
112+
'has_entity_name': True,
113+
'hidden_by': None,
114+
'icon': None,
115+
'id': <ANY>,
116+
'labels': set({
117+
}),
118+
'name': None,
119+
'options': dict({
120+
}),
121+
'original_device_class': None,
122+
'original_icon': None,
123+
'original_name': 'FLM 1 accessory',
124+
'platform': 'nibe_heatpump',
125+
'previous_unique_id': None,
126+
'suggested_object_id': 'flm_1_accessory_48071',
127+
'supported_features': 0,
128+
'translation_key': None,
129+
'unique_id': 'mock_entry_unique_id-48071',
130+
'unit_of_measurement': None,
131+
})
132+
# ---
133+
# name: test_update[Model.F1255-48071-OFF][switch.flm_1_accessory_48071-state]
134+
StateSnapshot({
135+
'attributes': ReadOnlyDict({
136+
'friendly_name': 'F1255 FLM 1 accessory',
137+
}),
138+
'context': <ANY>,
139+
'entity_id': 'switch.flm_1_accessory_48071',
140+
'last_changed': <ANY>,
141+
'last_reported': <ANY>,
142+
'last_updated': <ANY>,
143+
'state': 'off',
144+
})
145+
# ---
146+
# name: test_update[Model.F1255-48071-ON][switch.flm_1_accessory_48071-entry]
147+
EntityRegistryEntrySnapshot({
148+
'aliases': set({
149+
}),
150+
'area_id': None,
151+
'capabilities': None,
152+
'config_entry_id': <ANY>,
153+
'config_subentry_id': <ANY>,
154+
'device_class': None,
155+
'device_id': <ANY>,
156+
'disabled_by': None,
157+
'domain': 'switch',
158+
'entity_category': <EntityCategory.CONFIG: 'config'>,
159+
'entity_id': 'switch.flm_1_accessory_48071',
160+
'has_entity_name': True,
161+
'hidden_by': None,
162+
'icon': None,
163+
'id': <ANY>,
164+
'labels': set({
165+
}),
166+
'name': None,
167+
'options': dict({
168+
}),
169+
'original_device_class': None,
170+
'original_icon': None,
171+
'original_name': 'FLM 1 accessory',
172+
'platform': 'nibe_heatpump',
173+
'previous_unique_id': None,
174+
'suggested_object_id': 'flm_1_accessory_48071',
175+
'supported_features': 0,
176+
'translation_key': None,
177+
'unique_id': 'mock_entry_unique_id-48071',
178+
'unit_of_measurement': None,
179+
})
180+
# ---
181+
# name: test_update[Model.F1255-48071-ON][switch.flm_1_accessory_48071-state]
182+
StateSnapshot({
183+
'attributes': ReadOnlyDict({
184+
'friendly_name': 'F1255 FLM 1 accessory',
185+
}),
186+
'context': <ANY>,
187+
'entity_id': 'switch.flm_1_accessory_48071',
188+
'last_changed': <ANY>,
189+
'last_reported': <ANY>,
190+
'last_updated': <ANY>,
191+
'state': 'on',
192+
})
193+
# ---
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""Test the Nibe Heat Pump binary sensor entities."""
2+
3+
from typing import Any
4+
from unittest.mock import patch
5+
6+
from nibe.heatpump import Model
7+
import pytest
8+
from syrupy.assertion import SnapshotAssertion
9+
10+
from homeassistant.const import Platform
11+
from homeassistant.core import HomeAssistant
12+
from homeassistant.helpers import entity_registry as er
13+
14+
from . import async_add_model
15+
16+
from tests.common import snapshot_platform
17+
18+
19+
@pytest.fixture(autouse=True)
20+
async def fixture_single_platform():
21+
"""Only allow this platform to load."""
22+
with patch(
23+
"homeassistant.components.nibe_heatpump.PLATFORMS", [Platform.BINARY_SENSOR]
24+
):
25+
yield
26+
27+
28+
@pytest.mark.parametrize(
29+
("model", "address", "value"),
30+
[
31+
(Model.F1255, 49239, "OFF"),
32+
(Model.F1255, 49239, "ON"),
33+
],
34+
)
35+
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
36+
async def test_update(
37+
hass: HomeAssistant,
38+
entity_registry: er.EntityRegistry,
39+
model: Model,
40+
address: int,
41+
value: Any,
42+
coils: dict[int, Any],
43+
snapshot: SnapshotAssertion,
44+
) -> None:
45+
"""Test setting of value."""
46+
coils[address] = value
47+
48+
entry = await async_add_model(hass, model)
49+
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)

tests/components/nibe_heatpump/test_button.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Test the Nibe Heat Pump config flow."""
1+
"""Test the Nibe Heat Pump buttons."""
22

33
from typing import Any
44
from unittest.mock import AsyncMock, patch

0 commit comments

Comments
 (0)