The widget rendered "Keine gültigen Live-Werte" the moment SMARD's
load filter (id 410) lagged behind the production filters by even one
slot — the aggregator coalesced "filter unavailable" with "filter
returned 0" and the percent calculation refused to divide by zero.
Three changes:
1. SmardSnapshot.values now uses `number | null` so callers can tell
"filter genuinely missing" apart from "filter reported zero" (e.g.
solar at night, decommissioned nuclear).
2. Aggregator pulls Energy-Charts (CMS strommix_de) in parallel and
uses it as a per-field fallback for any SMARD null. New
`dataSource: "smard+energy-charts"` flag travels in the response so
the attribution stays honest. Pure SMARD when everything resolves;
pure Energy-Charts when SMARD is entirely down; the hybrid label
for the common case where only load drops out.
3. Widget renders the production breakdown + context row + price row
even when the percentage is unavailable, with a clear "Lastwert
von SMARD gerade nicht verfügbar" hint instead of going blank.
Audit at 22:15 MESZ flagged the conventional sum (lignite + hard coal
+ gas + nuclear) as 19.1 GW in the widget vs 15.65 GW in reality. The
breakdown showed the gap was Energy-Charts' `Fossil gas` (6.9 GW)
which bundles natural gas + GuD + similar, while SMARD's `Erdgas`
filter 4069 (3.8 GW) tracks just natural gas the way the widget label
implies. SMARD is the canonical German grid feed; switching the
primary source resolves the discrepancy directly.
- New `lib/smard.ts` fetches the 11 relevant filter IDs in parallel:
conventional (1223/4070/4069/1224), wind (4067/1225), solar (1226),
hydro (1228), biomass (4066), other-conventional + pumped storage
(1227/4071, surfaced separately), load (410). Two-step protocol
(index.json → archive.json) handled inside; output is MW (MWh × 4)
aligned to one common slot timestamp so every value on screen comes
from the same point in time.
- Aggregator route uses SMARD for production + load, Energy-Charts
only for cross-border saldo + day-ahead prices (where SMARD has no
convenient single-call endpoint). `dataSource: "smard" |
"energy-charts"` flag travels in the response so the widget can
attribute the numbers and fall back gracefully when SMARD is down.
- StrommixBlock gets a "Werte prüfen" disclosure that lists every
component (wind onshore + offshore, solar, the four conventional
buckets, biomass, hydro, load) with its MW value and the slot
timestamp + data source. Fact-check users can verify the addition
themselves now without asking.
Verified live: SMARD @ 21:00 UTC = lignite 8484 + hard coal 3480 +
gas 3811 + nuclear 0 = 15.78 GW conventional. Matches the user's
ground-truth 15.65 GW within sampling noise.