feat: add typed SupportedAlias parsing and per-type resolution - #2232
Open
iMicknl wants to merge 2 commits into
Open
feat: add typed SupportedAlias parsing and per-type resolution#2232iMicknl wants to merge 2 commits into
iMicknl wants to merge 2 commits into
Conversation
core:SupportedAliases can list several ids for the same type, each advertising a different subset of features. Consumers had to walk the raw attribute themselves, which in practice meant treating every entry as a distinct control instead of the single one the official app resolves to. Closes #2224
Every observed core:SupportedAliases payload reports ids as strings. The normalization stays because goToAlias takes a string parameter and attrs does not enforce the declared type.
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Documentation incorrectly claims parity with the official app despite omitted capability-tier filtering.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds typed parsing and per-type deduplication for device-supported aliases.
Changes:
- Introduces
SupportedAliasandDevicealias helpers. - Adds parsing and resolution tests.
- Documents alias resolution.
File summaries
| File | Description |
|---|---|
pyoverkiz/models.py |
Implements typed alias parsing and selection. |
tests/test_models.py |
Tests parsing, normalization, and deduplication. |
docs/device-control.md |
Documents the new helpers. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 3
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+149
to
+150
| The official app shows a single control per type and targets the most featured | ||
| id, which `get_most_featured_aliases()` reproduces: |
Comment on lines
+529
to
+534
| """Return the alias to use per type, mirroring how the Somfy app resolves them. | ||
|
|
||
| A device can advertise several ids for the same type, each covering a | ||
| different subset of features. The app shows a single control per type and | ||
| targets the most featured id, preferring the earliest one on a tie. | ||
| """ |
| """Tests for parsing and resolving the core:SupportedAliases attribute.""" | ||
|
|
||
| @staticmethod | ||
| def _device_with_aliases(value: list[dict] | None) -> Device: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2224.
core:SupportedAliasesis currently exposed as a raw, untyped list, so every consumer has to walk the attribute themselves — and, as #2224 describes, most will treat it as "one entry per type" and get duplicate behavior. A Somfyogp:VenetianBlindreports up to sixfavorite1slots for what is functionally a single "My position" preset.What this adds
Two
Devicemethods:get_supported_aliases() -> list[SupportedAlias]— the slots exactly as reported, empty when the attribute is absent or not a list.get_most_featured_aliases() -> dict[str, SupportedAlias]— one alias per type, picking the id with the mostfeatures, ties broken by array order (first wins). This is the "simpler and sufficient" variant sketched at the end of core:SupportedAliases can list multiple entries with the same type (e.g. favorite1); add a helper to resolve the one the app would use #2224; the value is ready to pass straight togoToAlias.Deliberately left out
required_featurescapability tiers (step 3 of the app's algorithm in core:SupportedAliases can list multiple entries with the same type (e.g. favorite1); add a helper to resolve the one the app would use #2224). Consumers that show one control per type — which is what the app does — already land on the most capable id via the most-featured pick, so the tiers add an API surface nobody currently needs. Easy to add later without breaking this signature.OverkizAliasTypeenum.typestaysstrso unknown types survive parsing instead of being dropped. Home Assistant relies on this to log a warning and fall back to a generated name when it meets a type it has no translation for; dropping unknown entries would hide new alias types instead of surfacing them.Naming note: #2224 floated
get_most_featured_alias_by_type; I went withget_most_featured_aliasessince thedict[str, ...]return already says "by type". Happy to rename.idis normalized withstr()becausegoToAliasis declared as taking a singleSTRINGparameter on every server indocs/data, and attrs does not enforce the annotation. Every payload observed indocs/dataand in the Home Assistant fixtures already reports ids as strings.Tests
Six tests in
tests/test_models.py::TestSupportedAliasescovering the absent attribute, parsing, id normalization, most-featured resolution, array-order tie-breaking, and that one alias is kept per type.tests/test_models.pypasses (184 tests).Also documented under "Resolve supported aliases" in
docs/device-control.md.Downstream
home-assistant/core#175567 consumes this: it replaces hand-rolled dict-walking with
get_most_featured_aliases(), which collapses the six duplicate "My position" buttons on the venetian blind in HA's own fixtures down to one.