Skip to content

feat: Expose sync module scheduler status and toggle controls#1215

Open
aefo wants to merge 2 commits into
fronzbot:devfrom
aefo:dev
Open

feat: Expose sync module scheduler status and toggle controls#1215
aefo wants to merge 2 commits into
fronzbot:devfrom
aefo:dev

Conversation

@aefo

@aefo aefo commented Apr 11, 2026

Copy link
Copy Markdown

Resolves Issue: Fixes #1214

Description of Changes:
This PR exposes the Blink native scheduling state and provides mechanisms to toggle it, addressing the feature request in #1214 to allow Home Assistant to automate based on the active schedule.

Key additions:

  • API Endpoints: Added request_programs, request_program_enable, and request_program_disable to api.py to directly interact with network programs.
  • State Property: Added scheduler_enabled to BlinkSyncModule. This correctly reads active_program_id from the network info summary, gracefully falling back to iteratively checking the cached programs list if the summary is sparse.
  • Control Method: Added async_set_scheduler(enable: bool).

Optimizations & Edge Cases Checked:

  • Cache Optimization: Because async_set_scheduler is heavily reliant on the programs payload to target the correct schedule ID, the method prioritizes the program list already cached during standard get_network_info refresh cycles, entirely bypassing a redundant/wasteful API HTTP fetch.
  • Optimistic Cache Updates: The Blink API endpoints for toggling a schedule (802/803) only return a generic success message, not the updated state. Therefore, async_set_scheduler implements an optimistic local cache update upon detecting an HTTP success. This guarantees scheduler_enabled flips instantly and remains synchronously accurate, eliminating the need to force a full system refresh().

Verification:

  • Local tests with pytest run successfully (67/67 passing).
  • Local tests with tox run successfully (Note: tox environment bootstrapping fails on Windows MAX_PATH length limits for deep directories, but the underlying pytest framework and black linter both pass with 100% success locally).
  • Tested against a live physical Blink network, successfully toggling the schedule and appropriately logging optimistic cache responses.

- Add 
equest_programs, 
equest_program_enable, and 
equest_program_disable to API layer.

- Add scheduler_enabled property to BlinkSyncModule with fallback to programs list.

- Implement �sync_set_scheduler with optimistic caching to prevent redundant API refreshes.

- Expand test coverage for scheduler property, optimistic cache interactions, and network failure modes.
Comment thread tests/test_sync_module.py

@fronzbot fronzbot left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

There's a lot of weird stuff in here such that I'm pretty confident this PR was submitted by a rather poorly tuned agent. I'm uncomfortable merging this code as a result, but will give you a chance to respond to the comments.

Comment thread tests/test_api.py

response = await api.wait_for_command(self.blink, None)
self.assertFalse(response)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

One test that should be added is to validate the programs flow if the api.request_programs method returns None (which is the fallback state for http_get)

Comment thread blinkpy/sync_module.py
Comment on lines +394 to +397
if self.network_info is None:
self.available = False
return False

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Why were these lines added?

Comment thread blinkpy/sync_module.py
Comment on lines +129 to +134
_LOGGER.warning(
"Programs list not yet populated for network %s; "
"scheduler_enabled may be inaccurate. "
"Call get_network_info() first.",
self.name,
)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This is an inappropriate warning since the usage of this library makes the get_network_info method transparent.

Comment thread blinkpy/sync_module.py
pass

if program_id is None:
_LOGGER.error("Could not find an active program to disable.")

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Is this really an error?

Comment thread blinkpy/sync_module.py
try:
program_id = cached_programs[0]["id"]
except (KeyError, IndexError, TypeError):
_LOGGER.error(

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Again, I'm not sure that this should be logged as an error. There wasn't a fundamental API issue, it's just missing information

Comment thread blinkpy/sync_module.py
Comment on lines +236 to +244
for program in self.network_info.get("programs", []):
if program.get("id") == program_id:
program["status"] = status
_LOGGER.debug(
"Optimistically updated program %s status to %s.",
program_id,
status,
)
break

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Whoa, what's this? We're looping through every element of a list trying to find a match? That's...not great

Comment thread blinkpy/sync_module.py
Comment on lines +185 to +188
for program in cached_programs:
if program.get("status") == "enabled":
program_id = program.get("id")
break

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

There's more pythonic ways to do this- this is very brute force

Comment thread blinkpy/sync_module.py
# scheduler_enabled, so keep it consistent with the new state.
network = self.network_info.get("network", {})
if status == "disabled":
network.pop("active_program_id", None)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Do you really want to delete the active_program_id key from network when this is called?

@aefo

aefo commented Jun 14, 2026

Copy link
Copy Markdown
Author

There's a lot of weird stuff in here such that I'm pretty confident this PR was submitted by a rather poorly tuned agent. I'm uncomfortable merging this code as a result, but will give you a chance to respond to the comments.

Thanks for the comments. If you're open to the goal of the change, I will take a loop at the areas flagged to look at adjusting them

Thanks

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.

Feature Request: Expose Blink Scheduling status (Programs Enabled/Disabled)

2 participants