Improve incomfort binary sensors (#119292)

* Improve incomfort binary_sensor, add is_burning, is_pumping and is_tapping

* Update test snapshot

* Use helper for fault code label name

* Update tests

* Remove extra state attribute

* Make default Fault `none` to supprt localization

* Update snapshot
This commit is contained in:
Jan Bouwhuis 2024-06-10 20:57:36 +02:00 committed by GitHub
parent 53d5a65f2c
commit 51d78c3c25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 1698 additions and 23 deletions

View File

@ -26,7 +26,7 @@ class IncomfortBinarySensorEntityDescription(BinarySensorEntityDescription):
"""Describes Incomfort binary sensor entity."""
value_key: str
extra_state_attributes_fn: Callable[[dict[str, Any]], dict[str, Any]]
extra_state_attributes_fn: Callable[[dict[str, Any]], dict[str, Any]] | None = None
SENSOR_TYPES: tuple[IncomfortBinarySensorEntityDescription, ...] = (
@ -35,7 +35,27 @@ SENSOR_TYPES: tuple[IncomfortBinarySensorEntityDescription, ...] = (
translation_key="fault",
device_class=BinarySensorDeviceClass.PROBLEM,
value_key="is_failed",
extra_state_attributes_fn=lambda status: {"fault_code": status["fault_code"]},
extra_state_attributes_fn=lambda status: {
"fault_code": status["fault_code"] or "none",
},
),
IncomfortBinarySensorEntityDescription(
key="is_pumping",
translation_key="is_pumping",
device_class=BinarySensorDeviceClass.RUNNING,
value_key="is_pumping",
),
IncomfortBinarySensorEntityDescription(
key="is_burning",
translation_key="is_burning",
device_class=BinarySensorDeviceClass.RUNNING,
value_key="is_burning",
),
IncomfortBinarySensorEntityDescription(
key="is_tapping",
translation_key="is_tapping",
device_class=BinarySensorDeviceClass.RUNNING,
value_key="is_tapping",
),
)
@ -77,6 +97,8 @@ class IncomfortBinarySensor(IncomfortBoilerEntity, BinarySensorEntity):
return self._heater.status[self.entity_description.value_key]
@property
def extra_state_attributes(self) -> dict[str, Any]:
def extra_state_attributes(self) -> dict[str, Any] | None:
"""Return the device state attributes."""
return self.entity_description.extra_state_attributes_fn(self._heater.status)
if (attributes_fn := self.entity_description.extra_state_attributes_fn) is None:
return None
return attributes_fn(self._heater.status)

View File

@ -56,7 +56,23 @@
"entity": {
"binary_sensor": {
"fault": {
"name": "Fault"
"name": "Fault",
"state_attributes": {
"fault_code": {
"state": {
"none": "None"
}
}
}
},
"is_burning": {
"name": "Burner"
},
"is_pumping": {
"name": "Pump"
},
"is_tapping": {
"name": "Hot water tap"
}
},
"sensor": {

View File

@ -3,6 +3,7 @@
from typing import Any
from unittest.mock import AsyncMock, MagicMock, patch
from incomfortclient import DisplayCode
import pytest
from typing_extensions import Generator
@ -18,6 +19,23 @@ MOCK_CONFIG = {
"password": "verysecret",
}
MOCK_HEATER_STATUS = {
"display_code": DisplayCode(126),
"display_text": "standby",
"fault_code": None,
"is_burning": False,
"is_failed": False,
"is_pumping": False,
"is_tapping": False,
"heater_temp": 35.34,
"tap_temp": 30.21,
"pressure": 1.86,
"serial_no": "c0ffeec0ffee",
"nodenr": 249,
"rf_message_rssi": 30,
"rfstatus_cntr": 0,
}
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
@ -48,22 +66,7 @@ def mock_config_entry(
@pytest.fixture
def mock_heater_status() -> dict[str, Any]:
"""Mock heater status."""
return {
"display_code": 126,
"display_text": "standby",
"fault_code": None,
"is_burning": False,
"is_failed": False,
"is_pumping": False,
"is_tapping": False,
"heater_temp": 35.34,
"tap_temp": 30.21,
"pressure": 1.86,
"serial_no": "c0ffeec0ffee",
"nodenr": 249,
"rf_message_rssi": 30,
"rfstatus_cntr": 0,
}
return dict(MOCK_HEATER_STATUS)
@pytest.fixture

File diff suppressed because it is too large Load Diff

View File

@ -39,7 +39,7 @@
StateSnapshot({
'attributes': ReadOnlyDict({
'current_temperature': 35.3,
'display_code': 126,
'display_code': <DisplayCode.STANDBY: 126>,
'display_text': 'standby',
'friendly_name': 'Boiler',
'icon': 'mdi:thermometer-lines',

View File

@ -2,6 +2,8 @@
from unittest.mock import MagicMock, patch
from incomfortclient import FaultCode
import pytest
from syrupy import SnapshotAssertion
from homeassistant.config_entries import ConfigEntry
@ -9,6 +11,8 @@ from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from .conftest import MOCK_HEATER_STATUS
from tests.common import snapshot_platform
@ -23,3 +27,31 @@ async def test_setup_platform(
"""Test the incomfort entities are set up correctly."""
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
@pytest.mark.parametrize(
"mock_heater_status",
[
MOCK_HEATER_STATUS
| {
"is_failed": True,
"display_code": None,
"fault_code": FaultCode.CV_TEMPERATURE_TOO_HIGH_E1,
},
MOCK_HEATER_STATUS | {"is_pumping": True},
MOCK_HEATER_STATUS | {"is_burning": True},
MOCK_HEATER_STATUS | {"is_tapping": True},
],
ids=["is_failed", "is_pumping", "is_burning", "is_tapping"],
)
@patch("homeassistant.components.incomfort.PLATFORMS", [Platform.BINARY_SENSOR])
async def test_setup_binary_sensors_alt(
hass: HomeAssistant,
mock_incomfort: MagicMock,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
mock_config_entry: ConfigEntry,
) -> None:
"""Test the incomfort heater ."""
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)