diff --git a/CHANGES.rst b/CHANGES.rst index 5620cd1..d609625 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ A list of changes between each release 0.8.0.dev (Development version) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Added support for battery voltage level +- Added motion detection per camera +- Added fully accessible camera configuration dict 0.7.0 (2018-02-08) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/blinkpy/blinkpy.py b/blinkpy/blinkpy.py index 6ed5fc9..43fd8e9 100644 --- a/blinkpy/blinkpy.py +++ b/blinkpy/blinkpy.py @@ -114,7 +114,7 @@ class BlinkCamera(object): self.image_link = None self.arm_link = None self.region_id = config['region_id'] - self.battery_voltage = -180 + self.battery_voltage = -180 self.motion_detected = None self.wifi_strength = None self.camera_config = dict() @@ -190,19 +190,21 @@ class BlinkCamera(object): self.notifications = values['notifications'] try: - cfg = self.blink._camera_config_request(self.id) + cfg = self.blink.camera_config_request(self.id) self.camera_config = cfg - except: - _LOGGER.warning("Could not get config for {} with id {}".format( - self.name, self.id)) + except requests.exceptions.RequestException as err: + _LOGGER.warning("Could not get config for %s with id %s", + self.name, self.id) + _LOGGER.warning("Exception raised: %s", err) + try: self.battery_voltage = cfg['camera'][0]['battery_voltage'] self.motion_detected = cfg['camera'][0]['motion_alert'] self.wifi_strength = cfg['camera'][0]['wifi_strength'] self.temperature = cfg['camera'][0]['temperature'] except KeyError: - _LOGGER.warning("Problem extracting config for camera {}".format( - self.name)) + _LOGGER.warning("Problem extracting config for camera %s", + self.name) def image_refresh(self): """Refresh current thumbnail.""" @@ -352,6 +354,7 @@ class Blink(object): videos.append(this_page) for page in videos: + _LOGGER.debug("Retrieved video page %s", page) for entry in page: camera_name = entry['camera_name'] clip_addr = entry['address'] @@ -524,7 +527,7 @@ class Blink(object): headers = self._auth_header return _request(self, url=url, headers=headers, reqtype='get') - def _camera_config_request(self, camera_id): + def camera_config_request(self, camera_id): """Retrieve more info about Blink config.""" url = "{}/network/{}/camera/{}/config".format(self.urls.base_url, self.network_id, diff --git a/tests/test_blink_cameras.py b/tests/test_blink_cameras.py index 859a2cf..98b40b9 100644 --- a/tests/test_blink_cameras.py +++ b/tests/test_blink_cameras.py @@ -15,6 +15,17 @@ import tests.mock_responses as mresp USERNAME = 'foobar' PASSWORD = 'deadbeef' +CAMERA_CFG = { + 'camera': [ + { + 'battery_voltage': 90, + 'motion_alert': True, + 'wifi_strength': -30, + 'temperature': 68 + } + ] +} + class TestBlinkCameraSetup(unittest.TestCase): """Test the Blink class in blinkpy.""" @@ -35,6 +46,7 @@ class TestBlinkCameraSetup(unittest.TestCase): 'notifications': 2, 'region_id': 'test' } + self.blink.urls = blinkpy.BlinkURLHandler('test') self.blink.network_id = '0000' @@ -42,11 +54,13 @@ class TestBlinkCameraSetup(unittest.TestCase): """Clean up after test.""" self.blink = None + @mock.patch('blinkpy.blinkpy.Blink.camera_config_request', + return_value=CAMERA_CFG) @mock.patch('blinkpy.blinkpy.requests.post', side_effect=mresp.mocked_requests_post) @mock.patch('blinkpy.blinkpy.requests.get', side_effect=mresp.mocked_requests_get) - def test_camera_properties(self, mock_get, mock_post): + def test_camera_properties(self, mock_get, mock_post, mock_cfg): """Tests all property set/recall.""" self.blink.urls = blinkpy.BlinkURLHandler('test') @@ -56,7 +70,7 @@ class TestBlinkCameraSetup(unittest.TestCase): for name in self.blink.cameras: camera = self.blink.cameras[name] - + camera.update(self.camera_config) self.assertEqual(camera.id, '1111') self.assertEqual(camera.name, 'foobar') self.assertEqual(camera.armed, False) @@ -68,11 +82,14 @@ class TestBlinkCameraSetup(unittest.TestCase): camera.clip, "https://rest.test.{}/test/clip/clip.mp4".format(BLINK_URL) ) - self.assertEqual(camera.temperature, 70) - self.assertEqual(camera.battery, 3) + self.assertEqual(camera.temperature, 68) + self.assertEqual(camera.battery, 50) self.assertEqual(camera.battery_string, "OK") self.assertEqual(camera.notifications, 2) self.assertEqual(camera.region_id, 'test') + self.assertEqual(camera.motion_detected, True) + self.assertEqual(camera.wifi_strength, -30) + camera_config = self.camera_config camera_config['active'] = 'armed' camera_config['thumbnail'] = '/test2/image' @@ -80,7 +97,6 @@ class TestBlinkCameraSetup(unittest.TestCase): camera_config['temp'] = 60 camera_config['battery'] = 0 camera_config['notifications'] = 4 - for name in self.blink.cameras: camera = self.blink.cameras[name] camera.update(camera_config) @@ -93,8 +109,8 @@ class TestBlinkCameraSetup(unittest.TestCase): camera.clip, "https://rest.test.{}/test2/clip.mp4".format(BLINK_URL) ) - self.assertEqual(camera.temperature, 60) - self.assertEqual(camera.battery, 0) + self.assertEqual(camera.temperature, 68) + self.assertEqual(camera.battery, 50) self.assertEqual(camera.battery_string, "Low") self.assertEqual(camera.notifications, 4) camera_config['battery'] = -10 @@ -107,7 +123,9 @@ class TestBlinkCameraSetup(unittest.TestCase): self.blink.cameras['foobar'] = camera_object self.assertEqual(camera_object, self.blink.cameras['fOoBaR']) - def test_camera_attributes(self): + @mock.patch('blinkpy.blinkpy.Blink.camera_config_request', + return_value=CAMERA_CFG) + def test_camera_attributes(self, mock_cfg): """Tests camera attributes.""" self.blink.urls = blinkpy.BlinkURLHandler('test') @@ -117,6 +135,7 @@ class TestBlinkCameraSetup(unittest.TestCase): for name in self.blink.cameras: camera = self.blink.cameras[name] + camera.update(self.camera_config) camera_attr = camera.attributes self.assertEqual(camera_attr['device_id'], '1111') self.assertEqual(camera_attr['name'], 'foobar') @@ -129,7 +148,9 @@ class TestBlinkCameraSetup(unittest.TestCase): camera_attr['video'], "https://rest.test.{}/test/clip/clip.mp4".format(BLINK_URL) ) - self.assertEqual(camera_attr['temperature'], 70) - self.assertEqual(camera_attr['battery'], 3) + self.assertEqual(camera_attr['temperature'], 68) + self.assertEqual(camera_attr['battery'], 50) self.assertEqual(camera_attr['notifications'], 2) self.assertEqual(camera_attr['network_id'], '0000') + self.assertEqual(camera_attr['motion_detected'], True) + self.assertEqual(camera_attr['wifi_strength'], -30) diff --git a/tests/test_blink_functions.py b/tests/test_blink_functions.py index aa8f24a..97911c7 100644 --- a/tests/test_blink_functions.py +++ b/tests/test_blink_functions.py @@ -61,9 +61,17 @@ class TestBlinkFunctions(unittest.TestCase): '/test/thumb') @mock.patch('blinkpy.blinkpy._request') - def test_get_cameras(self, req): + @mock.patch('blinkpy.blinkpy.Blink._video_request') + def test_get_cameras(self, vid_req, req): """Test camera extraction.""" req.return_value = {'devices': [self.config]} + vid_req.return_value = [ + { + 'camera_name': 'foobar', + 'address': '/new.mp4', + 'thumbnail': '/new' + } + ] self.blink.get_cameras() self.assertTrue('foobar' in self.blink.cameras)