diff --git a/.vscode/settings.json b/.vscode/settings.json index dc1fa43..2c809d1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,8 @@ { "python.formatting.provider": "black", "python.pythonPath": "/usr/local/bin/python", - "python.testing.pytestEnabled": true + "python.testing.pytestEnabled": true, + "cSpell.words": [ + "Schlage" + ] } \ No newline at end of file diff --git a/pyschlage/code.py b/pyschlage/code.py index 3761ea3..c92ec30 100644 --- a/pyschlage/code.py +++ b/pyschlage/code.py @@ -194,14 +194,14 @@ def from_json(cls, auth: Auth, device: Device, json: dict[str, Any]) -> AccessCo else: schedule = TemporarySchedule.from_json(json) + access_code_length = json.get("accessCodeLength", 4) return AccessCode( _auth=auth, _json=json, _device=device, access_code_id=json["accesscodeId"], name=json["friendlyName"], - # TODO: We assume codes are always 4 characters. - code=f"{json['accessCode']:04}", + code=f"{json['accessCode']:0{access_code_length}}", notify_on_use=bool(json["notification"]), disabled=bool(json.get("disabled", None)), schedule=schedule, @@ -216,7 +216,9 @@ def to_json(self) -> dict: json = { "friendlyName": self.name, "accessCode": int(self.code), + "accessCodeLength": len(self.code), "notification": int(self.notify_on_use), + "notificationEnabled": self.notify_on_use, "disabled": int(self.disabled), "activationSecs": _MIN_TIME, "expirationSecs": _MAX_TIME, @@ -245,7 +247,15 @@ def save(self): command = "updateaccesscode" if self.access_code_id else "addaccesscode" resp = self._device.send_command(command, self.to_json()) - self._update_with(self._device, resp.json()) + + # Either `{ "accesscodeId": "XXX" }` appears to be returned on `addaccesscode`; + # otherwise {} is returned when updated. + # Thus, calling `self._update_with()` does now work here as it calls + # `from_json()` which currently requires the presence other parameters. + resp_json = resp.json() + if "accesscodeId" in resp_json: + self.access_code_id = resp_json["accesscodeId"] + self.device_id = self._device.device_id if self._notification is None: self._notification = Notification( diff --git a/tests/conftest.py b/tests/conftest.py index 992d148..6580f18 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -195,11 +195,13 @@ def access_code_json(): return { "accessCode": 123, "accesscodeId": "__access_code_uuid__", + "accessCodeLength": 4, "activationSecs": 0, "disabled": 0, "expirationSecs": 4294967295, "friendlyName": "Friendly name", "notification": 0, + "notificationEnabled": False, "schedule1": { "daysOfWeek": "7F", "endHour": 23, diff --git a/tests/test_code.py b/tests/test_code.py index 3f56fd2..6bc44f9 100644 --- a/tests/test_code.py +++ b/tests/test_code.py @@ -87,10 +87,7 @@ def test_save( code.code = "1122" old_json = code.to_json() - new_json = deepcopy(access_code_json) - new_json["accessCode"] = "1122" - # Simulate another change that happened out of band. - new_json["friendlyName"] = "New name" + new_json = {"accesscodeId": "2211"} with patch( "pyschlage.code.Notification", autospec=True @@ -106,8 +103,7 @@ def test_save( "updateaccesscode", old_json ) assert code.code == "1122" - # Ensure the name was updated. - assert code.name == "New name" + assert code.access_code_id == "2211" def test_delete(self, mock_auth: Mock, access_code_json: dict[str, Any]): with pytest.raises(NotAuthenticatedError):