diff --git a/homeassistant/components/bosch_shc/strings.json b/homeassistant/components/bosch_shc/strings.json index 6a42437524bb..942933f9e374 100644 --- a/homeassistant/components/bosch_shc/strings.json +++ b/homeassistant/components/bosch_shc/strings.json @@ -144,6 +144,9 @@ "camera_light": { "name": "Camera light" }, + "camera_notification": { + "name": "Notifications" + }, "child_lock": { "name": "Child lock" }, diff --git a/homeassistant/components/bosch_shc/switch.py b/homeassistant/components/bosch_shc/switch.py index c59e13dbdf29..bf953c1f2763 100644 --- a/homeassistant/components/bosch_shc/switch.py +++ b/homeassistant/components/bosch_shc/switch.py @@ -9,6 +9,7 @@ from boschshcpy import ( CameraAmbientLightService, CameraFrontLightService, CameraLightService, + CameraNotificationService, PowerSwitchService, PrivacyModeService, SHCShutterContact2, @@ -88,6 +89,15 @@ SWITCH_TYPES: dict[str, SHCSwitchEntityDescription] = { on_value=PrivacyModeService.State.DISABLED, should_poll=True, ), + "camera360_notification": SHCSwitchEntityDescription( + key="camera360_notification", + translation_key="camera_notification", + device_class=SwitchDeviceClass.SWITCH, + entity_category=EntityCategory.CONFIG, + on_key="cameranotification", + on_value=CameraNotificationService.State.ENABLED, + should_poll=True, + ), "cameraoutdoorgen2": SHCSwitchEntityDescription( key="cameraoutdoorgen2", device_class=SwitchDeviceClass.SWITCH, @@ -336,6 +346,18 @@ async def async_setup_entry( for switch in session.device_helper.camera_360 ) + entities.extend( + SHCSwitch( + hass=hass, + device=switch, + parent_id=shc_info.unique_id, + entry_id=config_entry.entry_id, + description=SWITCH_TYPES["camera360_notification"], + unique_id_suffix="camera360_notification", + ) + for switch in session.device_helper.camera_360 + ) + entities.extend( SHCSwitch( hass=hass, diff --git a/tests/components/bosch_shc/conftest.py b/tests/components/bosch_shc/conftest.py index c2d5771f49fc..ac66e05b931e 100644 --- a/tests/components/bosch_shc/conftest.py +++ b/tests/components/bosch_shc/conftest.py @@ -12,10 +12,12 @@ from boschshcpy import ( CameraAmbientLightService, CameraFrontLightService, CameraLightService, + CameraNotificationService, PowerSwitchService, PrivacyModeService, RoutingService, SHCBatteryDevice, + SHCCamera360, SHCCameraEyes, SHCCameraOutdoorGen2, SHCLightSwitchBSM, @@ -193,6 +195,28 @@ def camera_eyes_device( return device +def camera_360_device( + device_id: str = "hdm:Cameras:360-1", + name: str = "Camera 360", + privacymode: PrivacyModeService.State = PrivacyModeService.State.ENABLED, + cameranotification: CameraNotificationService.State = CameraNotificationService.State.DISABLED, +) -> SHCCamera360: + """Build a minimal device double for the camera_360 bucket.""" + device = create_autospec(SHCCamera360, 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 = "CAMERA_360" + device.device_services = [] + device.deleted = False + device.status = "AVAILABLE" + device.privacymode = privacymode + device.cameranotification = cameranotification + return device + + def camera_outdoor_gen2_device( device_id: str = "hdm:Cameras:outdoorgen2-1", name: str = "Outdoor Camera", diff --git a/tests/components/bosch_shc/test_switch.py b/tests/components/bosch_shc/test_switch.py index c9facef23119..e8910b3dd2c9 100644 --- a/tests/components/bosch_shc/test_switch.py +++ b/tests/components/bosch_shc/test_switch.py @@ -8,6 +8,7 @@ from boschshcpy import ( CameraAmbientLightService, CameraFrontLightService, CameraLightService, + CameraNotificationService, PrivacyModeService, SilentModeService, ThermostatService, @@ -25,6 +26,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from .conftest import ( + camera_360_device, camera_eyes_device, camera_outdoor_gen2_device, light_switch_bsm_device, @@ -1049,6 +1051,50 @@ async def test_camera_eyes_cameralight( assert device.cameralight is False +@pytest.mark.parametrize( + "device_buckets", + [ + { + "camera_360": [ + camera_360_device( + cameranotification=CameraNotificationService.State.ENABLED + ) + ] + } + ], + indirect=True, +) +@pytest.mark.usefixtures("mock_session") +async def test_camera_360_notification( + hass: HomeAssistant, + mock_session: MagicMock, + mock_config_entry: MockConfigEntry, +) -> None: + """A Camera 360's notifications are exposed and controllable as a switch.""" + await setup_integration(hass, mock_config_entry) + device = mock_session.device_helper.camera_360[0] + + state = hass.states.get("switch.camera_360_notifications") + assert state is not None + assert state.state == "on" + + await hass.services.async_call( + SWITCH_DOMAIN, + SERVICE_TURN_OFF, + {ATTR_ENTITY_ID: "switch.camera_360_notifications"}, + blocking=True, + ) + assert device.cameranotification is False + + await hass.services.async_call( + SWITCH_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: "switch.camera_360_notifications"}, + blocking=True, + ) + assert device.cameranotification is True + + @pytest.mark.parametrize( "device_buckets", [