Add Priority Status sensor to Lyric integration - #177065
Conversation
Resideo's priority endpoint reports a top-level hold status (e.g. "NoHold") alongside the room priority data already used by the Room Priority select entity. This was parsed but never surfaced. Adds a dedicated diagnostic sensor reading from priorities_dict, gated the same way as the existing select entity (thermostat device with populated room data).
|
Hey there @timmo001, mind taking a look at this pull request as it has been labeled with an integration ( Code owner commandsCode owners of
|
There was a problem hiding this comment.
Pull request overview
Adds a diagnostic Lyric sensor exposing the thermostat’s room-priority hold status.
Changes:
- Creates the sensor for thermostats with room data.
- Reads status from
priorities_dict. - Adds the entity translation.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
homeassistant/components/lyric/sensor.py |
Implements and registers the priority-status sensor. |
homeassistant/components/lyric/strings.json |
Adds the sensor name. |
| priority = self.coordinator.data.priorities_dict.get(self._mac_id) | ||
| if priority is None: | ||
| return None | ||
| return priority.status |
| _attr_entity_category = EntityCategory.DIAGNOSTIC | ||
| _attr_translation_key = "priority_status" |
| if accessory_sensor.suitable_fn(room, accessory) | ||
| ) | ||
|
|
||
| async_add_entities( |
abmantis
left a comment
There was a problem hiding this comment.
Please keep this as draft until the other PR fixing the coordinator is merged.
We don't want to add a new sensor that is always unavailable.
| if accessory_sensor.suitable_fn(room, accessory) | ||
| ) | ||
|
|
||
| async_add_entities( |
There was a problem hiding this comment.
although this integration was already doing it, usually async_add_entities is called once, with the full list of entities to add.
I think it is ok to keep it, but would be nice to change it later for consistency
There was a problem hiding this comment.
Agreed — this follows the pattern already established in the file (two separate async_add_entities calls existed before this PR for DEVICE_SENSORS/ACCESSORY_SENSORS). Happy to consolidate all three into a single call in a small follow-up cleanup PR if that's useful, rather than expanding this one's diff. Let me know if you'd rather I just do it here.
| _attr_entity_category = EntityCategory.DIAGNOSTIC | ||
| _attr_translation_key = "priority_status" |
|
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
- Port the shared conftest.py fixtures from the sibling binary-sensor branch (real config-entry setup, aiolyric client patched at the Lyric.get_locations/get_thermostat_rooms boundary rather than mocked HTTP), since this branch predates that infrastructure. - Add an xfail(strict=True) end-to-end test documenting that the entity isn't created at all today: its creation gate reads rooms_dict, which never populates under the currently-pinned aiolyric (same currentPriority/priority key bug as the room_motion entity), and even if it did, LyricPriority.status reads the wrong JSON key too. Both are fixed in the same upstream aiolyric#165 diff. - Add direct unit tests for LyricPriorityStatusSensor.native_value (present/missing priority data), which don't depend on that fix and give real, non-xfail coverage of the new entity class and the async_add_entities gating logic - closing the codecov/patch gap Copilot flagged (new code in an already well-covered sensor.py). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
| @pytest.mark.xfail( | ||
| strict=True, | ||
| reason=( |
…ntirely Same fixture/patching cleanup already applied to the sibling branches, plus the bigger change joostlek's "let's not add failing tests directly" pushed toward: replace the xfail end-to-end test and the two direct LyricPriorityStatusSensor.native_value unit tests with a single real snapshot_platform test. - fixtures/locations.json now has two devices: one with a priority entry (state "NoHold"), one with room data but no priority entry (state "unknown") - both branches of native_value get exercised through real entity state instead of direct property calls. - rooms_dict/priorities_dict are set directly with lightweight stand-ins rather than real LyricPriority objects, since LyricPriority.status/ current_priority's field-name bugs (aiolyric#165) are aiolyric's own test suite's concern, not this integration's - this fixture tests our gating/display logic assuming the data contract is met, independent of whether the currently-pinned library can produce it today. - Verified new code (the async_add_entities generator + the whole LyricPriorityStatusSensor class) has zero coverage gaps; the only remaining "missing" lines are pre-existing, unrelated to this PR.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
tests/components/lyric/conftest.py:81
- Condense this fixture docstring to the non-obvious upstream constraint. Most of it narrates the setup and coverage already visible below, making the fixture harder to maintain.
"""Mock the aiolyric client, backed by a real Location and directly-set priority data.
Patches Lyric where the integration imports it (autospec, like the
mealie client mock). Location/device data comes from a real
LyricLocation parsed from a live-shaped fixture, so field-name
tests/components/lyric/test_sensor.py:38
- Move these unused fixtures to a
@pytest.mark.usefixturesdecorator. Neither fixture value is consumed by the test, so keeping them as parameters obscures which inputs the assertions actually use.
setup_credentials: None,
mock_lyric_api: MagicMock,
…ract Resideo's own API docs document locationID as an Integer, and aiolyric's get_thermostat_rooms already types it int, but this fixture quoted it as a string - inherited from early in this session before checking the real docs. No behavior change (the value is only ever interpolated into a URL), but the fixture now matches reality.
- Condense mock_lyric_api's docstring to the non-obvious constraint (the aiolyric field-name bug and why the second device exists); drop the narration of setup mechanics already visible in the code below. - Apply setup_credentials/mock_lyric_api via usefixtures in test_sensor instead of injecting them as unused parameters, matching our own "don't inject unused fixture arguments" rule.
Resideo's priority endpoint reports a top-level hold status (e.g. "NoHold") alongside the room priority data already used by the Room Priority select entity. This was parsed but never surfaced. Adds a dedicated diagnostic sensor reading from priorities_dict, gated the same way as the existing select entity (thermostat device with populated room data).
Proposed change
Resideo's priority endpoint reports a top-level hold status (e.g.
"NoHold")alongside the room priority data already used by the Room Priority select entity.
This was parsed but never surfaced. Adds a dedicated diagnostic sensor reading from
priorities_dict, gated the same way as the existing select entity (thermostatdevice with populated room data).
Dependency note: needs both #177022 (coordinator fetching priority data) and the
pending aiolyric field-name fix (
LyricPriority.statuscurrently reads the wrongJSON key) to report the real value. Safe to merge independently — it'll report
unavailable/an incorrect value until both land.Type of change
Additional information
LyricPriority.statusfix intimmo001/aiolyric#165Checklist
ruff format homeassistant tests)If user exposed functionality or configuration variables are added/changed:
Lyric binary sensor and new sensors docs #46986
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest.requirements_all.txt.Updated by running
python3 -m script.gen_requirements_all.To help with the load of incoming pull requests: