From 0847b734430010adba4e2609b6a48fc5b817a87d Mon Sep 17 00:00:00 2001 From: Marcelo Moreira de Mello Date: Sat, 30 Sep 2017 01:28:44 -0400 Subject: [PATCH 1/2] Implemented health attributes to Ring devices --- README.rst | 2 ++ ring_doorbell/__init__.py | 38 ++++++++++++++++++++++++++++++++++---- ring_doorbell/const.py | 3 +++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index ff16441e..3963a8bc 100644 --- a/README.rst +++ b/README.rst @@ -84,6 +84,8 @@ Playing with the attributes and functions print('ID: %s' % dev.id) print('Name: %s' % dev.name) print('Timezone: %s' % dev.timezone) + print('Wifi Name: %s' % dev.wifi_name) + print('Wifi RSSI: %s' % dev.wifi_signal_strength) # setting dev volume print('Volume: %s' % dev.volume) diff --git a/ring_doorbell/__init__.py b/ring_doorbell/__init__.py index 744c3c8c..dfa6af0c 100644 --- a/ring_doorbell/__init__.py +++ b/ring_doorbell/__init__.py @@ -20,10 +20,10 @@ CHIME_VOL_MIN, CHIME_VOL_MAX, DEVICES_ENDPOINT, DOORBELLS_ENDPOINT, DOORBELL_VOL_MIN, DOORBELL_VOL_MAX, DOORBELL_EXISTING_TYPE, DINGS_ENDPOINT, FILE_EXISTS, - HEADERS, LINKED_CHIMES_ENDPOINT, LIVE_STREAMING_ENDPOINT, - NEW_SESSION_ENDPOINT, MSG_BOOLEAN_REQUIRED, MSG_EXISTING_TYPE, - MSG_GENERIC_FAIL, MSG_VOL_OUTBOUND, - NOT_FOUND, URL_DOORBELL_HISTORY, URL_RECORDING, + HEADERS, HEALTH_CHIMES_ENDPOINT, HEALTH_DOORBELL_ENDPOINT, + LINKED_CHIMES_ENDPOINT, LIVE_STREAMING_ENDPOINT, NEW_SESSION_ENDPOINT, + MSG_BOOLEAN_REQUIRED, MSG_EXISTING_TYPE, MSG_GENERIC_FAIL, + MSG_VOL_OUTBOUND, NOT_FOUND, URL_DOORBELL_HISTORY, URL_RECORDING, POST_DATA, PERSIST_TOKEN_ENDPOINT, PERSIST_TOKEN_DATA, RETRY_TOKEN, TESTSOUND_CHIME_ENDPOINT, CHIME_TEST_SOUND_KINDS, KIND_DING) @@ -266,6 +266,7 @@ def __init__(self, ring, name, shared=False): self.name = name self.shared = shared self._attrs = None + self._health_attrs = None # alerts notifications self.alert_expires_at = None @@ -285,6 +286,7 @@ def family(self): def update(self): """Refresh attributes.""" self._get_attrs() + self._get_health_attrs() self._update_alert() @property @@ -325,6 +327,14 @@ def _get_attrs(self): self._attrs = lst[index] return True + def _get_health_attrs(self): + """Return health attributes.""" + if self.family == 'doorbots' or self.family == 'stickup_cams': + url = API_URI + HEALTH_DOORBELL_ENDPOINT.format(self.account_id) + elif self.family == 'chimes': + url = API_URI + HEALTH_CHIMES_ENDPOINT.format(self.account_id) + self._health_attrs = self._ring.query(url).get('device_health') + @property def account_id(self): """Return account ID.""" @@ -366,6 +376,21 @@ def timezone(self): """Return timezone.""" return self._attrs.get('time_zone') + @property + def wifi_name(self): + """Return wifi ESSID name.""" + return self._health_attrs.get('wifi_name') + + @property + def wifi_signal_strength(self): + """Return wifi RSSI.""" + return self._health_attrs.get('latest_signal_strength') + + @property + def wifi_signal_category(self): + """Return wifi signal category.""" + return self._health_attrs.get('latest_signal_category') + class RingChime(RingGeneric): """Implementation for Ring Chime.""" @@ -375,6 +400,11 @@ def family(self): """Return Ring device family type.""" return 'chimes' + @property + def battery_life(self): + """Return battery life.""" + return self._health_attrs.get('battery_percentage') + @property def volume(self): """Return if chime volume.""" diff --git a/ring_doorbell/const.py b/ring_doorbell/const.py index 00d6ec3c..f820539b 100644 --- a/ring_doorbell/const.py +++ b/ring_doorbell/const.py @@ -33,9 +33,12 @@ DOORBELLS_ENDPOINT = '/clients_api/doorbots/{0}' PERSIST_TOKEN_ENDPOINT = '/clients_api/device' +HEALTH_DOORBELL_ENDPOINT = DOORBELLS_ENDPOINT + '/health' +HEALTH_CHIMES_ENDPOINT = CHIMES_ENDPOINT + '/health' LINKED_CHIMES_ENDPOINT = CHIMES_ENDPOINT + '/linked_doorbots' LIVE_STREAMING_ENDPOINT = DOORBELLS_ENDPOINT + '/vod' NEW_SESSION_ENDPOINT = '/clients_api/session' +RINGTONES_ENDPOINT = '/ringtones' TESTSOUND_CHIME_ENDPOINT = CHIMES_ENDPOINT + '/play_sound' URL_DOORBELL_HISTORY = DOORBELLS_ENDPOINT + '/history' URL_RECORDING = '/clients_api/dings/{0}/recording' From 9c3472cd73d47cc3d80bf9a637c6de08f84d2b88 Mon Sep 17 00:00:00 2001 From: Marcelo Moreira de Mello Date: Sat, 30 Sep 2017 04:13:55 -0400 Subject: [PATCH 2/2] Added unittests to wifi health parameters --- tests/fixtures/ring_chime_health_attrs.json | 19 ++++++++++++++ .../fixtures/ring_doorboot_health_attrs.json | 19 ++++++++++++++ .../ring_doorboot_health_attrs_id987653.json | 19 ++++++++++++++ tests/test_ring.py | 26 +++++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 tests/fixtures/ring_chime_health_attrs.json create mode 100644 tests/fixtures/ring_doorboot_health_attrs.json create mode 100644 tests/fixtures/ring_doorboot_health_attrs_id987653.json diff --git a/tests/fixtures/ring_chime_health_attrs.json b/tests/fixtures/ring_chime_health_attrs.json new file mode 100644 index 00000000..a9e5a845 --- /dev/null +++ b/tests/fixtures/ring_chime_health_attrs.json @@ -0,0 +1,19 @@ +{ + "device_health": { + "average_signal_category": "good", + "average_signal_strength": -39, + "battery_percentage": 100, + "battery_percentage_category": null, + "battery_voltage": null, + "battery_voltage_category": null, + "firmware": "1.2.3", + "firmware_out_of_date": false, + "id": 999999, + "latest_signal_category": "good", + "latest_signal_strength": -39, + "updated_at": "2017-09-30T07:05:03Z", + "wifi_is_ring_network": false, + "wifi_name": "ring_mock_wifi" + } +} + diff --git a/tests/fixtures/ring_doorboot_health_attrs.json b/tests/fixtures/ring_doorboot_health_attrs.json new file mode 100644 index 00000000..11f00886 --- /dev/null +++ b/tests/fixtures/ring_doorboot_health_attrs.json @@ -0,0 +1,19 @@ +{ + "device_health": { + "average_signal_category": "good", + "average_signal_strength": -39, + "battery_percentage": 100, + "battery_percentage_category": null, + "battery_voltage": null, + "battery_voltage_category": null, + "firmware": "1.9.2", + "firmware_out_of_date": false, + "id": 987652, + "latest_signal_category": "good", + "latest_signal_strength": -58, + "updated_at": "2017-09-30T07:05:03Z", + "wifi_is_ring_network": false, + "wifi_name": "ring_mock_wifi" + } +} + diff --git a/tests/fixtures/ring_doorboot_health_attrs_id987653.json b/tests/fixtures/ring_doorboot_health_attrs_id987653.json new file mode 100644 index 00000000..063efabd --- /dev/null +++ b/tests/fixtures/ring_doorboot_health_attrs_id987653.json @@ -0,0 +1,19 @@ +{ + "device_health": { + "average_signal_category": "good", + "average_signal_strength": -39, + "battery_percentage": 100, + "battery_percentage_category": null, + "battery_voltage": null, + "battery_voltage_category": null, + "firmware": "1.9.2", + "firmware_out_of_date": false, + "id": 987653, + "latest_signal_category": "good", + "latest_signal_strength": -58, + "updated_at": "2017-09-30T07:05:03Z", + "wifi_is_ring_network": false, + "wifi_name": "ring_mock_wifi" + } +} + diff --git a/tests/test_ring.py b/tests/test_ring.py index 810a7914..11f8d407 100644 --- a/tests/test_ring.py +++ b/tests/test_ring.py @@ -14,6 +14,12 @@ def test_basic_attributes(self, mock): """Test the Ring class and methods.""" mock.get('https://api.ring.com/clients_api/ring_devices', text=load_fixture('ring_devices.json')) + mock.get('https://api.ring.com/clients_api/chimes/999999/health', + text=load_fixture('ring_chime_health_attrs.json')) + mock.get('https://api.ring.com/clients_api/doorbots/987652/health', + text=load_fixture('ring_doorboot_health_attrs.json')) + mock.get('https://api.ring.com/clients_api/doorbots/987653/health', + text=load_fixture('ring_doorboot_health_attrs_id987653.json')) data = self.ring self.assertTrue(data.is_connected) @@ -29,6 +35,8 @@ def test_chime_attributes(self, mock): """Test the Ring Chime class and methods.""" mock.get('https://api.ring.com/clients_api/ring_devices', text=load_fixture('ring_devices.json')) + mock.get('https://api.ring.com/clients_api/chimes/999999/health', + text=load_fixture('ring_chime_health_attrs.json')) data = self.ring dev = data.chimes[0] @@ -40,6 +48,9 @@ def test_chime_attributes(self, mock): self.assertIsNotNone(dev.latitude) self.assertEqual('America/New_York', dev.timezone) self.assertEqual(2, dev.volume) + self.assertEqual('ring_mock_wifi', dev.wifi_name) + self.assertEqual('good', dev.wifi_signal_category) + self.assertNotEqual(100, dev.wifi_signal_strength) @requests_mock.Mocker() def test_doorbell_attributes(self, mock): @@ -47,6 +58,10 @@ def test_doorbell_attributes(self, mock): text=load_fixture('ring_devices.json')) mock.get('https://api.ring.com/clients_api/doorbots/987652/history', text=load_fixture('ring_doorbots.json')) + mock.get('https://api.ring.com/clients_api/doorbots/987652/health', + text=load_fixture('ring_doorboot_health_attrs.json')) + mock.get('https://api.ring.com/clients_api/doorbots/987653/health', + text=load_fixture('ring_doorboot_health_attrs_id987653.json')) data = self.ring_persistent for dev in data.doorbells: @@ -66,6 +81,9 @@ def test_doorbell_attributes(self, mock): self.assertEqual('Mechanical', dev.existing_doorbell_type) self.assertTrue(data._persist_token) + self.assertEqual('ring_mock_wifi', dev.wifi_name) + self.assertEqual('good', dev.wifi_signal_category) + self.assertEqual(-58, dev.wifi_signal_strength) @requests_mock.Mocker() def test_shared_doorbell_attributes(self, mock): @@ -73,6 +91,10 @@ def test_shared_doorbell_attributes(self, mock): text=load_fixture('ring_devices.json')) mock.get('https://api.ring.com/clients_api/doorbots/987652/history', text=load_fixture('ring_doorbots.json')) + mock.get('https://api.ring.com/clients_api/doorbots/987652/health', + text=load_fixture('ring_doorboot_health_attrs.json')) + mock.get('https://api.ring.com/clients_api/doorbots/987653/health', + text=load_fixture('ring_doorboot_health_attrs_id987653.json')) data = self.ring_persistent for dev in data.doorbells: @@ -92,6 +114,10 @@ def test_doorbell_alerts(self, mock): text=load_fixture('ring_devices.json')) mock.get('https://api.ring.com/clients_api/dings/active', text=load_fixture('ring_ding_active.json')) + mock.get('https://api.ring.com/clients_api/doorbots/987652/health', + text=load_fixture('ring_doorboot_health_attrs.json')) + mock.get('https://api.ring.com/clients_api/doorbots/987653/health', + text=load_fixture('ring_doorboot_health_attrs_id987653.json')) data = self.ring_persistent for dev in data.doorbells: