Full-stack energy management system for Tianpu Daxing campus. - Frontend: React 19 + TypeScript + Ant Design + ECharts - Backend: FastAPI + SQLAlchemy + PostgreSQL/TimescaleDB - Features: PV monitoring, heat pump management, carbon tracking, alarms, reports Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
75 lines
3.0 KiB
Python
75 lines
3.0 KiB
Python
from datetime import datetime, timedelta, timezone
|
|
from fastapi import APIRouter, Depends, Query
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import select, func, and_, text
|
|
from app.core.database import get_db
|
|
from app.core.deps import get_current_user
|
|
from app.models.carbon import CarbonEmission, EmissionFactor
|
|
from app.models.user import User
|
|
|
|
router = APIRouter(prefix="/carbon", tags=["碳排放管理"])
|
|
|
|
|
|
@router.get("/overview")
|
|
async def carbon_overview(db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
|
|
"""碳排放总览"""
|
|
now = datetime.now(timezone.utc)
|
|
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
|
month_start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
|
year_start = now.replace(month=1, day=1, hour=0, minute=0, second=0, microsecond=0)
|
|
|
|
async def sum_carbon(start, end):
|
|
r = await db.execute(
|
|
select(func.sum(CarbonEmission.emission), func.sum(CarbonEmission.reduction))
|
|
.where(and_(CarbonEmission.date >= start, CarbonEmission.date < end))
|
|
)
|
|
row = r.first()
|
|
return {"emission": row[0] or 0, "reduction": row[1] or 0}
|
|
|
|
today = await sum_carbon(today_start, now)
|
|
month = await sum_carbon(month_start, now)
|
|
year = await sum_carbon(year_start, now)
|
|
|
|
# 各scope分布
|
|
scope_q = await db.execute(
|
|
select(CarbonEmission.scope, func.sum(CarbonEmission.emission))
|
|
.where(CarbonEmission.date >= year_start)
|
|
.group_by(CarbonEmission.scope)
|
|
)
|
|
by_scope = {row[0]: round(row[1], 2) for row in scope_q.all()}
|
|
|
|
return {
|
|
"today": {"emission": round(today["emission"], 2), "reduction": round(today["reduction"], 2)},
|
|
"month": {"emission": round(month["emission"], 2), "reduction": round(month["reduction"], 2)},
|
|
"year": {"emission": round(year["emission"], 2), "reduction": round(year["reduction"], 2)},
|
|
"by_scope": by_scope,
|
|
}
|
|
|
|
|
|
@router.get("/trend")
|
|
async def carbon_trend(
|
|
days: int = Query(30, ge=1, le=365),
|
|
db: AsyncSession = Depends(get_db),
|
|
user: User = Depends(get_current_user),
|
|
):
|
|
"""碳排放趋势"""
|
|
start = datetime.now(timezone.utc) - timedelta(days=days)
|
|
result = await db.execute(
|
|
select(
|
|
func.date_trunc('day', CarbonEmission.date).label('day'),
|
|
func.sum(CarbonEmission.emission),
|
|
func.sum(CarbonEmission.reduction),
|
|
).where(CarbonEmission.date >= start)
|
|
.group_by(text('day')).order_by(text('day'))
|
|
)
|
|
return [{"date": str(r[0]), "emission": round(r[1], 2), "reduction": round(r[2], 2)} for r in result.all()]
|
|
|
|
|
|
@router.get("/factors")
|
|
async def list_factors(db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
|
|
result = await db.execute(select(EmissionFactor).order_by(EmissionFactor.id))
|
|
return [{
|
|
"id": f.id, "name": f.name, "energy_type": f.energy_type, "factor": f.factor,
|
|
"unit": f.unit, "scope": f.scope, "region": f.region, "source": f.source,
|
|
} for f in result.scalars().all()]
|