mirror of
https://github.com/home-assistant/core.git
synced 2026-10-05 21:57:39 +01:00
Refactor bosch_shc ShutterContactSensor to entity-description pattern (#183115)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2ae015598d
commit
b8d535cdcf
3 files changed
+126
-2
No files matched your search
@@ -1,5 +1,7 @@
|
||||
"""Platform for binarysensor integration."""
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from boschshcpy import (
|
||||
@@ -13,6 +15,7 @@ from boschshcpy.device import SHCDevice
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorDeviceClass,
|
||||
BinarySensorEntity,
|
||||
BinarySensorEntityDescription,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
@@ -23,6 +26,19 @@ from .entity import SHCEntity
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class SHCShutterContactSensorEntityDescription(BinarySensorEntityDescription):
|
||||
"""Describes a SHC shutter contact binary sensor."""
|
||||
|
||||
is_on_fn: Callable[[SHCShutterContact], bool]
|
||||
|
||||
|
||||
SHUTTER_CONTACT_DESCRIPTION = SHCShutterContactSensorEntityDescription(
|
||||
key="shutter_contact",
|
||||
is_on_fn=lambda device: device.state is ShutterContactService.State.OPEN,
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: BoschConfigEntry,
|
||||
@@ -41,6 +57,7 @@ async def async_setup_entry(
|
||||
device=binary_sensor,
|
||||
parent_id=shc_info.unique_id,
|
||||
entry_id=config_entry.entry_id,
|
||||
entity_description=SHUTTER_CONTACT_DESCRIPTION,
|
||||
)
|
||||
for binary_sensor in (
|
||||
*session.device_helper.shutter_contacts,
|
||||
@@ -76,11 +93,18 @@ class ShutterContactSensor(SHCEntity, BinarySensorEntity):
|
||||
|
||||
_attr_name = None
|
||||
_device: SHCShutterContact
|
||||
entity_description: SHCShutterContactSensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self, hass: HomeAssistant, device: SHCDevice, parent_id: str, entry_id: str
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
device: SHCDevice,
|
||||
parent_id: str,
|
||||
entry_id: str,
|
||||
entity_description: SHCShutterContactSensorEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize an SHC shutter contact sensor."""
|
||||
self.entity_description = entity_description
|
||||
super().__init__(hass, device, parent_id, entry_id)
|
||||
switcher: dict[str | None, BinarySensorDeviceClass] = {
|
||||
"ENTRANCE_DOOR": BinarySensorDeviceClass.DOOR,
|
||||
@@ -96,7 +120,7 @@ class ShutterContactSensor(SHCEntity, BinarySensorEntity):
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return the state of the sensor."""
|
||||
return self._device.state is ShutterContactService.State.OPEN
|
||||
return self.entity_description.is_on_fn(self._device)
|
||||
|
||||
|
||||
class BatterySensor(SHCEntity, BinarySensorEntity):
|
||||
|
||||
@@ -16,6 +16,7 @@ from boschshcpy import (
|
||||
SHCMicromoduleRelay,
|
||||
SHCMotionDetector2,
|
||||
SHCPresenceSimulationSystem,
|
||||
SHCShutterContact,
|
||||
SHCShutterContact2,
|
||||
SHCShutterControl,
|
||||
SHCSmartPlug,
|
||||
@@ -24,6 +25,7 @@ from boschshcpy import (
|
||||
SHCThermostat,
|
||||
SHCThermostatGen2,
|
||||
SHCTwinguard,
|
||||
ShutterContactService,
|
||||
ShutterControlService,
|
||||
ThermostatService,
|
||||
)
|
||||
@@ -367,6 +369,28 @@ def presence_simulation_system_device(
|
||||
return device
|
||||
|
||||
|
||||
def shutter_contact_device(
|
||||
device_id: str = "hdm:ZigBee:shuttercontact1",
|
||||
name: str = "Shutter contact",
|
||||
device_class: str = "GENERIC",
|
||||
state: ShutterContactService.State = ShutterContactService.State.CLOSED,
|
||||
) -> SHCShutterContact:
|
||||
"""Build a minimal device double for the shutter_contacts bucket."""
|
||||
device = create_autospec(SHCShutterContact, instance=True, spec_set=True)
|
||||
device.name = name
|
||||
device.id = device_id
|
||||
device.root_device_id = "test-mac"
|
||||
device.serial = f"serial-{device_id}"
|
||||
device.manufacturer = "Bosch"
|
||||
device.device_model = "SWD"
|
||||
device.device_class = device_class
|
||||
device.device_services = []
|
||||
device.deleted = False
|
||||
device.status = "AVAILABLE"
|
||||
device.state = state
|
||||
return device
|
||||
|
||||
|
||||
def shutter_contact2_device(
|
||||
device_id: str = "hdm:ZigBee:shuttercontact1",
|
||||
name: str = "Shutter contact",
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
"""Tests for the Bosch SHC binary_sensor platform."""
|
||||
|
||||
from boschshcpy import ShutterContactService
|
||||
import pytest
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .conftest import setup_integration, shutter_contact_device
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"device_buckets",
|
||||
[
|
||||
{
|
||||
"shutter_contacts": [
|
||||
shutter_contact_device(state=ShutterContactService.State.CLOSED)
|
||||
]
|
||||
}
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_session")
|
||||
async def test_shutter_contact_closed(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""A closed Shutter Contact is reported as off."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
state = hass.states.get("binary_sensor.shutter_contact")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"device_buckets",
|
||||
[
|
||||
{
|
||||
"shutter_contacts": [
|
||||
shutter_contact_device(state=ShutterContactService.State.OPEN)
|
||||
]
|
||||
}
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_session")
|
||||
async def test_shutter_contact_open(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""An open Shutter Contact is reported as on."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
state = hass.states.get("binary_sensor.shutter_contact")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"device_buckets",
|
||||
[{"shutter_contacts": [shutter_contact_device(device_class="ENTRANCE_DOOR")]}],
|
||||
indirect=True,
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_session")
|
||||
async def test_shutter_contact_device_class(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""A Shutter Contact's device_class maps to the binary_sensor device class."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
state = hass.states.get("binary_sensor.shutter_contact")
|
||||
assert state is not None
|
||||
assert state.attributes["device_class"] == "door"
|
||||
Reference in new issue
Block a user