Skip to content

Don't fail the refresh when every entity has its own scan_interval - #276

Open
bprus wants to merge 2 commits into
timlaing:mainfrom
bprus:pr1-coordinator-empty-poll
Open

Don't fail the refresh when every entity has its own scan_interval#276
bprus wants to merge 2 commits into
timlaing:mainfrom
bprus:pr1-coordinator-empty-poll

Conversation

@bprus

@bprus bprus commented Aug 25, 2026

Copy link
Copy Markdown

Hi! So this is my first PR here in a small series that will follow. The end goal is to add read-modify-write feature to this integration. I needed it to integrate my Midea-based heat pump.

I want to be upfront. I wrote the code with the assistance of Claude Code. I'm myself a programmer, so I tried to check all the PRs myself to the best of my capabilities and reduce the slop to minimum.

Problem

ModbusCoordinator.async_update() raises UpdateFailed when the device returns no data. But the
coordinator only polls entities that have no scan_interval of their own — entities with one
are polled by their own timer.

So if every entity in a device config sets scan_interval, the coordinator's poll list is empty,
update_device() legitimately returns {}, and UpdateFailed is raised on every refresh. Home
Assistant then marks all the device's entities unavailable — including the ones whose own timers
are polling perfectly well.

The failure is confusing because the entities are being read successfully; only the coordinator's
own (empty) poll fails.

Fix

Treat an empty poll list as "nothing to do" rather than an error: return the existing data
(self.data or {}) instead of raising.

An empty result from a non-empty poll list still raises, so a genuinely failing device is still
reported.

Notes

Found on a device config where every entity had an explicit scan_interval; it cost a hardware test
run before the cause was clear. Tests cover both cases — empty poll list (no raise) and a real
failure (still raises).

bprus and others added 2 commits August 25, 2026 11:11
`async_update` polls only entities without a `scan_interval`. A device
config that sets one on every entity leaves that list empty,
`_update_device` returns {}, and the falsy check raised `UpdateFailed`
on every single refresh. That sets last_update_success False, which
marks ALL of the integration's entities unavailable - including the ones
their own timers are polling perfectly well.

The symptom is confusing: entities come up fine and then drop together
about one refresh interval later, with nothing wrong on the bus.

An empty poll list is not a failure. Return the data the per-entity
timers have already stored instead of discarding it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1a8b230a-753c-4597-9d52-4485c7b76e58

📥 Commits

Reviewing files that changed from the base of the PR and between cad0421 and eb9260c.

📒 Files selected for processing (2)
  • custom_components/modbus_local_gateway/coordinator.py
  • tests/test_coordinator.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Improved update handling when all entities use their own polling intervals.
    • Preserves existing data and avoids unnecessary device refreshes in this configuration.
  • Tests
    • Added coverage for configurations without coordinator-polled entities.

Walkthrough

async_update now returns cached data when no entities require coordinator polling. A test verifies that the device is not refreshed and existing data remains unchanged.

Changes

Coordinator polling

Layer / File(s) Summary
Cached data guard and validation
custom_components/modbus_local_gateway/coordinator.py, tests/test_coordinator.py
When the coordinator entity list is empty, async_update logs the condition and returns existing data. The test verifies that client.update_device is not called.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to eb926

The PR changes empty coordinator polls to remain valid without marking entities unavailable, while preserving failures for non-empty polls. No actionable merge-blocking risk remains.

Poem

A rabbit checks the timer’s beat
No shared device call repeats
Cached values stay in place
The empty list finds saving grace
Tests watch the update path retreat

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 2 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarises the main change: preventing refresh failures when all entities use their own scan interval.
Description check ✅ Passed The description accurately explains the empty coordinator poll problem, the proposed fix, and the test coverage.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@bprus bprus changed the title Pr1 coordinator empty poll Don't fail the refresh when every entity has its own scan_interval Aug 25, 2026
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.

1 participant