Files
infoscreen/SCREENSHOT_IMPLEMENTATION.md
RobbStarkAustria c193209326 feat: dashboard screenshot upload & retention (last 20 per client)
- Listener: subscribe to dashboard topic, forward screenshots to API
- API: store latest + last 20 timestamped screenshots per client, auto-delete older files
- Docs: updated README, TECH-CHANGELOG, and copilot-instructions for screenshot upload and retention policy
2025-11-30 13:38:07 +00:00

3.2 KiB

Screenshot Transmission Implementation

Overview

Clients send screenshots via MQTT during heartbeat intervals. The listener service receives these screenshots and forwards them to the server API for storage.

Architecture

MQTT Topic

  • Topic: infoscreen/{uuid}/screenshot
  • Payload Format:
    • Raw binary image data (JPEG/PNG), OR
    • JSON with base64-encoded image: {"image": "<base64-string>"}

Components

1. Listener Service (listener/listener.py)

  • Subscribes to: infoscreen/+/screenshot
  • Function: handle_screenshot(uuid, payload)
    • Detects payload format (binary or JSON)
    • Converts binary to base64 if needed
    • Forwards to API via HTTP POST

2. Server API (server/routes/clients.py)

  • Endpoint: POST /api/clients/<uuid>/screenshot
  • Authentication: No authentication required (internal service call)
  • Accepts:
    • JSON: {"image": "<base64-encoded-image>"}
    • Binary: raw image data
  • Storage:
    • Saves to server/screenshots/{uuid}_{timestamp}.jpg (with timestamp)
    • Saves to server/screenshots/{uuid}.jpg (latest, for quick retrieval)

3. Retrieval (server/wsgi.py)

  • Endpoint: GET /screenshots/<uuid>
  • Returns: Latest screenshot for the given client UUID
  • Nginx: Exposes /screenshots/{uuid}.jpg in production

Unified Identification Method

Screenshots are identified by client UUID:

  • Each client has a unique UUID stored in the clients table
  • Screenshots are stored as {uuid}.jpg (latest) and {uuid}_{timestamp}.jpg (historical)
  • The API endpoint requires UUID validation against the database
  • Retrieval is done via GET /screenshots/<uuid> which returns the latest screenshot

Data Flow

Client → MQTT (infoscreen/{uuid}/screenshot)
    ↓
Listener Service
    ↓ (validates client exists)
    ↓ (converts binary → base64 if needed)
    ↓
API POST /api/clients/{uuid}/screenshot
    ↓ (validates client UUID)
    ↓ (decodes base64 → binary)
    ↓
Filesystem: server/screenshots/{uuid}.jpg
    ↓
Dashboard/Nginx: GET /screenshots/{uuid}

Configuration

Environment Variables

  • Listener: API_BASE_URL (default: http://server:8000)
  • Server: Screenshots stored in server/screenshots/ directory

Dependencies

  • Listener: Added requests>=2.31.0 to listener/requirements.txt
  • Server: Uses built-in Flask and base64 libraries

Error Handling

  • Client Not Found: Returns 404 if UUID doesn't exist in database
  • Invalid Payload: Returns 400 if image data is missing or invalid
  • API Timeout: Listener logs error and continues (timeout: 10s)
  • Network Errors: Listener logs and continues operation

Security Considerations

  • Screenshot endpoint does not require authentication (internal service-to-service)
  • Client UUID must exist in database before screenshot is accepted
  • Base64 encoding prevents binary data issues in JSON transport
  • File size is tracked and logged for monitoring

Future Enhancements

  • Add screenshot retention policy (auto-delete old timestamped files)
  • Add compression before transmission
  • Add screenshot quality settings
  • Add authentication between listener and API
  • Add screenshot history API endpoint