From 78a7788785d3835572dc75124e0133d7bc626dcf Mon Sep 17 00:00:00 2001 From: Valentina Ceron Date: Mon, 23 Feb 2026 16:05:26 -0500 Subject: [PATCH 1/2] endpoint postgres --- realtimeMonitoring/realtimeGraph/urls.py | 3 ++ realtimeMonitoring/realtimeGraph/views.py | 58 +++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/realtimeMonitoring/realtimeGraph/urls.py b/realtimeMonitoring/realtimeGraph/urls.py index 4c80f61..fa3db9d 100644 --- a/realtimeMonitoring/realtimeGraph/urls.py +++ b/realtimeMonitoring/realtimeGraph/urls.py @@ -10,8 +10,11 @@ path('rema/', RemaView.as_view(), name='rema'), path("mapJson/", get_map_json, name="mapJson"), path("mapJson/", get_map_json, name="mapJson"), + path("hourlyStats/", hourly_stats, name="hourlyStats"), + path("hourlyStats/", hourly_stats, name="hourlyStats"), path('login/', LoginView.as_view(), name='login'), path('logout/', LogoutView.as_view(), name='logout'), path('historical/data', download_csv_data, name='historical-data'), + ] diff --git a/realtimeMonitoring/realtimeGraph/views.py b/realtimeMonitoring/realtimeGraph/views.py index a34b419..aefb13d 100644 --- a/realtimeMonitoring/realtimeGraph/views.py +++ b/realtimeMonitoring/realtimeGraph/views.py @@ -24,6 +24,7 @@ from realtimeMonitoring import settings import dateutil.relativedelta from django.db.models import Avg, Max, Min, Sum +from django.db.models.functions import TruncHour class DashboardView(TemplateView): @@ -673,3 +674,60 @@ def get_statistic(dictionary, key): @ register.filter def add_str(str1, str2): return str1 + str2 + + +# NUEVO ENDPOINT (POSTGRES) + + +def hourly_stats(request, **kwargs): + measureParam = kwargs.get("measure", None) + + # Selección de medida (igual idea que mapJson) + measurements = Measurement.objects.all() + if measureParam is not None: + selectedMeasure = Measurement.objects.filter(name=measureParam)[0] + elif measurements.count() > 0: + selectedMeasure = measurements[0] + else: + return JsonResponse({"error": "No measurements found"}, status=400) + + # Reutiliza el mismo parseo de fechas del proyecto (from/to vienen en milisegundos) + start, end = get_daterange(request) + + # Consulta: agrupar por hora y calcular agregados sobre "value" + qs = ( + Data.objects + .filter( + measurement__name=selectedMeasure.name, + time__gte=start, + time__lte=end, + ) + .annotate(hour=TruncHour("time")) + .values("hour") + .annotate( + min=Min("value"), + max=Max("value"), + avg=Avg("value"), + n=Count("id"), + ) + .order_by("hour") + ) + + points = [] + for row in qs: + hour_dt = row["hour"] + t_ms = int(hour_dt.timestamp() * 1000) if hour_dt else None + points.append({ + "t": t_ms, + "min": row["min"] if row["min"] is not None else 0, + "max": row["max"] if row["max"] is not None else 0, + "avg": round(row["avg"], 2) if row["avg"] is not None else 0, + "n": row["n"] if row["n"] is not None else 0, + }) + + return JsonResponse({ + "measure": selectedMeasure.name, + "from": int(start.timestamp() * 1000), + "to": int(end.timestamp() * 1000), + "points": points, + }) \ No newline at end of file From 80ff0f312f3742b237e82c231b69d013d92e665c Mon Sep 17 00:00:00 2001 From: Valentina Ceron Date: Mon, 23 Feb 2026 17:00:39 -0500 Subject: [PATCH 2/2] endpoint para postgres --- realtimeMonitoring/realtimeGraph/urls.py | 5 +++-- realtimeMonitoring/realtimeGraph/views.py | 17 ++++++----------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/realtimeMonitoring/realtimeGraph/urls.py b/realtimeMonitoring/realtimeGraph/urls.py index fa3db9d..3b417c7 100644 --- a/realtimeMonitoring/realtimeGraph/urls.py +++ b/realtimeMonitoring/realtimeGraph/urls.py @@ -10,11 +10,12 @@ path('rema/', RemaView.as_view(), name='rema'), path("mapJson/", get_map_json, name="mapJson"), path("mapJson/", get_map_json, name="mapJson"), - path("hourlyStats/", hourly_stats, name="hourlyStats"), - path("hourlyStats/", hourly_stats, name="hourlyStats"), path('login/', LoginView.as_view(), name='login'), path('logout/', LogoutView.as_view(), name='logout'), path('historical/data', download_csv_data, name='historical-data'), + #endpoint de estadisticas por hora + path("hourlyStats/", hourly_stats, name="hourlyStats"), + path("hourlyStats/", hourly_stats, name="hourlyStats"), ] diff --git a/realtimeMonitoring/realtimeGraph/views.py b/realtimeMonitoring/realtimeGraph/views.py index aefb13d..634d735 100644 --- a/realtimeMonitoring/realtimeGraph/views.py +++ b/realtimeMonitoring/realtimeGraph/views.py @@ -676,13 +676,10 @@ def add_str(str1, str2): return str1 + str2 -# NUEVO ENDPOINT (POSTGRES) - - +# POSTGRES def hourly_stats(request, **kwargs): measureParam = kwargs.get("measure", None) - # Selección de medida (igual idea que mapJson) measurements = Measurement.objects.all() if measureParam is not None: selectedMeasure = Measurement.objects.filter(name=measureParam)[0] @@ -691,10 +688,8 @@ def hourly_stats(request, **kwargs): else: return JsonResponse({"error": "No measurements found"}, status=400) - # Reutiliza el mismo parseo de fechas del proyecto (from/to vienen en milisegundos) start, end = get_daterange(request) - # Consulta: agrupar por hora y calcular agregados sobre "value" qs = ( Data.objects .filter( @@ -708,7 +703,7 @@ def hourly_stats(request, **kwargs): min=Min("value"), max=Max("value"), avg=Avg("value"), - n=Count("id"), + n=Count("time"), ) .order_by("hour") ) @@ -719,10 +714,10 @@ def hourly_stats(request, **kwargs): t_ms = int(hour_dt.timestamp() * 1000) if hour_dt else None points.append({ "t": t_ms, - "min": row["min"] if row["min"] is not None else 0, - "max": row["max"] if row["max"] is not None else 0, - "avg": round(row["avg"], 2) if row["avg"] is not None else 0, - "n": row["n"] if row["n"] is not None else 0, + "min": row["min"] or 0, + "max": row["max"] or 0, + "avg": round(row["avg"], 2) if row["avg"] else 0, + "n": row["n"] or 0, }) return JsonResponse({