Skip to content

Commit

Permalink
Merge pull request #527 from fronzbot/dev
Browse files Browse the repository at this point in the history
0.18.0
  • Loading branch information
fronzbot authored Dec 12, 2021
2 parents ff306b8 + 35c99ac commit d78d7e1
Show file tree
Hide file tree
Showing 10 changed files with 329 additions and 20 deletions.
9 changes: 9 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: 2
updates:
- package-ecosystem: pip
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
reviewers:
- fronzbot
26 changes: 26 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,29 @@ Changelog

A list of changes between each release

0.18.0 (2021-12-11)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

**Bugfixes:**

- None

**New Features:**

- Support for Blink Doorbell (`@magicalyak <https://github.com/fronzbot/blinkpy/pull/526>`__)

**Other:**

- Bump pytest-cov to 3.0.0
- Bump pre-commit to 2.15.0
- Bump pytest to 6.2.5
- Bump pylint to 2.10.2
- Bump pygments to 2.10.0
- Bump flake8-docstrings to 1.6.0
- Bump pydocstyle to 6.0.0
- Bump coverage to 5.5


0.17.1 (2021-02-18)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand All @@ -15,14 +38,17 @@ A list of changes between each release
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

**Bugfixes:**

- Fix video downloading bug (`#424 <https://github.com/fronzbot/blinkpy/pull/424>`__)
- Fix repeated authorization email bug (`#432 <https://github.com/fronzbot/blinkpy/pull/432>`__ and `#428 <https://github.com/fronzbot/blinkpy/pull/428>`__)

**New Features:**

- Add logout method (`#429 <https://github.com/fronzbot/blinkpy/pull/429>`__)
- Add camera record method (`#430 <https://github.com/fronzbot/blinkpy/pull/430>`__)

**Other:**

- Add debug script to main repo to help with general debug
- Upgrade login endpoint from v4 to v5
- Add python 3.9 support
Expand Down
36 changes: 35 additions & 1 deletion blinkpy/blinkpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from slugify import slugify

from blinkpy import api
from blinkpy.sync_module import BlinkSyncModule, BlinkOwl
from blinkpy.sync_module import BlinkSyncModule, BlinkOwl, BlinkLotus
from blinkpy.helpers import util
from blinkpy.helpers.constants import (
DEFAULT_MOTION_INTERVAL,
Expand Down Expand Up @@ -180,6 +180,36 @@ def setup_owls(self):
self.network_ids.extend(network_list)
return camera_list

def setup_lotus(self):
"""Check for doorbells cameras."""
network_list = []
camera_list = []
try:
for lotus in self.homescreen["doorbells"]:
name = lotus["name"]
network_id = str(lotus["network_id"])
if network_id in self.network_ids:
camera_list.append(
{
network_id: {
"name": name,
"id": network_id,
"type": "doorbell",
}
}
)
continue
if lotus["onboarded"]:
network_list.append(str(network_id))
self.sync[name] = BlinkLotus(self, name, network_id, lotus)
self.sync[name].start()
except KeyError:
# No sync-less devices found
pass

self.network_ids.extend(network_list)
return camera_list

def setup_camera_list(self):
"""Create camera list for onboarded networks."""
all_cameras = {}
Expand All @@ -194,9 +224,13 @@ def setup_camera_list(self):
{"name": camera["name"], "id": camera["id"]}
)
mini_cameras = self.setup_owls()
lotus_cameras = self.setup_lotus()
for camera in mini_cameras:
for network, camera_info in camera.items():
all_cameras[network].append(camera_info)
for camera in lotus_cameras:
for network, camera_info in camera.items():
all_cameras[network].append(camera_info)
return all_cameras
except (KeyError, TypeError):
_LOGGER.error("Unable to retrieve cameras from response %s", response)
Expand Down
39 changes: 39 additions & 0 deletions blinkpy/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,42 @@ def get_liveview(self):
server_split[0] = "rtsps:"
link = "".join(server_split)
return link


class BlinkDoorbell(BlinkCamera):
"""Define a class for a Blink Doorbell camera."""

def __init__(self, sync):
"""Initialize a Blink Doorbell."""
super().__init__(sync)
self.camera_type = "doorbell"

@property
def arm(self):
"""Return camera arm status."""
return self.sync.arm

@arm.setter
def arm(self, value):
"""Set camera arm status."""
_LOGGER.warning(
"Individual camera motion detection enable/disable for Blink Doorbell is unsupported at this time."
)

def snap_picture(self):
"""Snap picture for a blink doorbell camera."""
url = f"{self.sync.urls.base_url}/api/v1/accounts/{self.sync.blink.account_id}/networks/{self.network_id}/lotus/{self.camera_id}/thumbnail"
return api.http_post(self.sync.blink, url)

def get_sensor_info(self):
"""Get sensor info for blink doorbell camera."""

def get_liveview(self):
"""Get liveview link."""
url = f"{self.sync.urls.base_url}/api/v1/accounts/{self.sync.blink.account_id}/networks/{self.network_id}/lotus/{self.camera_id}/liveview"
response = api.http_post(self.sync.blink, url)
server = response["server"]
server_split = server.split(":")
server_split[0] = "rtsps:"
link = "".join(server_split)
return link
4 changes: 2 additions & 2 deletions blinkpy/helpers/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import os

