feat(scada): serve project devices through pooled API
This commit is contained in:
@@ -3,7 +3,6 @@ from uuid import UUID
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from psycopg import AsyncConnection
|
||||
|
||||
from app.infra.db.postgresql.scada import ScadaInfoRepository
|
||||
from app.infra.db.postgresql.analysis import AnalysisRepository
|
||||
from app.auth.project_dependencies import get_project_pg_connection
|
||||
|
||||
@@ -17,24 +16,6 @@ async def get_database_connection(
|
||||
yield conn
|
||||
|
||||
|
||||
@router.get("/scada-info/database-view", summary="获取SCADA信息", description="使用连接池查询所有SCADA信息")
|
||||
async def get_scada_info_with_connection(
|
||||
conn: AsyncConnection = Depends(get_database_connection),
|
||||
):
|
||||
"""
|
||||
获取所有SCADA信息
|
||||
|
||||
返回项目中所有的SCADA设备信息
|
||||
"""
|
||||
try:
|
||||
scada_data = await ScadaInfoRepository.get_scadas(conn)
|
||||
return {"success": True, "data": scada_data, "count": len(scada_data)}
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=500, detail=f"查询SCADA信息时发生错误: {str(e)}"
|
||||
)
|
||||
|
||||
|
||||
@router.get("/analysis/runs", summary="获取分析运行列表")
|
||||
async def get_analysis_runs(
|
||||
conn: AsyncConnection = Depends(get_database_connection),
|
||||
|
||||
@@ -1,34 +1,42 @@
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, Query
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from psycopg import AsyncConnection
|
||||
|
||||
from app.services.tjnetwork import (
|
||||
get_all_scada_info,
|
||||
get_scada_info,
|
||||
get_scada_info_schema,
|
||||
)
|
||||
from app.auth.project_dependencies import get_project_pg_connection
|
||||
from app.domain.schemas.scada import ScadaDeviceResponse
|
||||
from app.infra.db.postgresql.scada import ScadaInfoRepository, get_scada_info_schema
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/network-schemas/scada-device", summary="获取 SCADA 设备结构")
|
||||
def get_scada_device_schema(
|
||||
network: str = Query(..., description="管网名称(或数据库名称)"),
|
||||
) -> dict[str, dict[str, Any]]:
|
||||
return get_scada_info_schema(network)
|
||||
def get_scada_device_schema() -> dict[str, dict[str, Any]]:
|
||||
return get_scada_info_schema("")
|
||||
|
||||
|
||||
@router.get("/scada-devices", summary="获取 SCADA 设备列表")
|
||||
def get_scada_devices(
|
||||
network: str = Query(..., description="管网名称(或数据库名称)"),
|
||||
@router.get(
|
||||
"/scada-devices",
|
||||
summary="获取 SCADA 设备列表",
|
||||
response_model=list[ScadaDeviceResponse],
|
||||
)
|
||||
async def get_scada_devices(
|
||||
conn: AsyncConnection = Depends(get_project_pg_connection),
|
||||
) -> list[dict[str, Any]]:
|
||||
return get_all_scada_info(network)
|
||||
return await ScadaInfoRepository.get_scadas(conn)
|
||||
|
||||
|
||||
@router.get("/scada-devices/detail", summary="获取 SCADA 设备")
|
||||
def get_scada_device(
|
||||
network: str = Query(..., description="管网名称(或数据库名称)"),
|
||||
device_id: str = Query(..., description="SCADA 设备 ID"),
|
||||
@router.get(
|
||||
"/scada-devices/{device_id}",
|
||||
summary="获取 SCADA 设备",
|
||||
response_model=ScadaDeviceResponse,
|
||||
)
|
||||
async def get_scada_device(
|
||||
device_id: str,
|
||||
conn: AsyncConnection = Depends(get_project_pg_connection),
|
||||
) -> dict[str, Any]:
|
||||
return get_scada_info(network, device_id)
|
||||
device = await ScadaInfoRepository.get_scada(conn, device_id)
|
||||
if device is None:
|
||||
raise HTTPException(status_code=404, detail="SCADA 设备不存在")
|
||||
return device
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ScadaDeviceResponse(BaseModel):
|
||||
"""Project SCADA metadata keyed by the canonical device identifier."""
|
||||
|
||||
device_id: str
|
||||
device_type: str
|
||||
node_id: str | None = None
|
||||
link_id: str | None = None
|
||||
api_query_id: str | None = None
|
||||
transmission_mode: str
|
||||
transmission_frequency: str
|
||||
reliability: int | None = None
|
||||
x: float | None = None
|
||||
y: float | None = None
|
||||
longitude: float | None = None
|
||||
latitude: float | None = None
|
||||
@@ -9,7 +9,9 @@ from app.native.wndb.core.database import read_all, try_read
|
||||
|
||||
_SCADA_VIEW_SELECT = """
|
||||
SELECT id AS device_id, device_type, node_id, link_id, api_query_id,
|
||||
transmission_mode, transmission_frequency, reliability, x, y
|
||||
transmission_mode, transmission_frequency, reliability, x, y,
|
||||
ST_X(ST_Transform(geom, 4326)) AS longitude,
|
||||
ST_Y(ST_Transform(geom, 4326)) AS latitude
|
||||
FROM gis.scada_devices
|
||||
"""
|
||||
|
||||
@@ -60,6 +62,8 @@ def _device(record: dict[str, Any]) -> dict[str, Any]:
|
||||
"reliability": _optional_int(record["reliability"]),
|
||||
"x": _optional_float(record["x"]),
|
||||
"y": _optional_float(record["y"]),
|
||||
"longitude": _optional_float(record["longitude"]),
|
||||
"latitude": _optional_float(record["latitude"]),
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +80,18 @@ class ScadaInfoRepository:
|
||||
|
||||
return [_device(record) for record in records]
|
||||
|
||||
@staticmethod
|
||||
async def get_scada(
|
||||
conn: AsyncConnection, device_id: str
|
||||
) -> dict[str, Any] | None:
|
||||
async with conn.cursor() as cur:
|
||||
await cur.execute(
|
||||
_SCADA_VIEW_SELECT + " WHERE id = %s",
|
||||
(device_id,),
|
||||
)
|
||||
record = await cur.fetchone()
|
||||
return _device(record) if record else None
|
||||
|
||||
@staticmethod
|
||||
async def get_existing_device_ids(
|
||||
conn: AsyncConnection, device_ids: list[str]
|
||||
@@ -102,6 +118,8 @@ def get_scada_info_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
"reliability": {"type": "int", "optional": False, "readonly": True},
|
||||
"x": {"type": "float", "optional": True, "readonly": True},
|
||||
"y": {"type": "float", "optional": True, "readonly": True},
|
||||
"longitude": {"type": "float", "optional": True, "readonly": True},
|
||||
"latitude": {"type": "float", "optional": True, "readonly": True},
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user