Skip to content

feat(map): add V1 dynamic map command models - #1005

Merged
allenporter merged 1 commit into
mainfrom
codex/v1-dynamic-map-models
Nov 1, 2026
Merged

allenporter merged 1 commit into
mainfrom
codex/v1-dynamic-map-models

Conversation

@Lash-L

@Lash-L Lash-L commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator

Add typed result models for get_dynamic_map_diff, get_dynamic_data, and full-map snapshot metadata, plus request parameter builders that preserve the device's snake_case keys. This is B2 of the incremental-map series, following the merged block helpers in #1001.

The models preserve missing versus empty fields, retain unknown numeric element IDs, decode block data, and expose application status checks. Request helpers support an omitted round, validate logical ranges and 32-bit nonces, and preserve signed/unsigned nonce representations. Map identity comparisons use the nonce bit pattern. Base64 decoding and the shared result == 0 or count == 0 page predicate follow the app implementation.

This provides the data-model layer for subsequent incremental-map state and trait integration.

Validation:

  • pytest -q -p no:cacheprovider --benchmark-disable: 1,706 passed, 53 expected failures, 11 deselected; 99 snapshots passed.
  • pre-commit run --all-files: all hooks passed, including Ruff, Mypy and Codespell.
  • Independent subagent audit against app sources and 822 saved command responses: 796 diffs and 26 element pages decoded without field loss or input mutation. All 199 binary values parsed with the merged block helpers; the full-map JSON snapshot matched all 13 binary element nonces and the map nonce.

Capture coverage includes normal/mismatch/full-refresh statuses, inline path pages, empty elements and zero-length pose-only pages. Captured nonces are below 2^31 and base64 uses the standard alphabet; signed nonce reading, URL-safe decoding and crossover status fields are supported by the app code rather than observed device output. Request nonce representation is retained to avoid assuming how a device accepts high-bit nonces. No device commands were issued during this validation.

Add typed diff, element-page, and full-map snapshot models with base64 decoding, application status fallbacks, and snake_case request parameter builders.

Allow optional round markers and signed or unsigned 32-bit nonce representations. Preserve request nonce representation while comparing map identities by bit pattern. Match the app decoder alphabets and shared page-success predicate.

Cover empty and pose-only pages, unknown element IDs, nonce identity boundaries, malformed base64, and request validation. Checked independently against the app implementation and recorded device responses.
Copilot AI balanced review requested due to automatic review settings November 1, 2026 01:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@codecov

codecov Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
roborock/data/v1/__init__.py 100.00% <100.00%> (ø)
roborock/data/v1/v1_dynamic_map.py 100.00% <100.00%> (ø)
tests/data/v1/test_v1_dynamic_map.py 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Lash-L Lash-L left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated code review by Gemini 4 Argon in Antigravity using our /review (/code-review) skill (.agents/skills/code-review/SKILL.md / AGENTS.md).

Summary

Clean, well-scoped addition of the V1 dynamic map command wire models (DynamicMapDiffEntry, DynamicMapDiffResponse, DynamicDataResponse, DynamicMapSnapshotEntry, DynamicMapSnapshot, DynamicMapResult) and request parameter builders (dynamic_map_diff_params, dynamic_data_params).

  • Layer 1 — Public Trait APIs & Data Models: All domain/wire containers inherit from RoborockBase with @dataclass, avoid Any and TypedDict, preserve missing vs. empty fields (None vs. "" / {}), and convert numeric dictionary keys (diff: dict[int, DynamicMapDiffEntry], snapshot: dict[int, DynamicMapSnapshotEntry]) cleanly without dropping unknown element IDs.
  • Layer 2 — Lifecycle & State Management: Models are purely declarative and side-effect-free (decoded_data, decoded_robot_data, has_inline_page, is_success, is_for_map), keeping stateful element merging decoupled from wire deserialization.
  • Layer 3 — Wire Protocols, Codecs & Resilient Enums: DynamicMapResult subclasses RoborockEnum with unknown = -1 fallback resilience; _decode_base64 validates both standard and URL-safe base64 alphabets and wraps decoding errors in RoborockException; _validated_nonce and is_for_map handle signed/unsigned 32-bit nonce representations accurately; and dynamic_map_diff_params / dynamic_data_params preserve wire snake_case keys (data_id).
  • Layer 5 — Tests & Fixtures: Colocated unit test suite in tests/data/v1/test_v1_dynamic_map.py with thorough @pytest.mark.parametrize coverage across enum fallback, input immutability, inline vs. paged responses, empty/zero-length pages, 32-bit nonce boundary checks, malformed base64, and parameter validation.

No issues found — LGTM!

@Lash-L
Lash-L requested a review from allenporter November 1, 2026 03:56
@@ -0,0 +1,221 @@
"""Wire models for the V1 dynamic map diff commands.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain here what dynamic map is? e.g. compared to a regular map? how is it used from a user perspective

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will add in next dynamic map PR. basically, some newer vacs do dynamic updates giving just the changes since the last call. Can also be done locally.

Will update the docstring though

@@ -0,0 +1,221 @@
"""Wire models for the V1 dynamic map diff commands.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given this is in roborock/data/v1/ the v1_ prefix for the modules seems redundant if you want to just make it dynamic_map and test_dynamic_map

@allenporter

Copy link
Copy Markdown
Contributor

Feel free to address any comments in a follow up PR.

@allenporter
allenporter merged commit afee561 into main Nov 1, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants