.. SPDX-License-Identifier: GPL-3.0-or-later =============== Signage Devices =============== Author: Zhenyu Yang Last updated: Apr 24, 2026 Corresponding API docs: `Signage Device API <../../api/signage.rst>`__ ``signage`` Code Entry ---------------------- - ``backend/apps/signage/models/__init__.py`` - ``backend/apps/signage/views/__init__.py`` - ``backend/apps/signage/serializers/__init__.py`` - ``backend/apps/signage/authentication.py`` - ``backend/apps/signage/tokens.py`` ``signage`` Core Data --------------------- ``SignageDevice`` ~~~~~~~~~~~~~~~~~ - One-to-one with ``Classroom``. - Key fields: - ``device_code`` - ``device_label`` - ``signage_title`` - ``signage_subtitle`` - ``signage_config`` - ``device_token_hash`` - ``activation_code_hash`` - ``token_issued_at`` - ``activated_at`` - ``last_seen_at`` The backend only stores hashes of the activation code and device token; plaintext values are never persisted. Two Interface Surfaces ---------------------- Device Side ~~~~~~~~~~~ - ``POST /signage/activate`` - ``GET /signage/device`` - ``GET /signage/device/schedule`` The device side exclusively uses ``Authorization: Bearer ``; it does not use user JWTs. Admin Side ~~~~~~~~~~ - ``GET /signage/classrooms/`` - ``GET /signage/classrooms//schedule`` - ``PATCH /signage/classrooms//config`` - ``POST /signage/classrooms//activation-code`` - ``POST /signage/classrooms//revoke-token`` The admin side requires standard user authentication, and the current implementation only allows ``superadmin``. Activation Flow --------------- 1. The admin side issues a one-time ``activation_code`` for a classroom. 2. The Android signage device scans the QR code to obtain the ``classroom_id`` and ``activation_code``. 3. The device calls ``POST /signage/activate``. 4. The backend validates: - The activation code exists and has not expired. - The classroom matches. - If the device already has a bound ``device_code``, it must match. - The ``device_code`` must not conflict with another classroom’s device. 5. On success, a long-lived device token is issued and the one-time activation code is cleared. Schedule Source --------------- - Signage schedules read only from ``CourseOccurrence``. - Manual reservations are not merged. - The returned structure includes course name, course number, teacher name, class, class period, and time range. Configuration ------------- - Configurable fields: - ``device_label`` - ``signage_title`` - ``signage_subtitle`` - ``announcements`` - ``announcements`` are written to ``signage_config["announcements"]``. Current Boundaries ------------------ - Signage already has independent device authentication and an activation lifecycle. - Currently, signage is a display-only terminal; it does not write check-in records or call ``face-service``.