working push-data route

This commit is contained in:
Michi 2025-03-30 17:25:23 +02:00
parent 831ce1dbc8
commit 081241fd20
5 changed files with 107 additions and 64 deletions

8
webservice/README.md Normal file
View file

@ -0,0 +1,8 @@
# Webservice
Developer Mode starten: fastapi dev webservice.py
## Error Table
| Errorcode | Type | Definition |
| --- | --- | --- |

View file

@ -1,35 +1,23 @@
import psycopg2
from psycopg2.extras import execute_values
import os
from sqlmodel import create_engine, Session
from dotenv import load_dotenv
from models import SensorData, Client
# Lade Umgebungsvariablen
load_dotenv()
DB_CONNECTION_STRING = os.getenv("DB_CONNECTION_STRING", "postgresql://user:password@localhost/sensordb")
# Create a database connection
def connectDatabase():
conn = psycopg2.connect(
host=os.getenv('DBHOST'),
database=os.getenv('DBNAME'),
user=os.getenv('DBUSER'),
password=os.getenv('DBPASSWORD'),
port=os.getenv('DBPORT'),)
conn.autocommit = True
cursor = conn.cursor()
return cursor
# SQLAlchemy Setup
engine = create_engine(DB_CONNECTION_STRING, echo=True)
# Execute database query
def executeQuery(query):
conn = connectDatabase()
conn.execute(query)
result = conn.fetchall()
return result
# Funktion zum Speichern von Sensordaten
def save_sensor_data(db: Session, sensor_data: SensorData):
db.add(sensor_data) # Das Pydantic-Modell kann direkt hinzugefügt werden
db.commit()
db.refresh(sensor_data) # Holt die letzten Informationen des hinzugefügten Eintrags
return sensor_data
# Execute database query without fetching data
def executeWithoutFetch(query):
conn = connectDatabase()
conn.execute(query)
return None
def bulkInsert(query, data):
conn = connectDatabase()
return execute_values(conn, query, data)
# dbfunctions.py
def get_client_id_by_name(db: Session, client_name: str):
client = db.query(Client).filter(Client.name == client_name).first()
return client.id if client else None # Gibt die clientid zurück oder None, wenn nicht gefunden

33
webservice/models.py Normal file
View file

@ -0,0 +1,33 @@
from datetime import datetime
from pydantic import BaseModel, Field
from typing import Optional
from sqlmodel import SQLModel, Field
class MessageOnly(BaseModel):
message: str
timestamp: datetime = Field(default_factory=datetime.now)
class Client(SQLModel, table=True):
__tablename__ = "clients" # Definiere den Tabellennamen für Clients
id: int = Field(default=None, primary_key=True)
name: str = Field(max_length=50) # Stelle sicher, dass der Name der DB-Struktur entspricht
class SensorDataIn(BaseModel): # Klasse für den Input (d.h., die API-Dokumentation)
timestamp: datetime = Field(default_factory=datetime.now)
temperature: float = Field(default=None, nullable=True)
humidity: float = Field(default=None, nullable=True)
pressure: float = Field(default=None, nullable=True)
voc: float = Field(default=None, nullable=True)
gas: float = Field(default=None, nullable=True)
class SensorData(SQLModel, table=True):
__tablename__ = "sensor_data"
id: int = Field(default=None, primary_key=True)
timestamp: datetime = Field(default_factory=datetime.now)
temperature: float = Field(default=None, nullable=True)
humidity: float = Field(default=None, nullable=True)
pressure: float = Field(default=None, nullable=True)
voc: float = Field(default=None, nullable=True)
gas: float = Field(default=None, nullable=True)
clientid: int = Field(default=None, nullable=True)

View file

@ -5,3 +5,4 @@ psycopg2-binary
psycopg2-binary==2.9.9
python-dotenv==1.0.0
requests
sqlmodel

View file

@ -1,47 +1,60 @@
# Webservice
# INP21b - Timo Weber & Michael von Ah
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import psycopg2
import dbfunctions as db
import requests, secrets, hashlib, re, string, random, os
from datetime import datetime, timedelta, date, time
import json
from datetime import datetime
DATABASE_URL = os.getenv("DB_CONNECTION_STRING", "postgresql://user:password@localhost/sensordb")
""" class apiFunctions:
def __init__(self) -> None:
self.alternativeImage = "https://cdn.ep.neodym.dev/media/20240505-halloween.jpeg"
def getAttractionList(self):
query = 'SELECT "name", "id", "imageurl", "description" FROM "attraction" ORDER BY "name";'
attractions = db.executeQuery(query)
if attractions:
return attractions
else:
raise Exception("Cannot generate list of attractions. Request invalid") """
################ IMPORTS ################
from fastapi import FastAPI, Depends, HTTPException
from sqlmodel import Session
from dbfunctions import save_sensor_data, get_client_id_by_name, engine
from models import SensorDataIn, SensorData, MessageOnly
#### API ####
################ API ################
app = FastAPI(
title="M241-M245-BBZW-Horizion",
title="M241-M245-BBZW-Horizon",
description="BBZW-Horizon",
summary="BBZW-Horizon",
version="0.0.1"
)
class Session(BaseModel):
username: str = None
token: str = None
message: str = None
timestamp: datetime = datetime.now()
@app.post("/account/new-session", tags=["account"])
async def initNewSessionApi(username: str, password: str) -> Session:
# DB Session
def get_db():
db = Session(bind=engine)
try:
return Session(username="username", token="sessionToken", message="Session initiated successfully")
yield db
finally:
db.close()
# class Session(BaseModel):
# username: str = None
# token: str = None
# message: str = None
# timestamp: datetime = datetime.now()
# @app.post("/account/new-session", tags=["account"])
# async def initNewSessionApi(username: str, password: str) -> Session:
# try:
# return Session(username="username", token="sessionToken", message="Session initiated successfully")
# except Exception as error:
# raise HTTPException(status_code=401, detail=f"{error}")
@app.post("/sensors/push-data", response_model=MessageOnly, tags=["sensors"])
async def saveNewSensorData(token: str, client: str, data: SensorDataIn, db: Session = Depends(get_db)):
try:
# Ermittle die clientid basierend auf dem Client-Namen
client_id = get_client_id_by_name(db, client)
if client_id is None:
raise HTTPException(status_code=404, detail="Client not found")
# Erstelle ein SensorData-Objekt für die Datenbank
sensor_data = SensorData(**data.dict())
sensor_data.clientid = client_id # Setze die clientid aus der DB
# Speichern der Sensordaten in der Datenbank
save_sensor_data(db, sensor_data)
return MessageOnly(message="Sensor data saved successfully.")
except Exception as error:
raise HTTPException(status_code=401, detail=f"{error}")
raise HTTPException(status_code=500, detail=str(error))