mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 14:17:45 +00:00
Handle binary coils with non default mappings in nibe heatpump (#148354)
This commit is contained in:
parent
186c4e7038
commit
2377b136f3
@ -39,6 +39,7 @@ class BinarySensor(CoilEntity, BinarySensorEntity):
|
||||
def __init__(self, coordinator: CoilCoordinator, coil: Coil) -> None:
|
||||
"""Initialize entity."""
|
||||
super().__init__(coordinator, coil, ENTITY_ID_FORMAT)
|
||||
self._on_value = coil.get_mapping_for(1)
|
||||
|
||||
def _async_read_coil(self, data: CoilData) -> None:
|
||||
self._attr_is_on = data.value == "ON"
|
||||
self._attr_is_on = data.value == self._on_value
|
||||
|
@ -41,14 +41,16 @@ class Switch(CoilEntity, SwitchEntity):
|
||||
def __init__(self, coordinator: CoilCoordinator, coil: Coil) -> None:
|
||||
"""Initialize entity."""
|
||||
super().__init__(coordinator, coil, ENTITY_ID_FORMAT)
|
||||
self._on_value = coil.get_mapping_for(1)
|
||||
self._off_value = coil.get_mapping_for(0)
|
||||
|
||||
def _async_read_coil(self, data: CoilData) -> None:
|
||||
self._attr_is_on = data.value == "ON"
|
||||
self._attr_is_on = data.value == self._on_value
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the entity on."""
|
||||
await self._async_write_coil("ON")
|
||||
await self._async_write_coil(self._on_value)
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the entity off."""
|
||||
await self._async_write_coil("OFF")
|
||||
await self._async_write_coil(self._off_value)
|
||||
|
@ -24,6 +24,8 @@ MOCK_ENTRY_DATA = {
|
||||
"connection_type": "nibegw",
|
||||
}
|
||||
|
||||
MOCK_UNIQUE_ID = "mock_entry_unique_id"
|
||||
|
||||
|
||||
class MockConnection(Connection):
|
||||
"""A mock connection class."""
|
||||
@ -59,7 +61,9 @@ class MockConnection(Connection):
|
||||
|
||||
async def async_add_entry(hass: HomeAssistant, data: dict[str, Any]) -> MockConfigEntry:
|
||||
"""Add entry and get the coordinator."""
|
||||
entry = MockConfigEntry(domain=DOMAIN, title="Dummy", data=data)
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN, title="Dummy", data=data, unique_id=MOCK_UNIQUE_ID
|
||||
)
|
||||
|
||||
entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
|
@ -0,0 +1,97 @@
|
||||
# serializer version: 1
|
||||
# name: test_update[Model.F1255-49239-OFF][binary_sensor.eb101_installed_49239-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.eb101_installed_49239',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'EB101 Installed',
|
||||
'platform': 'nibe_heatpump',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': 'eb101_installed_49239',
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'mock_entry_unique_id-49239',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_update[Model.F1255-49239-OFF][binary_sensor.eb101_installed_49239-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'F1255 EB101 Installed',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.eb101_installed_49239',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_update[Model.F1255-49239-ON][binary_sensor.eb101_installed_49239-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.eb101_installed_49239',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'EB101 Installed',
|
||||
'platform': 'nibe_heatpump',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': 'eb101_installed_49239',
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'mock_entry_unique_id-49239',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_update[Model.F1255-49239-ON][binary_sensor.eb101_installed_49239-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'F1255 EB101 Installed',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.eb101_installed_49239',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
193
tests/components/nibe_heatpump/snapshots/test_switch.ambr
Normal file
193
tests/components/nibe_heatpump/snapshots/test_switch.ambr
Normal file
@ -0,0 +1,193 @@
|
||||
# serializer version: 1
|
||||
# name: test_update[Model.F1255-48043-ACTIVE][switch.holiday_activated_48043-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'switch.holiday_activated_48043',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Holiday - Activated',
|
||||
'platform': 'nibe_heatpump',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': 'holiday_activated_48043',
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'mock_entry_unique_id-48043',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_update[Model.F1255-48043-ACTIVE][switch.holiday_activated_48043-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'F1255 Holiday - Activated',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.holiday_activated_48043',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_update[Model.F1255-48043-INACTIVE][switch.holiday_activated_48043-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'switch.holiday_activated_48043',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Holiday - Activated',
|
||||
'platform': 'nibe_heatpump',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': 'holiday_activated_48043',
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'mock_entry_unique_id-48043',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_update[Model.F1255-48043-INACTIVE][switch.holiday_activated_48043-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'F1255 Holiday - Activated',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.holiday_activated_48043',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_update[Model.F1255-48071-OFF][switch.flm_1_accessory_48071-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'switch.flm_1_accessory_48071',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'FLM 1 accessory',
|
||||
'platform': 'nibe_heatpump',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': 'flm_1_accessory_48071',
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'mock_entry_unique_id-48071',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_update[Model.F1255-48071-OFF][switch.flm_1_accessory_48071-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'F1255 FLM 1 accessory',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.flm_1_accessory_48071',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_update[Model.F1255-48071-ON][switch.flm_1_accessory_48071-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'switch',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'switch.flm_1_accessory_48071',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'FLM 1 accessory',
|
||||
'platform': 'nibe_heatpump',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': 'flm_1_accessory_48071',
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'mock_entry_unique_id-48071',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_update[Model.F1255-48071-ON][switch.flm_1_accessory_48071-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'F1255 FLM 1 accessory',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'switch.flm_1_accessory_48071',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
49
tests/components/nibe_heatpump/test_binary_sensor.py
Normal file
49
tests/components/nibe_heatpump/test_binary_sensor.py
Normal file
@ -0,0 +1,49 @@
|
||||
"""Test the Nibe Heat Pump binary sensor entities."""
|
||||
|
||||
from typing import Any
|
||||
from unittest.mock import patch
|
||||
|
||||
from nibe.heatpump import Model
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import async_add_model
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
async def fixture_single_platform():
|
||||
"""Only allow this platform to load."""
|
||||
with patch(
|
||||
"homeassistant.components.nibe_heatpump.PLATFORMS", [Platform.BINARY_SENSOR]
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("model", "address", "value"),
|
||||
[
|
||||
(Model.F1255, 49239, "OFF"),
|
||||
(Model.F1255, 49239, "ON"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_update(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
model: Model,
|
||||
address: int,
|
||||
value: Any,
|
||||
coils: dict[int, Any],
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test setting of value."""
|
||||
coils[address] = value
|
||||
|
||||
entry = await async_add_model(hass, model)
|
||||
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)
|
@ -1,4 +1,4 @@
|
||||
"""Test the Nibe Heat Pump config flow."""
|
||||
"""Test the Nibe Heat Pump buttons."""
|
||||
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
@ -1,4 +1,4 @@
|
||||
"""Test the Nibe Heat Pump config flow."""
|
||||
"""Test the Nibe Heat Pump climate entities."""
|
||||
|
||||
from typing import Any
|
||||
from unittest.mock import call, patch
|
||||
|
@ -1,4 +1,4 @@
|
||||
"""Test the Nibe Heat Pump config flow."""
|
||||
"""Test the Nibe Heat Pump number entities."""
|
||||
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
133
tests/components/nibe_heatpump/test_switch.py
Normal file
133
tests/components/nibe_heatpump/test_switch.py
Normal file
@ -0,0 +1,133 @@
|
||||
"""Test the Nibe Heat Pump switch entities."""
|
||||
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from nibe.coil import CoilData
|
||||
from nibe.heatpump import Model
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.switch import (
|
||||
DOMAIN as SWITCH_PLATFORM,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import async_add_model
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
async def fixture_single_platform():
|
||||
"""Only allow this platform to load."""
|
||||
with patch("homeassistant.components.nibe_heatpump.PLATFORMS", [Platform.SWITCH]):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("model", "address", "value"),
|
||||
[
|
||||
(Model.F1255, 48043, "INACTIVE"),
|
||||
(Model.F1255, 48043, "ACTIVE"),
|
||||
(Model.F1255, 48071, "OFF"),
|
||||
(Model.F1255, 48071, "ON"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_update(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
model: Model,
|
||||
address: int,
|
||||
value: Any,
|
||||
coils: dict[int, Any],
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test setting of value."""
|
||||
coils[address] = value
|
||||
|
||||
entry = await async_add_model(hass, model)
|
||||
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("model", "address", "entity_id", "state"),
|
||||
[
|
||||
(Model.F1255, 48043, "switch.holiday_activated_48043", "INACTIVE"),
|
||||
(Model.F1255, 48071, "switch.flm_1_accessory_48071", "OFF"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_turn_on(
|
||||
hass: HomeAssistant,
|
||||
mock_connection: AsyncMock,
|
||||
model: Model,
|
||||
entity_id: str,
|
||||
address: int,
|
||||
state: Any,
|
||||
coils: dict[int, Any],
|
||||
) -> None:
|
||||
"""Test setting of value."""
|
||||
coils[address] = state
|
||||
|
||||
await async_add_model(hass, model)
|
||||
|
||||
# Write value
|
||||
await hass.services.async_call(
|
||||
SWITCH_PLATFORM,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
# Verify written
|
||||
args = mock_connection.write_coil.call_args
|
||||
assert args
|
||||
coil = args.args[0]
|
||||
assert isinstance(coil, CoilData)
|
||||
assert coil.coil.address == address
|
||||
assert coil.raw_value == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("model", "address", "entity_id", "state"),
|
||||
[
|
||||
(Model.F1255, 48043, "switch.holiday_activated_48043", "INACTIVE"),
|
||||
(Model.F1255, 48071, "switch.flm_1_accessory_48071", "ON"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_turn_off(
|
||||
hass: HomeAssistant,
|
||||
mock_connection: AsyncMock,
|
||||
model: Model,
|
||||
entity_id: str,
|
||||
address: int,
|
||||
state: Any,
|
||||
coils: dict[int, Any],
|
||||
) -> None:
|
||||
"""Test setting of value."""
|
||||
coils[address] = state
|
||||
|
||||
await async_add_model(hass, model)
|
||||
|
||||
# Write value
|
||||
await hass.services.async_call(
|
||||
SWITCH_PLATFORM,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
# Verify written
|
||||
args = mock_connection.write_coil.call_args
|
||||
assert args
|
||||
coil = args.args[0]
|
||||
assert isinstance(coil, CoilData)
|
||||
assert coil.coil.address == address
|
||||
assert coil.raw_value == 0
|
Loading…
x
Reference in New Issue
Block a user