Skip to content

fix(control): ignore stale load, missing SoC, and stale meters - #1170

Merged
frahlg merged 4 commits into
masterfrom
fix/control-stale-load-soc
Sep 12, 2026
Merged

frahlg merged 4 commits into
masterfrom
fix/control-stale-load-soc

Conversation

@frahlg

@frahlg frahlg commented Sep 8, 2026

Copy link
Copy Markdown
Member

Core can count offline battery/PV power as household load and issue discharge commands before a battery has reported SoC. The original patch blocked allocation but slew and fuse relief could restore a negative command.

Ignore watchdog-offline battery/PV readings in load math, require a live configured site-meter reading for the inner PV-curtail calculation, and block missing-SoC discharge through the final command pipeline. Fuse relief can cancel charging or use a sibling battery with known SoC; it cannot assume energy in an unknown pack. Recompute EV headroom after the final battery limits.

The existing outer site-meter freshness gate remains in place. The inner helper tests do not imply a live site previously dispatched with a stale meter.

Validation:

  • New regressions reproduce the previous head's failures for slew from autonomous discharge, fuse relief from idle/charge, dispatch holdoff, and a mixed known/unknown-SoC fleet.
  • All control tests pass, including charge-from-surplus with unknown SoC.
  • make verify passes: all Go packages, migration/release checks, vet and build. Native bundle integrity passes; native execution is skipped because this bundle has no worker for the Mac host.
  • git diff --check passes. The current master merge after verification adds only the selected vision/roadmap documentation.

No physical device commands, release or installation were part of this validation.


Note

Medium Risk
Changes core dispatch and PV curtail safety rails; incorrect gating could block legitimate discharge or curtail, but the intent is conservative (fail closed on unknown SoC/stale meters).

Overview
Tightens control safety when telemetry is stale or incomplete: household load math, battery discharge without SoC proof, and live PV curtail caps.

Load calculation (siteLoadW) now sums battery and PV watts only from drivers with live telemetry (sumOnlineSignedW), matching EV handling. Offline last-known PV/battery readings can no longer inflate apparent load and weaken DC-link / protective curtail.

Missing SoC batteries no longer assume ~10% energy for dispatch. Allocation marks them discharge-blocked; floorMissingSoCDischarge runs at the end of the safety pipeline so slew and fuse relief cannot issue negative targets. fuseTargetBounds treats nil SoC like “no discharge.” Charge-from-surplus with unknown SoC stays allowed; fuse relief can still use siblings with known SoC.

Live PV curtail (liveCurtailLimitW) goes through liveSiteMeter: configured site meter must be watchdog-online and ≤90s fresh. Stale or missing meter yields ok=false (planner static cap fallback); arbitrary battery readings are not used as grid except the configured combined-owner Ferroamp path.

Patch changeset plus regression tests for offline PV/battery load, missing-SoC paths (including fuse/holdoff), and live curtail meter gates.

Reviewed by Cursor Bugbot for commit 149596a. Bugbot is set up for automated code reviews on this repo. Configure here.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 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-09-08T09:34:54.772429Z cf4b332 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.

@cursor

cursor Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_789f4cf6-f7ea-4e1f-96c4-7009ad66c427)

@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: cf4b33283a

ℹ️ 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 thread go/internal/control/dispatch.go
@frahlg

frahlg commented Sep 8, 2026

Copy link
Copy Markdown
Member Author

Merge note: draft #888 also edits dispatch.go (PV export ceiling). This PR only changes siteLoadW, missing-SoC discharge, and liveCurtailLimitW. Rebase as needed; do not stack a large rewrite.

Skip watchdog-offline battery and PV watts in siteLoadW, block discharge
when a battery has never reported SoC, and require a fresh site meter
before liveCurtailLimitW returns a live cap.

Closes #1133 #1134 #1135

Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
@frahlg
frahlg force-pushed the fix/control-stale-load-soc branch from cf4b332 to 9e38fad Compare September 8, 2026 11:20
@cursor

cursor Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_ce222564-1db7-4973-b71d-004ad82bde18)

@miravoss26 miravoss26 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Three dispatch safety fixes: household load now skips watchdog-offline battery/PV watts (sumOnlineSignedW, mirrors SumOnlineEVW), missing-SoC batteries are discharge-blocked (default 0.0 + explicit block, charge-from-surplus untouched), and liveCurtailLimitW now requires the site meter to be telemetry-live and ≤90s fresh via the new liveSiteMeter helper (DerBattery fallback still scoped to the same configured site-meter driver only, no behavior change there).

Read through dispatch.go end to end — the logic matches the PR description and the closed issues (#1133/#1134/#1135) precisely, and stale_load_soc_test.go covers exactly the edge cases named (offline PV/battery in load math, SoC-nil discharge vs charge-from-surplus, stale/offline/missing meter for live curtail). No secrets, no new deps, no new network destinations, no authz changes.

CI shows 2 failures (core (Go), go test + vet) but both are in unrelated packages: internal/api's TestDuckDBHistoryBlocksImageOnlyDowngrade hit a GitHub-releases 504 (network flake), and internal/mpc's TestProcessTransportWriteCancellationRestartsWorker hit a "file already closed" race unrelated to this diff. internal/control itself passed clean (ok ... control 1.477s). Looks like pre-existing flakiness, not something this PR introduced.

Safe to merge from my read.

Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
@cursor

cursor Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_a1ca8674-d483-4306-93be-51fa7288f42a)

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.

2 participants