Skip to content

Commit 586a426

Browse files
committed
add v4 of the home data endpoint
1 parent 1e8819f commit 586a426

9 files changed

Lines changed: 32 additions & 8 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "roborock-local-server"
3-
version = "1.0.0"
3+
version = "1.0.1"
44
description = "private local Roborock server stack."
55
requires-python = ">=3.11,<3.14"
66
readme = "README.md"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 1.0.1
4+
5+
- Added support for the iOS app's `/v4/user/homes/{home_id}` home-data route so device lists no longer fall through to the generic catchall response.
6+
- Protected `/v4/user/*` routes with the same Hawk authentication used by existing user API versions.
7+
38
## 0.0.2-rc8
49

510
- Initial Home Assistant add-on manifest using the shared GHCR image.

roborock_local_server_addon/config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: Roborock Local Server
2-
version: "1.0.0"
2+
version: "1.0.1"
33
slug: roborock_local_server
44
description: Private Roborock HTTPS and MQTT stack for Home Assistant environments.
55
url: "https://github.com/Python-roborock/local_roborock_server"

src/roborock_local_server/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
__all__ = ["__version__"]
44

5-
__version__ = "1.0.0"
5+
__version__ = "1.0.1"

src/roborock_local_server/bundled_backend/https_server/routes/user/homes/item.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
def match(path: str) -> bool:
1313
clean = path.rstrip("/")
14-
return bool(re.fullmatch(r"/(?:(?:v2|v3)/)?user/homes/[^/]+", clean))
14+
return bool(re.fullmatch(r"/(?:(?:v2|v3|v4)/)?user/homes/[^/]+", clean))
1515

1616

1717
def build(

src/roborock_local_server/server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ def _required_protocol_auth(cls, clean_path: str) -> str | None:
717717
normalized = cls._normalized_path(clean_path)
718718
if cls._is_public_protocol_path(normalized):
719719
return None
720-
if normalized.startswith(("/user/", "/v2/user/", "/v3/user/")):
720+
if normalized.startswith(("/user/", "/v2/user/", "/v3/user/", "/v4/user/")):
721721
return "hawk"
722722
if normalized.startswith("/api/"):
723723
return "token"

tests/test_home_data_online.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from pathlib import Path
33

44
from fastapi.testclient import TestClient
5+
import pytest
56
from roborock.data import HomeData
67

78
from conftest import write_release_config
@@ -340,7 +341,8 @@ def test_device_detail_uses_runtime_connection_and_preserves_inventory_fields(tm
340341
assert device_data["deviceStatus"] == {"121": 10, "122": 99}
341342

342343

343-
def test_home_data_preserves_last_working_app_contract(tmp_path: Path) -> None:
344+
@pytest.mark.parametrize("home_path", ["/v3/user/homes/1233716", "/v4/user/homes/1233716"])
345+
def test_home_data_preserves_last_working_app_contract(tmp_path: Path, home_path: str) -> None:
344346
config_file = write_release_config(tmp_path)
345347
config = load_config(config_file)
346348
paths = resolve_paths(config_file, config)
@@ -423,7 +425,7 @@ def test_home_data_preserves_last_working_app_contract(tmp_path: Path) -> None:
423425
supervisor.refresh_inventory_state()
424426

425427
client = TestClient(supervisor.app)
426-
response = client.get("/v3/user/homes/1233716", headers=_hawk_headers(paths.cloud_snapshot_path, "/v3/user/homes/1233716"))
428+
response = client.get(home_path, headers=_hawk_headers(paths.cloud_snapshot_path, home_path))
427429
assert response.status_code == 200
428430

429431
home_data = response.json()["data"]

tests/test_protocol_auth.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,23 @@ def test_protected_routes_require_native_token_and_hawk_auth(tmp_path: Path) ->
139139
assert authed_inbox.status_code == 200
140140
assert authed_inbox.json()["data"]["count"] == 0
141141

142+
unauth_v4_home = client.get("/v4/user/homes/12345")
143+
assert unauth_v4_home.status_code == 401
144+
assert unauth_v4_home.json()["code"] == 40101
145+
assert unauth_v4_home.json()["data"]["auth"] == "hawk"
146+
147+
v4_home_headers = {
148+
"Authorization": build_hawk_authorization(
149+
user=user,
150+
path="/v4/user/homes/12345",
151+
timestamp=int(time.time()),
152+
nonce="nonce-protocol-auth-v4-home",
153+
)
154+
}
155+
authed_v4_home = client.get("/v4/user/homes/12345", headers=v4_home_headers)
156+
assert authed_v4_home.status_code == 200
157+
assert authed_v4_home.json()["data"]["id"] == 12345
158+
142159

143160
def test_token_auth_failures_use_roborock_invalid_credentials_code(tmp_path: Path) -> None:
144161
supervisor, _paths = _build_supervisor(tmp_path)

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)