mirror of
https://github.com/home-assistant/core.git
synced 2026-09-27 01:46:11 -04:00
bosch_shc: add Twinguard nightly promise (Heartbeat) switch entity (#182874)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
c600261063
commit
79224c3a1c
@@ -101,6 +101,9 @@
|
||||
"child_lock": {
|
||||
"name": "Child lock"
|
||||
},
|
||||
"nightly_promise_enabled": {
|
||||
"name": "Heartbeat"
|
||||
},
|
||||
"pet_immunity_enabled": {
|
||||
"name": "Pet immunity"
|
||||
},
|
||||
|
||||
@@ -108,6 +108,15 @@ SWITCH_TYPES: dict[str, SHCSwitchEntityDescription] = {
|
||||
on_value=BypassService.State.BYPASS_ACTIVE,
|
||||
should_poll=False,
|
||||
),
|
||||
"nightly_promise_enabled": SHCSwitchEntityDescription(
|
||||
key="nightly_promise_enabled",
|
||||
translation_key="nightly_promise_enabled",
|
||||
device_class=SwitchDeviceClass.SWITCH,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
on_key="nightly_promise_enabled",
|
||||
on_value=True,
|
||||
should_poll=False,
|
||||
),
|
||||
"pet_immunity_enabled": SHCSwitchEntityDescription(
|
||||
key="pet_immunity_enabled",
|
||||
translation_key="pet_immunity_enabled",
|
||||
@@ -278,6 +287,18 @@ async def async_setup_entry(
|
||||
for switch in session.device_helper.motion_detectors2
|
||||
)
|
||||
|
||||
entities.extend(
|
||||
SHCSwitch(
|
||||
hass=hass,
|
||||
device=switch,
|
||||
parent_id=shc_info.unique_id,
|
||||
entry_id=config_entry.entry_id,
|
||||
description=SWITCH_TYPES["nightly_promise_enabled"],
|
||||
)
|
||||
for switch in session.device_helper.twinguards
|
||||
if switch.supports_nightly_promise
|
||||
)
|
||||
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ from boschshcpy import (
|
||||
SHCShutterControl,
|
||||
SHCSmartPlug,
|
||||
SHCThermostat,
|
||||
SHCTwinguard,
|
||||
ShutterControlService,
|
||||
ThermostatService,
|
||||
)
|
||||
@@ -354,3 +355,25 @@ def motion_detector2_device(
|
||||
device.status = "AVAILABLE"
|
||||
device.pet_immunity_enabled = pet_immunity_enabled
|
||||
return device
|
||||
|
||||
|
||||
def twinguard_device(
|
||||
device_id: str = "hdm:HomeMaticIP:twinguard1",
|
||||
name: str = "Twinguard",
|
||||
supports_nightly_promise: bool = False,
|
||||
nightly_promise_enabled: bool = False,
|
||||
) -> SHCTwinguard:
|
||||
"""Build a minimal device double for the twinguards bucket."""
|
||||
device = create_autospec(SHCTwinguard, 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 = "TWINGUARD"
|
||||
device.device_services = []
|
||||
device.deleted = False
|
||||
device.status = "AVAILABLE"
|
||||
device.supports_nightly_promise = supports_nightly_promise
|
||||
device.nightly_promise_enabled = nightly_promise_enabled
|
||||
return device
|
||||
|
||||
@@ -25,6 +25,7 @@ from .conftest import (
|
||||
shutter_contact2_device,
|
||||
smart_plug_device,
|
||||
thermostat_device,
|
||||
twinguard_device,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
@@ -354,3 +355,63 @@ async def test_motion_detector2_pet_immunity(
|
||||
blocking=True,
|
||||
)
|
||||
assert device.pet_immunity_enabled is False
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"device_buckets",
|
||||
[
|
||||
{
|
||||
"twinguards": [
|
||||
twinguard_device(
|
||||
supports_nightly_promise=True, nightly_promise_enabled=False
|
||||
)
|
||||
]
|
||||
}
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_session")
|
||||
async def test_twinguard_nightly_promise(
|
||||
hass: HomeAssistant,
|
||||
mock_session: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""A Twinguard's nightly promise (Heartbeat) is exposed and controllable as a switch."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
device = mock_session.device_helper.twinguards[0]
|
||||
|
||||
state = hass.states.get("switch.twinguard_heartbeat")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: "switch.twinguard_heartbeat"},
|
||||
blocking=True,
|
||||
)
|
||||
assert device.nightly_promise_enabled is True
|
||||
|
||||
await hass.services.async_call(
|
||||
SWITCH_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: "switch.twinguard_heartbeat"},
|
||||
blocking=True,
|
||||
)
|
||||
assert device.nightly_promise_enabled is False
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"device_buckets",
|
||||
[{"twinguards": [twinguard_device(supports_nightly_promise=False)]}],
|
||||
indirect=True,
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_session")
|
||||
async def test_twinguard_no_nightly_promise_support(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""No switch is created for a Twinguard without nightly-promise support."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
assert hass.states.get("switch.twinguard_heartbeat") is None
|
||||
|
||||
Reference in New Issue
Block a user