From b468fb2ac020c80390d4fc66b13482f4e6d87fcd Mon Sep 17 00:00:00 2001
From: Robert Goldmann <deadlocker@gmx.de>
Date: Sat, 16 Jan 2021 16:38:45 +0100
Subject: [PATCH] added database access and routes for sensors

---
 src/logic/databaseNew/Crud.py    | 23 +++++++++++-
 src/logic/databaseNew/Models.py  |  2 +-
 src/logic/databaseNew/Schemas.py |  6 +++
 src/main.py                      |  3 +-
 src/routers/DeviceRouter.py      |  6 +--
 src/routers/SensorRouter.py      | 63 ++++++++++++++++++++++++++++++++
 6 files changed, 96 insertions(+), 7 deletions(-)
 create mode 100644 src/routers/SensorRouter.py

diff --git a/src/logic/databaseNew/Crud.py b/src/logic/databaseNew/Crud.py
index 21cab08..4fbe503 100644
--- a/src/logic/databaseNew/Crud.py
+++ b/src/logic/databaseNew/Crud.py
@@ -3,6 +3,9 @@ from sqlalchemy.orm import Session
 from logic.databaseNew import Models, Schemas
 
 
+# ===== devices =====
+
+
 def get_devices(db: Session, skip: int = 0, limit: int = 100):
     return db.query(Models.Device).offset(skip).limit(limit).all()
 
@@ -28,13 +31,29 @@ def delete_device(db: Session, device: Schemas.Device):
     db.commit()
 
 
+# ===== sensors =====
+
 def get_sensors(db: Session, skip: int = 0, limit: int = 100):
     return db.query(Models.Sensor).offset(skip).limit(limit).all()
 
 
-def create_sensor(db: Session, item: Schemas.SensorCreate, deviceId: int):
-    dbSensor = Models.Sensor(**item.dict(), deviceId=deviceId)
+def get_sensor(db: Session, sensorId: int):
+    return db.query(Models.Sensor).filter(Models.Sensor.id == sensorId).first()
+
+
+def get_sensor_by_name_and_device_id(db: Session, sensorName: str, deviceId: int):
+    return db.query(Models.Sensor).filter(
+        Models.Sensor.name == sensorName and Models.Sensor.deviceId == deviceId).first()
+
+
+def create_sensor(db: Session, sensor: Schemas.SensorCreate):
+    dbSensor = Models.Sensor(**sensor.dict())
     db.add(dbSensor)
     db.commit()
     db.refresh(dbSensor)
     return dbSensor
+
+
+def delete_sensor(db: Session, sensor: Schemas.Sensor):
+    db.delete(sensor)
+    db.commit()
diff --git a/src/logic/databaseNew/Models.py b/src/logic/databaseNew/Models.py
index f8fc1ea..8d73068 100644
--- a/src/logic/databaseNew/Models.py
+++ b/src/logic/databaseNew/Models.py
@@ -10,7 +10,7 @@ class Device(Base):
     id = Column(Integer, primary_key=True, index=True)
     name = Column(String, unique=True, index=True, nullable=False)
 
-    sensors = relationship('Sensor', back_populates='device')
+    sensors = relationship('Sensor', back_populates='device', cascade='all,delete')
 
 
 class Sensor(Base):
diff --git a/src/logic/databaseNew/Schemas.py b/src/logic/databaseNew/Schemas.py
index c82d577..7d15943 100644
--- a/src/logic/databaseNew/Schemas.py
+++ b/src/logic/databaseNew/Schemas.py
@@ -7,15 +7,20 @@ class Status(BaseModel):
     message: str
 
 
+# ===== sensor =====
 class SensorBase(BaseModel):
     id: int
     name: str
     type: str
 
+    class Config:
+        orm_mode = True
+
 
 class SensorCreate(BaseModel):
     name: str
     type: str
+    deviceId: int
 
 
 class Sensor(BaseModel):
@@ -28,6 +33,7 @@ class Sensor(BaseModel):
         orm_mode = True
 
 
+# ===== device =====
 class DeviceBase(BaseModel):
     id: int
     name: str
diff --git a/src/main.py b/src/main.py
index 5fcb30b..39099cf 100644
--- a/src/main.py
+++ b/src/main.py
@@ -9,7 +9,7 @@ from Settings import SETTINGS
 from logic import Constants
 from logic.databaseNew import Models
 from logic.databaseNew.Database import engine
-from routers import DeviceRouter
+from routers import DeviceRouter, SensorRouter
 
 LOGGER = DefaultLogger().create_logger_if_not_exists(Constants.APP_NAME)
 
