Modified tests, added homescreen thumbnail backup Fixes #93

This commit is contained in:
Kevin Fronczak
2018-10-15 20:52:05 -04:00
parent f7a5b5cc03
commit 1b9bba7c3d
7 changed files with 139 additions and 13 deletions
+3 -3
View File
@@ -56,7 +56,7 @@ def request_command_status(blink, network, command_id):
return http_get(blink, url) return http_get(blink, url)
def request_homescreen(blink, network): def request_homescreen(blink):
"""Request homescreen info.""" """Request homescreen info."""
url = "{}/homescreen".format(blink.urls.base_url) url = "{}/homescreen".format(blink.urls.base_url)
return http_get(blink, url) return http_get(blink, url)
@@ -144,8 +144,8 @@ def http_get(blink, url, stream=False, json=True):
""" """
if blink.auth_header is None: if blink.auth_header is None:
raise BlinkException(ERROR.AUTH_TOKEN) raise BlinkException(ERROR.AUTH_TOKEN)
return http_req(blink, url=url, headers=blink.auth_header, reqtype='get', return http_req(blink, url=url, headers=blink.auth_header,
stream=stream, json_resp=json) reqtype='get', stream=stream, json_resp=json)
def http_post(blink, url): def http_post(blink, url):
+31 -4
View File
@@ -102,16 +102,29 @@ class BlinkCamera():
self.battery_state = config['battery_state'] self.battery_state = config['battery_state']
self.temperature = config['temperature'] self.temperature = config['temperature']
self.wifi_strength = config['wifi_strength'] self.wifi_strength = config['wifi_strength']
if config['thumbnail']:
new_thumbnail = "{}{}.jpg".format(self.sync.urls.base_url,
config['thumbnail'])
# Check if thumbnail exists in config, if not try to
# get it from the homescreen info in teh sync module
# otherwise set it to None and log an error
new_thumbnail = None
if config['thumbnail']:
thumb_addr = config['thumbnail']
else:
thumb_addr = self.get_thumb_from_homescreen()
if thumb_addr is not None:
new_thumbnail = "{}{}.jpg".format(self.sync.urls.base_url,
thumb_addr)
# Check if a new motion clip has been recorded
# check_for_motion_method sets motion_detected variable
self.check_for_motion() self.check_for_motion()
if self.last_record: if self.last_record:
clip_addr = self.sync.all_clips[self.name][self.last_record[0]] clip_addr = self.sync.all_clips[self.name][self.last_record[0]]
self.clip = "{}{}".format(self.sync.urls.base_url, self.clip = "{}{}".format(self.sync.urls.base_url,
clip_addr) clip_addr)
# If the thumbnail or clip have changed, update the cache
update_cached_image = False update_cached_image = False
if new_thumbnail != self.thumbnail or self._cached_image is None: if new_thumbnail != self.thumbnail or self._cached_image is None:
update_cached_image = True update_cached_image = True
@@ -121,7 +134,7 @@ class BlinkCamera():
if self._cached_video is None or self.motion_detected: if self._cached_video is None or self.motion_detected:
update_cached_video = True update_cached_video = True
if update_cached_image or force_cache: if new_thumbnail is not None and (update_cached_image or force_cache):
self._cached_image = api.http_get(self.sync.blink, self._cached_image = api.http_get(self.sync.blink,
url=self.thumbnail, url=self.thumbnail,
stream=True, stream=True,
@@ -175,3 +188,17 @@ class BlinkCamera():
response = self._cached_video response = self._cached_video
with open(path, 'wb') as vidfile: with open(path, 'wb') as vidfile:
copyfileobj(response.raw, vidfile) copyfileobj(response.raw, vidfile)
def get_thumb_from_homescreen(self):
"""Retrieve thumbnail from homescreen."""
for device in self.sync.homescreen['devices']:
try:
device_type = device['device_type']
device_name = device['name']
device_thumb = device['thumbnail']
if device_type == 'camera' and device_name == self.name:
return device_thumb
except KeyError:
pass
_LOGGER.error("Could not find thumbnail for camera %s", self.name)
return None
+10 -3
View File
@@ -1,9 +1,9 @@
"""Useful functions for blinkpy.""" """Useful functions for blinkpy."""
import logging import logging
from requests import Request, Session from requests import Request, Session, exceptions
import blinkpy.helpers.errors as ERROR
from blinkpy.helpers.constants import BLINK_URL from blinkpy.helpers.constants import BLINK_URL
import blinkpy.helpers.errors as ERROR
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -41,13 +41,20 @@ def http_req(blink, url='http://example.com', data=None, headers=None,
elif reqtype == 'get': elif reqtype == 'get':
req = Request('GET', url, headers=headers) req = Request('GET', url, headers=headers)
else: else:
_LOGGER.error("Invalid request type: %s", reqtype)
raise BlinkException(ERROR.REQUEST) raise BlinkException(ERROR.REQUEST)
prepped = req.prepare() prepped = req.prepare()
response = blink.session.send(prepped, stream=stream)
try:
response = blink.session.send(prepped, stream=stream)
except (exceptions.ConnectionError, exceptions.Timeout):
_LOGGER.error("Cannot connect to server. Possible outage.")
return None
if json_resp and 'code' in response.json(): if json_resp and 'code' in response.json():
if is_retry: if is_retry:
_LOGGER.error("Cannot authenticate with server.")
raise BlinkAuthenticationException( raise BlinkAuthenticationException(
(response.json()['code'], response.json()['message'])) (response.json()['code'], response.json()['message']))
else: else:
+2 -2
View File
@@ -86,7 +86,7 @@ class BlinkSyncModule():
self.events = self.get_events() self.events = self.get_events()
self.homescreen = api.request_homescreen(self.blink, self.network_id) self.homescreen = api.request_homescreen(self.blink)
camera_info = self.get_camera_info() camera_info = self.get_camera_info()
for camera_config in camera_info: for camera_config in camera_info:
@@ -113,7 +113,7 @@ class BlinkSyncModule():
"""Get all blink cameras and pulls their most recent status.""" """Get all blink cameras and pulls their most recent status."""
self.events = self.get_events() self.events = self.get_events()
self.videos = self.get_videos() self.videos = self.get_videos()
self.homescreen = api.request_homescreen(self.blink, self.network_id) self.homescreen = api.request_homescreen(self.blink)
camera_info = self.get_camera_info() camera_info = self.get_camera_info()
for camera_config in camera_info: for camera_config in camera_info:
name = camera_config['name'] name = camera_config['name']
+32
View File
@@ -0,0 +1,32 @@
"""Test various api functions."""
import unittest
from blinkpy import api
from blinkpy.blinkpy import Blink
from blinkpy.helpers.util import create_session
class TestBlinkAPI(unittest.TestCase):
"""Test the blink api module."""
def setUp(self):
"""Initialize the blink module."""
self.blink = Blink()
self.blink.session = create_session()
# pylint: disable=protected-access
self.blink._auth_header = {}
def tearDown(self):
"""Tear down blink module."""
self.blink = None
def test_http_req_connect_error(self):
"""Test http_get error condition."""
expected = ("ERROR:blinkpy.helpers.util:"
"Cannot connect to server. Possible outage.")
with self.assertLogs() as getlog:
api.http_get(self.blink, 'http://notreal.fake')
with self.assertLogs() as postlog:
api.http_post(self.blink, 'http://notreal.fake')
self.assertEqual(getlog.output, [expected])
self.assertEqual(postlog.output, [expected])
+1 -1
View File
@@ -95,7 +95,7 @@ class TestBlinkSetup(unittest.TestCase):
# pylint: disable=protected-access # pylint: disable=protected-access
self.blink._auth_header = bad_header self.blink._auth_header = bad_header
self.assertEqual(self.blink.auth_header, bad_header) self.assertEqual(self.blink.auth_header, bad_header)
api.request_homescreen(self.blink, '1234') api.request_homescreen(self.blink)
self.assertEqual(self.blink.auth_header, original_header) self.assertEqual(self.blink.auth_header, original_header)
@mock.patch('blinkpy.blinkpy.time.time') @mock.patch('blinkpy.blinkpy.time.time')
+60
View File
@@ -117,3 +117,63 @@ class TestBlinkCameraSetup(unittest.TestCase):
'https://rest.test.immedia-semi.com/test.mp4') 'https://rest.test.immedia-semi.com/test.mp4')
self.assertEqual(self.camera.image_from_cache, 'test') self.assertEqual(self.camera.image_from_cache, 'test')
self.assertEqual(self.camera.video_from_cache, 'foobar') self.assertEqual(self.camera.video_from_cache, 'foobar')
def test_thumbnail_not_in_info(self, mock_sess):
"""Test that we grab thumbanil if not in camera_info."""
mock_sess.side_effect = ['foobar', 'barfoo']
self.camera.last_record = ['1']
self.camera.sync.record_dates['new'] = ['1']
self.camera.sync.all_clips = {'new': {'1': '/test.mp4'}}
config = {
'name': 'new',
'camera_id': 1234,
'network_id': 5678,
'serial': '12345678',
'enabled': False,
'battery_voltage': 90,
'battery_state': 'ok',
'temperature': 68,
'wifi_strength': 4,
'thumbnail': '',
}
self.camera.sync.homescreen = {
'devices': [
{'foo': 'bar'},
{'device_type': 'foobar'},
{'device_type': 'camera',
'name': 'new',
'thumbnail': '/new/thumb'}
]
}
self.camera.update(config)
self.assertEqual(self.camera.thumbnail,
'https://rest.test.immedia-semi.com/new/thumb.jpg')
def test_no_thumbnails(self, mock_sess):
"""Tests that thumbnail is 'None' if none found."""
mock_sess.return_value = 'foobar'
self.camera.last_record = ['1']
self.camera.sync.record_dates['new'] = ['1']
self.camera.sync.all_clips = {'new': {'1': '/test.mp4'}}
config = {
'name': 'new',
'camera_id': 1234,
'network_id': 5678,
'serial': '12345678',
'enabled': False,
'battery_voltage': 90,
'battery_state': 'ok',
'temperature': 68,
'wifi_strength': 4,
'thumbnail': '',
}
self.camera.sync.homescreen = {
'devices': []
}
with self.assertLogs() as logrecord:
self.camera.update(config)
self.assertEqual(self.camera.thumbnail, None)
self.assertEqual(
logrecord.output,
["ERROR:blinkpy.camera:Could not find thumbnail for camera new"]
)