From 00524a352cb3e75e131b080220e4a6e6557d2bc2 Mon Sep 17 00:00:00 2001 From: Nik Sauer Date: Thu, 31 Oct 2024 10:35:44 +0100 Subject: [PATCH 1/2] added StationStatus schema, create_station_status --- code/routers/station.py | 9 ++++++++- code/schemas.py | 8 +++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/code/routers/station.py b/code/routers/station.py index 56b46dd..a27961f 100644 --- a/code/routers/station.py +++ b/code/routers/station.py @@ -8,7 +8,7 @@ import io from models import Station, Location, Measurement, Values -from schemas import StationDataCreate, SensorsCreate +from schemas import StationDataCreate, SensorsCreate, StationStatus from utils import get_or_create_location, download_csv from services.hourly_average import calculate_hourly_average @@ -122,6 +122,13 @@ async def get_current_station_data( return Response(content=content, media_type=media_type) +@router.post("/status", tags=["station"]) +async def create_station_status(status: StationStatus): + print(f"{status=}") + + return {"status": "success"} + + @router.post("/data", tags=["station"]) async def create_station_data( station: StationDataCreate, diff --git a/code/schemas.py b/code/schemas.py index 276aa32..e9c045a 100644 --- a/code/schemas.py +++ b/code/schemas.py @@ -29,4 +29,10 @@ class SensorDataCreate(BaseModel): class SensorsCreate(RootModel[Dict[int, SensorDataCreate]]): - pass \ No newline at end of file + pass + + +class StationStatus(BaseModel): + time: datetime + level: str + message: str From 17ad287aba97df8d939f634e39b291e8f8edb7fd Mon Sep 17 00:00:00 2001 From: Nik Sauer Date: Tue, 5 Nov 2024 11:36:38 +0100 Subject: [PATCH 2/2] added db: StationStatus, wrapper to validate station info --- code/models.py | 10 ++- code/routers/station.py | 140 +++++++++++++++++++++++----------------- code/schemas.py | 4 +- 3 files changed, 93 insertions(+), 61 deletions(-) diff --git a/code/models.py b/code/models.py index 303d5cd..a46fb4d 100644 --- a/code/models.py +++ b/code/models.py @@ -106,4 +106,12 @@ class HourlyAverages(Base): avg_value = Column(Float) sensor_model = Column(Integer) dimension = Column(Integer) - timestamp = Column(DateTime) \ No newline at end of file + timestamp = Column(DateTime) + + +class StationStatus(Base): + id = Column(Integer, primary_key=True, index=True) + Column(Integer, ForeignKey('stations.id')) + timestamp = Column(DateTime) + level = Column(Integer) + message = Column(String) diff --git a/code/routers/station.py b/code/routers/station.py index a27961f..85c3393 100644 --- a/code/routers/station.py +++ b/code/routers/station.py @@ -12,6 +12,77 @@ from utils import get_or_create_location, download_csv from services.hourly_average import calculate_hourly_average + +def validate_station_info(f): + async def wrapper( + station: StationDataCreate, + sensors: SensorsCreate, + background_tasks: BackgroundTasks, + db: Session = Depends(get_db) + ): + # Prüfen, ob die Station bereits existiert + db_station = db.query(Station).filter(Station.device == station.device).first() + + if db_station is None: + # Neue Station und neue Location anlegen + new_location = Location( + lat=station.location.lat, + lon=station.location.lon, + height=float(station.location.height) + ) + db.add(new_location) + db.commit() + db.refresh(new_location) + + # Neue Station anlegen und das source-Feld überprüfen (Standardwert ist 1) + db_station = Station( + device=station.device, + firmware=station.firmware, + apikey=station.apikey, + location_id=new_location.id, + last_active=station.time, + source=station.source if station.source is not None else 1 + ) + db.add(db_station) + db.commit() + db.refresh(db_station) + else: + # Station existiert, API-Schlüssel überprüfen + if db_station.apikey != station.apikey: + raise HTTPException( + status_code=401, + detail="Invalid API key" + ) + + updated = False + + # Überprüfen, ob Location aktualisiert werden muss + if db_station.location is None or ( + db_station.location.lat != station.location.lat or + db_station.location.lon != station.location.lon or + db_station.location.height != float(station.location.height) + ): + new_location = get_or_create_location(db, station.location.lat, station.location.lon, float(station.location.height)) + db_station.location_id = new_location.id + updated = True + + if db_station.firmware != station.firmware: + db_station.firmware = station.firmware + updated = True + + if updated: + db.commit() + + return await f( + station = station, + sensors = sensors, + background_tasks = background_tasks, + db_station = db_station, + db = db + ) + return wrapper + + router = APIRouter() @@ -123,74 +194,27 @@ async def get_current_station_data( @router.post("/status", tags=["station"]) -async def create_station_status(status: StationStatus): - print(f"{status=}") - +@validate_station_info +async def create_station_status( + station: StationDataCreate, + status: StationStatus, + db_station: Station +): + return {"status": "success"} @router.post("/data", tags=["station"]) +@validate_station_info async def create_station_data( station: StationDataCreate, sensors: SensorsCreate, background_tasks: BackgroundTasks, - db: Session = Depends(get_db) + db_station: Station, + db: Session = Depends(get_db), ): # Empfangszeit des Requests erfassen - time_received = datetime.now() - - # Prüfen, ob die Station bereits existiert - db_station = db.query(Station).filter(Station.device == station.device).first() - - if db_station is None: - # Neue Station und neue Location anlegen - new_location = Location( - lat=station.location.lat, - lon=station.location.lon, - height=float(station.location.height) - ) - db.add(new_location) - db.commit() - db.refresh(new_location) - - # Neue Station anlegen und das source-Feld überprüfen (Standardwert ist 1) - db_station = Station( - device=station.device, - firmware=station.firmware, - apikey=station.apikey, - location_id=new_location.id, - last_active=station.time, - source=station.source if station.source is not None else 1 - ) - db.add(db_station) - db.commit() - db.refresh(db_station) - else: - # Station existiert, API-Schlüssel überprüfen - if db_station.apikey != station.apikey: - raise HTTPException( - status_code=401, - detail="Invalid API key" - ) - - updated = False - - # Überprüfen, ob Location aktualisiert werden muss - if db_station.location is None or ( - db_station.location.lat != station.location.lat or - db_station.location.lon != station.location.lon or - db_station.location.height != float(station.location.height) - ): - new_location = get_or_create_location(db, station.location.lat, station.location.lon, float(station.location.height)) - db_station.location_id = new_location.id - updated = True - - if db_station.firmware != station.firmware: - db_station.firmware = station.firmware - updated = True - - if updated: - db.commit() + time_received = datetime.now() # Durch alle Sensoren iterieren for sensor_id, sensor_data in sensors.root.items(): diff --git a/code/schemas.py b/code/schemas.py index e9c045a..65c1960 100644 --- a/code/schemas.py +++ b/code/schemas.py @@ -32,7 +32,7 @@ class SensorsCreate(RootModel[Dict[int, SensorDataCreate]]): pass -class StationStatus(BaseModel): +class StationStatusCreate(BaseModel): time: datetime - level: str + level: int message: str