Skip to content

feat: add grid charge blackout windows - #119

Merged
bolagnaise merged 3 commits into
mainfrom
feature/optionally-allow-site-specific-local-time--f08cf5aa-g2
Aug 29, 2026
Merged

feat: add grid charge blackout windows#119
bolagnaise merged 3 commits into
mainfrom
feature/optionally-allow-site-specific-local-time--f08cf5aa-g2

Conversation

@bolagnaise

@bolagnaise bolagnaise commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Summary

Adds site-local Smart Optimization grid-charge blackout windows with setup, options, and optimizer-settings support.

  • Evaluates overnight windows and daylight-saving schedule timestamps in local time.
  • Combines blackout eligibility with existing grid-charge constraints while preserving normal solar charging and manual force-charge ownership.
  • Reports when blackout windows uniquely make a Charge By Time target infeasible, and prevents optimizer-owned force charging at blackout boundaries.

Validation

  • tests/test_grid_charge_soc_cap.py
  • Focused adjacent regression suite: 287 passed; two unchanged Flow Power assertions on current main fail outside this change.
  • py_compile and git diff --check
  • release_preflight.py --target-version 2.12.1207

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 29, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-29T11:01:27.893865Z 14ca9f2 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 14ca9f2d53

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +9456 to +9459
if force_state.get("scope") == "optimizer":
self._clear_optimizer_force_state()
elif self._force_state_clearer:
self._force_state_clearer()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve force state until blackout restoration succeeds

When restore_normal() or set_self_consumption_mode() returns False, these lines have already cleared the optimizer/shared force state even though the inverter may still be force-charging. The failure branch then claims the state is retained for retry, but status and subsequent ownership checks can report no optimizer force, making cleanup unreliable during the blackout. Clear the state only after a successful restore, or snapshot and restore it on failure as the adjacent SOC-cap path does.

Useful? React with 👍 / 👎.

Comment on lines +17535 to +17540
return [
self._time_is_in_grid_charge_blackout(
localize(timestamp) if callable(localize) else timestamp,
windows,
)
for timestamp in self._price_timestamps(n)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Block slots that overlap minute-level blackout windows

For valid windows whose boundaries are not aligned to the fixed five-minute optimizer interval, the mask tests only each slot's start timestamp. A window such as 22:01–22:04 therefore matches no schedule slot, and the runtime gate is likewise only reached when an action is executed, so a planned charge spanning that entire window can continue unchanged. Either reject/round non-aligned times or mark every slot whose execution interval overlaps a blackout window.

Useful? React with 👍 / 👎.

Comment on lines +3584 to +3587
except ValueError:
# Do not persist malformed legacy/text-client input during
# setup. The options form also shows the field-specific error.
return await self.async_step_ml_options()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Surface setup validation errors instead of resetting the form

When a user enters malformed blackout JSON during initial setup, this exception path recursively renders the step with user_input=None, so no field error is shown and all submitted values are replaced by defaults. The user only sees that Continue did nothing, despite the new invalid_grid_charge_blackout_windows translation being available. Re-render the form with the field-specific error and preserve the submitted values, as the options-flow path does.

Useful? React with 👍 / 👎.

@bolagnaise
bolagnaise merged commit d61a09c into main Aug 29, 2026
2 checks passed
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