diff --git a/routes/reslevis.py b/routes/reslevis.py index 01af603..d99f5b8 100644 --- a/routes/reslevis.py +++ b/routes/reslevis.py @@ -1,7 +1,11 @@ -from fastapi import APIRouter, Depends, HTTPException, Request +import asyncio +import json +from urllib.parse import urlencode + +from fastapi import APIRouter, Depends, HTTPException, Query, Request import httpx import config_env -from typing import List +from typing import List, Optional from schemas.reslevis import ( BuildingItem, @@ -13,6 +17,7 @@ from schemas.reslevis import ( SubjectItem, AlarmItem, TrackItem, + TrackHistoryItem, TrackerZoneItem, SettingItem, ) @@ -33,6 +38,7 @@ from security import get_current_user #CORE SYNC CORE_BASE_URL = config_env.CORE_API_URL.rstrip("/") +TRACKS_CORE_BASE_URL = "http://localhost:1902" CORE_TIMEOUT = 2.0 # secondi async def sync_core_get(request: Request) -> None: @@ -120,6 +126,7 @@ def _normalize_tracker(row: dict) -> dict: def _normalize_track(row: dict) -> dict: row = dict(row) + row["ID"] = row.get("ID") row["gateway"] = _none_if_empty(row.get("gateway")) row["tracker"] = _none_if_empty(row.get("tracker")) row["subject"] = _none_if_empty(row.get("subject")) @@ -131,6 +138,9 @@ def _normalize_track(row: dict) -> dict: row["gatewayMac"] = _str_or_none(row.get("gatewayMac")) row["trackerMac"] = _str_or_none(row.get("trackerMac")) row["subjectName"] = _str_or_none(row.get("subjectName")) + row["x"] = None if row.get("x") in ("", None) else row.get("x") + row["y"] = None if row.get("y") in ("", None) else row.get("y") + row["z"] = None if row.get("z") in ("", None) else row.get("z") # signal resta float o None row["signal"] = None if row.get("signal") in ("", None) else row.get("signal") return row @@ -146,10 +156,44 @@ CORE_GET_SYNC = { "/reslevis/getGateways": (gateway_repo, _normalize_gateway), "/reslevis/getZones": (zone_repo, _normalize_zone), "/reslevis/getTrackers": (tracker_repo, _normalize_tracker), - "/reslevis/getTracks": (track_repo, _normalize_track), } +async def _fetch_tracks_for_tracker( + tracker_id: str, + params: Optional[dict] = None, +) -> List[dict]: + query_string = urlencode(params or {}) + url = f"{TRACKS_CORE_BASE_URL}/reslevis/getTracks/{tracker_id}" + if query_string: + url = f"{url}?{query_string}" + + process = await asyncio.create_subprocess_exec( + "curl", + "-sS", + "-X", + "GET", + url, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + ) + stdout, stderr = await process.communicate() + + if process.returncode != 0: + detail = (stderr or stdout).decode("utf-8", errors="replace").strip() or "CORE curl request failed" + raise HTTPException(status_code=502, detail=detail) + + try: + payload = json.loads(stdout.decode("utf-8")) + except ValueError as exc: + raise HTTPException(status_code=502, detail="Invalid CORE response") from exc + + if not isinstance(payload, list): + raise HTTPException(status_code=502, detail="Unexpected CORE response type") + + return [_normalize_track(row) for row in payload if isinstance(row, dict)] + + @router.get( "/getGateways", response_model=List[GatewayItem], @@ -319,12 +363,48 @@ def removeTrackerZone(tracker_zone_id: str): @router.get( "/getTracks", - response_model=List[TrackItem], + response_model=List[TrackHistoryItem], + tags=["Reslevis"], + dependencies=[Depends(get_current_user)], +) +async def getTracks( + tracker_id: str = Query(..., alias="id"), + limit: Optional[int] = Query(None, ge=1), + from_: Optional[str] = Query(None, alias="from"), + to: Optional[str] = Query(None), +): + params = {} + if limit is not None: + params["limit"] = limit + if from_: + params["from"] = from_ + if to: + params["to"] = to + + return await _fetch_tracks_for_tracker(tracker_id, params) + + +@router.get( + "/getTracks/{tracker_id}", + response_model=List[TrackHistoryItem], tags=["Reslevis"], dependencies=[Depends(get_current_user)], ) -def getTracks(): - return track_repo.list() +async def getTrack( + tracker_id: str, + limit: Optional[int] = Query(None, ge=1), + from_: Optional[str] = Query(None, alias="from"), + to: Optional[str] = Query(None), +): + params = {} + if limit is not None: + params["limit"] = limit + if from_: + params["from"] = from_ + if to: + params["to"] = to + + return await _fetch_tracks_for_tracker(tracker_id, params) @router.post("/postTrack", tags=["Reslevis"], dependencies=[Depends(get_current_user)]) diff --git a/schemas/reslevis.py b/schemas/reslevis.py index 05da507..9586197 100644 --- a/schemas/reslevis.py +++ b/schemas/reslevis.py @@ -121,6 +121,29 @@ class TrackItem(BaseModel): floor: Optional[UUID] = None signal: Optional[float] = None building: Optional[UUID] = None + x: Optional[float] = None + y: Optional[float] = None + z: Optional[float] = None + + +class TrackHistoryItem(BaseModel): + ID: Optional[int] = None + id: UUID + timestamp: Optional[str] = None + type: Optional[str] = None + status: Optional[str] = None + gateway: Optional[UUID] = None + gatewayMac: Optional[str] = None + tracker: Optional[UUID] = None + trackerMac: Optional[str] = None + subject: Optional[UUID] = None + subjectName: Optional[str] = None + floor: Optional[UUID] = None + signal: Optional[float] = None + building: Optional[UUID] = None + x: Optional[float] = None + y: Optional[float] = None + z: Optional[float] = None class TrackerZoneItem(BaseModel): id: UUID @@ -147,4 +170,4 @@ class CalibrationMetadata(BaseModel): #??? Da verificate ??? class DownloadFileImmage(): name : str - immage_path : str \ No newline at end of file + immage_path : str