from fastapi import APIRouter, Depends, HTTPException, Query, Path, Body from typing import List from datetime import datetime from psycopg import AsyncConnection from app.infra.db.timescaledb.repositories.scada import ScadaRepository from .dependencies import get_timescale_connection router = APIRouter() @router.post("/scada/batch", status_code=201, summary="批量插入SCADA监测数据") async def insert_scada_data( data: List[dict] = Body(..., description="SCADA设备监测数据列表"), conn: AsyncConnection = Depends(get_timescale_connection), ): """ 批量插入SCADA监测数据 将多个设备的实时监测数据批量插入时间序列数据库。 Args: data: SCADA设备监测数据列表,每项包含device_id、时间戳和监测值等信息 Returns: 插入成功的记录数 """ await ScadaRepository.insert_scada_batch(conn, data) return {"message": f"Inserted {len(data)} records"} @router.get("/scada/by-ids-time-range", summary="按设备ID和时间范围查询SCADA数据") async def get_scada_by_ids_time_range( start_time: datetime = Query(..., description="查询开始时间"), end_time: datetime = Query(..., description="查询结束时间"), device_ids: str = Query( ..., description="设备ID列表,逗号分隔,如 'device1,device2,device3'" ), conn: AsyncConnection = Depends(get_timescale_connection), ): """ 按设备ID和时间范围查询SCADA监测数据 查询多个设备在指定时间范围内的所有监测数据。 Args: start_time: 查询开始时间 end_time: 查询结束时间 device_ids: 设备ID列表,用逗号分隔 Returns: SCADA监测数据列表 """ device_ids_list = ( [id.strip() for id in device_ids.split(",") if id.strip()] if device_ids else [] ) return await ScadaRepository.get_scada_by_ids_time_range( conn, device_ids_list, start_time, end_time ) @router.get( "/scada/by-ids-field-time-range", summary="按设备ID、字段和时间范围查询SCADA数据" ) async def get_scada_field_by_ids_time_range( start_time: datetime = Query(..., description="查询开始时间"), end_time: datetime = Query(..., description="查询结束时间"), field: str = Query(..., description="要查询的字段名称"), device_ids: str = Query( ..., description="设备ID列表,逗号分隔,如 'device1,device2,device3'" ), conn: AsyncConnection = Depends(get_timescale_connection), ): """ 按设备ID、字段和时间范围查询特定SCADA数据 查询多个设备在指定时间范围内的特定字段监测数据。 Args: start_time: 查询开始时间 end_time: 查询结束时间 field: 字段名称 device_ids: 设备ID列表,用逗号分隔 Returns: SCADA字段数据列表 Raises: HTTPException: 当字段不存在或查询参数无效时返回400错误 """ try: device_ids_list = ( [id.strip() for id in device_ids.split(",") if id.strip()] if device_ids else [] ) return await ScadaRepository.get_scada_field_by_id_time_range( conn, device_ids_list, start_time, end_time, field ) except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) @router.patch("/scada/{device_id}/field", summary="更新SCADA设备字段") async def update_scada_field( device_id: str = Path(..., description="设备ID"), time: datetime = Query(..., description="更新数据的时间戳"), field: str = Query(..., description="要更新的字段名称"), value: float = Query(..., description="更新的字段值"), conn: AsyncConnection = Depends(get_timescale_connection), ): """ 更新指定设备的字段值 更新SCADA设备在特定时间的某个字段监测数据。 Args: device_id: 设备ID time: 数据时间戳 field: 字段名称 value: 字段新值 Returns: 更新结果信息 Raises: HTTPException: 当字段不存在或更新失败时返回400错误 """ try: await ScadaRepository.update_scada_field(conn, time, device_id, field, value) return {"message": "Updated successfully"} except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) @router.delete("/scada/by-id-time-range", summary="按设备ID和时间范围删除SCADA数据") async def delete_scada_data( device_id: str = Query(..., description="设备ID"), start_time: datetime = Query(..., description="删除开始时间"), end_time: datetime = Query(..., description="删除结束时间"), conn: AsyncConnection = Depends(get_timescale_connection), ): """ 删除指定设备和时间范围内的SCADA数据 删除在指定时间范围内的特定设备监测数据。 Args: device_id: 设备ID start_time: 删除开始时间 end_time: 删除结束时间 Returns: 删除结果信息 """ await ScadaRepository.delete_scada_by_id_time_range( conn, device_id, start_time, end_time ) return {"message": "Deleted successfully"}