Fix 30-minute skew in Total column between dashboard card and Predbat app plan view#3858
Merged
springfall2008 merged 2 commits intomainfrom May 3, 2026
Merged
Conversation
The JSON plan rows were using metric_end (cost at end of slot) for total_cost and carbon_amount_end for total_carbon, while the HTML plan was correctly using metric_start (cost at start of slot) and carbon_amount. This caused a 30-minute offset between the plan displayed in the dashboard card (HTML-rendered) and the plan shown in the Predbat app (JSON-rendered), with the Predbat app showing one slot ahead in the Total column. Fix: change total_cost and total_carbon in the JSON rows to use the start-of-slot values, consistent with the HTML plan and the documentation which states "Total - The total cumulative cost so far at the start of the slot". Agent-Logs-Url: https://github.com/springfall2008/batpred/sessions/a44e9bb5-5c3c-4bcb-b632-ed880a225406 Co-authored-by: springfall2008 <48591903+springfall2008@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix predbat plan costs skewing by 30 minutes on dashboard
Fix 30-minute skew in Total column between dashboard card and Predbat app plan view
May 3, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Aligns the Predbat web app’s JSON-rendered plan “Total” columns with the HTML dashboard plan so cumulative totals are reported at the start of each slot, eliminating the visible 30-minute skew.
Changes:
- Switch JSON row
total_costfrom usingmetric_endtometric_start(start-of-slot cumulative total). - Switch JSON row
total_carbonfrom usingcarbon_amount_endtocarbon_amount(start-of-slot cumulative total), when carbon is enabled.
Comment on lines
1570
to
+1575
| json_row["cost_change"] = dp2(metric_change / 100.0) | ||
| json_row["total_cost"] = dp2(metric_end / 100.0) | ||
| json_row["total_cost"] = dp2(metric_start / 100.0) | ||
| if self.carbon_enable: | ||
| json_row["carbon_intensity"] = carbon_intensity | ||
| json_row["carbon_change"] = carbon_change | ||
| json_row["total_carbon"] = dp2(carbon_amount_end / 1000.0) | ||
| json_row["total_carbon"] = dp2(carbon_amount / 1000.0) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Total column in the JSON-rendered plan (Predbat web app) was one slot ahead of the HTML-rendered plan (dashboard card), because the JSON rows were populated with
metric_end(cost at slot end) while the HTML usedmetric_start(cost at slot start) — causing a visible 30-minute offset.Change
In
output.py,publish_html_plan, align the JSON row values with the HTML plan:Both values now reflect the cumulative total at the start of the slot, consistent with the HTML plan and the documented semantics of the Total column.
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
api.octopus.energy/home/REDACTED/work/batpred/batpred/coverage/venv/bin/python3 python3 ../apps/predbat/unit_test.py --quick(dns block)gitlab.com/usr/lib/git-core/git-remote-https /usr/lib/git-core/git-remote-https origin REDACTED(dns block)https://api.github.com/repos/springfall2008/batpred/contents/apps/predbat/home/REDACTED/work/batpred/batpred/coverage/venv/bin/python3 python3 ../apps/predbat/unit_test.py --quick(http block)/home/REDACTED/work/batpred/batpred/coverage/venv/bin/python3 python3 ../apps/predbat/unit_test.py --test web_if --test model(http block)If you need me to access, download, or install something from one of these locations, you can either: