diff --git a/mcserver/views.py b/mcserver/views.py index fcc7556..ff1d820 100644 --- a/mcserver/views.py +++ b/mcserver/views.py @@ -91,6 +91,28 @@ sys.path.insert(0, '/code/mobilecap') +def _normalize_device_id(device_id): + return str(device_id).replace('-', '').upper() + +def _get_or_assign_phone_label(session, device_id): + if not device_id: + return None + + if not session.meta: + session.meta = {} + + camera_map = session.meta.setdefault("camera_map", {}) + normalized_device_id = _normalize_device_id(device_id) + if normalized_device_id not in camera_map: + phone_number = len(camera_map) + 1 + camera_map[normalized_device_id] = { + "phone_label": "Phone {}".format(phone_number), + "camera_label": "Cam{}".format(phone_number - 1), + } + session.save(update_fields=["meta"]) + + return camera_map[normalized_device_id] + class IsOwner(permissions.BasePermission): def has_permission(self, request, view): if not request.user.is_authenticated: @@ -865,6 +887,8 @@ def get_status(self, request, pk): trials = session.trial_set.order_by("-created_at") trial = None + device_id = request.GET.get("device_id") + phone_label = _get_or_assign_phone_label(session, device_id) status = "ready" # if no trials then "ready" (equivalent to trial_status = done) @@ -899,10 +923,10 @@ def get_status(self, request, pk): status = 'ready' # If status 'recording' and 'device_id' provided - if trial and trial.status == "recording" and "device_id" in request.GET: - if trial.video_set.filter(device_id=request.GET["device_id"]).count() == 0: + if trial and trial.status == "recording" and device_id: + if trial.video_set.filter(device_id=device_id).count() == 0: video = Video() - video.device_id = request.GET["device_id"] + video.device_id = device_id video.isLidar = str(request.GET.get("usingLidar", "")).lower() == "true" video.trial = trial video.save() @@ -922,8 +946,8 @@ def get_status(self, request, pk): n_cameras_using_lidar = trial.video_set.filter(isLidar=True).count() if trial else 0 video_url = None - if trial and trial.status == "recording" and "device_id" in request.GET: - videos = trial.video_set.filter(device_id=request.GET["device_id"]) + if trial and trial.status == "recording" and device_id: + videos = trial.video_set.filter(device_id=device_id) if videos.count() > 0: video_url = reverse('video-detail', kwargs={'pk': videos[0].id}) trial_url = reverse('trial-detail', kwargs={'pk': trial.id}) if trial else None @@ -959,6 +983,9 @@ def get_status(self, request, pk): if "device_id" not in request.GET: res["n_cameras_using_lidar"] = n_cameras_using_lidar + if phone_label: + res.update(phone_label) + if "ret_session" in request.GET: res["session"] = SessionSerializer(session, many=False).data diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 3ebfc63..27ece71 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -1,4 +1,5 @@ import tempfile +import uuid import zipfile from unittest import mock from django.contrib.auth.models import Group @@ -382,6 +383,26 @@ def test_status(self): resp = self.client.get(url) self.assertEqual(resp.status_code, 200) + def test_status_assigns_stable_phone_labels(self): + self._setup_session(public=False) + self.client.force_authenticate(user=self.owner) + first_device = str(uuid.uuid4()) + second_device = str(uuid.uuid4()) + + first_resp = self.client.get( + f'/sessions/{self.session.pk}/status/?device_id={first_device}') + second_resp = self.client.get( + f'/sessions/{self.session.pk}/status/?device_id={second_device}') + first_again_resp = self.client.get( + f'/sessions/{self.session.pk}/status/?device_id={first_device}') + + self.assertEqual(first_resp.data["phone_label"], "Phone 1") + self.assertEqual(first_resp.data["camera_label"], "Cam0") + self.assertEqual(second_resp.data["phone_label"], "Phone 2") + self.assertEqual(second_resp.data["camera_label"], "Cam1") + self.assertEqual(first_again_resp.data["phone_label"], "Phone 1") + self.assertEqual(first_again_resp.data["camera_label"], "Cam0") + def test_record(self): for public in [False, True]: self._setup_session(public)