Skip to content

Comments

Implemented differential poll intervals which significantly reduces polling#208

Merged
sveinse merged 4 commits intocustom-components:masterfrom
sveinse:feature-polling-fixups
Jul 22, 2025
Merged

Implemented differential poll intervals which significantly reduces polling#208
sveinse merged 4 commits intocustom-components:masterfrom
sveinse:feature-polling-fixups

Conversation

@sveinse
Copy link
Collaborator

@sveinse sveinse commented Jul 21, 2025

This PR implements the full system for differential poll intervals which significantly reduces the amount of polling. This fixes #205, #202, #199, #189 and is implementing as discussed in #188. Aims to address #165

  • Poll intervals adhere to the API guidelines
  • Implemented multiple coordinators to handle the various poll intervals
    • Top which polls for firmware updates, once every day
    • Info which polls for device info updates, once every hour
    • One per device for handling run-time state data update. Every minute during charging, 10 minute otherwise
  • Fixed trigger poll sequencer to use the coordinator and make sure only one run per device
  • API: Added Charger.is_charging() method
  • Removed user configurable scan interval

sveinse added 2 commits July 21, 2025 22:07
* Poll intervals adhere to the API guidelines
* Implemented multiple coordinators to handle the various poll intervals
  * Top which polls for firmware updates, once every day
  * Info which polls for device info updates, once every hour
  * One per device for handling run-time state data update. Every minute during charging, 10 minute otherwise
* Fixed trigger poll sequencer to use the coordinator and make sure only one run per device
* API: Added Charger.is_charging() method
* Removed user configurable scan interval
@sveinse sveinse added this to the v0.8 milestone Jul 21, 2025
Comment on lines 54 to 59
ZAPTEC_POLL_BUILD_INTERVAL,
ZAPTEC_POLL_CHARGER_TRIGGER_DELAYS,
ZAPTEC_POLL_CHARGING_INTERVAL,
ZAPTEC_POLL_INFO_INTERVAL,
ZAPTEC_POLL_INSTALLATION_TRIGGER_DELAYS,
ZAPTEC_POLL_IDLE_INTERVAL,
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't it be nicer to keep interval in front of the different states, so that the intervals stick together when alfabetized?

Suggested change
ZAPTEC_POLL_BUILD_INTERVAL,
ZAPTEC_POLL_CHARGER_TRIGGER_DELAYS,
ZAPTEC_POLL_CHARGING_INTERVAL,
ZAPTEC_POLL_INFO_INTERVAL,
ZAPTEC_POLL_INSTALLATION_TRIGGER_DELAYS,
ZAPTEC_POLL_IDLE_INTERVAL,
ZAPTEC_POLL_CHARGER_TRIGGER_DELAYS,
ZAPTEC_POLL_INSTALLATION_TRIGGER_DELAYS,
ZAPTEC_POLL_INTERVAL_BUILD,
ZAPTEC_POLL_INTERVAL_CHARGING,
ZAPTEC_POLL_INTERVAL_INFO,
ZAPTEC_POLL_INTERVAL_IDLE,

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Very good idea. Fixed.

Comment on lines 596 to 599
kw = {"state": True, "info": True}
else:
delays = ZAPTEC_POLL_CHARGER_TRIGGER_DELAYS
kw = {"state": True}
Copy link
Contributor

Choose a reason for hiding this comment

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

kw is no longer needed since it's now handled by self.options.poll_args

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, that kw does nothing. Removed.

@@ -507,22 +612,35 @@ async def _trigger_poll(self, obj: ZaptecBase) -> None:
delta,
kw,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
kw,
self.options.poll_args,

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No. kw, removed altogether. So fixed.


