From 99f36b10b8fc474eea156b841b32e4d08177c124 Mon Sep 17 00:00:00 2001 From: sosokker Date: Sun, 12 May 2024 18:05:54 +0700 Subject: [PATCH] Add endpoint to get camera snapshot url --- StreamServer/src/main.py | 3 ++- StreamServer/src/query/camera.py | 35 ++++++++++++++++++++++++++++++ StreamServer/src/routers/camera.py | 25 +++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 StreamServer/src/query/camera.py create mode 100644 StreamServer/src/routers/camera.py diff --git a/StreamServer/src/main.py b/StreamServer/src/main.py index 6301fa1..8924cc6 100644 --- a/StreamServer/src/main.py +++ b/StreamServer/src/main.py @@ -2,7 +2,7 @@ import uvicorn from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware -from routers import video, weather, prediction +from routers import video, weather, prediction, camera app = FastAPI( @@ -32,6 +32,7 @@ app.add_middleware( app.include_router(video.router, prefix="/camera") app.include_router(weather.router, prefix="/weather") app.include_router(prediction.router, prefix="/weather") +app.include_router(camera.router, prefix="/camera") @app.get("/") def read_root(): diff --git a/StreamServer/src/query/camera.py b/StreamServer/src/query/camera.py new file mode 100644 index 0000000..9fb1bfc --- /dev/null +++ b/StreamServer/src/query/camera.py @@ -0,0 +1,35 @@ +from datetime import datetime, timedelta +from minio.error import InvalidResponseError +from pytz import UTC + +from config import VIDEO_BUCKET +from database import minio_client + + +def list_objects_with_timestamp(bucket_name: str = VIDEO_BUCKET) -> list[tuple[str, datetime]]: + """List objects in the specified bucket with their last modified timestamp""" + try: + objects = minio_client.list_objects(bucket_name, recursive=True) + jpeg_objects = [(obj.object_name, obj.last_modified) for obj in objects if obj.object_name.endswith('.jpg') or obj.object_name.endswith('.jpeg')] + return jpeg_objects + except InvalidResponseError as err: + print(err) + return [] + + +def filter_objects_by_date(objects_with_timestamp: list, interval: str) -> list: + """List objects with timestamp within the specified interval. Supported intervals: 'today', 'week', 'month', 'all'""" + now_datetime = datetime.now(UTC) + + if interval == "today": + start_datetime = now_datetime - timedelta(days=1) + elif interval == "week": + start_datetime = now_datetime - timedelta(days=7) + elif interval == "month": + start_datetime = now_datetime - timedelta(days=30) + elif interval == "all": + start_datetime = datetime.min.replace(tzinfo=UTC) # Consider all dates + else: + raise ValueError("Invalid interval. Supported intervals: 'today', 'week', 'month', 'all'") + + return [obj for obj, timestamp in objects_with_timestamp if start_datetime <= timestamp <= now_datetime] diff --git a/StreamServer/src/routers/camera.py b/StreamServer/src/routers/camera.py new file mode 100644 index 0000000..b690d2f --- /dev/null +++ b/StreamServer/src/routers/camera.py @@ -0,0 +1,25 @@ +from datetime import timedelta + +from fastapi import APIRouter, HTTPException + +from query.camera import list_objects_with_timestamp, filter_objects_by_date + +from config import VIDEO_BUCKET +from database import minio_client + + +router = APIRouter() + + +@router.get("/snapshot/{interval}", response_model=list[str]) +async def get_snapshot(interval: str): + """Return the list of URLs of camera snapshot within the specified interval. Supported intervals: 'today', 'week', 'month', 'all'""" + try: + res = filter_objects_by_date(list_objects_with_timestamp(), interval) + except ValueError as err: + raise HTTPException(status_code=400, detail=str(err)) + + if not res: + raise HTTPException(status_code=404, detail="No snapshot found") + + return [minio_client.presigned_get_object(VIDEO_BUCKET, obj, expires=timedelta(days=1), response_headers={'response-content-type': 'image/jpeg'}) for obj in res] \ No newline at end of file