bosch_shc: add Outdoor Camera Gen2 ambient light switch (#183632)

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Thomas
2026-09-30 12:08:30 +01:00
committed by GitHub
co-authored by Claude Sonnet 5.5
parent 06aabd6e5e
commit 7702b2103d
4 changed files with 73 additions and 0 deletions
@@ -135,6 +135,9 @@
"bypass_infinite": {
"name": "Break function never expires"
},
"camera_ambientlight": {
"name": "Ambient light"
},
"camera_light": {
"name": "Camera light"
},
@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING, Any, override
from boschshcpy import (
BypassService,
CameraAmbientLightService,
CameraLightService,
PowerSwitchService,
PrivacyModeService,
@@ -93,6 +94,15 @@ SWITCH_TYPES: dict[str, SHCSwitchEntityDescription] = {
on_value=PrivacyModeService.State.DISABLED,
should_poll=True,
),
"cameraoutdoorgen2_cameraambientlight": SHCSwitchEntityDescription(
key="cameraoutdoorgen2_cameraambientlight",
translation_key="camera_ambientlight",
device_class=SwitchDeviceClass.SWITCH,
entity_category=EntityCategory.CONFIG,
on_key="cameraambientlight",
on_value=CameraAmbientLightService.State.ON,
should_poll=True,
),
"child_lock": SHCSwitchEntityDescription(
key="child_lock",
translation_key="child_lock",
@@ -327,6 +337,18 @@ async def async_setup_entry(
for switch in session.device_helper.camera_outdoor_gen2
)
entities.extend(
SHCSwitch(
hass=hass,
device=switch,
parent_id=shc_info.unique_id,
entry_id=config_entry.entry_id,
description=SWITCH_TYPES["cameraoutdoorgen2_cameraambientlight"],
unique_id_suffix="cameraoutdoorgen2_cameraambientlight",
)
for switch in session.device_helper.camera_outdoor_gen2
)
entities.extend(
SHCSwitch(
hass=hass,
+3
View File
@@ -9,6 +9,7 @@ from boschshcpy import (
AlarmService,
BatteryLevelService,
BypassService,
CameraAmbientLightService,
CameraLightService,
PowerSwitchService,
PrivacyModeService,
@@ -195,6 +196,7 @@ def camera_outdoor_gen2_device(
device_id: str = "hdm:Cameras:outdoorgen2-1",
name: str = "Outdoor Camera",
privacymode: PrivacyModeService.State = PrivacyModeService.State.ENABLED,
cameraambientlight: CameraAmbientLightService.State = CameraAmbientLightService.State.OFF,
) -> SHCCameraOutdoorGen2:
"""Build a minimal device double for the camera_outdoor_gen2 bucket."""
device = create_autospec(SHCCameraOutdoorGen2, instance=True, spec_set=True)
@@ -208,6 +210,7 @@ def camera_outdoor_gen2_device(
device.deleted = False
device.status = "AVAILABLE"
device.privacymode = privacymode
device.cameraambientlight = cameraambientlight
return device
+45
View File
@@ -5,6 +5,7 @@ from unittest.mock import MagicMock, patch
from boschshcpy import (
BypassService,
CameraAmbientLightService,
CameraLightService,
PrivacyModeService,
SilentModeService,
@@ -1087,3 +1088,47 @@ async def test_camera_outdoor_gen2_privacy_mode(
blocking=True,
)
assert device.privacymode is False
@pytest.mark.parametrize(
"device_buckets",
[
{
"camera_outdoor_gen2": [
camera_outdoor_gen2_device(
cameraambientlight=CameraAmbientLightService.State.OFF
)
]
}
],
indirect=True,
)
@pytest.mark.usefixtures("mock_session")
async def test_camera_outdoor_gen2_ambient_light(
hass: HomeAssistant,
mock_session: MagicMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""An Outdoor Camera Gen2's ambient light is exposed and controllable as a switch."""
await setup_integration(hass, mock_config_entry)
device = mock_session.device_helper.camera_outdoor_gen2[0]
state = hass.states.get("switch.outdoor_camera_ambient_light")
assert state is not None
assert state.state == "off"
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "switch.outdoor_camera_ambient_light"},
blocking=True,
)
assert device.cameraambientlight is True
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "switch.outdoor_camera_ambient_light"},
blocking=True,
)
assert device.cameraambientlight is False