- 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
3.2 KiB
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
- JSON:
- Storage:
- Saves to
server/screenshots/{uuid}_{timestamp}.jpg(with timestamp) - Saves to
server/screenshots/{uuid}.jpg(latest, for quick retrieval)
- Saves to
3. Retrieval (server/wsgi.py)
- Endpoint:
GET /screenshots/<uuid> - Returns: Latest screenshot for the given client UUID
- Nginx: Exposes
/screenshots/{uuid}.jpgin production
Unified Identification Method
Screenshots are identified by client UUID:
- Each client has a unique UUID stored in the
clientstable - 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.0tolistener/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