diff --git a/backend/app/urls.py b/backend/app/urls.py index 04e3c88160ba9116ab1e2d4b0c4b7a63f6613e37..f1076e4be4ca9d2b9c1686cbc06481a698708fde 100644 --- a/backend/app/urls.py +++ b/backend/app/urls.py @@ -9,4 +9,6 @@ urlpatterns = [ path("api/register", views.register, name="register"), path("api/room_data_range", views.room_data_range, name="room_data_range"), path("api/get_rooms", views.get_rooms, name="get_rooms"), + path("api/room_data_csv", views.room_data_csv_view, name="room_data_csv_view"), + path("api/room_data_csv_download", views.room_data_csv_download, name="room_data_csv_download"), ] diff --git a/backend/app/views.py b/backend/app/views.py index 9712f56c282f35600ddcede4f428e979d2498386..299efdca4fef758e95571bb99c0067670425d385 100644 --- a/backend/app/views.py +++ b/backend/app/views.py @@ -1,9 +1,12 @@ +import csv +from io import StringIO import os +from django.http import HttpResponse from django.shortcuts import render from django.http import JsonResponse from django.views.decorators.csrf import ensure_csrf_cookie, csrf_protect import json -from backend.utils.influx import InfluxDBHelper +from utils.influx import InfluxDBHelper from dotenv import load_dotenv from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import csrf_exempt @@ -71,10 +74,9 @@ def register(request): @require_http_methods(["GET"]) def room_data_range(request): try: - data = json.loads(request.body.decode("utf-8")) - room = data["room"] - start = data["start"] - stop = data["stop"] + room = request.GET.get("room") + start = request.GET.get("start", "-30d") + stop = request.GET.get("stop", "now()") if not room: return JsonResponse({"error": "Missing 'room' parameter"}, status=400) @@ -120,3 +122,59 @@ def get_rooms(request): rooms.add(record.get_value()) return JsonResponse({"rooms": sorted(rooms)}) + +@require_http_methods(["GET"]) +def room_data_csv_view(request): + room = request.GET.get("room") + start = request.GET.get("start", "-30d") + stop = request.GET.get("stop", "now()") + + if not room: + return JsonResponse({"error": "Missing 'room' parameter"}, status=400) + + client = InfluxDBHelper( + url=os.getenv("INFLUXDB_URL"), + token=os.getenv("INFLUXDB_TOKEN"), + org=os.getenv("INFLUXDB_ORG"), + bucket=os.getenv("INFLUXDB_BUCKET"), + ) + csv_stream = client.get_room_data_csv(room_id=room, start=start, stop=stop) + + decoded = csv_stream.decode("utf-8") + f = StringIO(decoded) + reader = csv.DictReader(f) + + results = [] + for row in reader: + # optional: nur Datenzeilen filtern + if row.get("_field") and row.get("_value"): + results.append({ + "time": row["_time"], + "field": row["_field"], + "value": row["_value"], + }) + + return JsonResponse({"room": room, "data": results}) + +@require_http_methods(["GET"]) +def room_data_csv_download(request): + room = request.GET.get("room") + start = request.GET.get("start", "-30d") + stop = request.GET.get("stop", "now()") + + if not room: + return JsonResponse({"error": "Missing 'room' parameter"}, status=400) + + client = InfluxDBHelper( + url=os.getenv("INFLUXDB_URL"), + token=os.getenv("INFLUXDB_TOKEN"), + org=os.getenv("INFLUXDB_ORG"), + bucket=os.getenv("INFLUXDB_BUCKET"), + ) + + csv_data = client.get_room_data_csv(room, start, stop) + + response = HttpResponse(csv_data, content_type="text/csv") + response["Content-Disposition"] = f'attachment; filename="{room}_data.csv"' + return response + diff --git a/backend/utils/influx.py b/backend/utils/influx.py index 01408c685ea7de624a56fd3dd1403d9e5fcf2f0e..f34d3b75d065fc600e570e0275db5bf392516ebd 100644 --- a/backend/utils/influx.py +++ b/backend/utils/influx.py @@ -69,6 +69,17 @@ class InfluxDBHelper: ''' return self.query_api.query(org=self.org, query=query) + def get_room_data_csv(self, room_id: str, start: str = "-30d", stop: str = "now()"): + query = f''' + from(bucket: "{self.bucket}") + |> range(start: {start}, stop: {stop}) + |> filter(fn: (r) => r["_measurement"] == "sensor_data") + |> filter(fn: (r) => r["room"] == "{room_id}") + |> filter(fn: (r) => r["_field"] == "co2" or r["_field"] == "humidity" or r["_field"] == "temperature") + ''' + return self.query_api.query_csv(query=query, org=self.org) + + def get_aggregated_room_data(self, room_id: str, window: str = "1h"): query = f''' from(bucket: "{self.bucket}")