Skip to content

Commit f743885

Browse files
committed
feat: Initialize only boolean fields in DeviceFeatures and enhance APP_GET_INIT_STATUS mock data with model-specific feature information
1 parent 76590f8 commit f743885

File tree

5 files changed

+67
-58
lines changed

5 files changed

+67
-58
lines changed

.pre-commit-config.yaml

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,51 @@
11
# See https://pre-commit.com for more information
22
# See https://pre-commit.com/hooks.html for more hooks
33
exclude: "CHANGELOG.md"
4-
default_stages: [ pre-commit ]
4+
default_stages: [pre-commit]
55

66
repos:
7-
- repo: https://github.com/pre-commit/pre-commit-hooks
8-
rev: v4.5.0
9-
hooks:
10-
- id: debug-statements
11-
- id: check-builtin-literals
12-
- id: check-case-conflict
13-
- id: check-docstring-first
14-
- id: check-json
15-
- id: check-toml
16-
- id: check-yaml
17-
- id: detect-private-key
18-
- id: end-of-file-fixer
19-
- id: trailing-whitespace
20-
- repo: https://github.com/astral-sh/uv-pre-commit
21-
rev: 0.9.1
22-
hooks:
7+
- repo: https://github.com/pre-commit/pre-commit-hooks
8+
rev: v4.5.0
9+
hooks:
10+
- id: debug-statements
11+
- id: check-builtin-literals
12+
- id: check-case-conflict
13+
- id: check-docstring-first
14+
- id: check-json
15+
- id: check-toml
16+
- id: check-yaml
17+
- id: detect-private-key
18+
- id: end-of-file-fixer
19+
- id: trailing-whitespace
20+
- repo: https://github.com/astral-sh/uv-pre-commit
21+
rev: 0.9.1
22+
hooks:
2323
- id: uv-sync
2424
args: ["--locked", "--all-packages"]
25-
- repo: https://github.com/codespell-project/codespell
26-
rev: v2.2.6
27-
hooks:
28-
- id: codespell
29-
exclude: >
30-
(?x)^(
31-
.*\.ambr
32-
)$
33-
- repo: https://github.com/charliermarsh/ruff-pre-commit
34-
rev: v0.13.2
35-
hooks:
36-
- id: ruff-format
37-
- id: ruff
38-
args:
39-
- --fix
40-
- repo: https://github.com/pre-commit/mirrors-mypy
41-
rev: v1.7.1
42-
hooks:
43-
- id: mypy
44-
exclude: cli.py
45-
additional_dependencies: [ "types-paho-mqtt" ]
46-
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
47-
rev: v9.23.0
48-
hooks:
49-
- id: commitlint
50-
stages: [commit-msg]
51-
additional_dependencies: ['@commitlint/config-conventional']
25+
- repo: https://github.com/codespell-project/codespell
26+
rev: v2.2.6
27+
hooks:
28+
- id: codespell
29+
exclude: >
30+
(?x)^(
31+
.*\.ambr
32+
)$
33+
- repo: https://github.com/charliermarsh/ruff-pre-commit
34+
rev: v0.13.2
35+
hooks:
36+
- id: ruff-format
37+
- id: ruff
38+
args:
39+
- --fix
40+
- repo: https://github.com/pre-commit/mirrors-mypy
41+
rev: v1.7.1
42+
hooks:
43+
- id: mypy
44+
exclude: cli.py
45+
additional_dependencies: ["types-paho-mqtt", "types-pyyaml"]
46+
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
47+
rev: v9.23.0
48+
hooks:
49+
- id: commitlint
50+
stages: [commit-msg]
51+
additional_dependencies: ["@commitlint/config-conventional"]

roborock/device_features.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
from __future__ import annotations
2-
31
from dataclasses import dataclass, field, fields
42
from enum import IntEnum, StrEnum
5-
from typing import Any
3+
from typing import Any, Self
64

