- 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
95 lines
3.2 KiB
Markdown
95 lines
3.2 KiB
Markdown
# 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
|