mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-11-13 09:13:30 +01:00
feat(pvforecast): add adaptive per-plane PV learning and diagnostics (#1422)
PV arrays with different orientations and curtailment need separate plant calibration and weather correction. This opt-in provider publishes normal EOS AC/DC forecast keys at 15-minute resolution. - Preserve daily per-plane energy/shape calibration and validated short-term local/trend selection. Curtailment-sensitive arrays require a fresh release flag or an explicitly configured learning guard. - Add switchable empirical solar-angle response relative to separate eligible reference arrays, removing their common weather error. This learns angular residuals, not physical angles or a measured geometric horizon. - Archive actually received weather model inputs, first local receipt and frozen per-member PV candidates. Returned past weather is excluded; unknown source issuance remains explicit. Learn model weights and forecast-regime bias separately at 2–6, 6–24 and 24–48 hours. - New long-horizon candidates remain in shadow until their genuinely issued outputs improve equal-day MAE by the configured margin, win on at least 60% of validation days and pass a matched-support energy-bias guard. Insufficient evidence retains calibration. Daily yields still require complete local days, including DST. - Expose fitted parameters, independent training/validation day counts, errors, selected methods and persistence in the existing status API, with additional normal prediction keys for Grafana. Retain physical DC through angular/weather corrections an enforce individual inverter AC limits. Co-authored-by: Normann <github@koldrack.com> Co-authored-by: Christin <chrissi@von-perbandt.de> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: YMT <yn276364@dal.ca> Co-authored-by: sarankumar1325 <120080287+sarankumar1325@users.noreply.github.com>
This commit is contained in:
co-authored by
Normann
Christin
Claude Opus 5.5
YMT
sarankumar1325
parent
298d46a527
commit
f804d48072
+24
-1
@@ -10,7 +10,7 @@ import shutil
|
||||
import tempfile
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import AsyncIterator, Optional, Type
|
||||
from typing import Any, AsyncIterator, Optional, Type, cast
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
@@ -876,3 +876,26 @@ class TestPerformance:
|
||||
assert loaded == n
|
||||
print(f"\nLoaded {n} records in {load_duration:.2f}s "
|
||||
f"({n / load_duration:.0f} rec/s)")
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sqlite_bulk_operations_rollback_as_one_transaction(config_eos):
|
||||
import sqlite3
|
||||
|
||||
config_eos.database.provider = "SQLite"
|
||||
db = get_database()
|
||||
await db.open()
|
||||
try:
|
||||
await db.save_records([(b"first", b"original"), (b"second", b"other")], namespace="atomic")
|
||||
with pytest.raises(sqlite3.ProgrammingError):
|
||||
await db.save_records(
|
||||
[(b"first", b"changed"), (b"bad", cast(Any, object()))], namespace="atomic"
|
||||
)
|
||||
assert dict([row async for row in db.iterate_records(namespace="atomic")]) == {
|
||||
b"first": b"original",
|
||||
b"second": b"other",
|
||||
}
|
||||
with pytest.raises(sqlite3.ProgrammingError):
|
||||
await db.delete_records([b"first", cast(Any, object())], namespace="atomic")
|
||||
assert await db.count_records(namespace="atomic") == 2
|
||||
finally:
|
||||
await db.close()
|
||||
|
||||
Reference in New Issue
Block a user