diff --git a/StreamServer/src/main.py b/StreamServer/src/main.py index 69f95a4..4f4c09b 100644 --- a/StreamServer/src/main.py +++ b/StreamServer/src/main.py @@ -1,10 +1,10 @@ import uvicorn from fastapi import FastAPI -from routers import video +from routers import video, weather app = FastAPI( - title="Dispatch", + title="Healthcare-System", description="Hello Stranger.", root_path="/api/v1", docs_url="/docs/swagger", @@ -13,6 +13,7 @@ app = FastAPI( ) app.include_router(video.router, prefix="/camera") +app.include_router(weather.router, prefix="/weather") @app.get("/") def read_root(): diff --git a/StreamServer/src/models.py b/StreamServer/src/models.py index 0a006c2..a7a27d0 100644 --- a/StreamServer/src/models.py +++ b/StreamServer/src/models.py @@ -5,7 +5,8 @@ This file contains the SQLAlchemy model for the weather data. from sqlalchemy import Column, Integer, Float, DateTime, Text from sqlalchemy.orm import relationship -from .database import Base +from database import Base + class WeatherData(Base): __tablename__ = "data" diff --git a/StreamServer/src/query/weather.py b/StreamServer/src/query/weather.py new file mode 100644 index 0000000..3c51167 --- /dev/null +++ b/StreamServer/src/query/weather.py @@ -0,0 +1,68 @@ +from datetime import datetime, timedelta + +from sqlalchemy import func +from sqlalchemy.orm import Session + +from models import WeatherData + + +def _get_weather_data_query(session: Session): + return session.query( + WeatherData.timestamp, WeatherData.outdoor_temp, WeatherData.outdoor_feels_like, + WeatherData.outdoor_pressure, WeatherData.outdoor_humidity, WeatherData.outdoor_weather, + WeatherData.outdoor_description, WeatherData.outdoor_pm25, WeatherData.outdoor_pm10, + WeatherData.indoor_temp, WeatherData.indoor_light + ).order_by(WeatherData.timestamp.desc()) + +def get_weather_data(session: Session): + """ + Get all weather data from the database. + """ + return _get_weather_data_query(session).all() + +def get_last_n_day_data(session: Session, n: int): + """ + Get the weather data for the last n days from the database. + """ + start_date = datetime.now() - timedelta(days=n) + return _get_weather_data_query(session).filter(WeatherData.timestamp >= start_date).all() + +def get_indoor_data(session: Session, limit: int = 10): + """ + Get the latest indoor data from the database. + """ + return session.query( + WeatherData.timestamp, WeatherData.indoor_temp, WeatherData.indoor_light + ).order_by(WeatherData.timestamp.desc()).limit(limit).all() + +def get_outdoor_data(session: Session, limit: int = 10): + """ + Get the latest outdoor data from the database. + """ + return session.query( + WeatherData.timestamp, WeatherData.outdoor_temp, WeatherData.outdoor_feels_like, + WeatherData.outdoor_pressure, WeatherData.outdoor_humidity, WeatherData.outdoor_weather, + WeatherData.outdoor_description, WeatherData.outdoor_pm25, WeatherData.outdoor_pm10 + ).order_by(WeatherData.timestamp.desc()).limit(limit).all() + +def _get_average_data_query(session: Session, columns, n: int): + start_date = datetime.now() - timedelta(days=n) + return session.query(*columns).filter(WeatherData.timestamp >= start_date) + +def get_average_outdoor_data_last_n_day(session: Session, n: int): + """ + Get the average outdoor data for the last n days from the database. + """ + columns = [ + func.avg(WeatherData.outdoor_temp), func.avg(WeatherData.outdoor_feels_like), + func.avg(WeatherData.outdoor_pressure), func.avg(WeatherData.outdoor_humidity), + func.avg(WeatherData.outdoor_pm25), func.avg(WeatherData.outdoor_pm10) + ] + return _get_average_data_query(session, columns, n).first() + +def get_average_indoor_data_last_n_day(session: Session, n: int): + """ + Get the average indoor data for the last n days from the database. + """ + columns = [func.avg(WeatherData.indoor_temp), func.avg(WeatherData.indoor_light)] + return _get_average_data_query(session, columns, n).first() \ No newline at end of file diff --git a/StreamServer/src/routers/weather.py b/StreamServer/src/routers/weather.py new file mode 100644 index 0000000..4d4a85a --- /dev/null +++ b/StreamServer/src/routers/weather.py @@ -0,0 +1,85 @@ +from sqlalchemy import func +from sqlalchemy.orm import Session + +from database import engine, SessionLocal, Base +from scheme import WeatherDataBase, IndoorDataBase, OutdoorDataBase, AverageIndoorData, AverageOutdoorData +from query.weather import (get_weather_data, get_last_n_day_data, get_indoor_data, get_outdoor_data, + get_average_outdoor_data_last_n_day, get_average_indoor_data_last_n_day) + +from fastapi import APIRouter, Depends, HTTPException + +Base.metadata.create_all(bind=engine) + +router = APIRouter() + +#Dependency +def get_db(): + db = SessionLocal() + try : + yield db + finally: + db.close() + + +@router.get("/", response_model=list[WeatherDataBase]) +async def get_latest_weather_data(db: Session = Depends(get_db)): + weather_data = get_weather_data(db) + if not weather_data: + raise HTTPException(status_code=404, detail="Weather data not found") + return weather_data + + +@router.get("/{days}", response_model=list[WeatherDataBase]) +async def get_weather_data_last_n_days(days: int, db: Session = Depends(get_db)): + weather_data = get_last_n_day_data(db, days) + if not weather_data: + raise HTTPException(status_code=404, detail=f"Weather data for the last {days} days not found") + return weather_data + + +@router.get("/indoor/{days}", response_model=list[IndoorDataBase]) +async def get_indoor_data_last_n_days(days: int, db: Session = Depends(get_db)): + indoor_data = get_indoor_data(db, days) + if not indoor_data: + raise HTTPException(status_code=404, detail=f"Indoor data for the last {days} days not found") + return indoor_data + +@router.get("/outdoor/{days}", response_model=list[OutdoorDataBase]) +async def get_outdoor_data_last_n_days(days: int, db: Session = Depends(get_db)): + outdoor_data = get_outdoor_data(db, days) + if not outdoor_data: + raise HTTPException(status_code=404, detail="Outdoor data not found") + return outdoor_data + + +@router.get("/average/outdoor/{days}", response_model=AverageOutdoorData) +async def get_average_outdoor_data(days: int, db: Session = Depends(get_db)): + average_outdoor_data = get_average_outdoor_data_last_n_day(db, days) + print("HERERERERERE ", average_outdoor_data) + if not average_outdoor_data: + raise HTTPException(status_code=404, detail=f"Average outdoor data for the last {days} days not found") + + average_outdoor_model = AverageOutdoorData( + avg_outdoor_temp=average_outdoor_data[0], + avg_outdoor_feels_like=average_outdoor_data[1], + avg_outdoor_pressure=average_outdoor_data[2], + avg_outdoor_humidity=average_outdoor_data[3], + avg_outdoor_pm25=average_outdoor_data[4], + avg_outdoor_pm10=average_outdoor_data[5] +) + + return average_outdoor_model + + +@router.get("/average/indoor/{days}", response_model=AverageIndoorData) +async def get_average_indoor_data(days: int, db: Session = Depends(get_db)): + average_indoor_data = get_average_indoor_data_last_n_day(db, days) + if not average_indoor_data: + raise HTTPException(status_code=404, detail=f"Average indoor data for the last {days} days not found") + + average_indoor_model = AverageIndoorData( + avg_indoor_temp=average_indoor_data[0], + avg_indoor_light=average_indoor_data[1] + ) + + return average_indoor_model \ No newline at end of file diff --git a/StreamServer/src/scheme.py b/StreamServer/src/scheme.py index d1a1d1b..6c83774 100644 --- a/StreamServer/src/scheme.py +++ b/StreamServer/src/scheme.py @@ -6,6 +6,31 @@ from pydantic import BaseModel from typing import Optional from datetime import datetime + +class IndoorDataBase(BaseModel): + timestamp: Optional[datetime] + indoor_temp: Optional[float] + indoor_light: Optional[int] + + class Config: + from_attributes = True + + +class OutdoorDataBase(BaseModel): + timestamp: Optional[datetime] + outdoor_temp: Optional[float] + outdoor_feels_like: Optional[float] + outdoor_pressure: Optional[int] + outdoor_humidity: Optional[int] + outdoor_weather: Optional[str] + outdoor_description: Optional[str] + outdoor_pm25: Optional[int] + outdoor_pm10: Optional[int] + + class Config: + from_attributes = True + + class WeatherDataBase(BaseModel): timestamp: Optional[datetime] outdoor_temp: Optional[float] @@ -22,6 +47,20 @@ class WeatherDataBase(BaseModel): class Config: from_attributes = True + +class AverageOutdoorData(BaseModel): + avg_outdoor_temp: Optional[float] + avg_outdoor_feels_like: Optional[float] + avg_outdoor_pressure: Optional[float] + avg_outdoor_humidity: Optional[float] + avg_outdoor_pm25: Optional[float] + avg_outdoor_pm10: Optional[float] + + +class AverageIndoorData(BaseModel): + avg_indoor_temp: Optional[float] + avg_indoor_light: Optional[float] + class Camera(BaseModel): camera_id: int link: str \ No newline at end of file