API Changelog
Chronological public API changes (newest first). Contract = /docs spec + OpenAPI. AI overview: /docs/llms.txt.
This page documents changes to the public SpotpriceAPI in chronological order (newest first). Breaking changes are announced at least 30 days before removal, with a deprecation notice.
2026-08-30
- Sparvo/Portal — WhatsApp referral: “Share via WhatsApp” / referral WhatsApp forms use
data-sf-no-page-loading— no “Loading …” overlay before redirect to WhatsApp (fix: overlay stuck after cancel/back in the PWA). Additionally: loading modal dismisses onvisibilitychangeback to the app when the page was already fully loaded.
2026-08-28
- Hours v1.11 (
hours_demand_v1.11): Reserve (prep) sizing after planned cover/bridge/opp kWh (SOC path, not natural trough only) —basis.forward_prep.energy_kwhnever above v0; optionalnotes:sized_after_cover. Decide + storage tile family B (simulate_week_grid, same predicates). Cover slots unchanged (non-regression). Kill-switchHOURS_PREP_AFTER_COVER=0. Audit-fix:plan_feasibilityrefreshed after prep trim — cover shortfall stayspartial, prep-only trim does not falsestorage_undersized. All plants/keys. No PicoC repaste. - Hours cover slot rank (refactor,
hours_demand_v1.10): Cover picker: per calendar day price rank, global cheapest day-head merge — same rule all days. Dominated-hour guard everywhere. Decide + explain. Family B: policy intent (autark, prep predicates, port room) — not the full picker/dominated guard insimulate_week_grid. - Portal/Sparvo — dump-price toggle removed: Day navigator (
/live-strompreise, login, admin), Sparvo/prices,/plant,/plant-outlook, and/code-samplesnow display and calculate with model/point price only (price_ct_kwh/price_eur_mwh) — bars, min/max/avg, switch-on planning, grid-charge ranking, FC verification savings sim (/fc-verification, admin), landing#planung-live. No No dump correction | Dump price toggle, no midday hatch overlay.price_view=scenarioin URLs is ignored. API fieldsdump_risk*/dump_scenario_*remain optional onGET /v1/forecast(unchanged). FC verification detail + CSV/PDF dump history unchanged. Cleanup: deleteddump-view-pref.js, removed dead i18n/CSS/JS remnants, code samples no longer inject dump helpers. - Wiki audit (lead + PicoC): Regression tests for lead blockquote on all
PAGE_SLUGSDE+EN and PicoC ``fences alongsidedocs-lead` (copy-paste windows unchanged). Concept [API-DOCUMENTATION-PUBLIC-KONZEPT.md](../../API-DOCUMENTATION-PUBLIC-KONZEPT.md) § llms + wiki lead updated. - Wiki detail guide lead blockquotes: All Loxone PicoC guides (Hours, telemetry, Flex, legacy Windows, Forecast, PV, Weather) plus Plant telemetry, Webhooks, Weather, Errors, Download and Changelog DE+EN get lead
>summaries (endpoint, PicoC version, Community 120/day, Loxone-first). Rendererdocs-leadunchanged. - llms.txt v2 + wiki agent optimization:
/llms.txt,/llms-full.txt, and new/docs/llms.txtfollow llmstxt.org (blockquote summary, markdown links, pricing numbers, endpoint overview, cURL/Python/Loxone examples). Wiki hub and lead pages DE+EN consolidated (Loxone as primary EMS path, open REST API). Sparvo/llms.txtwith GEO keywords, PWA/no-login, EV/heat-pump USPs. - Hours explain cover label: Cover slots show “economical cover hour” only — suffix “not the cheapest hour of the day” removed (portal/Sparvo, poll
hours-decision-explain.js). - Hours cover slot rank (hotfix 2b / hotfix,
hours_demand_v1.10): Dominated-hour guard on follow days; price rank all calendar days. Family B: policy shared, not full picker. No PicoC repaste. - Hours autarky gate v1.10 (
hours_demand_v1.10): When PV+battery cover the horizon without grid charging (basis.autark_ok), planned charging is 0 kWh (cover, prep, dump, bridge) — Decide and the portal “battery size & spot cost” tile share the same policy. Gate window \(H_{gate}\) = rest-of-today from decide + next calendar day until morning sun (gate_hinautark_notes). All plants/keys. Additive:basis.autark_ok,basis.autark_notes. Kill-switchHOURS_AUTARK_GATE=0. No PicoC repaste (Extract v1.17 / Fetch v1.15). - Hours cover short-term v1.9 (
hours_demand_v1.9): “Until this morning” SOC projection uses meter actuals (partial hour + 2–4 h recent rate) for cover load/PV and the grid-charge engine — consistent in Portal/Sparvo Hours explain and API (basis.load_refine,hourly_load_cover_kwh). Follow-day load profile unchanged. No PicoC repaste (Extract v1.17 / Fetch v1.15 unchanged). - Hours v1.9 audit fix: No double partial-hour in slot picker/consolidate after refine;
awaiting_first_deltakeeps meter-budget norm; plant-outlook chart uses the same cover load as Hours; SOC slice indices clamped to real hours. Extract v1.17:periodup to 48, no 40 h reset oflastOkAbs. ExtractPvDaily v2.2: optional O8–O13 zeroed when JSON fields missing. - Hours v1.9 audit fix (2): Snapshot-first outlook patches cover load like live resolve; cross-midnight cover writes D+1 hours;
load_kwhrecomputed after patch. Extract v1.17 fallback O2 = hours in window (inclusive end hour). - Hours explain SoC sync: “Now” in grid-charge explain uses live telemetry SoC (not older decide snapshot); forecast stamps shift by SoC drift. Live-telem poll patches explain client-side.
- Hours SOC sync audit fix: No cumulative projection drift on telem polls; idempotent server overlay (
*_at_decidebaselines); outlook patch recomputespv_kwh. - Loxone offline fallback (Forecast · PV · Flex): PicoC fetch blocks use
rename()backup instead of truncating JSON; on API outage O1=12 (Forecast/PV) and switching from last JSON (Flex boot phase 30). Versions: DebugSpotpriceFile v5.6, ParseSpotpriceForecast v18, DebugPvForecast v1.3, ExtractPvDaily v2.2, SpotpriceFlexWindows v0.6.11. Wiki DE+EN + code samples updated. No REST API change.
2026-08-27
- Page-loading modal: Arm on
submitonly after sync handlers (setTimeout 0) — cancelled forms (empty admin password / dismissedconfirmon members) no longer leave “Loading …” stuck over the page. - Landing + Sparvo marketing IA (Hours-first): Lower funnel Proof → Sparvo (guest
app.sparvo.at/try) → Steps → wiki band/docs→ FAQ (7) → CTA. Lead products Hours · PV · Windows Flex · 168h; Weather API not marketed. Portal SEO defaults + legacy refresh on portal boot. sparvo.at: FAQ/VideoObject, wiki footer, hero “specs in the wiki”. - Page-loading modal (Sparvo/Portal/websites): Same-origin navigations and slow first paints show a “Loading …” dialog until the HTML is ready (
DOMContentLoaded). Fast pages (<≈280 ms) stay without overlay. Opt-out:data-sf-no-page-loadingon body/link/form. Embeds unchanged. - Lazy-load Anlagenprognose (Sparvo/Portal): First paint uses
mode=shell(PV + telem, no Hours Decide); Hours/horizon hydrate via/api/plant-outlook/dataor/plant-outlook/data(mode=full). Hours resolve capped byHOURS_RESOLVE_MAX_PARALLEL(default 2, non-blocking); busy slots return JSONstatus=computing+ HTTP 200 +Retry-Afterwith client backoff (body remains parseable; Hours explain and day charge chips are kept on soft-busy — no day clobber). Soft-busy only forstatus=computing(notpending_hoursalone). Incomplete/failed shells setpending_hours=falseand do not show loaders without a hydrate mount. HTTP 503 (includingoutlook_failed) and 429 use the same backoff. Fetch/horizon chains use generation+abort; after Hours failure or horizon abandon (retry exhaust/hard error) only the loading skeleton is cleared (real fragments kept);charge_hours_sourcewarning updates on hydrate. Horizon HTML: empty partial → empty fragment. TTL cache returns deep copies. Empty explain/horizon templates are shell-safe (fmt_numUndefined guard). Docs Markdown renderer process-lru_cache. Public API JSON contracts unchanged. - Hotfix PV-day on /plant: Precomputed outlook PV (midnight→…) is realigned from now for Hours/cover/follow-days — morning-sun stamps no longer show 23:00/00:00.
- Audit fix plant primary / plant-weather: Claims transfer on set-primary runs in the same DB transaction as the primary flag; portal invalidates plan freezes like Sparvo; remove/leave/delete primary likewise. Secondary no longer counts
skipped_secondaryas a weather error (incl. geo-save). Wiki Weather/PV: refresh 05:20 + 12:20 Vienna (HA primary). - Battery size & spot cost (outlook/Sparvo): Chips split price basis (4 typical spot weeks / fallback) and load & PV (meter seasons / hybrid / estimate); 12‑month spot Ø remains meta. Season price state
data/state/season_price_basis_latest.json(HA primary soft-fail). PV weather cache 2×/Vienna day (05:20 + 12:20), on-demand writes primary only. Citizen explain for the scale-up./plantshort-TTL + PV/forecast/meter dedupe. Hours Decide:basis.storage_horizonannual fields remain null. Sparvo/llms.txt+/ai.txt(marketing + app). - Plant primary user: Setting primary always moves device care and EMS connection (confirm dialog); clear-primary UI removed. Deactivating/deleting a primary returns claims to the plant administrator.
- Hours auto-decide near min SoC (bidirectional): SOC ping at 10 pp / 5 pp / floor relative to
min_soc_pct, and the mirror on recovery (floor → 5 pp → 10 pp → headroom / full O12). Internal async Decide (snapshot +plant.plan_updatedon delta). Sparvo/Portal live; webhook immediately; Loxone Extract on the next Hours Decide. No Decision quota. Kill-switchHOURS_SOC_NEAR_MIN_REPLAN=0.
2026-08-26
- Hours reserve v1.8 (
hours_demand_v1.8): Cap =min(target, max(min+10 pp, min(target−10 pp, 85 %))). Lookback onlyvorrat_wuerdig(P20 ∧ absolute guard; dump on → ≤ limit incl. 0). Fill-day blocks prep including night. Dump before reserve (sizing + placement). Sticky lookback ≤P25. Force D0+Near ∪ D+1. Family B: Cap+port+same predicate. Soft-Stop overnight only cover/prep kWh. PicoC wiring unchanged (O1/O4 values follow engine). - Hours v1.8 audit fix: Sticky reads top-level
forward_prep(snapshot shape); Force no longer bypasses Fill-day; Dump placement ≤ limit; Dump rank without Force; layer-B onlyvorrat_wuerdig; bridge separate; Family-B Cap clip. Docs:charge_nowinstead ofcharge_active. PicoC wiring unchanged. - Hours v1.8 follow-up: Sticky works outside P20 (≤P25); Family-B cheap picks stay in the calendar day; Sticky price from live series; storage tile kWh with 1 decimal.
- Grid charge O11 vs connection rating:
charge_power_kw(Loxone Extract O11) ismin(inverter/max_charge, connection × 0.80 − base load)— not the raw grid connection rating. Portal/Sparvo plant profile shows the computed power under the connection slider. Thin Decide withoutbattery.max_charge_kw; after saving the profile, tap Fetch I6. Planned hourly kWh may stay SoC/reserve-limited (not always full cap). - Portal navigation Plant: Under Plant, new Devices (SSO → Sparvo
/devices, preconfigure devices) and EMS connection (/settings/ems, PicoC slots). EMS connection no longer under Account. - Plant primary user (Sparvo + Portal): Settings → Account shows plant administrator and plant primary user with badges (like Admin). The plant administrator can assign or clear the primary role among co-users — only after admin password (Portal:
/settings/members; Sparvo: Account or/settings/members). Optional EMS claim transfer. - Sparvo/Portal EMS: UI Schedule (API field
recipesunchanged). PicoC slots only in Portal EMS connection (/settings/ems) — Sparvo/migration never inventwallbox_*/flex_*. Unbound catalog devices: “EMS pending” chip + Portal link. Roles: Plant administrator / Plant primary user / Co-user. Catalogplant_sparvo_prefsperapi_key_id. Binding is the serve source of truth for the slot (schedules / Flex merge). - Flex Sparvo merge:
flex_pack=0/ I6=0 reads schedules from plant catalogplant_sparvo_prefs(owner prefs fallback). PicoC slot only via Portal EMS; claim preserved on re-bind. - EMS bind overlay: Serve/Flex use only bound PicoC slots (
plant_ems_bindings); conflict losers and unbound catalog rows expose no slot in merge/schedules/Portal UI. - Following-days tile: Planned grid charge line only for planned hours on the tile’s calendar date — not hours listed as skipped cheap hours, and not next-day overnight charge inside the sun→sun window. Without·with grid at morning sun stays the real trajectory.
- Reserve/cover before a later morning sun: The min+10 pp soft-cap applies before every morning sun (cover and reserve, not only the first night). Reserve fills only to the prep floor, not target SoC/100 % — expensive nights such as Mon 03:00/04:00 do not fill the pack when PV + cheaper daytime hours suffice. Survival (min SoC) stays separate.
- PV-hour grid cap (hotfix): Re-assigning the same hour must not exceed remaining
charge power − PV(no fallback to pack headroom → no 14,9 kWh slots on a 1,7 kW port room). After the picker, chronological clip: no further grid charge once Stopp-SOC is 100 % / pack full (e.g. no 0,8 kWh right after 13:00→100 %). - Hours backward-prep (
hours_demand_v1.7): Each gap day looks back within pack carry \(H_{eff}\) (basis.carry_hours) — \(H_{prep}\) is the data window only, not clipped at \(t=0+H_{eff}\). A source day already filled by PV without grid (full PV, no 70% discount) takes no prep kWh — including evening after the fill. Far-cover only in[trough−H_{eff}, trough]and not on fill-days (no backdoor). Cover stretch ends at the last complete PV-day. Slot roleprep→ “reserve hour”. Every successful Decide (ok) runs prep + the slot picker (including when grid charge is off — then energy is zeroed). The battery size & spot cost tile (family B) uses the same sizing. PV hour: grid onlycharge power − PV(1 h: kWh≡kW); skippv_fills_charge_powerwhen PV saturates charge power. Ist/Sinnvoll € may change. Telemetry does not plan.
2026-08-25
- Flex PicoC v0.6.10: I1=−1 clears
lastEin; I1 off→on reparses in the same hour. Hours FetchPlantHours v1.15: 3‑minute pause is same-hour only (:00 after a late previous-hour Decide). ExtractHoursDemand v1.17: age in UTC hours — DST/month wrap no longer latches the 12 h fallback. Sparvo: duration0,25h on list/today; recipe summary without Loxone link; planner kWh in More disabled (recipe 0 wins); live telemetry day kWh one decimal. - Flex PicoC v0.6.9: Window-end stamps
lastHonly when I1=−1 — with I1 on, the hour reparse still runs so overnight does not stay on after winE. Sparvo: recipe 0,25 h stays 0,25; kWh recipes writetarget_kwh; weekly chips do not override recipes; oven and similar presets cannot stayapi_linked. - Flex PicoC v0.6.8: I1=−1 writes the runtime file once at window end; I6=0 wipes leftover hours when the slot turns off (not only at 00:00/06:00); boot/I2/I7 stamp
lastAutoHour(no double fetch in the same hour). Hours FetchPlantHours v1.14: I8 :00/:05 uses the 3‑minute cooldown (no Decide storm after FAIL). ExtractHoursDemand v1.16: month wrap no longer latches the 12 h fallback. PV/Weather debug v1.2: 0→10 hold 200 ms. - Sparvo/Portal: Empty recipe days stay empty after save/edit. Off-ladder recipe hours (e.g. 7 h) stay. AC preset 1,2 kW. Mix chips and week-glance kWh use a comma; plant-outlook kWh one decimal. EN wiring
O3 on/off. - Flex PicoC v0.6.7: I6=0 wipes runtime at 00:00 and 06:00 only if the slot is off — leftover evening hours no longer block the next morning window. Hours FetchPlantHours v1.13:
lastDecHouronly after Decide OK (:05 retries a failed :00); I6 during a fetch queues Decide. - Sparvo/portal: same-clock recipe window shows a 24h hint. Week-glance hours use a comma (not
4.5). - Flex PicoC v0.6.6: I7 (wallbox Vc) re-arms after a fetch when the input falls to 0 — unplug/plug during a poll fetches again. Hours FetchPlantHours v1.12: O1 pause before Extract is 200 ms (Extract loop 100 ms) so Decide is not swallowed.
- Sparvo devices: recipe summary in EN uses Mon–Sun; a
00–00window shows 24h. Duration dropdown and recipe 1 (hours) stay in sync; save copies recipe hours onto device duration. - Flex PicoC v0.6.5: I2 (manual) re-arms after the first pulse when the input falls to 0 — a button fetches again. Runtime counts only while idle. Hours FetchPlantHours v1.11: an I5/I6 edge during a fetch is no longer lost.
- Sparvo device form: Preset duration writes recipe 1 (hours) while that recipe still has the same number.
- Sparvo device form: “Daytime only (08–22)” removed (it fought overnight wallbox/HP). Tap schedule weekdays to deselect; schedules 2–4 can be removed. All days off stays off (edit does not force Mo–So again). PicoC output O1–O8 was chosen in the Sparvo form then (since 26.08. only Portal EMS connection). With EMS on, More hides planner-only fields (values stay). Overlap 400 keeps days/windows. An existing EMS link stays visible without an API key.
- Flex PicoC v0.6.4: I6=0 wipes runtime at 06:00 only if this slot is off (a 05–08 morning window keeps hours). I1=−1 no longer swallows I2/I7 edges or the hour change — returning I1 to 0 reparses or fetches.
- Flex PicoC v0.6.3: I7/I2 edge after a fetch starts again (an edge during the poll is no longer lost). Overnight: do not wipe runtime at midnight (I6=0 resets at 06:00; I6 overnight at window end). I1=−1 also clears error/busy.
- Flex PicoC v0.6.2: On the hour, on goes off if the new hour is not in
slots[](no staleload_nowuntil :04). Runtime file always writes an ASCII dot (1.25), not a locale comma. - Flex PicoC v0.6.1: VO like Hours —
{"slot_id":"3","flex_pack":<v.0>}(slot_idtyped). Five<v.n>in one command is wrong (Loxone = one analog). I1=−1 clears O1–O8 latches. I6=0 sends progress/plug (segments=0); merge still runs. I7 edge fetches again. On the hour PicoC re-reads JSON locally (:04 stays the HTTP fetch). Omittingmode/roledefaults tocheapest/consume. POST body accepts decimal commas. Hours persist is POST-only, ≤70 min. - Flex Sparvo/PicoC v0.6.0: Hours = battery, Flex = loads on/off. Sparvo recipes 1–4 +
slot_idmerge (flex_pack=0omitted). PicoC O1–O8, I6=0 does not force 7, I1=0 means on. Hours O12 ×battery_to_ev_pct(ev_charge_block/ev_charge_limit). Flex wiki rewritten;loxone.mdbudget 7/8 (skip weather). - Flex PicoC v0.5.1: Parse failure keeps LoadNow (
wantLoad); I1=0 also clearsViGridChargeReq; Windows docs say Flex v0.5. - Flex PicoC v0.5: LoadNow from current slot hour (no stale
ems.load_nowon hourly reparse); live I7 each loop; nocontinue; I1=0 resets state; wiki I9+I10 required forhours_completed;flex_packoverrides bodysegments. - Docs UX Flex guide:
/docs/loxone-windows-flexrewritten (short steps,step/examplecallouts, SVG flow, PicoC in appendix). Guide pattern in concept §12. Renderer:step+examplecallouts. - Flex deep-audit v0.4d: ISO window +
deadline_hourwithoutwindow_*infers clock hours fromstart/end(18:00→06:00, deadline 22 drops 02:00). Naivehour≤deadlineremoved. A deadline outside the window does not empty it. Flex wiki walkthrough DE+EN (calloutsstep/example,flow.svg), OpenAPI/concept §8.6 updated. - Flex deep-audit v0.4c:
deadline_hour(Sparvo latest start) filters Flex candidates overnight-aware;windows_querycarriesdeadline_hour; request echowindow_source(flex_pack\|window_hours\|iso);deadline_strict/repeat_dailydocumented as echo/reserved; PicoC I1=0 also clears Demand/Period; concept §15.1 E =flex_pack. - Flex deep-audit v0.4b:
device-schedulesuses the same rolling overnight logic (post-midnight fix);windows_querycarries onlywindow_*hours (no ISO); request echo showsflex_pack/window_*; wiki explains why not multi-VO like Hours; Step 5 without ISO. - Hours/Flex deep audit:
deadline_hour= latest start (overnight-aware, Sparvo). PV-days ignore brief midday dips; an incomplete last PV-day without the next morning sun gets no \(L_D\); prior-day hours only when \(P_{ref}(D)\) is finite.energy_deficit_kwh= placed need (leftover prep excluded). OpenAPI:start/endoptional,flex_pack/window_*documented. PicoC I12 is diagnose-only;repeat_dailyis not applied in v0.4. - Flex PicoC v0.4 + rolling window:
window_start_hour/window_end_houror Loxoneflex_pack(I4|I5<<5|I6<<10|done<<16) in one<v.0>— no daily ISOstart/end. PicoC I4–I6 are the source of truth. O5 always writes the pack, never rawhours_completed. LoadNow only fromems.load_now(notwindow.start).prep_extra_energy_kwh= placed prep kWh. A Flex window beyond the tier isno_slots, notdeadline. - Flex deep audit: live floor (no past hours in flex window); chronological
next_slot_start; soft fallback prefers longest block; afterendDemand/slots=0 + statusdeadline; empty flex exits keepems; PicoC I1=0 clears LoadNow; OverrideEnable documented as reserved.
- Flex PicoC v0.3 + API hardening: Poll accepts
deadline/no_slots; PO Demand = remaining hours (0whensegment_completeor afterend);deadline_reachedwhenevernow ≥ end; live slots only from the current hour; chronological overnight slots; I7 gates LoadNow; I1=0 clears LoadNow;window.hours_requested= remaining need; DA baseline empty when remaining = 0;softtakes the longest block (price is tie-break only);ems.next_slot_start= next hour from now. (Historical: first-wallbox autoslot_idwallbox_1— since 26.08. Portal EMS only.)
- Flex docs completeness: Concept §19.5/§19.6 → POST +
<v.0>; OpenAPI stub GET flex params + POST +device-schedules; PicoC then v0.2; now v0.4. - Windows Flex Loxone VO = Hours pattern:
POST /v1/decision/windowswith JSON body; dynamic values only via<v.0>/<v.2>on the VO Input (v0.4:flex_pack). Named<v.Vi…>dropped. PicoC then v0.2, wiki/docs/loxone-windows-flexupdated. - Hours forward-prep (
hours_demand_v1.6): After cover, every Decide sizes multi-gap prep (layer A \(G_{min}\) + layer B in PV-days \(D-2..D\)) inside \(H_{eff}\) (usable band / load-PV, summer floor0.25·load, no jump to 168). Fieldshours_needed_prep,prep_extra_energy_kwh,basis.forward_prep,basis.prep_horizon_hours. Slot roleprep(“forward-prep hour”). Cheap-hold stays cover-only. Near soft-cap applies to cover and to prep hours before morning sun (no fill above min+10 pp). Storage-size tile uses the same policy; Ist/Sinnvoll € may change. - Docs/Wiki hub: Flex Windows linked from overview DE/EN (
/docs/loxone-windows-flex); Loxone template + integrations README marked live (Wallbox step 1). - Loxone Flex Windows wiki: New step-by-step
/docs/loxone-windows-flex(DE/EN) · PicoCSpotpriceFlexWindows. - Plant Device Schedules (Sparvo Flex 1b):
GET /v1/plant/device-schedulesreturns Sparvoapi_linkeddevices (slot id, segments, window, deadline) for Loxone/EMS. Community+; HTTP 200 withdecision_status. - Loxone FetchPlantHours v1.10: Auto-Decide at hour :00 (I7+I8), :05 fallback only. Fixes relay gap: Extract clears O3/
charge_nowon hour tick; previously Decide waited until :05 so manual “fetch plan” was needed. Re-paste PicoC from/docs/loxone-hours. - Hours stop-SOC follow-on slots: When several charge hours fall on the same day, displayed stop SOC is non-decreasing in time (later hour ≥ earlier). Slot picker refreshes
soc_projected_*from the final charge map (price order previously left stale end SOC). - Hours near/far cover (
hours_demand_v1.5): Survival and hours until first morning sun (cover_window_hours_pv) only take the near need (chrono to PV + cover buffer, soft-cap morning SOC ≤min_soc+ 10 pp). Reserve-stretch kWh (weekend trough) schedule after morning sun — no more front-loading a full charge-power hour today (symptom: 8.3 kWh “minimum charge level” with morning with-grid ~45 %). Cover buffer again visibly affects the near share. Basis:energy_cover_near_kwh. - Decision Windows Flex v1.1 (additive): Optional query params
segments,segment_consecutive(off/soft/required),hours_completed,current_segment_index,repeat_daily,deadline_strict,slot_id. With flex:decision_engine: windows_v1.1,emsblock right afterdecision_status(PO Demand =ems.current_segment_hours, Period =ems.period_hours_todayuntil window end). Without flex params, unchangedwindows_v1. Deploy:deploy.sh api-only. - Explain stop-SOC / balance bars: Survival O4 pins to
min_soc_pctonly when below that floor. Stop SOC on every plan-slot line. Usable battery · now (night) / · At HH:MM (following day = PV-day start). Clock-only stamp in DE: um 08:00. Poll assetshx22.
2026-08-24
- Hours DA replan (production): After day-ahead + inference, a batch replans all active plants (
resolve_hours_demand, snapshot +plant.plan_updated). Poll hook + hourly timer 15:00–23:00 Vienna. Webhook materiality now includes the full plan (not just today’s slots) — EMS should pullhours_demand_urlafter the event. Optionalplan_hashin payload. - Explain cover label: “economical cover hour” instead of “cheapest hour”. Cover slots that are not the day’s minimum get “not the cheapest hour of the day”. The “Cheaper hour skipped: …” line (
cheaper_skipped) is not shown in portal/Sparvo (snapshot/diagnose only). Poll assetshx18. - P1-v2 same-day relocate:
HOURS_CHARGE_DAY_CONSOLIDATE=1(code default OFF) moves cover including survival onto cheaper chargeable hours of the same calendar day — including a single slot; current hour inclusive; elapsed hours stay. 0 €/MWh counts (not missing). Small survival (under 5 kWh) is omitted only when the SoC path still holds the reserve including slack. Slack belowmin_soconly with a price advantage. No new API field, nowait_cheap; O12 unchanged. Shadow loghours_consolidate_shadow.jsonl. Ops diagnose:diagnose-hours-charge-plan.py. - Fix: skipped-hours full list (portal/Sparvo): “Show all N” on
/plant/skipped-hoursor/plant-outlook/skipped-hoursreturned 500 Internal Server Error (Jinja:group.itemsresolved to the dict method, not the key). Full list renders chronologically by day again. - Following days charge effect + ⓘ: Per PV day in portal/Sparvo Explain: line Planned grid charge … kWh · Effect at morning sun: +X % (
pv_day_charge_kwh,soc_delta_pctin snapshotrest_day_balances, UI-only). ⓘ explains reserve floor, direct grid supply below min SoC, and morning-sun stamp (not right after the charge hour). Poll assetshx17. - Week glance day label:
hours_needed_daysmaps onto the calendar grid (D0…D6), not the sparseday_planlist — a day with charge shows 1 h planned again instead of “No charging” with a visible bar (wg6). - Hours API calendar day vs. app PV day: Decide/EMS (
hours_needed_today,period_hours_today,prefix_*,day_plan) stay on calendar days 00:00–24:00 (Period until 23:00). Only Explain Following days in the snapshot (rest_day_balances) uses PV days sun→sun — not in the API response. - Storage tile expand: control rule clarified (discharge throttle only when demand is not covered autonomously from PV+battery); “Without a battery … kWh/day on the grid” line removed. Prefix-view line (“Optimizer period …”) hidden in Explain (EMS field unchanged).
- Grid-charge plan summary copy: Replaced “Next PV yield …” (misleading at midday when PV is producing) with Current period: still X hours until … and In this period … grid-charge hours (portal + Sparvo).
- Following days as PV days (sun→sun): After midnight until morning sun, the night belongs under Until tomorrow morning; the first following day is the current PV day from morning sun to next-day morning sun (not a second night stub). After morning sun / before midnight: following days start at the next morning sun. Bars and without·with grid share that window (portal + Sparvo).
- Hours O12 when the pack is full: cheap-hold (discharge 0) only if there is a cover gap until the next morning sun. Not at SoC ≥99 % and not in a PV-surplus hour — a later reserve trough (e.g. Wednesday) alone must not close O12.
- Hours cover/survival not in PV surplus: the slot picker does not grid-charge an hour whose PV exceeds load (and SoC is above min). Stretch must not pick the cheap solar peak (e.g. 10:00) as “minimum charge level”.
- Hours interim 24 h: “next cheap hour” is only inside the next 24 h (not the cheapest slot in the 168 h horizon). No bridge charge in a PV-surplus hour. Reserve-survival later in the week is kept.
- Hours dawn cover: a 3-hour lookahead alone does not count as “already in PV”.
cover_window_hours_pvends at today’s first good PV hour (not tomorrow 07:00). Survival stop-SOC (O4) is the reserve floor (min_soc_pct) only when below that floor; otherwise trajectory/target (never below live SOC). Interim grid charge only when there is a reale_gap(not a full hour at 0). - Plant outlook expand: plant-specific copy — extra grid kWh + € vs no battery; larger pack kWh + further €/year. Control rule (charge on cover gap; throttle discharge in cheapest hours only when not autonomously covered from PV+battery). Hours JSON unchanged.
- Plant outlook storage tile: Sensible only if year € is cheaper and average ct/kWh is not higher than current — otherwise current / “fits”. Hours JSON unchanged.
2026-08-23
- Hours cheap-hold (v1.4): Only when PV+battery cannot cover forecast load (
load_covered_by_soc_pv=false): O12 = 0 in the cheapest N hours of the calendar day when not charging (cheap_hold) — house from the grid. If cover is already satisfied, discharge stays on (no speculative hold). Full cap whilecharge_now. N =ceil(daily load / charge kW). Annual tile uses the same cover gate. Fieldscheap_take_hours,hour_is_cheap,cheap_hold. - Plant outlook storage tile: Copy is N cheapest hours + winter average (not autonomy days). Sensible only if the year is cheaper than current — otherwise current / “fits”. 24 h daily-load floor only while extra kWh do not raise year cost. Hours JSON still has no annual €.
- Adaptive Hours cap, no default 36: without a request cap the server uses
ceil(usable kWh / kW)+12, max 168.max_hours_today(default 12) is clamped to that cap.basis.storage_horizonomits annual € / size ladder (autonomy, defer, cap only). Annual spot and sensible size live on plant outlook (4 season weeks + 12-month market average). - ExtractHoursDemand v1.15: fallback after 12 h without API (summer 11–15 / winter 01–03, target 35 %). Txt2/Txt3: no-charge /
X Std, Y kWh. Wiki/wiring aligned. Relay latch reset on hour change; year wrap counts as stale. - Plant following-days SoC: Portal/Sparvo show without·with grid per following day at the next morning sun (same as “Until tomorrow morning”), not at midnight. The last day may show a forecast-end stamp.
- PV day navigation D0–D6: Portal plant outlook and Sparvo Plant PV bar chart show all 7 days (today…D+6) again — the UI had capped at 6 while backend/API already delivered 7.
- Grid-charge dispatch unified: Annual storage cost (Familie B) and Hours EMS share
grid_charge_dispatch— cheap hours are always FORWARD over this pack’s adaptive window (no 36 h default). Adaptivemax_hours_horizon: without a request cap, Hours derives it from battery + charge power (need_h+12, max 168). Portal shows planning meta + warning on price heuristic without Hours engine. fc-verification stays a generic archive comparison (slider kWh/kW), not plant SOC simulation.
2026-08-22
- Plant profile annual load: typical meter day × 365 (ceiled to 100 kWh) is written into the profile (portal/Sparvo open + save, telemetry including SOC-only, Hours, outlook, savings page) — not display-only. A stale form value (e.g. 6000) cannot overwrite the estimate.
- Adaptive discharge reserve-protect:
discharge_power_kw(O12) only throttles near min SoC and when no economical recharge is planned (interimpass/ no charge slots). Otherwise full user cap. Charge hours stay at full cap (inverter already takes grid+PV). 0 kW only at/below min SoC with no recharge, or when the user cap is 0. No more spot-hold. Hours +plant.plan_updatedincludedischarge_reason; an O12 cap change is material (webhook). - ExtractHoursDemand v1.11 (Breaking): API fields
prefix_*instead ofloxone_*; newcharge_now,charge_stop_soc_pct,target_soc_pct,capacity_kwh. O3 =charge_now(relay), O4 = stop SOC %, O9 = remaining kWh (SOC delta), O1 = 0 when O9=0. Re-paste PicoC from/docs/loxone-hours. Legacyloxone_*in old JSON readable until re-Decide. - Hours Interim Econ default ON:
HOURS_INTERIM_ECONis on (kill-switch=0).plant.plan_updatedincludes the same EMS scalars (prefix_*,charge_now,charge_stop_soc_pct,discharge_power_kw,adaptive_discharge,min_soc_pct,charge_power_kw,grid_charge_allowed). - Storage horizon is physical: Annual spot € uses PV→battery / battery→load / residual import in the same hour. Cheap hours only fill unused SoC — leftover annual kWh is not repriced onto the cheapest hours (that made 5 kWh look cheaper than 30 kWh).
- UI decimal separator always comma: Portal/Sparvo/Admin display and Loxone
txt_*use,in DE and EN (fmt_num/SpotDecimal). Machine values (data-*, JSON, CSS vars) keep ASCII dots. - Sparvo bar focus: Tap again shows kWh/ct (raw number in
data-price, format display-only). - Plant explain backup reserve: “Without grid” rolls with profile min SoC (backup reserve), not a 0 % floor. Interim
passno longer strips survival slots — reserve charging stays in the plan. Bridge-charge copy +{min} %reserve only when SoC+PV do not already cover the window (otherwise “covered”). Following days: without·with grid always shown; with grid grayed when equal (<1 % diff). O12 kW hint under the plan card removed. - Grid-charge explain plan summary: Portal/Sparvo replace chip/period pill with: next PV yield in X h from HH:MM · grid-charge hours until then · later charge list (date, day kWh, start·kWh). ⓘ only when cover is stretched → minimum charge level. Dump/bridge/off/none keep chip + short copy.
- Charge-hour hint: Each planned hour shows a short reason (
survival→ hold min charge level, cover → cheapest hour, opp → opportunistic fill, bridge → bridge charge).
2026-08-21
- Plant UI V1: Sparvo/Portal order Live → PV (day PV kWh stats only) → Plan/Explain → rest. Plan-span chart load + SoC with/without grid until morning sun; KPI at morning end. Live meter label “since {date}” (
meter_baseline_at/ reset fallback). - Hours Interim Econ (opt-in): Env
HOURS_INTERIM_ECON(default off). When on: if SoC would breach min before the next cheap hour, compare bridge-charge € vs spot pass-through; only charge when strictly cheaper (+0.02 €EPS).period_hours_todaymay shrink (cap 5 h); EMScharge_hours_todaythen has at most one interim slot (later same-day cover stays inday_plan/charge_hours). Additive fields:period_hours_today_default,interim_period_active,interim_needed,interim_decision,interim_period_cap_h,interim_cost_*_eur,interim_slot_start,interim_reason. Extract O2 unchanged. Details: Hours Demand. - Explain: next planned grid charge clarity: Chip/headline for
latershow day kWh + planned HH:MM of the next charge day (not EMS total target and not the night-end stamp). Following-days stamp is a from–to range (night_end→ reserve / last rest charge morning). Both cards list day blocks (kWh + time chips); survival slots marked (survival) with a short tip. 10‑min pollhx11. - Plant explain two horizons: Portal/Sparvo split Until tomorrow morning (load/PV/battery bars only through
cover_window_hours_pv) and Following days (cover remainder when stretched). Battery always With·Without grid. PV week: dual EOD D0…D6 + stats row load·PV·battery With/Without. Skip copy in future tense; 10‑min poll redraws both cards (hx10). - Hours ↔ Loxone grid charge bidirectional: Decide JSON top-level
grid_charge_allowed(EMS front). ExtractHoursDemand v1.17 → O10 = 0/1. Write: partialPOST /v1/plant/telemetry{"grid_charge_allowed":0|1}(VO like SOC/meter). Omit field = profile unchanged. Last-write-wins with Sparvo/portal. - Hours night vs reserve: Explain splits Tonight (
cover_window_hours_pv, first morning sun) and Reserve holds (cover_window_hoursonly whencover_extended_for_reserve). SoC without/with grid at both stamps. Chip stays “Today N h · M h in total”. Today 0 / week > 0 stayscharge_kind=later(with-grid still shown at the reserve stamp). - Master switch
grid_charge_allowed: Default on. Off →hours_needed*=0, empty slots, kindgrid_off/ reasongrid_charge_disabled. Dump has no effect. An explicit telemetry field may set the profile; Decide without the field is read-only. Sparvo + portal location + plant badge. - Midday skip
pv_will_fill_today: Look-ahead (PV×0.70, the slot’s calendar day, fresh SoC) replaces the single-hour PV formula. Leftover headroom instead of a binary skip. Survival candidates before fill. SNAP stays a device layer. - PV card day-end: D0 shows With grid / Without grid (
soc_end_pct_with_grid/soc_end_pct_no_grid; aliassoc_end_pct= with grid). - Portal/Sparvo grid-charge explain: Chip/headline now separate today’s EMS hours from hours until planning-window end (no more “32 kWh in 1 hour”). Skipped cheap hours are chronological with weekday+date; more than 6 rows link to
/plant/skipped-hoursor/plant-outlook/skipped-hours. - Hours cover on a weak weekend: Min SoC applies across D0…D6, not only until the first morning sun. If Saturday/Sunday sit on the reserve without PV carrying the pack, the engine stretches the cover window (
cover_extended_for_reserve,cover_window_hours_pv= first PV recovery) and schedules mandatory grid charge (trough below the reserve, not the week’s net load). Raising min SoC (e.g. 20→40 %) must not merely pin end-of-day levels to the new floor. Portal/Sparvo week glance and the Hours API share this path. - Loxone
d0_soc_eodload shape: End-of-day SoC now rolls the same hourly load/PV shape as plant outlook (meter/profile, D0 from the current hour). Flat 1/24 only as fallback without meter/shape. Meaning stays “midnight today”; values can differ from the old even split. - Portal/Sparvo timeline label (DE): German UI now reads “Zu Planende am {time}” (was “Am Planende um …”). English remains “At window end / at {time}”.
- Plant outlook D0 SoC from now: End-of-day roll starts from the live SoC at the current local hour (no replaying midnight→now). After Hours
day_plan, the SOC path is re-chained with the same charge chips. Loxone display pack uses the same D0-from-now logic. Prevents implausible calendar EOD vs plan-end when no grid charge is planned.
2026-08-20
- Wiki
access.tier: documented values arebasic,community,full_trial,full_active(notprofessional/oemas JSON enum). Rate-limit table uses the same codes; Professional/OEM remain product labels. Telemetry softcaps: Community 2000/day, paid 10000/day. - Webhooks: registration and dispatch require HTTPS to a public host (HTTP, loopback, and RFC1918 rejected; redirects not followed).
GET /v1/statusno longer includescache_path. - Hours cover load with sparse meter telemetry: WD/WE hourly shape no longer treats missing samples (
None) as 0 kWh. Days with <12 observed hours are skipped for the shape (flat 1/24 fallback); never-seen hours get a flat prior. Flat same-day overlay keeps rest-of-today positive (so_far + typical × remaining clock share) so cover evenings are not zeroed. Stops plan-end SoC stuck near 100% when the cover window includes the night (e.g. EMS posts only in the afternoon). - Portal/Sparvo plan-end battery level: “At window end” / Without·With grid projects SoC hour-by-hour over the cover window (no longer a bulk PV−load window sum). Surplus solar while the battery is already full is clipped — overnight drain shows a plausible plan-end level. Basis includes
hourly_load_cover_kwh/hourly_pv_cover_kwh/hourly_grid_charge_cover_kwh. Cover shortfall also uses the same chronological check (maxwith bulk) so “no grid charge” is not claimed when the night would breach min SoC. Plan-end clock = hour floor + cover length (end of the last rolled hour). Rest-of-today load is spread across all remaining today hours (not only hour 0). Dump/Opp after the cover window does not raise plan-end SoC. Engine cover load/PV = sum of the hourly series (no parallel flat cover total). Legacy snapshots missingprojected_soc_pct_with_gridno longer invent With-grid via an energy lump; Opp cap uses chronological cover need. Bulk fallback also respectsallow_untimed_grid_lump.
2026-08-19
- Hours Demand v1.3 — SOC-feasible grid charge: Engine
hours_demand_v1.3picks charge slots only when the battery has headroom and PV does not already fill the hour. Cheap but impossible hours appear inskipped_slots[](always included); shifted charging in later feasible slots.plan_feasibilityreportspartial/storage_undersizedwhen not all kWh can be scheduled. P1 survival before price; hourly load profile (WD/WE shape) in the SOC roll. Portal/Sparvo explain: new reason codesslots_skipped,storage_undersizedplus lines like “16:00 cheap, battery full → next charge 03:00” in the Grid charge block (live resolve). PicoC/Extract unchanged (additive). Details: Hours Demand. - Plant weather for new sites: Daily
spotforecast-plant-weatherscans active API keys with Lat/Lon inuser_plant_locations(discovery without a second timer) and writesdata/plant_weather/{api_key_id}/. Also: portal geo-save and first PV/Weather request (on-demand). Directory ownership*:forecastmode2775. PV Forecast Loxone pack uses the same request-path weather payload for Tmin/Tmax even if a disk write fails once. - Live strip day use after first meter ping: Portal/Sparvo Day use so far stays waiting for meter data (API
day_import_kwh=0) until the first positive delta. The first cumulative total (or a 0 placeholder then the real total) is baseline only — not today’s kWh. No portal Reset meter needed for a new API key.
2026-08-18
- Hours EMS Period until midnight:
period_hours_todayis hours remaining until 23:00 (00:00 → 23, 13:00 → 10, 22:00 → 1). At 23:00 it resets to 24. Demand/charge_hours_todayonly include slots in that window (hour 23 only from 23:00). Extract O2 maps the field (missing/<1→ 24).
- Portal/Sparvo grid-charge blocks: Cover headline and cheapest charge times come from the same live Hours plan as the week glance (
hours_decisioninbuild_plant_outlook). Battery rules, dump, and location saves refresh the explain snapshot. A stale EMS snapshot may still updatecharge_power_kw, but not the hour count without new slots.
- Hours grid-charge power:
charge_power_kwismin(battery.max_charge_kw, grid connection × 0.80 − base load)(20 % reserve, same as Sparvo devices).hours_neededsplits the kWh target across as many cheapest hours as that power allows (20 kWh at a 10 kW connection → 3 h at ~8 kW headroom, not 1 h × 20 kW).
- Hours/profile min SOC default 20 %: When request and plant profile omit
battery.min_soc_pct, the engine default is 20 (was 15). Stored profile values are unchanged. UI: portal/settings/locationand Sparvo Settings → Battery rules (/settings#sv-storage-rules) with sliders for min/target battery level (0–100 %) and grid buffer (0–50 %, default 10 %). - Hours validation:
battery.min_soc_pct/target_soc_pctoutside 0…100 →invalid_input(same pattern as cover buffer 0…50). - Portal/Sparvo plant UI — less duplication: The live strip is the only display for battery level, day import, and meter total (portal
/plant-outlook, Sparvo/plant). Below it: controls only — manual starting battery level (slider, fallback without live telemetry) and Reset meter baseline — no second value grid when live telemetry is active. - Hours explain block: Chip + headline only — the extra net summary under the balance chart is removed (same deficit was shown three times).
- Sparvo
/plant: Order is Live → Hours explain → PV day chart; Planned grid charge lists price/kWh per hour (switch days); need/rationale stays in the explain block above.
2026-08-17
- Hours/portal load profile — same-day overlay: Estimated day use and remaining-today blend typical with meter-so-far using the WD/WE hour shape (not clock × 24). Incomplete today never counts as a full day, including for D+1. Same number in Hours, Sparvo live strip, and outlook D0. Engine tag stays
hours_demand_v1.2. PicoC unchanged (fieldshours_needed*/d0_load_kwhunchanged). - Loxone docs consolidation + PicoC audit: Canonical Loxone overview (one host VO, minute plan, max 8 PicoCs). Weather v1.1 start+:10 (no longer :05 next to Hours Decide). Forecast Debug v5.5 start+:01. Windows v2.2 auto :03. Hours Extract v1.8 reads JSON on start. Re-paste PicoCs from the guides.
- Loxone PV Forecast auto-fetch v1.1 / Extract v2.1: Debug fetches on start (~3 s) and then hourly at :08 (not :05, so Hours Decide stays clear). Extract reads an existing
spotprice_pv.jsonimmediately after Miniserver reboot. Hours users: reuse the same VO parent and add only commandFetchPvForecast. Re-paste both PicoCs from/docs/loxone-pv-forecast. - Loxone PV Forecast Extract v2.0: One GET
/v1/plant/pv-forecastadds ready-madetxt_d0/txt_d1lines (weekday, date, PV, optional load, end-of-day SoC, Tmin–Tmax) plusweek_kwh,d0_load_kwh,d1_load_kwh,d0_soc_eod,d0_tmax,d0_tminnext tod0_kwh…d6_kwh. Missing parts are omitted (no default SoC 30%). End-of-day SoC includes grid charge only with a fresh Hours snapshot; otherwise PV vs load.loxone{}is at the start of the JSON. PicoC Extract v2.0 (O1…O13, Txt1…Txt3); Debug stays v1.0. Guide:/docs/loxone-pv-forecast.
- Hours Demand cover buffer: Default 10 % on a positive cover shortfall (
battery.cover_buffer_pct/ plant profile; portal location + Sparvo Settings → Cover buffer, 0–50 %).energy_charge_kwhand hours include the buffer; a zero shortfall stays 0. Engine tag remainshours_demand_v1.2. - Sparvo cover buffer in Settings: Field under Settings → Cover buffer (
/settings#sv-cover-buffer) and Cheap grid charging (/settings/dump) — not only Plant → location. - Grid-charge copy: Portal/Sparvo plant chip and headline show target kWh in the planned hour (charge only until that amount is in), not “for 1 h”.
- Loxone FetchPlantHours v1.9 + ExtractHoursDemand v1.7: SOC 10% bands up and down → Telemetry+Decide; I7 every 15 min Telemetry, Decide only smart (today still needs charge and SOC rising); I8 :05 fallback; 3 min cooldown. Extract O1/O9 follow the API down as well (grid charge can stop). Re-paste PicoC from
/docs/loxone-hours.
- Hours Demand — slots from now: Charge times and price ranking start at the current local hour (no leftover midnight-window slots).
hours_needed_today=0stays 0 (no fallback to the week total). Portal/Sparvo clear charge chips on days without engineday_plan; D0 drops hours before *now*. energy_charge_kwh: Grid-charge target rounded up to the next whole kWh (1.4 → 2), not max kW × hours. EMS fields sit at the start of the JSON (Loxone Extract ~2.3 KB fread).- Portal/Sparvo grid-charge chip: When today=0 but later days >0, no longer “No grid charging needed” — shows next grid charge (
next_charge_start/next_charge_hours), same semantics as Extract Txt3. Week-glance chip Next …. - Loxone ExtractHoursDemand v1.5: new output O3 =
energy_charge_kwh(optional kWh limiter) plus energy ratchet. Fetch stays v1.8. Re-paste PicoC from/docs/loxone-hours.
2026-08-16
- Docs sync: Loxone overview / Hours / Telemetry / Plant Telemetry bumped to Fetch v1.8 + Extract v1.4; Hours Demand documents cover/dump/bridge; Telemetry guide links to Hours for the PicoC paste (no duplicate embed).
- Loxone FetchPlantHours v1.8 + ExtractHoursDemand v1.4: Downward SOC bands 90→80→…→0 trigger Telemetry+Decide (in addition to hourly :05); Extract ratchets Demand upward within the calendar day (
N_locked), midnight reset. Docs DE/EN Hours + Telemetry + code samples synced. - Hours Demand bridge fix: Bridge charge (
hours_needed_bridge) only when Dump/Opp is on. With Dump off and cover satisfied →hours_needed = 0(no spurious 1h bridge). Engine tag remainshours_demand_v1.2. - Portal/Sparvo grid-charge UI: Cover shortfall vs dump top-up separated (chip/headline/net); dump status + threshold in the section; Sparvo Settings → Cheap grid charging (
/settings/dump).
2026-08-12
- PV/Weather audit fix: Request-path Open-Meteo timeout 8 s (no 60 s worker freeze);
cache_needs_refreshwithout empty-daily refresh loop;wind_speed_unit=kmh; Loxone double-GET coalesce forpv/weather;not_availablebefore quota reserve + middlewarequota_class(access_denied/pv/weather) so basic does not burn decision fair-use. - Plant-weather schema v2 live: Cache includes display fields (humidity, pressure, wind, weather code, daily min/max/sun); timer
spotforecast-plant-weather05:20 Vienna; deploy starts a background refresh for schema heal. - PV Forecast + Weather APIs (public):
GET /v1/plant/pv-forecast(7-day yield kWh, classpv, Community 48/day) andGET /v1/plant/weather(site weather, classweather, 48/day). Docs DE/EN:/docs/pv-forecast,/docs/weather; Loxone guides/docs/loxone-pv-forecast,/docs/loxone-weatherwith PicoC Debug/Extract v1.0 + flow SVGs. - Hours info ⓘ UX: Tips on portal/Sparvo appear next to the tapped ⓘ (fixed) and close on re-tap/click, outside pointer, scroll, resize, or Escape.
- Week-glance copy: Removed “(shared engine)” from visible portal/Sparvo strings (source line + charge hint).
- Live strip UX: Removed method subtitle under “Estimated day total” (meter history / load profile) on portal
/plant-outlookand Sparvo — tile shows the value only. - Portal/Sparvo week glance — audit fixes: missing
strip_ariai18n, demo hint instead of silent hide, explain link only when week glance is present, bar height/CSS, Sparvo glance refresh, Loxone Hours prose O1/O2 → today-slice v1.3, DE Hours aligned to EN. - Portal/Sparvo Hours week glance: Plant outlook and Sparvo Plant show the 7-day plan (
day_plan, default horizon 168 h) from the shared engine — separate from the cover planning window / last EMS decide. Docs DE/EN Hours + Loxone Extract table synced. - Hours Demand v1.2 — dual horizon: Default plan horizon 168 (request overrides). Caps
max_hours_today=12/max_hours_horizon=36. Additive response:hours_needed_today,charge_hours_today,period_hours_today,day_plan. EMS/Loxone Extract v1.3 reads the today slice (optimizer Period stays 24). Portal/Sparvo plant outlook charge chips from shared Hours engine (side_effects=False). Webhookplant.plan_updatedcompact (today + URL). Opp still only below Grenzpreis; cover still PV-recovery.
2026-08-10
- Lead-aware dump scenario:
dump_scenario_ct_kwh/dump_scenario_eur_mwhblend towardprice × pct/100when pct > 0 with lead weights D+1=1.0/ D+2=0.45/ D+3+=0.30(never above the model price). Scope stays midday (midday_11_16) — no evening dump correction.price_ct_kwhunchanged. Clients should use APIdump_scenario_*, not recompute locally.
2026-08-06
- Live strip auto-refresh: Portal + Sparvo Live-Anlage strip refreshes ~every 15 min while the tab is visible (
/plant-outlook/live-telem, Sparvo/api/live-telem) with an updated timestamp — no full page reload. - Estimated day use sooner from meter: Portal (
/plant-outlook), Sparvo live telemetry, and Hours/load profile use meter history after ≥1 full meter day (was ≥2); until then annual÷365. Docs DE/EN + code samples synced.
2026-08-05
- Docs / code-samples sync (Hours v1.1):
/docs/hours-demand+/docs/plant-telemetry(DE/EN) and portal/code-samplesHours explain cover-until-PV, spike damping, and ≥2 full meter days; samples printdecision_engine,cover_window_hours,remaining_today_load_kwh. - Portal live-telemetry hint: estimated day use correctly detects
site_meter_history_*(previously exact matchsite_meter_historyonly → false annual÷365 hint). - Plant Telemetry / Outlook: SOC pings store history (
plant_soc_samples); plant outlook shows hourly load/PV/SOC simulation (soc_model=hourly_v1); day chart: toggle Last/SOC, PV bars always on. - Hours Demand — load-learning spike damping: meter-day typical uses a soft cap (≤2× median of last 4 days) + 25 % robust blend — sustained load jumps still follow; one-off EV/spike days do not overdrive grid-charge planning.
- Hours Demand v1.1 — cover until PV recovery: engine charges only the energy gap until the next good PV block (rest-of-today + D0/D1 window, cap ≈ rest-today+36 h), not the full 7-day load. Load profile: recency-weighted daily mean (half-life ~2 d, WD/WE).
charge_hoursprefer slots inside the cover window. New basis fields:cover_window_hours,remaining_today_load_kwh,horizon_load_kwh; engine taghours_demand_v1.1. - Portal plant-outlook Load/PV/SOC: chart load from meter-delta day buckets (+ Hours estimate for D0…D6); D0 SOC = live; client refresh every 15 min via
/plant-outlook/data; week line = grid charge cost (not household use). - Portal plant-outlook meter total: restored Import meter + day-so-far values in the “Live telemetry (EMS)” card (regression after the live strip).
- Loxone telemetry-only guide: new Community page
/docs/loxone-telemetry(DE/EN) after Overview — Analog Memory wiring, screenshot, FetchPlantHours v1.7 copy-paste; nav + pager +/docs-assets/…. - FetchPlantHours v1.7: ~1 s O4 pulse for Analog Memory Set; Txt points to Memory→VO
<v.2>; removed deadpulseTelpath; meter magnitude for VI/checks (meterAbs). - Portal SOC slider vs live telemetry: Hours/telemetry SOC (
hours_api) overrides manual slider values and locks the slider (~36 h freshness) on/plant-outlookand location settings; without fresh API SOC the slider stays available as fallback. - Telemetry rate limit: softcap for
/v1/plant/telemetryraised to 2000/day (Community) / 10000/day (other) — still does not count against Decision fair-use. - Loxone telemetry
<v.2>+ partial POST: API accepts SOC-only / meter-only bodies; docs/VO guide use official Input placeholders instead of<v.ViName>; FetchPlantHours v1.6. - Live telemetry UI (portal + Sparvo): strip with battery SOC %, day import so far, estimated day total (meter history or load profile), and current meter total — Sparvo home,
/plant,/plant-outlook. - Loxone FetchPlantHours v1.5 + Telemetry
diag: API detects unsubstituted<v.…>tags (hint=loxone_vi_not_substituted) and returns quote-freediagfor Txt2/Txt3; aggressive decimal-comma sanitization; PicoC v1.5 readsdiagfirst. - Loxone FetchPlantHours v1.3: telemetry polls
/user/common/spotprice_telemetry.json(like Decide) — Txt1/Txt2 + O13 show OK/FAIL/timeout instead of only “Telemetry done”. - Plant Telemetry API: empty/invalid body → HTTP 200 with
telemetry_status+hint(no more FastAPI 422); accepts missingContent-Typeand locale comma decimals. - Portal plant outlook — live telemetry:
/plant-outlookshows SOC source/time, import meter total, day import so far, meter timestamp; Reset meter baseline button (next EMS ping = new start value). First meter total (e.g. 3725 kWh) is always baseline (meter.is_baseline). - Telemetry API response: explicit
meter.is_baseline,meter.import_kwh_total,meter.observed_at; docs DE/EN synced. - Rate-limit headers on success: successful
/v1/*responses now includeX-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset, andX-RateLimit-Scope(same headers as on 429;Retry-Afterstill 429-only). - Decision Windows missing params: missing
start/end/mode/rolereturn HTTP 400incomplete_request(aligned with docs; no longer FastAPI 422). - API usage — Loxone double-GET coalesce: Identical
api_key+ path + method within 3 s is logged asquota_class=duplicateand does not increment portal/rate-limit counters (response still returned). Fixes Miniserver Virtual Output analog double-fire. Loxone tip: enable Use as digital output, leave Command OFF empty. DebugSpotpriceFile v5.4 keeps O4 high during fetch. - Loxone Forecast DebugSpotpriceFile v5.4: keeps O4 high during fetch (no mid-pulse
1→0); I1-rising trigger only + cooldown. Docs/samples synced. - Loxone Forecast — double API count: Not a server double-count bug — the Miniserver sent two real
GET /v1/forecastcalls (~2 s apart). Typical cause: Virtual Output Command OFF filled with the same URL as ON (PicoC pulse ON→OFF = 2 GETs). Fix: leave Command OFF + Header OFF empty; DebugSpotpriceFile v5.3 triggers manually only on I1 rising edge (not everynEvents). Docs DE/EN +/code-samplessynced.
2026-08-04
- Landing
#planung-live: removed No dump correction \| Dump price toggle; ranking/sums again always use the model price (same as/fc-verification). Day navigator, Sparvo, and/code-sampleskeep their dump toggle. - Sparvo
/prices+ PDN: negative prices draw bars below the zero line (signed scale); PDN negative bar height fixed (more negative → taller downward). - Loxone Forecast PicoC v5.2 / v17 (live-verified): Debug requires a real forecast payload (
"forecast":+price_ct_kwh+ file length ≥ ~7 KB) — no false OK onforecast_status. Parse v17 reads price now/+1 h viastartneedles without pointer walks (v11–v16 hung on Miniservers after dump-JSON growth). Portal/code-samplesLoxone Forecast ships both programs. Docs DE/EN/docs/loxone+/docs/loxone-forecastsynced. - PDN UI: removed duplicate hour/price label in the chart header on hover/touch (
#pdn-chart-focus); floating tooltip remains the sole detail surface (landing#strompreise,/forecast,/admin/forecast) - API hygiene —
dump_scenario_*aligned to row price: After copying onto Decision /charge_hours/ Windows slots,dump_scenario_ct_kwh/dump_scenario_eur_mwhare always recomputed from that row’s price ×dump_risk_pct(no float drift from EUR÷10). Windows slots strip internal_keys; public ranking stays on the model price. - PDN/Sparvo UI declutter: removed the “Dump risk” chip, help sheet, risk dot, Sparvo hint, home line, and tooltip “Possible dump (illustration)” — No dump correction \| Dump price toggle and midday hatching remain. API
dump_risk*fields unchanged. - Sparvo tap focus: with Dump price active the focus line shows the dump price; with No dump correction it shows the point forecast.
- Portal
/fc-verification: removed the No dump correction \| Dump price toggle; savings simulation and chart again always rank on the model price (dump ranking skewed the savings % for end users). Dump history remains on/fc-verification/detail+ CSV/PDF. Day navigator, Sparvo, and/code-sampleskeep their dump toggle; landing#planung-livealso has no dump toggle (model price). - Forecast API —
dump_scenario_*always usable:dump_scenario_ct_kwh/dump_scenario_eur_mwhhold the dump price whendump_risk_pct> 0, otherwise the point price (nevernullonly because there is no dump). Clients need no null-check; whether a dump is active is shown bydump_risk_pct/dump_risk. Public Windows ranking stays on the model price. Loxone ParseSpotpriceForecast bumped to v14 (O6 = always-usable scenario/point price; show “Dump price” only when pct > 0). Docs + code samples synced. - Forecast API —
dump_risk_pct+dump_scenario_*always on hours: every hour object onGET /v1/forecast(and inherited ondecision[]/forecast[]in Decision, slots in Windows,charge_hours[]in Hours Demand) now always carriesdump_risk_pct(0…100, nevernull) anddump_scenario_ct_kwh/dump_scenario_eur_mwh.dump_risk_pstays 0…1 unchanged (compat).price_ct_kwh/price_eur_mwhare never rewritten. - Portal dump-price toggle (Decision demo,
/code-samples): same Overlay/Dump-price view as the day navigator/Sparvo on the landing planning demo and code samples — display/ranking only, in the portal UI or in the generated sample code. Public endpoints (GET /v1/forecast,GET /v1/decision/windows, …) keep returning the point price unchanged;price_ct_kwhnever changes. - Docs/samples sync — dump risk & field
start: Forecast docs DE/EN fixtimestamp→start; dump risk only on ML hours (forecast_d*), no soft-dump; Loxone ParseSpotpriceForecast v12 (O4 = risk code, O1/O2 unchanged); portal/code-samplesprint optionaldump_risk/dump_risk_p - UI Dump price default: Day navigator (landing/user/admin) + Sparvo default to Dump price; Min/Max/Avg follow displayed dump/point prices
- Sparvo/PDN focus: Tap/touch on dump-risk bars shows the displayed price in the floating tooltip (PDN); Sparvo keeps its tap focus line (toggle: dump vs point)
- Forecast API — Dump risk (additive):
GET /v1/forecastmay includedump_risk,dump_risk_p,dump_risk_scope,dump_risk_versionon midday ML hours (11–16 Vienna). No effect onprice_ct_kwh/price_eur_mwh. Live experiment (ML_DUMP_RISK=live); kill-switch0. Portal bar toggle Overlay \| Dump price.
2026-08-01
- /docs Loxone wiring plan: overview + detailed plans (ASCII + output→input checklist) for Hours, Windows, Forecast; heading fragment anchors
- Loxone FetchPlantHours v1.1: after Decide wait ~3 s then O1 0→10 for Parse (fix: O1 stuck at 10 → no hourly re-parse); Telemetry no longer triggers Parse; diagrams separate Telemetry vs Decide file
- Loxone PicoC harden v1.2: FetchPlantHours polls
decision_status(backup/truncate/timeout restore); Parse Hours/Windows/Forecast trigger only on O1 ≥10 (not fail=9) - Loxone PicoC harden v1.3: Parse keeps last Demand if file missing; Windows/Forecast VO pulse ~200 ms (v2.1/v5.1); Fetch poll requires status plus
hours_needed/charge_hours - Loxone PicoC harden v1.4: commit Demand/slots only on
decision_status=ok/ valid Windows JSON — empty/invalid file no longer zeroes the optimizer - /docs Loxone version table: overview lists current PicoC versions (Fetch v1.2, Parse Hours/Windows v1.4, Debug Windows v2.1, Forecast v5.1/v11); guides re-synced with embedded sources
- /docs beginner rewrite: full plain-language rewrite with everyday examples; Loxone guides step-by-step for users who have never used PicoC
- /docs prev/next: every docs page including the hub has bottom Previous / Next controls (order = sidebar /
PAGE_SLUGS) - /docs mobile UX: mobile-first layout, burger for the docs table of contents (same pattern as portal main nav), and a top-right copy-to-clipboard control on every code block
- Loxone integration guides (new): public docs menu Loxone with overview, Hours & telemetry, Decision Windows, Forecast — step-by-step wiring and PicoC copy-paste at
/docs/loxone - Hours Demand —
charge_hours[]:POST /v1/decision/hours-demandindecidemode now always returns concrete start/end times and prices for every recommended charging hour whendecision_status: ok, not just the count (hours_needed) - Plant Telemetry (new):
POST /v1/plant/telemetry— submit battery SOC% and cumulative import meter readings; own quota classtelemetry, does not count against the Decision fair-use limit - Hours Demand —
mode: "telemetry": the same ingest path as Plant Telemetry is now also reachable directly viaPOST /v1/decision/hours-demandwithmode: "telemetry" - Bridge breakdown in Hours Demand: new fields
hours_needed_cover,hours_needed_opp,hours_needed_bridge, andplant_freshnessin the decide response - Webhook
plant.plan_updated(new): sent to your registered webhook URL wheneverhours_neededorcharge_hours[]change materially — same URL and secret asforecast.updated - Public API documentation (new): a full developer wiki at
/docs, in German and English, crawlable and without login — replaces the previous plain status link in the footer
Earlier
- Decision Windows API (
GET /v1/decision/windows, enginewindows_v1) — contiguous time windows with a full constraint set (min_gap_hours,max_consecutive,allowed_hours,weekdays,allocation) - Decision API (
GET /v1/decision, enginequartile_v1) — quartile-based hourly signalscharge/discharge/hold - Hours Demand Core (
POST /v1/decision/hours-demand, enginehours_demand_v1) — first version withhours_neededderived from a SOC/load/PV balance - Forecast webhook (
forecast.updated) — push notification after every successful forecast update - Forecast API (
GET /v1/forecast) — hourly EPEX AT price series, 48h Basic / 168h full version
Version notes
- API version:
v1(in theapi_versionresponse field) - Engine tags per endpoint:
quartile_v1(Decision),windows_v1(Windows),hours_demand_v1…hours_demand_v1.11(Hours Demand; prep after cover v1.11, autark v1.10, prep v1.8) - Breaking changes are recorded here with date, affected endpoint, and migration window
Next steps
- Downloads — the current OpenAPI specification with every field
- Forecast API · Decision API · Hours Demand API
Register for Community or code samples with your personal key.