bosch_shc: add Micromodule Relay swap-inputs/outputs switch entities (#183107)

This commit is contained in:
Thomas
2026-09-26 20:56:52 +02:00
committed by GitHub
parent 999e1c81f9
commit 42b3a5c1f2
4 changed files with 169 additions and 0 deletions
@@ -125,6 +125,12 @@
"smart_sensitivity_enabled": {
"name": "Automatic sensitivity"
},
"swap_inputs": {
"name": "Swap inputs"
},
"swap_outputs": {
"name": "Swap outputs"
},
"tamper_protection_enabled": {
"name": "Sabotage detection"
},
@@ -190,6 +190,24 @@ SWITCH_TYPES: dict[str, SHCSwitchEntityDescription] = {
on_value=True,
should_poll=False,
),
"swap_inputs": SHCSwitchEntityDescription(
key="swap_inputs",
translation_key="swap_inputs",
device_class=SwitchDeviceClass.SWITCH,
entity_category=EntityCategory.CONFIG,
on_key="swap_inputs",
on_value=True,
should_poll=False,
),
"swap_outputs": SHCSwitchEntityDescription(
key="swap_outputs",
translation_key="swap_outputs",
device_class=SwitchDeviceClass.SWITCH,
entity_category=EntityCategory.CONFIG,
on_key="swap_outputs",
on_value=True,
should_poll=False,
),
}
@@ -467,6 +485,34 @@ async def async_setup_entry(
if switch.supports_smart_sensitivity
)
entities.extend(
SHCSwitch(
hass=hass,
device=switch,
parent_id=shc_info.unique_id,
entry_id=config_entry.entry_id,
description=SWITCH_TYPES["swap_inputs"],
unique_id_suffix="swap_inputs",
)
for switch in session.device_helper.micromodule_relays
if getattr(switch, "supports_switch_configuration", False)
and getattr(switch, "swap_inputs", None) is not None
)
entities.extend(
SHCSwitch(
hass=hass,
device=switch,
parent_id=shc_info.unique_id,
entry_id=config_entry.entry_id,
description=SWITCH_TYPES["swap_outputs"],
unique_id_suffix="swap_outputs",
)
for switch in session.device_helper.micromodule_relays
if getattr(switch, "supports_switch_configuration", False)
and getattr(switch, "swap_outputs", None) is not None
)
async_add_entities(entities)
+6
View File
@@ -311,6 +311,9 @@ def micromodule_relay_device(
device_id: str = "hdm:ZigBee:relay1",
name: str = "Relay",
child_lock: bool = False,
supports_switch_configuration: bool = False,
swap_inputs: bool = False,
swap_outputs: bool = False,
) -> SHCMicromoduleRelay:
"""Build a minimal device double for the micromodule_relays bucket."""
device = create_autospec(SHCMicromoduleRelay, instance=True, spec_set=True)
@@ -324,6 +327,9 @@ def micromodule_relay_device(
device.deleted = False
device.status = "AVAILABLE"
device.child_lock = child_lock
device.supports_switch_configuration = supports_switch_configuration
device.swap_inputs = swap_inputs
device.swap_outputs = swap_outputs
return device
+111
View File
@@ -890,3 +890,114 @@ async def test_motion_detector2_no_smart_sensitivity_support(
await setup_integration(hass, mock_config_entry)
assert hass.states.get("switch.motion_detector_automatic_sensitivity") is None
@pytest.mark.parametrize(
"device_buckets",
[
{
"micromodule_relays": [
micromodule_relay_device(
supports_switch_configuration=True, swap_inputs=False
)
]
}
],
indirect=True,
)
@pytest.mark.usefixtures("mock_session")
async def test_micromodule_relay_swap_inputs(
hass: HomeAssistant,
mock_session: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""A Micromodule Relay's swap-inputs setting is exposed and controllable."""
await setup_integration(hass, mock_config_entry)
device = mock_session.device_helper.micromodule_relays[0]
state = hass.states.get("switch.relay_swap_inputs")
assert state is not None
assert state.state == "off"
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "switch.relay_swap_inputs"},
blocking=True,
)
assert device.swap_inputs is True
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "switch.relay_swap_inputs"},
blocking=True,
)
assert device.swap_inputs is False
@pytest.mark.parametrize(
"device_buckets",
[
{
"micromodule_relays": [
micromodule_relay_device(
supports_switch_configuration=True, swap_outputs=False
)
]
}
],
indirect=True,
)
@pytest.mark.usefixtures("mock_session")
async def test_micromodule_relay_swap_outputs(
hass: HomeAssistant,
mock_session: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""A Micromodule Relay's swap-outputs setting is exposed and controllable."""
await setup_integration(hass, mock_config_entry)
device = mock_session.device_helper.micromodule_relays[0]
state = hass.states.get("switch.relay_swap_outputs")
assert state is not None
assert state.state == "off"
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "switch.relay_swap_outputs"},
blocking=True,
)
assert device.swap_outputs is True
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "switch.relay_swap_outputs"},
blocking=True,
)
assert device.swap_outputs is False
@pytest.mark.parametrize(
"device_buckets",
[
{
"micromodule_relays": [
micromodule_relay_device(supports_switch_configuration=False)
]
}
],
indirect=True,
)
@pytest.mark.usefixtures("mock_session")
async def test_micromodule_relay_no_switch_configuration_support(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
) -> None:
"""No swap-inputs/outputs switches are created without switch-configuration support."""
await setup_integration(hass, mock_config_entry)
assert hass.states.get("switch.relay_swap_inputs") is None
assert hass.states.get("switch.relay_swap_outputs") is None