.. SPDX-License-Identifier: GPL-3.0-or-later Signage device API ================== 1. Activate a signage device (public, one-time activation code) --------------------------------------------------------------- The current Android signage device obtains an ``activation_code`` by scanning a QR code, then exchanges it for a long-lived device token through this endpoint. .. code:: bash POST /api/v1/signage/activate Content-Type: application/json Request body: - ``activation_code``: one-time activation code. - ``classroom_id``: classroom ID carried in the QR code; used for activation validation. - ``device_code``: device code generated locally by Android and uploaded to the backend to identify the physical device. If the classroom already has a recorded device code, this value must match it. - ``device_name``: optional device name. - ``app_version``: optional signage app version. - ``install_id``: optional device installation identifier. Response: .. code:: json { "code": 0, "message": "success", "data": { "token": "device_token_here", "device": { "id": 1, "device_code": "8d0e1cb5-6f74-4d95-b861-3a0c2af18413", "device_label": "5A203 Signage", "building": "5A", "room_number": "203", "capacity": 60, "status": "available", "signage_title": "5A203", "signage_subtitle": "Digital Signage", "signage_config": { "announcements": [ { "label": "Notice", "text": "Please keep the classroom clean.", "type": "warn" } ] }, "activated_at": "2026-04-08T10:00:00+08:00", "token_issued_at": "2026-04-08T10:00:00+08:00", "last_seen_at": "2026-04-08T10:05:00+08:00", "activation_code_issued_at": null, "activation_code_expires_at": null, "is_bound": true } } } Notes: - Activation codes are single-use and have an expiration time. - The backend stores only the token hash. The plaintext token is returned only once, after successful activation. - Devices must use ``Authorization: Bearer `` to access signage APIs afterward. 2. Current signage device information (device authentication) ------------------------------------------------------------- .. code:: bash GET /api/v1/signage/device Authorization: Bearer Returns the signage configuration for the classroom bound to the current token. The signage device does not need to pass ``classroom_id``. Response: .. code:: json { "code": 0, "message": "success", "data": { "id": 1, "device_code": "SIG-ABC123456789", "device_label": "5A203 Signage", "building": "5A", "room_number": "203", "capacity": 60, "status": "available", "signage_title": "5A203", "signage_subtitle": "Digital Signage", "signage_config": { "announcements": [ { "label": "Info", "text": "Device is connected.", "type": "info" } ] }, "activated_at": "2026-04-08T10:00:00+08:00", "token_issued_at": "2026-04-08T10:00:00+08:00", "last_seen_at": "2026-04-08T10:05:00+08:00", "activation_code_issued_at": null, "activation_code_expires_at": null, "is_bound": true } } 3. Current signage device schedule (device authentication) ---------------------------------------------------------- .. code:: bash GET /api/v1/signage/device/schedule Authorization: Bearer Query: - ``start_date`` (``YYYY-MM-DD``) - ``end_date`` (``YYYY-MM-DD``) Response: .. code:: json { "code": 0, "message": "success", "data": { "items": [ { "start_time": "2026-02-04T08:00:00+08:00", "end_time": "2026-02-04T09:40:00+08:00", "course_id": 12, "course_name": "Calculus", "course_code": "MATH101", "teacher_name": "John Smith", "class_name": "CS 2024", "sections": [1, 2], "source": "course_occurrence" } ] } } Notes: - The backend resolves ``SignageDevice.classroom_id`` from the device token. - The current signage device displays only schedules generated by the course system and does not merge manual borrowings. 4. Generate signage binding QR code data (admin) ------------------------------------------------ .. code:: bash POST /api/v1/signage/classrooms/{id}/activation-code Authorization: Bearer Content-Type: application/json Request body (optional): - ``expires_in_minutes``: activation-code validity period in minutes. Default: 10 minutes. Response: .. code:: json { "code": 0, "message": "success", "data": { "activation_code": "ACT-ABC123456789", "expires_at": "2026-04-08T10:10:00+08:00", "qr_payload": { "base_url": "https://example.com/api/v1/", "classroom_id": 1, "activation_code": "ACT-ABC123456789" } } } Notes: - The current implementation generates a one-time ``activation_code``. A long-lived device token is issued only after the signage device scans the code and activates successfully. - Android signage devices generate and persist ``device_code`` locally, then upload it to the backend during activation. - If a classroom has already been bound to a device and the backend has recorded ``device_code``, later activations with a different uploaded ``device_code`` are rejected. - Android signage devices remain compatible with the old QR-code payload that directly binds a ``token``, but the admin side generates the ``activation_code`` payload by default. 5. Admin-side signage configuration APIs (admin) ------------------------------------------------ The following endpoints let the admin side view or control the signage device for a classroom: .. code:: bash GET /api/v1/signage/classrooms/{id} GET /api/v1/signage/classrooms/{id}/schedule PATCH /api/v1/signage/classrooms/{id}/config POST /api/v1/signage/classrooms/{id}/revoke-token Example body for ``PATCH /api/v1/signage/classrooms/{id}/config``: .. code:: json { "device_label": "5A203 Signage", "signage_title": "5A203", "signage_subtitle": "Welcome to Smart Signage", "announcements": [ { "label": "Notice", "text": "Please keep the classroom clean.", "type": "info" } ] } Important notes: - These are admin-side APIs, not public signage-device APIs. - Current Android signage devices should not directly call ``/signage/classrooms/{id}`` or its ``/schedule`` and ``/config`` endpoints. - After ``revoke-token`` is executed, the old token for the bound device becomes invalid immediately, and the device must scan a QR code again to bind.