MAJOR_VERSION = 0
MINOR_VERSION = 17
PATCH_VERSION = 1
MINOR_VERSION = 18
PATCH_VERSION = 0

__version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}.{PATCH_VERSION}"

Expand Down
87 changes: 84 additions & 3 deletions blinkpy/sync_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from requests.structures import CaseInsensitiveDict
from blinkpy import api
from blinkpy.camera import BlinkCamera, BlinkCameraMini
from blinkpy.camera import BlinkCamera, BlinkCameraMini, BlinkDoorbell
from blinkpy.helpers.util import time_to_seconds
from blinkpy.helpers.constants import ONLINE

Expand Down Expand Up @@ -126,11 +126,14 @@ def update_cameras(self, camera_type=BlinkCamera):
name = camera_config["name"]
self.motion[name] = False
owl_info = self.get_owl_info(name)
lotus_info = self.get_lotus_info(name)
if blink_camera_type == "mini":
camera_type = BlinkCameraMini
if blink_camera_type == "lotus":
camera_type = BlinkDoorbell
self.cameras[name] = camera_type(self)
camera_info = self.get_camera_info(
camera_config["id"], owl_info=owl_info
camera_config["id"], owl_info=owl_info, lotus_info=lotus_info
)
self.cameras[name].update(camera_info, force_cache=True, force=True)

Expand All @@ -149,6 +152,16 @@ def get_owl_info(self, name):
pass
return None

def get_lotus_info(self, name):
"""Extract lotus information."""
try:
for doorbell in self.blink.homescreen["doorbells"]:
if doorbell["name"] == name:
return doorbell
except (TypeError, KeyError):
pass
return None

def get_events(self, **kwargs):
"""Retrieve events from server."""
force = kwargs.pop("force", False)
Expand All @@ -164,6 +177,9 @@ def get_camera_info(self, camera_id, **kwargs):
owl = kwargs.get("owl_info", None)
if owl is not None:
return owl
lotus = kwargs.get("lotus_info", None)
if lotus is not None:
return lotus
response = api.request_camera_info(self.blink, self.network_id, camera_id)
try:
return response["camera"][0]
Expand All @@ -190,7 +206,9 @@ def refresh(self, force_cache=False):
for camera_name in self.cameras.keys():
camera_id = self.cameras[camera_name].camera_id
camera_info = self.get_camera_info(
camera_id, owl_info=self.get_owl_info(camera_name)
camera_id,
owl_info=self.get_owl_info(camera_name),
lotus_info=self.get_lotus_info(camera_name),
)
self.cameras[camera_name].update(camera_info, force_cache=force_cache)
self.available = True
Expand Down Expand Up @@ -294,3 +312,66 @@ def network_info(self):
@network_info.setter
def network_info(self, value):
"""Set network_info property."""


class BlinkLotus(BlinkSyncModule):
"""Representation of a sync-less device."""

def __init__(self, blink, name, network_id, response):
"""Initialize a sync-less object."""
cameras = [{"name": name, "id": response["id"]}]
super().__init__(blink, name, network_id, cameras)
self.sync_id = response["id"]
self.serial = response["serial"]
self.status = response["enabled"]
if not self.serial:
self.serial = f"{network_id}-{self.sync_id}"

def sync_initialize(self):
"""Initialize a sync-less module."""
self.summary = {
"id": self.sync_id,
"name": self.name,
"serial": self.serial,
"status": self.status,
"onboarded": True,
"account_id": self.blink.account_id,
"network_id": self.network_id,
}
return self.summary

def update_cameras(self, camera_type=BlinkDoorbell):
"""Update sync-less cameras."""
return super().update_cameras(camera_type=BlinkDoorbell)

def get_camera_info(self, camera_id, **kwargs):
"""Retrieve camera information."""
try:
for doorbell in self.blink.homescreen["doorbells"]:
if doorbell["name"] == self.name:
self.status = doorbell["enabled"]
return doorbell
except (TypeError, KeyError):
pass
return None

def get_network_info(self):
"""Get network info for sync-less module."""
return True

@property
def network_info(self):
"""Format lotus response to resemble sync module."""
return {
"network": {
"id": self.network_id,
"name": self.name,
"armed": self.status,
"sync_module_error": False,
"account_id": self.blink.account_id,
}
}

@network_info.setter
def network_info(self, value):
"""Set network_info property."""
18 changes: 9 additions & 9 deletions requirements_test.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
black==19.10b0
coverage==5.4
flake8==3.8.4
flake8-docstrings==1.5.0
pre-commit==2.10.1
pylint==2.6.2
pydocstyle==5.1.1
pytest==6.2.2
pytest-cov==2.11.1
coverage==5.5
flake8==3.9.1
flake8-docstrings==1.6.0
pre-commit==2.15.0
pylint==2.10.2
pydocstyle==6.0.0
pytest==6.2.5
pytest-cov==3.0.0
pytest-sugar==0.9.4
pytest-timeout==1.4.2
restructuredtext-lint==1.3.2
pygments==2.8.0
pygments==2.10.0
testtools>=2.4.0
Loading

0 comments on commit d78d7e1

Please sign in to comment.