x
This commit is contained in:
@@ -349,8 +349,6 @@ async def run_daily_plan(site_id: int, db, triggered_by: str = "scheduler:daily"
|
||||
logger.info(f"[site={site_id}] Daily plan: {horizon_from} → {horizon_to}")
|
||||
|
||||
slots = await _load_slots(site_id, horizon_from, horizon_to, db)
|
||||
if not slots:
|
||||
raise RuntimeError(f"No planning slots for site_id={site_id} (prices/forecast horizon?)")
|
||||
|
||||
battery, hp, grid, vehicles, ev_sessions, soc_wh, tuv_temp = await _load_site_context(
|
||||
site_id, db
|
||||
@@ -430,9 +428,6 @@ async def run_rolling_replan(
|
||||
correction_factor, correction_log = await compute_correction_factor(site_id, now, db)
|
||||
|
||||
slots = await _load_slots(site_id, replan_from, horizon_to, db)
|
||||
if not slots:
|
||||
logger.warning(f"[site={site_id}] Rolling replan: no slots, running daily plan")
|
||||
return await run_daily_plan(site_id, db, triggered_by=triggered_by)
|
||||
|
||||
slots = apply_forecast_correction(slots, now, correction_factor)
|
||||
|
||||
@@ -477,7 +472,13 @@ async def run_rolling_replan(
|
||||
return run_id, duration_ms
|
||||
|
||||
|
||||
async def run_plan_api(site_id: int, db, plan_type: str, triggered_by: str = "api") -> tuple[int, int]:
|
||||
async def run_plan_api(
|
||||
site_id: int,
|
||||
plan_type: str,
|
||||
db,
|
||||
*,
|
||||
triggered_by: str = "api",
|
||||
) -> tuple[int, int]:
|
||||
"""Ruční / UI spuštění plánu. Vždy vrátí (run_id, solver_duration_ms)."""
|
||||
pt = plan_type.lower().strip()
|
||||
if pt == "daily":
|
||||
@@ -671,10 +672,10 @@ async def _load_site_context(site_id: int, db):
|
||||
site_id,
|
||||
)
|
||||
if soc_pct is None:
|
||||
soc_wh = reserve_wh
|
||||
soc_wh = uc * 0.5
|
||||
else:
|
||||
soc_wh = float(soc_pct) / 100.0 * uc
|
||||
soc_wh = max(reserve_wh, min(soc_wh, soc_max_wh))
|
||||
soc_wh = max(reserve_wh, min(soc_wh, soc_max_wh))
|
||||
|
||||
tuv = await db.fetchval(
|
||||
"""
|
||||
@@ -701,9 +702,9 @@ async def _load_slots(site_id, from_dt, to_dt, db) -> list[PlanningSlot]:
|
||||
COALESCE(fpi_a.power_w, 0) AS pv_a_forecast_w,
|
||||
COALESCE(fpi_b.power_w, 0) AS pv_b_forecast_w,
|
||||
COALESCE(cbi.power_w, 500) AS load_baseline_w,
|
||||
-- EV připojení z aktuálního stavu nabíječek
|
||||
(ev1.status NOT IN ('available', 'unavailable')) AS ev1_connected,
|
||||
(ev2.status NOT IN ('available', 'unavailable')) AS ev2_connected
|
||||
-- EV připojení z poslední telemetrie nabíječek (bez řádku = nepřipojeno)
|
||||
(COALESCE(ev1.status, 'available') NOT IN ('available', 'unavailable')) AS ev1_connected,
|
||||
(COALESCE(ev2.status, 'available') NOT IN ('available', 'unavailable')) AS ev2_connected
|
||||
FROM ems.vw_site_effective_price ep
|
||||
-- FVE pole A forecast
|
||||
LEFT JOIN LATERAL (
|
||||
@@ -762,6 +763,10 @@ async def _load_slots(site_id, from_dt, to_dt, db) -> list[PlanningSlot]:
|
||||
ev2_connected=bool(d["ev2_connected"]),
|
||||
)
|
||||
)
|
||||
if not out:
|
||||
raise RuntimeError(
|
||||
"No planning slots available – check market prices and horizon settings"
|
||||
)
|
||||
return out
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user