first commit
This commit is contained in:
commit
4b98219bf7
144 changed files with 31561 additions and 0 deletions
82
backend/api/routes/alarms.py
Normal file
82
backend/api/routes/alarms.py
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
from fastapi import APIRouter, Depends, Query, HTTPException
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from core.database import get_session
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def list_alarms(
|
||||
site_id: str = Query(...),
|
||||
state: str = Query("active", description="active | resolved | acknowledged | all"),
|
||||
limit: int = Query(50, ge=1, le=200),
|
||||
session: AsyncSession = Depends(get_session),
|
||||
):
|
||||
where = "WHERE site_id = :site_id"
|
||||
if state != "all":
|
||||
where += " AND state = :state"
|
||||
|
||||
result = await session.execute(text(f"""
|
||||
SELECT id, sensor_id, site_id, room_id, rack_id,
|
||||
severity, message, state, triggered_at,
|
||||
acknowledged_at, resolved_at
|
||||
FROM alarms
|
||||
{where}
|
||||
ORDER BY triggered_at DESC
|
||||
LIMIT :limit
|
||||
"""), {"site_id": site_id, "state": state, "limit": limit})
|
||||
return [dict(r) for r in result.mappings().all()]
|
||||
|
||||
|
||||
@router.post("/{alarm_id}/acknowledge")
|
||||
async def acknowledge_alarm(
|
||||
alarm_id: int,
|
||||
session: AsyncSession = Depends(get_session),
|
||||
):
|
||||
result = await session.execute(text("""
|
||||
UPDATE alarms
|
||||
SET state = 'acknowledged', acknowledged_at = NOW()
|
||||
WHERE id = :id AND state = 'active'
|
||||
RETURNING id
|
||||
"""), {"id": alarm_id})
|
||||
await session.commit()
|
||||
if not result.fetchone():
|
||||
raise HTTPException(status_code=404, detail="Alarm not found or not active")
|
||||
return {"id": alarm_id, "state": "acknowledged"}
|
||||
|
||||
|
||||
@router.post("/{alarm_id}/resolve")
|
||||
async def resolve_alarm(
|
||||
alarm_id: int,
|
||||
session: AsyncSession = Depends(get_session),
|
||||
):
|
||||
result = await session.execute(text("""
|
||||
UPDATE alarms
|
||||
SET state = 'resolved', resolved_at = NOW()
|
||||
WHERE id = :id AND state IN ('active', 'acknowledged')
|
||||
RETURNING id
|
||||
"""), {"id": alarm_id})
|
||||
await session.commit()
|
||||
if not result.fetchone():
|
||||
raise HTTPException(status_code=404, detail="Alarm not found or already resolved")
|
||||
return {"id": alarm_id, "state": "resolved"}
|
||||
|
||||
|
||||
@router.get("/stats")
|
||||
async def alarm_stats(
|
||||
site_id: str = Query(...),
|
||||
session: AsyncSession = Depends(get_session),
|
||||
):
|
||||
result = await session.execute(text("""
|
||||
SELECT
|
||||
COUNT(*) FILTER (WHERE state = 'active') AS active,
|
||||
COUNT(*) FILTER (WHERE state = 'acknowledged') AS acknowledged,
|
||||
COUNT(*) FILTER (WHERE state = 'resolved') AS resolved,
|
||||
COUNT(*) FILTER (WHERE state = 'active' AND severity = 'critical') AS critical,
|
||||
COUNT(*) FILTER (WHERE state = 'active' AND severity = 'warning') AS warning
|
||||
FROM alarms
|
||||
WHERE site_id = :site_id
|
||||
"""), {"site_id": site_id})
|
||||
row = result.mappings().one()
|
||||
return {k: int(v) for k, v in row.items()}
|
||||
Loading…
Add table
Add a link
Reference in a new issue