Added image and video caching

This commit is contained in:
Kevin Fronczak
2018-09-25 12:03:32 -04:00
parent ae26a9e371
commit 672f59ab4e
2 changed files with 48 additions and 19 deletions
+44 -15
View File
@@ -16,8 +16,8 @@ import json
import getpass
from shutil import copyfileobj
import logging
import requests
import time
import requests
from requests.structures import CaseInsensitiveDict
import blinkpy.helpers.errors as ERROR
from blinkpy.helpers.constants import (
@@ -124,6 +124,8 @@ class BlinkCamera():
self.camera_config = dict()
self.motion_enabled = None
self.last_record = list()
self._cached_image = None
self._cached_video = None
@property
def attributes(self):
@@ -177,6 +179,20 @@ class BlinkCamera():
"""Return temperature in celcius."""
return round((self.temperature - 32) / 9.0 * 5.0, 1)
@property
def image_from_cache(self):
"""Return the most recently cached image."""
if self._cached_image:
return self._cached_image
return None
@property
def video_from_cache(self):
"""Return the most recently cached video."""
if self._cached_video:
return self._cached_video
return None
def snap_picture(self):
"""Take a picture with camera to create a new thumbnail."""
_request(self.blink, url=self.image_link,
@@ -192,17 +208,21 @@ class BlinkCamera():
_request(self.blink, url=url + 'disable',
headers=self.header, reqtype='post')
def update(self, values):
def update(self, values, force_cache=False, skip_cache=False):
"""Update camera information."""
self.name = values['name']
self._status = values['active']
self.clip = "{}{}".format(
self.urls.base_url, values['video'])
self.thumbnail = "{}{}.jpg".format(
new_thumbnail = "{}{}.jpg".format(
self.urls.base_url, values['thumbnail'])
self._battery_string = values['battery']
self.notifications = values['notifications']
update_cached_image = False
if new_thumbnail != self.thumbnail or self._cached_image is None:
update_cached_image = True
self.thumbnail = new_thumbnail
try:
cfg = self.blink.camera_config_request(self.id)
self.camera_config = cfg
@@ -239,6 +259,16 @@ class BlinkCamera():
_LOGGER.warning("Could not extract clip info from camera %s",
self.name)
if not skip_cache:
if update_cached_image or force_cache:
self._cached_image = _request(
self.blink, url=self.image_refresh(), headers=self.header,
reqtype='get', stream=True, json_resp=False)
if (self.clip is None) or self.motion_detected or force_cache:
self._cached_video = _request(
self.blink, url=self.clip, headers=self.header,
reqtype='get', stream=True, json_resp=False)
def image_refresh(self):
"""Refresh current thumbnail."""
url = self.urls.home_url
@@ -259,22 +289,18 @@ class BlinkCamera():
def image_to_file(self, path):
"""Write image to file."""
_LOGGER.debug("Writing image from %s to %s", self.name, path)
thumb = self.image_refresh()
if not thumb:
thumb = self.thumbnail
response = _request(self.blink, url=thumb, headers=self.header,
reqtype='get', stream=True, json_resp=False)
response = self._cached_image
if response.status_code == 200:
with open(path, 'wb') as imgfile:
copyfileobj(response.raw, imgfile)
else:
print(response)
_LOGGER.error("Cannot write image to file, response %s",
response.status_code)
def video_to_file(self, path):
"""Write video to file."""
_LOGGER.debug("Writing video from %s to %s", self.name, path)
response = _request(self.blink, url=self.clip, headers=self.header,
reqtype='get', stream=True, json_resp=False)
response = self._cached_video
with open(path, 'wb') as vidfile:
copyfileobj(response.raw, vidfile)
@@ -282,7 +308,8 @@ class BlinkCamera():
class Blink():
"""Class to initialize communication and sync module."""
def __init__(self, username=None, password=None, refresh_rate=REFRESH_RATE):
def __init__(self, username=None, password=None,
refresh_rate=REFRESH_RATE):
"""Initialize Blink system."""
self._username = username
self._password = password
@@ -365,12 +392,13 @@ class Blink():
value_to_append)
_request(self, url=url, headers=self._auth_header, reqtype='post')
def refresh(self):
def refresh(self, force_cache=False):
"""Get all blink cameras and pulls their most recent status."""
current_time = int(time.time())
last_refresh = self.last_refresh
if last_refresh is None:
last_refresh = 0
force_cache = True
if current_time >= (last_refresh + self.refresh_rate):
_LOGGER.debug("Attempting refresh of cameras.")
self._summary = self._summary_request()
@@ -383,8 +411,9 @@ class Blink():
try:
if str(element['device_id']) == camera.id:
element['video'] = self.videos[name][0]['clip']
element['thumbnail'] = self.videos[name][0]['thumb']
camera.update(element)
thumb = self.videos[name][0]['thumb']
element['thumbnail'] = thumb
camera.update(element, force_cache=force_cache)
except KeyError:
pass
self.last_refresh = int(time.time())
+4 -4
View File
@@ -70,7 +70,7 @@ class TestBlinkCameraSetup(unittest.TestCase):
for name in self.blink.cameras:
camera = self.blink.cameras[name]
camera.update(self.camera_config)
camera.update(self.camera_config, skip_cache=True)
self.assertEqual(camera.id, '1111')
self.assertEqual(camera.name, 'foobar')
self.assertEqual(camera.armed, False)
@@ -100,7 +100,7 @@ class TestBlinkCameraSetup(unittest.TestCase):
camera_config['notifications'] = 4
for name in self.blink.cameras:
camera = self.blink.cameras[name]
camera.update(camera_config)
camera.update(camera_config, skip_cache=True)
self.assertEqual(camera.armed, True)
self.assertEqual(
camera.thumbnail,
@@ -115,7 +115,7 @@ class TestBlinkCameraSetup(unittest.TestCase):
self.assertEqual(camera.battery_string, "Low")
self.assertEqual(camera.notifications, 4)
camera_config['battery'] = -10
camera.update(camera_config)
camera.update(camera_config, skip_cache=True)
self.assertEqual(camera.battery_string, "Unknown")
def test_camera_case(self):
@@ -136,7 +136,7 @@ class TestBlinkCameraSetup(unittest.TestCase):
for name in self.blink.cameras:
camera = self.blink.cameras[name]
camera.update(self.camera_config)
camera.update(self.camera_config, skip_cache=True)
camera_attr = camera.attributes
self.assertEqual(camera_attr['device_id'], '1111')
self.assertEqual(camera_attr['name'], 'foobar')