FastAPI app that pulls interval usage from Sungrow iSolarCloud (OAuth2), caches AER Consumer Data Right electricity plan data, and compares actual metered usage against every available plan to estimate real annual cost (TOU, tiered feed-in, and flat tariffs). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
45 lines
1.1 KiB
Python
45 lines
1.1 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.staticfiles import StaticFiles
|
|
|
|
from app.api import isolarcloud as isolarcloud_api
|
|
from app.api import plans as plans_api
|
|
from app.api import settings as settings_api
|
|
from app.api import usage as usage_api
|
|
from app.db.session import init_db
|
|
from app.scheduler.setup import build_scheduler
|
|
from app.web.routes import router as web_router
|
|
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
init_db()
|
|
scheduler = build_scheduler()
|
|
scheduler.start()
|
|
app.state.scheduler = scheduler
|
|
try:
|
|
yield
|
|
finally:
|
|
scheduler.shutdown(wait=False)
|
|
|
|
|
|
app = FastAPI(title="Power Compare", lifespan=lifespan)
|
|
|
|
app.include_router(usage_api.router)
|
|
app.include_router(plans_api.router)
|
|
app.include_router(settings_api.router)
|
|
app.include_router(isolarcloud_api.router)
|
|
app.include_router(web_router)
|
|
|
|
app.mount("/static", StaticFiles(directory="app/static"), name="static")
|
|
|
|
|
|
@app.get("/health")
|
|
def health() -> dict:
|
|
return {"status": "ok"}
|