@@ -24,6 +24,7 @@ app = FastAPI(title=Constants.APP_NAME,
               description='The StorageLeaf API',
               servers=[{'url': SETTINGS['api']['url'], 'description': f'{Constants.APP_NAME} API'}])
 app.include_router(DeviceRouter.router)
+app.include_router(SensorRouter.router)
 
 
 @app.get('/')
diff --git a/src/routers/DeviceRouter.py b/src/routers/DeviceRouter.py
index 9471e50..29b0d41 100644
--- a/src/routers/DeviceRouter.py
+++ b/src/routers/DeviceRouter.py
@@ -9,8 +9,7 @@ from logic.databaseNew.Schemas import Status
 
 router = APIRouter(
     prefix='/device',
-    tags=['device'],
-    responses={404: {'description': 'Not found'}},
+    tags=['device']
 )
 
 
@@ -42,7 +41,8 @@ async def create_device(device: Schemas.DeviceCreate, db: Session = Depends(get_
 
 
 @router.delete('/{deviceId}', response_model=Status,
-               summary='Gets a specific device',
+               summary='Deletes a specific device',
+               description='All corresponding sensors and measurements will be deleted too.',
                responses={404: {'description': 'Device not found'}},
                dependencies=[Depends(check_api_key)])
 async def delete_device(deviceId: int, db: Session = Depends(get_database)):
diff --git a/src/routers/SensorRouter.py b/src/routers/SensorRouter.py
new file mode 100644
index 0000000..0ba15e2
--- /dev/null
+++ b/src/routers/SensorRouter.py
@@ -0,0 +1,63 @@
+from typing import List
+
+from fastapi import APIRouter, HTTPException, Depends
+from sqlalchemy.orm import Session
+
+from Dependencies import get_database, check_api_key
+from logic.databaseNew import Schemas, Crud
+from logic.databaseNew.Schemas import Status
+
+router = APIRouter(
+    prefix='/sensor',
+    tags=['sensor']
+)
+
+
+@router.get('/', response_model=List[Schemas.Sensor],
+            summary='Gets all sensors')
+async def read_sensors(skip: int = 0, limit: int = 100, db: Session = Depends(get_database)):
+    return Crud.get_sensors(db, skip=skip, limit=limit)
+
+
+@router.get('/{sensorId}', response_model=Schemas.Sensor,
+            summary='Gets a specific sensor',
+            responses={404: {'description': 'Sensor not found'}})
+async def read_sensor(sensorId: int, db: Session = Depends(get_database)):
+    sensor = Crud.get_sensor(db, sensorId=sensorId)
+    if sensor is None:
+        raise HTTPException(status_code=404, detail='Sensor not found')
+    return sensor
+
+
+@router.post('/', response_model=Schemas.Sensor,
+             summary='Adds a new sensor',
+             responses={400: {'description': 'A sensor called "{sensor.name}" already exists '
+                                             '(ID: {existingSensor.id}) for device {sensor.deviceId}'},
+                        404: {'description': 'No device with id "{sensor.deviceId}" existing'}},
+             dependencies=[Depends(check_api_key)])
+async def create_sensor(sensor: Schemas.SensorCreate, db: Session = Depends(get_database)):
+    existingDevice = Crud.get_device(db, sensor.deviceId)
+    if not existingDevice:
+        raise HTTPException(status_code=404, detail=f'No device with id "{sensor.deviceId}" existing')
+
+    existingSensor = Crud.get_sensor_by_name_and_device_id(db, sensor.name, sensor.deviceId)
+    if existingSensor:
+        raise HTTPException(status_code=400,
+                            detail=f'A sensor called "{sensor.name}" already exists '
+                                   f'(ID: {existingSensor.id}) for device {sensor.deviceId}')
+
+    return Crud.create_sensor(db=db, sensor=sensor)
+
+
+@router.delete('/{sensorId}', response_model=Status,
+               summary='Deletes a specific sensor',
+               description='All corresponding measurements will be deleted too.',
+               responses={404: {'description': 'Sensor not found'}},
+               dependencies=[Depends(check_api_key)])
+async def delete_sensor(sensorId: int, db: Session = Depends(get_database)):
+    sensor = Crud.get_sensor(db, sensorId=sensorId)
+    if sensor is None:
+        raise HTTPException(status_code=404, detail='Sensor not found')
+
+    Crud.delete_sensor(db, sensor)
+    return Status(message=f'Deleted sensor {sensor.id}')
-- 
GitLab