"""Define SimpliSafe cameras (SimpliCams).""" from __future__ import annotations from enum import Enum from typing import TYPE_CHECKING, Any, cast from urllib.parse import urlencode from simplipy.const import LOGGER from simplipy.device import DeviceV3 if TYPE_CHECKING: from simplipy.system.v3 import SystemV3 DEFAULT_AUDIO_ENCODING = "AAC" DEFAULT_MEDIA_URL_BASE = "https://media.simplisafe.com/v1" DEFAULT_VIDEO_WIDTH = 1280 class CameraTypes(Enum): """Define camera types based on internal SimpliSafe ID number.""" CAMERA = 0 DOORBELL = 1 OUTDOOR_CAMERA = 2 UNKNOWN = 99 MODEL_TO_TYPE = { "SS001": CameraTypes.CAMERA, "SS002": CameraTypes.DOORBELL, "SS003": CameraTypes.CAMERA, "SSOBCM4": CameraTypes.OUTDOOR_CAMERA, } class Camera(DeviceV3): """Define a SimpliCam.""" _system: SystemV3 @property def camera_settings(self) -> dict[str, Any]: """Return the camera settings. Returns: A dictionary of camera settings. """ return cast( dict[str, Any], self._system.camera_data[self._serial]["cameraSettings"] ) @property def camera_type(self) -> CameraTypes: """Return the type of camera. Returns: The camera type. """ try: return MODEL_TO_TYPE[self._system.camera_data[self._serial]["model"]] except KeyError: LOGGER.error( "Unknown camera type: %s", self._system.camera_data[self._serial]["model"], ) return CameraTypes.UNKNOWN @property def name(self) -> str: """Return the camera name. Returns: The camera name. """ return cast( str, self._system.camera_data[self._serial]["cameraSettings"]["cameraName"] ) @property def serial(self) -> str: """Return the camera's serial number. Returns: The camera serial number. """ return self._serial @property def shutter_open_when_away(self) -> bool: """Return whether the privacy shutter is open in away mode. Returns: The camera's "shutter open when away" status. """ val = self._system.camera_data[self._serial]["cameraSettings"]["shutterAway"] return cast(bool, val == "open") @property def shutter_open_when_home(self) -> bool: """Return whether the privacy shutter is open in home mode. Returns: The camera's "shutter open when home" status. """ val = self._system.camera_data[self._serial]["cameraSettings"]["shutterHome"] return cast(bool, val == "open") @property def shutter_open_when_off(self) -> bool: """Return whether the privacy shutter is open when the alarm is disarmed. Returns: The camera's "shutter open when off" status. """ val = self._system.camera_data[self._serial]["cameraSettings"]["shutterOff"] return cast(bool, val == "open") @property def status(self) -> str: """Return the camera status. Returns: The camera status. """ return cast(str, self._system.camera_data[self._serial]["status"]) @property def subscription_enabled(self) -> bool: """Return the camera subscription status. Returns: The camera subscription status. """ return cast( bool, self._system.camera_data[self._serial]["subscription"]["enabled"] ) def as_dict(self) -> dict[str, Any]: """Return dictionary version of this device. Returns: A dict representation of this device. """ return { "camera_settings": self.camera_settings, "camera_type": self.camera_type.value, "name": self.name, "serial": self.serial, "shutter_open_when_away": self.shutter_open_when_away, "shutter_open_when_home": self.shutter_open_when_home, "shutter_open_when_off": self.shutter_open_when_off, "status": self.status, "subscription_enabled": self.subscription_enabled, } def video_url( self, width: int = DEFAULT_VIDEO_WIDTH, audio_encoding: str = DEFAULT_AUDIO_ENCODING, **kwargs: Any, ) -> str: """Return the camera video URL. Args: width: The video width. audio_encoding: The audio encoding. kwargs: Additional parameters. Returns: The camera video URL. """ url_params = {"x": width, "audioEncoding": audio_encoding, **kwargs} return f"{DEFAULT_MEDIA_URL_BASE}/{self.serial}/flv?{urlencode(url_params)}"