| @@ -18,6 +18,7 @@ GATEWAY_JSON_PATH = DATA_DIR / "gateway_list.json" | |||||
| BUILDING_JSON_PATH = DATA_DIR / "building.json" | BUILDING_JSON_PATH = DATA_DIR / "building.json" | ||||
| FLOOR_JSON_PATH = DATA_DIR / "floors.json" | FLOOR_JSON_PATH = DATA_DIR / "floors.json" | ||||
| ZONE_JSON_PATH = DATA_DIR / "zone_list.json" | ZONE_JSON_PATH = DATA_DIR / "zone_list.json" | ||||
| ZONE_AREA_DEFINITION_JSON_PATH = DATA_DIR / "zone_area_definition.json" | |||||
| TRACKER_JSON_PATH = DATA_DIR / "tracker_conf.json" | TRACKER_JSON_PATH = DATA_DIR / "tracker_conf.json" | ||||
| OPERATOR_JSON_PATH = DATA_DIR / "oper_conf.json" | OPERATOR_JSON_PATH = DATA_DIR / "oper_conf.json" | ||||
| SUBJECT_JSON_PATH = DATA_DIR / "subject.json" | SUBJECT_JSON_PATH = DATA_DIR / "subject.json" | ||||
| @@ -0,0 +1,72 @@ | |||||
| import json | |||||
| from typing import List, Dict, Any, Optional | |||||
| from fastapi.encoders import jsonable_encoder | |||||
| from schemas.reslevis import ZoneAreaDefinitionItem | |||||
| from .config import ZONE_AREA_DEFINITION_JSON_PATH | |||||
| from .gateway import _LockedFile, _atomic_write, _norm_str | |||||
| class ZoneAreaDefinitionJsonRepository: | |||||
| def __init__(self, json_path: str = ZONE_AREA_DEFINITION_JSON_PATH): | |||||
| self.path = json_path | |||||
| def _read_all(self) -> List[Dict[str, Any]]: | |||||
| with _LockedFile(self.path, "r") as fp: | |||||
| try: | |||||
| fp.seek(0) | |||||
| data = fp.read().strip() | |||||
| return json.loads(data) if data else [] | |||||
| except json.JSONDecodeError: | |||||
| return [] | |||||
| def _write_all(self, rows: List[Dict[str, Any]]) -> None: | |||||
| payload = json.dumps(rows, ensure_ascii=False, indent=2) | |||||
| _atomic_write(self.path, payload) | |||||
| def _index_by_uuid(self, rows: List[Dict[str, Any]], item_uuid: str) -> Optional[int]: | |||||
| target = _norm_str(item_uuid) | |||||
| for idx, row in enumerate(rows): | |||||
| if _norm_str(row.get("UUID")) == target: | |||||
| return idx | |||||
| return None | |||||
| def list(self, item_uuid: Optional[str] = None) -> List[Dict[str, Any]]: | |||||
| rows = self._read_all() | |||||
| if item_uuid: | |||||
| idx = self._index_by_uuid(rows, item_uuid) | |||||
| return [rows[idx]] if idx is not None else [] | |||||
| return rows | |||||
| def add(self, item: ZoneAreaDefinitionItem) -> None: | |||||
| rows = self._read_all() | |||||
| obj = jsonable_encoder(item) | |||||
| obj_uuid = _norm_str(obj.get("UUID")) | |||||
| if self._index_by_uuid(rows, obj_uuid) is not None: | |||||
| raise ValueError(f"ZoneAreaDefinition con UUID '{obj_uuid}' già presente") | |||||
| rows.append(obj) | |||||
| self._write_all(rows) | |||||
| def update(self, item: ZoneAreaDefinitionItem) -> None: | |||||
| rows = self._read_all() | |||||
| obj = jsonable_encoder(item) | |||||
| obj_uuid = _norm_str(obj.get("UUID")) | |||||
| idx = self._index_by_uuid(rows, obj_uuid) | |||||
| if idx is None: | |||||
| raise ValueError(f"ZoneAreaDefinition con UUID '{obj_uuid}' non trovato") | |||||
| rows[idx] = obj | |||||
| self._write_all(rows) | |||||
| def remove(self, item_uuid: str) -> None: | |||||
| rows = self._read_all() | |||||
| idx = self._index_by_uuid(rows, item_uuid) | |||||
| if idx is None: | |||||
| raise ValueError(f"ZoneAreaDefinition con UUID '{item_uuid}' non trovato") | |||||
| del rows[idx] | |||||
| self._write_all(rows) | |||||
| @@ -11,6 +11,7 @@ from schemas.reslevis import ( | |||||
| BuildingItem, | BuildingItem, | ||||
| FloorItem, | FloorItem, | ||||
| ZoneItem, | ZoneItem, | ||||
| ZoneAreaDefinitionItem, | |||||
| GatewayItem, | GatewayItem, | ||||
| TrackerItem, | TrackerItem, | ||||
| OperatorItem, | OperatorItem, | ||||
| @@ -26,6 +27,7 @@ from logica_reslevis.gateway import GatewayJsonRepository | |||||
| from logica_reslevis.building import BuildingJsonRepository | from logica_reslevis.building import BuildingJsonRepository | ||||
| from logica_reslevis.floor import FloorJsonRepository | from logica_reslevis.floor import FloorJsonRepository | ||||
| from logica_reslevis.zone import ZoneJsonRepository | from logica_reslevis.zone import ZoneJsonRepository | ||||
| from logica_reslevis.zone_area_definition import ZoneAreaDefinitionJsonRepository | |||||
| from logica_reslevis.tracker import TrackerJsonRepository | from logica_reslevis.tracker import TrackerJsonRepository | ||||
| from logica_reslevis.operator import OperatorJsonRepository | from logica_reslevis.operator import OperatorJsonRepository | ||||
| from logica_reslevis.setting import SettingJsonRepository | from logica_reslevis.setting import SettingJsonRepository | ||||
| @@ -74,6 +76,7 @@ gateway_repo = GatewayJsonRepository() | |||||
| building_repo = BuildingJsonRepository() | building_repo = BuildingJsonRepository() | ||||
| floor_repo = FloorJsonRepository() | floor_repo = FloorJsonRepository() | ||||
| zone_repo = ZoneJsonRepository() | zone_repo = ZoneJsonRepository() | ||||
| zone_area_definition_repo = ZoneAreaDefinitionJsonRepository() | |||||
| tracker_repo = TrackerJsonRepository() | tracker_repo = TrackerJsonRepository() | ||||
| operator_repo = OperatorJsonRepository() | operator_repo = OperatorJsonRepository() | ||||
| subject_repo = SubjectJsonRepository() | subject_repo = SubjectJsonRepository() | ||||
| @@ -306,6 +309,34 @@ def removeZone(zone_id: str): | |||||
| return {"message": "OK"} | return {"message": "OK"} | ||||
| @router.get( | |||||
| "/getZoneAreaDefinitions", | |||||
| response_model=List[ZoneAreaDefinitionItem], | |||||
| tags=["Reslevis"], | |||||
| dependencies=[Depends(get_current_user)], | |||||
| ) | |||||
| def getZoneAreaDefinitions(UUID: str | None = None): | |||||
| return zone_area_definition_repo.list(UUID) | |||||
| @router.post("/postZoneAreaDefinition", tags=["Reslevis"], dependencies=[Depends(get_current_user)]) | |||||
| def postZoneAreaDefinition(item: ZoneAreaDefinitionItem): | |||||
| zone_area_definition_repo.add(item) | |||||
| return {"message": "OK"} | |||||
| @router.put("/updateZoneAreaDefinition", tags=["Reslevis"], dependencies=[Depends(get_current_user)]) | |||||
| def updateZoneAreaDefinition(item: ZoneAreaDefinitionItem): | |||||
| zone_area_definition_repo.update(item) | |||||
| return {"message": "OK"} | |||||
| @router.delete("/removeZoneAreaDefinition/{zone_area_definition_uuid}", tags=["Reslevis"], dependencies=[Depends(get_current_user)]) | |||||
| def removeZoneAreaDefinition(zone_area_definition_uuid: str): | |||||
| zone_area_definition_repo.remove(zone_area_definition_uuid) | |||||
| return {"message": "OK"} | |||||
| @router.get( | @router.get( | ||||
| "/getTrackers", | "/getTrackers", | ||||
| response_model=List[TrackerItem], | response_model=List[TrackerItem], | ||||
| @@ -29,6 +29,17 @@ class ZoneItem(BaseModel): | |||||
| floor: Optional[UUID] = None | floor: Optional[UUID] = None | ||||
| building: Optional[UUID] = None | building: Optional[UUID] = None | ||||
| class ZoneAreaPointItem(BaseModel): | |||||
| x: float | |||||
| y: float | |||||
| class ZoneAreaDefinitionItem(BaseModel): | |||||
| UUID: UUID | |||||
| ZoneUUID: UUID | |||||
| points: List[ZoneAreaPointItem] | |||||
| class GatewayItem(BaseModel): | class GatewayItem(BaseModel): | ||||
| id: UUID | id: UUID | ||||
| name: str | name: str | ||||