diff --git a/main.py b/main.py index b27da03..9622a8d 100644 --- a/main.py +++ b/main.py @@ -1,3 +1,4 @@ +import io import sys import bme680 @@ -8,7 +9,9 @@ import time import threading import pymysql from fastapi.middleware.cors import CORSMiddleware +from picamera2 import Picamera2 +from starlette.responses import StreamingResponse db_user = 'sensor_user' db_password = 'dein_passwort' @@ -52,6 +55,11 @@ sensor_pin = 22 GPIO.setmode(GPIO.BCM) GPIO.setup(sensor_pin, GPIO.IN) +# --- Camera Pins +camera_pin = 17 +GPIO.setmode(GPIO.BCM) +GPIO.setup(camera_pin, GPIO.IN) + # --- Global shared state variables --- state = 0 motion_detected = False # Shared state @@ -59,6 +67,19 @@ temperature = 0 humidity = 0 pressure = 0 gas_resistance = 0 +is_recording = False +picam2 = None + +def camera_loop(): + try: + while True: + val = GPIO.input(camera_pin) + print(val) + + except Exception as e: + print(f"Camera error: {e}") + finally: + GPIO.cleanup() # ------------------------------------------------------------- # @function proxmity_loop @@ -87,6 +108,30 @@ def proxmity_loop(): GPIO.cleanup() +def init_camera(): + global picam2 + try: + camera = Picamera2() + + # capture_file(..., format="jpeg") kodiert die Frames selbst als JPEG. + # Der Kamerastream bleibt deshalb ein normaler RGB-Stream. + camera_config = camera.create_preview_configuration(main={"format": "RGB888", "size": (640, 480)}) + camera.configure(camera_config) + + camera.start() + picam2 = camera + print("Kamera bereit für das Streaming!") + except Exception as e: + picam2 = None + print(f"Kamera konnte nicht initialisiert werden: {e}") + + +def capture_jpeg_frame(camera): + stream = io.BytesIO() + camera.capture_file(stream, format="jpeg") + return stream.getvalue() + + # ------------------------------------------------------------- # @function sensor_loop # @description Reads data from the BME680 sensor (temperature, humidity, pressure, gas resistance) @@ -192,6 +237,10 @@ def startup_event(): database_thread = threading.Thread(target=database_loop, daemon=True) database_thread.start() + if use_camera: + init_camera() + #camera_thread = threading.Thread(target=camera_loop, daemon=True) + #camera_thread.start() print("Sensor thread started") @@ -269,9 +318,31 @@ async def getRegression(): return lineare_regression(countGuest, temps, [0, 60, 120]) +def gen_frames(): + global picam2 + while True: + camera = picam2 + if camera is not None: + try: + frame_bytes = capture_jpeg_frame(camera) + + # MJPEG-Boundary-Stream zusammensetzen + yield (b'--frame\r\n' + b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n') + + except Exception as e: + print(f"Fehler beim Frame-Grabbing: {e}") + time.sleep(1) + + time.sleep(0.04) # ~25 FPS + +# Der neue FastAPI-Endpoint für dein Frontend +@app.get("/video_feed") +async def video_feed(): + return StreamingResponse(gen_frames(), media_type="multipart/x-mixed-replace; boundary=frame") # ------------------------------------------------------------- # @entrypoint # @description Starts the FastAPI app server using Uvicorn. # ------------------------------------------------------------- if __name__ == "__main__": - uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True) \ No newline at end of file + uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)