From 58ce109518df273517f666cc8ad4147279015762 Mon Sep 17 00:00:00 2001 From: Kevin Fronczak Date: Tue, 21 May 2019 22:09:36 -0400 Subject: [PATCH 1/5] Use UTC for time conversions --- blinkpy/helpers/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blinkpy/helpers/util.py b/blinkpy/helpers/util.py index e2e44a4..196c904 100644 --- a/blinkpy/helpers/util.py +++ b/blinkpy/helpers/util.py @@ -15,7 +15,7 @@ def get_time(time_to_convert=None): """Create blink-compatible timestamp.""" if time_to_convert is None: time_to_convert = time.time() - return time.strftime(TIMESTAMP_FORMAT, time.localtime(time_to_convert)) + return time.strftime(TIMESTAMP_FORMAT, time.gmtime(time_to_convert)) def merge_dicts(dict_a, dict_b): From 85c14ede8d2fc50c871b5ffbc72f98714aaff700 Mon Sep 17 00:00:00 2001 From: Kevin Fronczak Date: Tue, 21 May 2019 22:23:31 -0400 Subject: [PATCH 2/5] Move constants into helpers/constants.py --- blinkpy/helpers/constants.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/blinkpy/helpers/constants.py b/blinkpy/helpers/constants.py index 9acc021..cc907bd 100644 --- a/blinkpy/helpers/constants.py +++ b/blinkpy/helpers/constants.py @@ -60,3 +60,7 @@ ONLINE = {'online': True, 'offline': False} OTHER ''' TIMESTAMP_FORMAT = '%Y-%m-%dT%H:%M:%S%Z' + +DEFAULT_MOTION_INTERVAL = 0 +DEFAULT_REFRESH = 30 +MIN_THROTTLE_TIME = 2 From 93472e38de875b64e2ed4f5df1b8f6eb97e80743 Mon Sep 17 00:00:00 2001 From: Kevin Fronczak Date: Tue, 21 May 2019 22:36:46 -0400 Subject: [PATCH 3/5] Added in motion interval to allow for looking at historic motion events. - Good debug utility - Helps iron out rapid motion events, or missed events due to quick calls to refresh method --- blinkpy/blinkpy.py | 16 +++++++++------- blinkpy/sync_module.py | 10 +++++++++- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/blinkpy/blinkpy.py b/blinkpy/blinkpy.py index 279c513..53f0ca8 100644 --- a/blinkpy/blinkpy.py +++ b/blinkpy/blinkpy.py @@ -30,14 +30,10 @@ from blinkpy.helpers.util import ( create_session, merge_dicts, get_time, BlinkURLHandler, BlinkAuthenticationException, Throttle) from blinkpy.helpers.constants import ( - BLINK_URL, LOGIN_URL, OLD_LOGIN_URL, LOGIN_BACKUP_URL) + BLINK_URL, LOGIN_URL, OLD_LOGIN_URL, LOGIN_BACKUP_URL, + DEFAULT_MOTION_INTERVAL, DEFAULT_REFRESH, MIN_THROTTLE_TIME) from blinkpy.helpers.constants import __version__ -REFRESH_RATE = 30 - -# Prevents rapid calls to blink.refresh() -# with the force_cache flag set to True -MIN_THROTTLE_TIME = 2 _LOGGER = logging.getLogger(__name__) @@ -46,7 +42,8 @@ class Blink(): """Class to initialize communication.""" def __init__(self, username=None, password=None, - refresh_rate=REFRESH_RATE): + refresh_rate=DEFAULT_REFRESH, + motion_interval=DEFAULT_MOTION_INTERVAL): """ Initialize Blink system. @@ -54,6 +51,10 @@ class Blink(): :param password: Blink password :param refresh_rate: Refresh rate of blink information. Defaults to 15 (seconds) + :param motion_interval: How far back to register motion in minutes. + Defaults to last refresh time. + Useful for preventing motion_detected property + from de-asserting too quickly. """ self._username = username self._password = password @@ -73,6 +74,7 @@ class Blink(): self.cameras = CaseInsensitiveDict({}) self.video_list = CaseInsensitiveDict({}) self._login_url = LOGIN_URL + self.motion_interval = DEFAULT_MOTION_INTERVAL self.version = __version__ @property diff --git a/blinkpy/sync_module.py b/blinkpy/sync_module.py index 337b56c..6c6a6ce 100644 --- a/blinkpy/sync_module.py +++ b/blinkpy/sync_module.py @@ -33,6 +33,7 @@ class BlinkSyncModule(): self.network_info = None self.events = [] self.cameras = CaseInsensitiveDict({}) + self.motion_interval = blink.motion_interval self.motion = {} self.last_record = {} self.camera_list = camera_list @@ -161,8 +162,15 @@ class BlinkSyncModule(): def check_new_videos(self): """Check if new videos since last refresh.""" + try: + interval = self.blink.last_refresh - self.motion_interval*60 + except TypeError: + # This is the first start, so refresh hasn't happened yet. + # No need to check for motion. + return False + resp = api.request_videos(self.blink, - time=self.blink.last_refresh, + time=interval, page=1) for camera in self.cameras.keys(): From b88a5feddf3524fa39372348c7daa4be6f260124 Mon Sep 17 00:00:00 2001 From: Kevin Fronczak Date: Tue, 21 May 2019 22:38:49 -0400 Subject: [PATCH 4/5] Change default interval to one minute --- blinkpy/helpers/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blinkpy/helpers/constants.py b/blinkpy/helpers/constants.py index cc907bd..28eb8e0 100644 --- a/blinkpy/helpers/constants.py +++ b/blinkpy/helpers/constants.py @@ -61,6 +61,6 @@ OTHER ''' TIMESTAMP_FORMAT = '%Y-%m-%dT%H:%M:%S%Z' -DEFAULT_MOTION_INTERVAL = 0 +DEFAULT_MOTION_INTERVAL = 1 DEFAULT_REFRESH = 30 MIN_THROTTLE_TIME = 2 From 50b1a351685d275e80690c8f7b7a4c89fc6ee31d Mon Sep 17 00:00:00 2001 From: Kevin Fronczak Date: Tue, 21 May 2019 22:46:11 -0400 Subject: [PATCH 5/5] Update tests --- tests/test_sync_module.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/test_sync_module.py b/tests/test_sync_module.py index 7962a07..191e83c 100644 --- a/tests/test_sync_module.py +++ b/tests/test_sync_module.py @@ -17,12 +17,14 @@ class TestBlinkSyncModule(unittest.TestCase): def setUp(self): """Set up Blink module.""" self.blink = blinkpy.Blink(username=USERNAME, - password=PASSWORD) + password=PASSWORD, + motion_interval=0) # pylint: disable=protected-access self.blink._auth_header = { 'Host': 'test.url.tld', 'TOKEN_AUTH': 'foobar123' } + self.blink.last_refresh = 0 self.blink.urls = blinkpy.BlinkURLHandler('test') self.blink.sync['test'] = BlinkSyncModule(self.blink, 'test', @@ -59,6 +61,12 @@ class TestBlinkSyncModule(unittest.TestCase): self.assertEqual(self.blink.sync['test'].get_camera_info('1234'), 'foobar') + def test_check_new_videos_startup(self, mock_resp): + """Test that check_new_videos does not block startup.""" + sync_module = self.blink.sync['test'] + self.blink.last_refresh = None + self.assertFalse(sync_module.check_new_videos()) + def test_check_new_videos(self, mock_resp): """Test recent video response.""" mock_resp.return_value = {