From 82088d9b35082b5d0e462dfcb9a312e66c89dcf0 Mon Sep 17 00:00:00 2001 From: Brian Goldstein Date: Fri, 30 Aug 2024 07:17:01 -0700 Subject: [PATCH 1/7] Changing existing_doorbell_type_enabled from bool to int --- ring_doorbell/const.py | 25 +------------------------ ring_doorbell/doorbot.py | 14 ++++++++------ 2 files changed, 9 insertions(+), 30 deletions(-) diff --git a/ring_doorbell/const.py b/ring_doorbell/const.py index f0b085b..6b1cd34 100644 --- a/ring_doorbell/const.py +++ b/ring_doorbell/const.py @@ -38,7 +38,6 @@ class RingCapability(Enum): OPEN = auto() KNOCK = auto() PRE_ROLL = auto() - DING = auto() @staticmethod def from_name(name: str) -> RingCapability: @@ -73,10 +72,7 @@ def from_name(name: str) -> RingCapability: DEFAULT_LISTEN_EVENT_EXPIRES_IN = 180 # for Ring android app. 703521446232 for ring-site -FCM_RING_SENDER_ID = "876313859327" -FCM_API_KEY = "AIzaSyCv-hdFBmmdBBJadNy-TFwB-xN_H5m3Bk8" -FCM_PROJECT_ID = "ring-17770" -FCM_APP_ID = "1:876313859327:android:e10ec6ddb3c81f39" +RING_SENDER_ID = 876313859327 CLI_TOKEN_FILE = "ring_token.cache" # noqa: S105 GCM_TOKEN_FILE = "ring_gcm_token.cache" # noqa: S105 @@ -116,11 +112,6 @@ def from_name(name: str) -> RingCapability: KIND_DING = "ding" KIND_MOTION = "motion" KIND_INTERCOM_UNLOCK = "intercom_unlock" -KIND_ALARM_MODE_NONE = "alarm_mode_none" -KIND_ALARM_MODE_SOME = "alarm_mode_some" -KIND_ALARM_SIREN = "alarm_siren" -KIND_ALARM_SILENCED = "alarm_silenced" - # chime test sound kinds CHIME_TEST_SOUND_KINDS = (KIND_DING, KIND_MOTION) @@ -180,7 +171,6 @@ def from_name(name: str) -> RingCapability: INTERCOM_KINDS = ["intercom_handset_audio"] # error strings -MSG_BOOLEAN_REQUIRED = "Boolean value is required." MSG_EXISTING_TYPE = f"Integer value where {DOORBELL_EXISTING_TYPE}." MSG_GENERIC_FAIL = "Sorry.. Something went wrong..." FILE_EXISTS = "The file {0} already exists." @@ -192,19 +182,6 @@ def from_name(name: str) -> RingCapability: PUSH_ACTION_MOTION = "com.ring.push.HANDLE_NEW_motion" PUSH_ACTION_INTERCOM_UNLOCK = "com.ring.push.INTERCOM_UNLOCK_FROM_APP" -PUSH_NOTIFICATION_KINDS = { - PUSH_ACTION_DING: KIND_DING, # legacy - "com.ring.pn.live-event.ding": KIND_DING, - PUSH_ACTION_MOTION: KIND_MOTION, # legacy - "com.ring.pn.live-event.motion": KIND_MOTION, - "com.ring.pn.live-event.intercom": KIND_DING, - PUSH_ACTION_INTERCOM_UNLOCK: KIND_INTERCOM_UNLOCK, - "com.ring.push.HANDLE_NEW_SECURITY_PANEL_MODE_NONE_NOTICE": KIND_ALARM_MODE_NONE, - "com.ring.push.HANDLE_NEW_SECURITY_PANEL_MODE_SOME_NOTICE": KIND_ALARM_MODE_SOME, - "com.ring.push.HANDLE_NEW_USER_SOUND_SIREN": KIND_ALARM_SIREN, - "com.ring.push.HANDLE_NEW_NON_ALARM_SIREN_SILENCED": KIND_ALARM_SILENCED, -} - POST_DATA_JSON = { "api_version": API_VERSION, "device_model": "ring-doorbell", diff --git a/ring_doorbell/doorbot.py b/ring_doorbell/doorbot.py index 35be013..5f6d6a5 100644 --- a/ring_doorbell/doorbot.py +++ b/ring_doorbell/doorbot.py @@ -32,7 +32,6 @@ HEALTH_DOORBELL_ENDPOINT, LIVE_STREAMING_ENDPOINT, MSG_ALLOWED_VALUES, - MSG_BOOLEAN_REQUIRED, MSG_EXISTING_TYPE, MSG_EXPECTED_ATTRIBUTE_NOT_FOUND, MSG_VOL_OUTBOUND, @@ -214,14 +213,17 @@ def existing_doorbell_type_enabled(self) -> bool | None: return self._get_chime_setting("enable") return False - async def async_set_existing_doorbell_type_enabled(self, value: bool) -> None: # noqa: FBT001 - """Enable/disable the existing doorbell if Digital/Mechanical.""" + async def async_set_existing_doorbell_type_enabled(self, value: int) -> None: + """Enable/disable the existing doorbell if Digital/Mechanical. + 0: Off + 1: On + """ + if self.existing_doorbell_type: - if not isinstance(value, bool): - raise RingError(MSG_BOOLEAN_REQUIRED) if self.existing_doorbell_type == DOORBELL_EXISTING_TYPE[2]: - return + msg = f"In-Home chime is not present." + raise RingError(msg) params = { "doorbot[description]": self.name, From 2d5d4cc4531ae0b9e928dcfe212483a4229d2eef Mon Sep 17 00:00:00 2001 From: Brian Goldstein Date: Fri, 30 Aug 2024 07:20:51 -0700 Subject: [PATCH 2/7] replacing with latest const.py from main repo --- ring_doorbell/const.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/ring_doorbell/const.py b/ring_doorbell/const.py index 6b1cd34..27e2136 100644 --- a/ring_doorbell/const.py +++ b/ring_doorbell/const.py @@ -38,6 +38,7 @@ class RingCapability(Enum): OPEN = auto() KNOCK = auto() PRE_ROLL = auto() + DING = auto() @staticmethod def from_name(name: str) -> RingCapability: @@ -72,7 +73,10 @@ def from_name(name: str) -> RingCapability: DEFAULT_LISTEN_EVENT_EXPIRES_IN = 180 # for Ring android app. 703521446232 for ring-site -RING_SENDER_ID = 876313859327 +FCM_RING_SENDER_ID = "876313859327" +FCM_API_KEY = "AIzaSyCv-hdFBmmdBBJadNy-TFwB-xN_H5m3Bk8" +FCM_PROJECT_ID = "ring-17770" +FCM_APP_ID = "1:876313859327:android:e10ec6ddb3c81f39" CLI_TOKEN_FILE = "ring_token.cache" # noqa: S105 GCM_TOKEN_FILE = "ring_gcm_token.cache" # noqa: S105 @@ -112,6 +116,11 @@ def from_name(name: str) -> RingCapability: KIND_DING = "ding" KIND_MOTION = "motion" KIND_INTERCOM_UNLOCK = "intercom_unlock" +KIND_ALARM_MODE_NONE = "alarm_mode_none" +KIND_ALARM_MODE_SOME = "alarm_mode_some" +KIND_ALARM_SIREN = "alarm_siren" +KIND_ALARM_SILENCED = "alarm_silenced" + # chime test sound kinds CHIME_TEST_SOUND_KINDS = (KIND_DING, KIND_MOTION) @@ -171,6 +180,7 @@ def from_name(name: str) -> RingCapability: INTERCOM_KINDS = ["intercom_handset_audio"] # error strings +MSG_BOOLEAN_REQUIRED = "Boolean value is required." MSG_EXISTING_TYPE = f"Integer value where {DOORBELL_EXISTING_TYPE}." MSG_GENERIC_FAIL = "Sorry.. Something went wrong..." FILE_EXISTS = "The file {0} already exists." @@ -182,6 +192,19 @@ def from_name(name: str) -> RingCapability: PUSH_ACTION_MOTION = "com.ring.push.HANDLE_NEW_motion" PUSH_ACTION_INTERCOM_UNLOCK = "com.ring.push.INTERCOM_UNLOCK_FROM_APP" +PUSH_NOTIFICATION_KINDS = { + PUSH_ACTION_DING: KIND_DING, # legacy + "com.ring.pn.live-event.ding": KIND_DING, + PUSH_ACTION_MOTION: KIND_MOTION, # legacy + "com.ring.pn.live-event.motion": KIND_MOTION, + "com.ring.pn.live-event.intercom": KIND_DING, + PUSH_ACTION_INTERCOM_UNLOCK: KIND_INTERCOM_UNLOCK, + "com.ring.push.HANDLE_NEW_SECURITY_PANEL_MODE_NONE_NOTICE": KIND_ALARM_MODE_NONE, + "com.ring.push.HANDLE_NEW_SECURITY_PANEL_MODE_SOME_NOTICE": KIND_ALARM_MODE_SOME, + "com.ring.push.HANDLE_NEW_USER_SOUND_SIREN": KIND_ALARM_SIREN, + "com.ring.push.HANDLE_NEW_NON_ALARM_SIREN_SILENCED": KIND_ALARM_SILENCED, +} + POST_DATA_JSON = { "api_version": API_VERSION, "device_model": "ring-doorbell", @@ -213,4 +236,4 @@ def from_name(name: str) -> RingCapability: "device[metadata][device_type]": "desktop", "device[metadata][architecture]": "x86", "device[metadata][language]": "en", -} +} \ No newline at end of file From ea3fb0772eb2e399d6b63a9654033d810749a053 Mon Sep 17 00:00:00 2001 From: Brian Goldstein Date: Fri, 30 Aug 2024 07:23:23 -0700 Subject: [PATCH 3/7] Update const.py removing boolean message as only async_set_existing_doorbell_type_duration used it and is no longer needed. --- ring_doorbell/const.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ring_doorbell/const.py b/ring_doorbell/const.py index 27e2136..bec7a21 100644 --- a/ring_doorbell/const.py +++ b/ring_doorbell/const.py @@ -180,7 +180,6 @@ def from_name(name: str) -> RingCapability: INTERCOM_KINDS = ["intercom_handset_audio"] # error strings -MSG_BOOLEAN_REQUIRED = "Boolean value is required." MSG_EXISTING_TYPE = f"Integer value where {DOORBELL_EXISTING_TYPE}." MSG_GENERIC_FAIL = "Sorry.. Something went wrong..." FILE_EXISTS = "The file {0} already exists." From 7cd4a0c05fdd6eca6123a751b794562a05aa0d2e Mon Sep 17 00:00:00 2001 From: Brian Goldstein Date: Fri, 30 Aug 2024 07:52:54 -0700 Subject: [PATCH 4/7] Update doorbot.py Blank lines added to summary/description text per ruff check. --- ring_doorbell/doorbot.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ring_doorbell/doorbot.py b/ring_doorbell/doorbot.py index 5f6d6a5..08cc360 100644 --- a/ring_doorbell/doorbot.py +++ b/ring_doorbell/doorbot.py @@ -215,8 +215,10 @@ def existing_doorbell_type_enabled(self) -> bool | None: async def async_set_existing_doorbell_type_enabled(self, value: int) -> None: """Enable/disable the existing doorbell if Digital/Mechanical. + 0: Off 1: On + """ if self.existing_doorbell_type: From 1591eb1557d052d6bcb885c693b3cfd4bc576bc2 Mon Sep 17 00:00:00 2001 From: Brian Goldstein Date: Fri, 30 Aug 2024 10:28:43 -0700 Subject: [PATCH 5/7] Switching back to bool and converting to int in the function --- ring_doorbell/const.py | 3 ++- ring_doorbell/doorbot.py | 19 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ring_doorbell/const.py b/ring_doorbell/const.py index bec7a21..f0b085b 100644 --- a/ring_doorbell/const.py +++ b/ring_doorbell/const.py @@ -180,6 +180,7 @@ def from_name(name: str) -> RingCapability: INTERCOM_KINDS = ["intercom_handset_audio"] # error strings +MSG_BOOLEAN_REQUIRED = "Boolean value is required." MSG_EXISTING_TYPE = f"Integer value where {DOORBELL_EXISTING_TYPE}." MSG_GENERIC_FAIL = "Sorry.. Something went wrong..." FILE_EXISTS = "The file {0} already exists." @@ -235,4 +236,4 @@ def from_name(name: str) -> RingCapability: "device[metadata][device_type]": "desktop", "device[metadata][architecture]": "x86", "device[metadata][language]": "en", -} \ No newline at end of file +} diff --git a/ring_doorbell/doorbot.py b/ring_doorbell/doorbot.py index 08cc360..697cb7c 100644 --- a/ring_doorbell/doorbot.py +++ b/ring_doorbell/doorbot.py @@ -32,6 +32,7 @@ HEALTH_DOORBELL_ENDPOINT, LIVE_STREAMING_ENDPOINT, MSG_ALLOWED_VALUES, + MSG_BOOLEAN_REQUIRED, MSG_EXISTING_TYPE, MSG_EXPECTED_ATTRIBUTE_NOT_FOUND, MSG_VOL_OUTBOUND, @@ -213,23 +214,21 @@ def existing_doorbell_type_enabled(self) -> bool | None: return self._get_chime_setting("enable") return False - async def async_set_existing_doorbell_type_enabled(self, value: int) -> None: - """Enable/disable the existing doorbell if Digital/Mechanical. - - 0: Off - 1: On - - """ - + async def async_set_existing_doorbell_type_enabled(self, value: bool) -> None: # noqa: FBT001 + """Enable/disable the existing doorbell if Digital/Mechanical.""" if self.existing_doorbell_type: + if not isinstance(value, bool): + raise RingError(MSG_BOOLEAN_REQUIRED) if self.existing_doorbell_type == DOORBELL_EXISTING_TYPE[2]: - msg = f"In-Home chime is not present." + msg = "In-Home chime is not present." raise RingError(msg) + int_value = int(value) + params = { "doorbot[description]": self.name, - "doorbot[settings][chime_settings][enable]": value, + "doorbot[settings][chime_settings][enable]": int_value, } url = DOORBELLS_ENDPOINT.format(self.device_api_id) await self._ring.async_query(url, extra_params=params, method="PUT") From 548af2dabdb0278e038fabb9be82878b8ac06d1f Mon Sep 17 00:00:00 2001 From: Brian Goldstein Date: Sun, 1 Sep 2024 21:46:28 -0700 Subject: [PATCH 6/7] Adding test for async_set_existing_doorbell_type_enabled --- tests/test_ring.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test_ring.py b/tests/test_ring.py index 6ff48a3..668a5c2 100644 --- a/tests/test_ring.py +++ b/tests/test_ring.py @@ -289,3 +289,15 @@ def test_sync_queries_with_no_event_loop(): with pytest.deprecated_call(): auth.close() + + +async def test_async_set_existing_doorbell_type_enabled(ring): + data = ring.devices() + dev = data["doorbots"][0] + assert dev.existing_doorbell_type == "Mechanical" + + # Attempting to torn off the in-home chime + await dev.async_set_existing_doorbell_type_enabled(value=False) + + # Attempting to torn on the in-home chime + await dev.async_set_existing_doorbell_type_enabled(value=True) From 4706f9e0c21b3ca8dfbfe296dcd61e81605e234e Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Mon, 2 Sep 2024 11:13:48 +0100 Subject: [PATCH 7/7] Add asserts and extra test steps --- tests/test_ring.py | 55 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/tests/test_ring.py b/tests/test_ring.py index 668a5c2..26afaac 100644 --- a/tests/test_ring.py +++ b/tests/test_ring.py @@ -6,7 +6,7 @@ import pytest from freezegun.api import FrozenDateTimeFactory from ring_doorbell import Auth, Ring, RingError -from ring_doorbell.const import USER_AGENT +from ring_doorbell.const import MSG_EXISTING_TYPE, USER_AGENT from ring_doorbell.util import parse_datetime from .conftest import json_request_kwargs, load_fixture_as_dict, nojson_request_kwargs @@ -291,13 +291,60 @@ def test_sync_queries_with_no_event_loop(): auth.close() -async def test_async_set_existing_doorbell_type_enabled(ring): +async def test_set_existing_doorbell_type(ring, aioresponses_mock): data = ring.devices() dev = data["doorbots"][0] assert dev.existing_doorbell_type == "Mechanical" - # Attempting to torn off the in-home chime + kwargs = nojson_request_kwargs() + + aioresponses_mock.requests.clear() + # Attempting to turn off the in-home chime await dev.async_set_existing_doorbell_type_enabled(value=False) + kwargs["params"] = { + "doorbot[description]": dev.name, + "doorbot[settings][chime_settings][enable]": 0, + } + aioresponses_mock.assert_called_with( + url="https://api.ring.com/clients_api/doorbots/987652", + method="PUT", + **kwargs, + ) - # Attempting to torn on the in-home chime + aioresponses_mock.requests.clear() + # Attempting to turn on the in-home chime await dev.async_set_existing_doorbell_type_enabled(value=True) + kwargs["params"] = { + "doorbot[description]": dev.name, + "doorbot[settings][chime_settings][enable]": 1, + } + aioresponses_mock.assert_called_with( + url="https://api.ring.com/clients_api/doorbots/987652", + method="PUT", + **kwargs, + ) + + aioresponses_mock.requests.clear() + # Attempting to set the doorbell type + await dev.async_set_existing_doorbell_type(2) + kwargs["params"] = { + "doorbot[description]": dev.name, + "doorbot[settings][chime_settings][type]": 2, + } + aioresponses_mock.assert_called_with( + url="https://api.ring.com/clients_api/doorbots/987652", + method="PUT", + **kwargs, + ) + + # Attempting to enable when no chime present + settings = dev._attrs["settings"]["chime_settings"] + settings["type"] = 2 + assert dev.existing_doorbell_type == "Not Present" + + with pytest.raises(RingError, match="In-Home chime is not present."): + await dev.async_set_existing_doorbell_type_enabled(value=True) + + # Attempting to set the doorbell type to an invalid value + with pytest.raises(RingError, match=f"value must be in {MSG_EXISTING_TYPE}"): + await dev.async_set_existing_doorbell_type(4)