Skip to content

Commit

Permalink
Added support to expose camera and doorbell data (#182)
Browse files Browse the repository at this point in the history
* Added support to expose camera and doorbell data

* Added support to expose camera and doorbell data

* Refactored cameras and doorbells, fixed reviewed

* Styling updates

* Revert version property on system class

* Refactored code to avoid duplication

* Simplifying camera/doorbell logic

* Removed doorbells property from system

* Improve support for camera type

* Refactoring
  • Loading branch information
nzapponi authored Oct 8, 2020
1 parent f8066d6 commit cf11b61
Show file tree
Hide file tree
Showing 9 changed files with 1,066 additions and 190 deletions.
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
- Scott Newman (https://github.com/greencoder)
- Scott Silence (https://github.com/ssilence5)
- William Scanlon (https://github.com/w1ll1am23)
- Niccolo Zapponi (https://github.com/nzapponi)
1 change: 1 addition & 0 deletions simplipy/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ async def get_systems(self) -> Dict[str, System]:
system = system_class(
self.request, self._get_subscription_data, system_data["location"]
)

await system.update(include_system=False)
systems[system_data["sid"]] = system

Expand Down
114 changes: 114 additions & 0 deletions simplipy/camera.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import logging
from urllib.parse import urlencode

from simplipy.entity import Entity

_LOGGER: logging.Logger = logging.getLogger(__name__)

MEDIA_URL_BASE: str = "https://media.simplisafe.com/v1"
DEFAULT_VIDEO_WIDTH: int = 1280
DEFAULT_AUDIO_ENCODING: str = "AAC"

CAMERA_MODEL_CAMERA: str = "CAMERA"
CAMERA_MODEL_DOORBELL: str = "DOORBELL"
CAMERA_MODEL_UNKNOWN: str = "CAMERA_MODEL_UNKNOWN"

MODEL_TO_TYPE = {
"SS001": CAMERA_MODEL_CAMERA,
"SS002": CAMERA_MODEL_DOORBELL,
}


class Camera(Entity):
"""A SimpliCam."""

@property
def camera_settings(self) -> dict:
"""Return the camera settings.
:rtype: ``dict``
"""
return self.entity_data["cameraSettings"]

@property
def camera_type(self) -> str:
"""Return the type of camera.
:rtype: ``str``
"""

try:
return MODEL_TO_TYPE[self.entity_data["model"]]
except KeyError:
_LOGGER.error("Unknown camera type: %s", self.entity_data["model"])
return CAMERA_MODEL_UNKNOWN

@property
def name(self) -> str:
"""Return the entity name.
:rtype: ``str``
"""
return self.entity_data["cameraSettings"]["cameraName"]

@property
def serial(self) -> str:
"""Return the entity's serial number.
:rtype: ``str``
"""
return self.entity_data["uuid"]

@property
def shutter_open_when_away(self) -> bool:
"""Return whether the privacy shutter is open when alarm system is armed in away mode.
:rtype: ``bool``
"""
return self.camera_settings["shutterAway"] == "open"

@property
def shutter_open_when_home(self) -> bool:
"""Return whether the privacy shutter is open when alarm system is armed in home mode.
:rtype: ``bool``
"""
return self.camera_settings["shutterHome"] == "open"

@property
def shutter_open_when_off(self) -> bool:
"""Return whether the privacy shutter is open when alarm system is off.
:rtype: ``bool``
"""
return self.camera_settings["shutterOff"] == "open"

@property
def status(self) -> str:
"""Return the camera status.
:rtype: ``str``
"""
return self.entity_data["status"]

@property
def subscription_enabled(self) -> bool:
"""Return the camera subscription status.
:rtype: ``bool``
"""
return self.entity_data["subscription"]["enabled"]

def video_url(
self,
width: int = DEFAULT_VIDEO_WIDTH,
audio_encoding: str = DEFAULT_AUDIO_ENCODING,
**kwargs,
) -> str:
"""Return the camera video URL.
:rtype: ``str``
"""
url_params = {"x": width, "audioEncoding": audio_encoding, **kwargs}

return f"{MEDIA_URL_BASE}/{self.serial}/flv?{urlencode(url_params)}"
20 changes: 20 additions & 0 deletions simplipy/system/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import logging
from typing import Any, Callable, Coroutine, Dict, List, Optional, Set, Type, Union

from simplipy.camera import Camera
from simplipy.entity import Entity, EntityTypes
from simplipy.errors import PinError, SimplipyError
from simplipy.lock import Lock
Expand Down Expand Up @@ -197,6 +198,25 @@ def alarm_going_off(self) -> bool:
"""
return self._location_info["system"]["isAlarming"]

@property
def cameras(self) -> Dict[str, Camera]:
"""Return list of cameras and doorbells.
:rtype: ``Dict[str, :meth:`simplipy.camera.Camera`]``
"""

cameras_doorbells = [
Camera(
self._request,
self._get_entities,
self.system_id,
EntityTypes.camera,
camera,
)
for camera in self._location_info["system"]["cameras"]
]
return {camera.serial: camera for camera in cameras_doorbells}

@property # type: ignore
@guard_from_missing_data()
def connection_type(self) -> str:
Expand Down
3 changes: 3 additions & 0 deletions tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
TEST_ACCESS_TOKEN = "abcde12345"
TEST_ACCOUNT_ID = 12345
TEST_ADDRESS = "1234 Main Street"
TEST_CAMERA_ID = "1234567890"
TEST_CAMERA_ID_2 = "1234567891"
TEST_CAMERA_TYPE = "CAMERA"
TEST_CLIENT_ID = "12345DEFG"
TEST_EMAIL = "[email protected]"
TEST_LOCK_ID = "987"
Expand Down
Loading

0 comments on commit cf11b61

Please sign in to comment.