From ed270f558a738a84ef7263a0f9d7c7e8d06f3308 Mon Sep 17 00:00:00 2001 From: Jonas Fors Lellky Date: Sun, 21 Jan 2024 12:35:21 +0100 Subject: [PATCH] Add binary sensors to flexit_bacnet integration (#108571) * Adds binary sensors to flexit_bacnet integration * Review comments * Removes binary sensor for electric heater Will add switch or service later --- .../components/flexit_bacnet/__init__.py | 2 +- .../components/flexit_bacnet/binary_sensor.py | 72 +++++++++++++++++++ .../components/flexit_bacnet/strings.json | 5 ++ .../snapshots/test_binary_sensor.ambr | 45 ++++++++++++ .../flexit_bacnet/test_binary_sensor.py | 35 +++++++++ 5 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/flexit_bacnet/binary_sensor.py create mode 100644 tests/components/flexit_bacnet/snapshots/test_binary_sensor.ambr create mode 100644 tests/components/flexit_bacnet/test_binary_sensor.py diff --git a/homeassistant/components/flexit_bacnet/__init__.py b/homeassistant/components/flexit_bacnet/__init__.py index 40537306c0b..27800af6626 100644 --- a/homeassistant/components/flexit_bacnet/__init__.py +++ b/homeassistant/components/flexit_bacnet/__init__.py @@ -8,7 +8,7 @@ from homeassistant.core import HomeAssistant from .const import DOMAIN from .coordinator import FlexitCoordinator -PLATFORMS: list[Platform] = [Platform.CLIMATE, Platform.SENSOR] +PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.CLIMATE, Platform.SENSOR] async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: diff --git a/homeassistant/components/flexit_bacnet/binary_sensor.py b/homeassistant/components/flexit_bacnet/binary_sensor.py new file mode 100644 index 00000000000..b014fbca415 --- /dev/null +++ b/homeassistant/components/flexit_bacnet/binary_sensor.py @@ -0,0 +1,72 @@ +"""The Flexit Nordic (BACnet) integration.""" +from collections.abc import Callable +from dataclasses import dataclass + +from flexit_bacnet import FlexitBACnet + +from homeassistant.components.binary_sensor import ( + BinarySensorDeviceClass, + BinarySensorEntity, + BinarySensorEntityDescription, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import FlexitCoordinator +from .const import DOMAIN +from .entity import FlexitEntity + + +@dataclass(kw_only=True, frozen=True) +class FlexitBinarySensorEntityDescription(BinarySensorEntityDescription): + """Describes a Flexit binary sensor entity.""" + + value_fn: Callable[[FlexitBACnet], bool] + + +SENSOR_TYPES: tuple[FlexitBinarySensorEntityDescription, ...] = ( + FlexitBinarySensorEntityDescription( + key="air_filter_polluted", + device_class=BinarySensorDeviceClass.PROBLEM, + translation_key="air_filter_polluted", + value_fn=lambda data: data.air_filter_polluted, + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up Flexit (bacnet) binary sensor from a config entry.""" + coordinator: FlexitCoordinator = hass.data[DOMAIN][config_entry.entry_id] + + async_add_entities( + FlexitBinarySensor(coordinator, description) for description in SENSOR_TYPES + ) + + +class FlexitBinarySensor(FlexitEntity, BinarySensorEntity): + """Representation of a Flexit binary Sensor.""" + + entity_description: FlexitBinarySensorEntityDescription + + def __init__( + self, + coordinator: FlexitCoordinator, + entity_description: FlexitBinarySensorEntityDescription, + ) -> None: + """Initialize Flexit (bacnet) sensor.""" + super().__init__(coordinator) + + self.entity_description = entity_description + self._attr_unique_id = ( + f"{coordinator.device.serial_number}-{entity_description.key}" + ) + + @property + def is_on(self) -> bool: + """Return value of binary sensor.""" + return self.entity_description.value_fn(self.coordinator.data) diff --git a/homeassistant/components/flexit_bacnet/strings.json b/homeassistant/components/flexit_bacnet/strings.json index b9348ebedcd..aeb349dd1d4 100644 --- a/homeassistant/components/flexit_bacnet/strings.json +++ b/homeassistant/components/flexit_bacnet/strings.json @@ -17,6 +17,11 @@ } }, "entity": { + "binary_sensor": { + "air_filter_polluted": { + "name": "Air filter polluted" + } + }, "sensor": { "outside_air_temperature": { "name": "Outside air temperature" diff --git a/tests/components/flexit_bacnet/snapshots/test_binary_sensor.ambr b/tests/components/flexit_bacnet/snapshots/test_binary_sensor.ambr new file mode 100644 index 00000000000..a6f4137d03e --- /dev/null +++ b/tests/components/flexit_bacnet/snapshots/test_binary_sensor.ambr @@ -0,0 +1,45 @@ +# serializer version: 1 +# name: test_binary_sensors[binary_sensor.device_name_air_filter_polluted-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': None, + 'entity_id': 'binary_sensor.device_name_air_filter_polluted', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Air filter polluted', + 'platform': 'flexit_bacnet', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'air_filter_polluted', + 'unique_id': '0000-0001-air_filter_polluted', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.device_name_air_filter_polluted-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'problem', + 'friendly_name': 'Device Name Air filter polluted', + }), + 'context': , + 'entity_id': 'binary_sensor.device_name_air_filter_polluted', + 'last_changed': , + 'last_updated': , + 'state': 'on', + }) +# --- diff --git a/tests/components/flexit_bacnet/test_binary_sensor.py b/tests/components/flexit_bacnet/test_binary_sensor.py new file mode 100644 index 00000000000..df363086f63 --- /dev/null +++ b/tests/components/flexit_bacnet/test_binary_sensor.py @@ -0,0 +1,35 @@ +"""Tests for the Flexit Nordic (BACnet) binary sensor entities.""" +from unittest.mock import AsyncMock + +from syrupy.assertion import SnapshotAssertion + +from homeassistant.const import Platform +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from tests.common import MockConfigEntry +from tests.components.flexit_bacnet import setup_with_selected_platforms + + +async def test_binary_sensors( + hass: HomeAssistant, + snapshot: SnapshotAssertion, + entity_registry: er.EntityRegistry, + mock_flexit_bacnet: AsyncMock, + mock_config_entry: MockConfigEntry, +) -> None: + """Test binary sensor states are correctly collected from library.""" + + await setup_with_selected_platforms( + hass, mock_config_entry, [Platform.BINARY_SENSOR] + ) + entity_entries = er.async_entries_for_config_entry( + entity_registry, mock_config_entry.entry_id + ) + + assert entity_entries + for entity_entry in entity_entries: + assert entity_entry == snapshot(name=f"{entity_entry.entity_id}-entry") + assert hass.states.get(entity_entry.entity_id) == snapshot( + name=f"{entity_entry.entity_id}-state" + )