feat(pool): řízení bazénu Phase 1 — nejlevnější okno + dump-load (bez solveru)
fn_pool_schedule_slot: nejlevnější souvislé okno denního runtime budgetu (fn_pool_daily_runtime_min) z vw_site_effective_price + dump-load při sell<=0. fn_pool_control_tick: každých 15 min spočte stav a zařadí POOL_PUMP_ON (jen když existuje signal_route → bezpečné před aktivací). lifespan job pool_control. Shelly přes signal_service, žádné Modbus. Bazál odečet (R__003) se tím stává správným (řízená+plánovaná zátěž). Aktivace provozně: daily_runtime_min=480, schedulable, signal_route. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -161,6 +161,22 @@ async def lifespan(app: FastAPI):
|
||||
except Exception:
|
||||
logger.exception("scheduled_signal_outbound_verify failed")
|
||||
|
||||
async def scheduled_pool_control() -> None:
|
||||
# Bazén: SQL-first rozhodnutí (fn_pool_control_tick) — nejlevnější souvislé
|
||||
# okno denního runtime + dump-load při sell<=0; zařadí POOL_PUMP_ON (jen když
|
||||
# existuje signal_route). Doručení řeší signal_outbound_send. Žádné Modbus.
|
||||
try:
|
||||
async with app.state.pg_pool.acquire() as conn:
|
||||
rows = await conn.fetch("select * from ems.fn_pool_control_tick()")
|
||||
for r in rows:
|
||||
logger.info(
|
||||
"pool control site=%s pump=%s on=%s runtime_min=%s route=%s enq=%s",
|
||||
r["site_id"], r["pump_id"], r["desired_on"],
|
||||
r["runtime_min"], r["has_route"], r["enqueued"],
|
||||
)
|
||||
except Exception:
|
||||
logger.exception("scheduled_pool_control failed")
|
||||
|
||||
async def scheduled_verify_modbus() -> None:
|
||||
"""
|
||||
Ověří příkazy ve stavu written z posledních 20 minut.
|
||||
@@ -413,6 +429,14 @@ async def lifespan(app: FastAPI):
|
||||
id="signal_outbound_verify",
|
||||
replace_existing=True,
|
||||
)
|
||||
scheduler.add_job(
|
||||
scheduled_pool_control,
|
||||
"cron",
|
||||
minute="*/15",
|
||||
second=2,
|
||||
id="pool_control",
|
||||
replace_existing=True,
|
||||
)
|
||||
scheduler.add_job(scheduled_daily_plan, "cron", hour=15, minute=0, id="daily_plan")
|
||||
scheduler.add_job(
|
||||
scheduled_rolling_replan,
|
||||
|
||||
Reference in New Issue
Block a user