75
from roborock.data.code_mappings import RoborockProductNickname
86
from roborock.data.containers import RoborockBase
@@ -566,7 +564,7 @@ def from_feature_flags(
566564
new_feature_info_str: str,
567565
feature_info: list[int],
568566
product_nickname: RoborockProductNickname | None,
569-
) -> DeviceFeatures:
567+
) -> Self:
570568
"""Creates a DeviceFeatures instance from raw feature flags.
571569
:param new_feature_info: A int from get_init_status (sometimes can be found in homedata, but it is not always)
572570
:param new_feature_info_str: A hex string from get_init_status or home_data.

roborock/devices/traits/v1/device_features.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@ def __init__(self, product: HomeDataProduct, device_cache: DeviceCache) -> None:
4040
self.converter = DeviceTraitsConverter(product)
4141
self._product = product
4242
self._device_cache = device_cache
43-
# All fields of DeviceFeatures are required. Initialize them to False
43+
# All boolean fields of DeviceFeatures are required. Initialize them to False
4444
# so we have some known state.
4545
for field in fields(self):
46-
setattr(self, field.name, False)
46+
if field.type is bool:
47+
setattr(self, field.name, False)
4748

4849
def is_field_supported(self, cls: type[RoborockBase], field_name: FieldNameBase) -> bool:
4950
"""Determines if the specified field is supported by this device.

tests/devices/traits/v1/fixtures.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,21 @@ def dock_type_code_fixture(request: pytest.FixtureRequest) -> RoborockDockTypeCo
110110

111111
@pytest.fixture(name="mock_app_get_init_status")
112112
def mock_app_get_init_status_fixture(device_info: HomeDataDevice, products: list[HomeDataProduct]) -> dict[str, Any]:
113-
"""Fixture to provide a DeviceFeaturesInfo instance for tests."""
113+
"""Fixture to provide model-specific APP_GET_INIT_STATUS data.
114+
115+
Uses real device feature data from device_info.yaml when available for the
116+
product model, falling back to the default mock data otherwise.
117+
"""
114118
product = next(filter(lambda product: product.id == device_info.product_id, products))
115119
if not product:
116120
raise ValueError(f"Product {device_info.product_id} not found")
117-
return mock_data.APP_GET_INIT_STATUS
121+
device_info_data = mock_data.DEVICE_INFO.get(product.model)
122+
if device_info_data is None:
123+
return mock_data.APP_GET_INIT_STATUS
124+
return {
125+
**mock_data.APP_GET_INIT_STATUS,
126+
**device_info_data,
127+
}
118128

119129

120130
@pytest.fixture(autouse=True)

tests/mock_data.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,14 @@
143143
ZEO_ONE_DEVICE_DATA = DEVICES["home_data_device_zeo_one.json"]
144144
SAROS_10R_DEVICE_DATA = DEVICES["home_data_device_saros_10r.json"]
145145

146-
# Additional Device Features info from YAML. In the future we can merge these
147-
# all into a similar format or get from diagnostrics.
146+
# Additional Device Features info from YAML keyed by product model.
147+
# Each entry contains the fields needed for APP_GET_INIT_STATUS responses.
148148
_DEVICE_INFO_DATA = yaml.safe_load(pathlib.Path("device_info.yaml").read_text())
149-
DEVICE_INFO = {
149+
DEVICE_INFO: dict[str, dict[str, Any]] = {
150150
product_model: {
151-
"new_feature_info": data.get("New Feature Info"),
152-
"new_feature_info_str": data.get("New Feature Info Str"),
153-
"feature_info": data.get("Feature Info"),
151+
"new_feature_info": data.get("new_feature_info"),
152+
"new_feature_info_str": data.get("new_feature_info_str"),
153+
"feature_info": data.get("feature_info", []),
154154
}
155155
for product_model, data in _DEVICE_INFO_DATA.items()
156156
}

0 commit comments

Comments
 (0)