Files
robot-command-center/backend/monitoring/views.py
2026-04-18 12:52:32 +08:00

92 lines
2.6 KiB
Python

from __future__ import annotations
import json
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse, StreamingHttpResponse
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .services import gps_service, network_service, video_service
@api_view(["GET"])
def dashboard_snapshot(request):
return Response(
{
"gps": gps_service.get_latest(),
"network": network_service.get_latest(),
"video": video_service.get_status(),
}
)
@api_view(["GET"])
def gps_latest(request):
return Response(gps_service.get_latest())
@api_view(["GET"])
def network_latest(request):
return Response(network_service.get_latest())
@api_view(["GET"])
def video_status(request):
return Response(video_service.get_status())
def video_frame(request):
try:
frame, headers = video_service.get_next_frame_with_headers()
except (FileNotFoundError, RuntimeError) as error:
status = video_service.get_status()
return HttpResponse(
status.get("source_detail") or str(error),
status=503,
content_type="text/plain; charset=utf-8",
)
response = HttpResponse(frame, content_type="image/jpeg")
response["Cache-Control"] = "no-store, no-cache, must-revalidate, max-age=0"
for key, value in headers.items():
response[key] = value
return response
def video_stream(request):
status = video_service.get_status()
if not status["available"]:
return HttpResponse(
status.get("source_detail") or f"JPEG frame directory not found: {status['frame_dir']}",
status=503,
content_type="text/plain; charset=utf-8",
)
try:
fps = float(request.GET.get("fps", status["fps"]))
except (TypeError, ValueError):
fps = float(status["fps"])
response = StreamingHttpResponse(
video_service.iter_mjpeg(fps=fps),
content_type="multipart/x-mixed-replace; boundary=frame",
)
response["Cache-Control"] = "no-store, no-cache, must-revalidate, max-age=0"
return response
@csrf_exempt
@api_view(["POST"])
def video_display_probe(request):
try:
payload = json.loads(request.body.decode("utf-8"))
except (UnicodeDecodeError, json.JSONDecodeError):
return Response({"detail": "invalid json"}, status=400)
if not isinstance(payload, dict):
return Response({"detail": "expected json object"}, status=400)
video_service.record_display_probe(payload)
return Response({"ok": True})