This function is called on data updates from the coordinator.
"""
zaptec_obj = self.options.zaptec_object
Copy link
Contributor

Choose a reason for hiding this comment

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

since zaptec_obj.is_charging() only exists if zaptec_obj is a Charger, I think we can make it explicit:

Suggested change
zaptec_obj = self.options.zaptec_object
zaptec_obj: Charger = self.options.zaptec_object

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added. I also made the code even more defensive and raise an error if zaptec_object is anything else than a Charger. Its good to be explicit.

zaptec_obj = zaptec[deviceid]

if isinstance(zaptec_obj, Installation):
poll_args = {"state": True, "info": True, "firmware": False}
Copy link
Contributor

Choose a reason for hiding this comment

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

Does polling installation state do anything?

Copy link
Contributor

Choose a reason for hiding this comment

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

And since installation info is already handled by info_coordinator, do we even want a timed polling of this here, or do we just want the ones triggered by HA-actions?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Technically inthe info_coordinator and the device_coordinator overlaps on info polling for installations. My thinking is that the device coordinator is a replacement of not having state, and that we poll it every 10 minutes. The info coordinator is run every 60 minutes, so it doesn't overload the server having them both.

The great thing about having the device coordinator for the installation is that it automatically provides the mechanism for sequenced polls if the "max current" number dial is changed. Which I've seen many times is needed.

What this doesn't have thou, is your comment that triggers of changes in the installation device, should also trigger its chargers. That we'll have to look at later.

Copy link
Contributor

Choose a reason for hiding this comment

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

What this doesn't have thou, is your comment that triggers of changes in the installation device, should also trigger its chargers. That we'll have to look at later.

As long as this is covered before we fully close #202, I think we're good here.

options=ZaptecUpdateOptions(
name=deviceid,
update_interval=ZAPTEC_POLL_IDLE_INTERVAL,
charging_update_interval=ZAPTEC_POLL_CHARGING_INTERVAL,
Copy link
Contributor

Choose a reason for hiding this comment

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

From here it looks like installation also changes polling frequency during charging, and it's not until you check in the ZaptecUpdateCoordinator constructor it becomes apparent that that is not the case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, I changed the code to make it more explicit. Please take a look and see if it is easier to follow now. Thanks.

* Fixed naming of `ZAPTEC_POLL_INTERVAL_` to make them order nicely
* Added more documentation around device entity creation
* Make code more explicit
* Removed left-overs
@steinmn
Copy link
Contributor

steinmn commented Jul 22, 2025

LGTM

The only question I have is what happens if a periodic poll fails at some point, especially the long period ones?

I occasionally get some failed after 9 retries: Cannot connect to host api.zaptec.com:443 ssl:default [Timeout while contacting DNS servers]-errors, and while that's probably just caused by my dev-container setup and/or running it in parallel with my regular HA-instance on the same network, I'm still curious how other errors would affect the system. Do we have some recovery mechanism that retries more often, or are the affected devices/entities now unavailable for the next full poll interval?

@sveinse
Copy link
Collaborator Author

sveinse commented Jul 22, 2025

@steinmn

LGTM

Thank you.

The only question I have is what happens if a periodic poll fails at some point, especially the long period ones?

The flippant answer is: The same way all other poll requests from HA are handled :D The more serious response is that I believe the coordinator have a mechanism for handling that, but I'm not 100% sure. It's a valid question.

I occasionally get some failed after 9 retries: Cannot connect to host api.zaptec.com:443 ssl:default [Timeout while contacting DNS servers]-errors, and while that's probably just caused by my dev-container setup and/or running it in parallel with my regular HA-instance on the same network, I'm still curious how other errors would affect the system. Do we have some recovery mechanism that retries more often, or are the affected devices/entities now unavailable for the next full poll interval?

This is interesting, because say that there is some mechanism in coordinators that handles connection issues, that would not affect the other coordinators. They will keep on trying and eventually time out. This is something we definitely need to test more when the beta is out.

@sveinse sveinse merged commit 9ba9216 into custom-components:master Jul 22, 2025
1 check passed
@sveinse sveinse deleted the feature-polling-fixups branch July 22, 2025 11:26
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.

Remove user settable scan/poll interval

2 participants