feat(mqtt): finalize dashboard screenshot payload v2 and trigger flow
- switch dashboard payload to grouped schema v2.0 in simclient - support immediate event-triggered screenshot sends via meta.json signaling - update README and copilot instructions to document v2 payload and trigger behavior - update migration checklist to reflect completed client/server rollout
This commit is contained in:
51
.github/copilot-instructions.md
vendored
51
.github/copilot-instructions.md
vendored
@@ -12,6 +12,9 @@
|
||||
- ✅ **Keep screenshot consent notice in docs** when describing dashboard screenshot feature
|
||||
- ✅ **Event-start/event-stop screenshots must preserve metadata** - See SCREENSHOT_MQTT_FIX.md for critical race condition that was fixed
|
||||
- ✅ **Screenshot updates must keep `latest.jpg` and `meta.json` in sync** (simclient prefers `latest.jpg`)
|
||||
- ✅ **Dashboard payload uses grouped v2 schema** (`message/content/runtime/metadata`, `schema_version="2.0"`)
|
||||
- ✅ **Event-triggered screenshots**: `display_manager` arms a `threading.Timer` after start/stop, captures, writes `meta.json` with `send_immediately=true`; simclient fires within ≤1s
|
||||
- ✅ **Payload assembly is centralized** in `_build_dashboard_payload()` — do not build dashboard JSON at call sites
|
||||
|
||||
### Key Files & Locations
|
||||
- **Display logic**: `src/display_manager.py` (controls presentations/video/web)
|
||||
@@ -488,31 +491,49 @@ The screenshot capture and transmission system has been implemented with separat
|
||||
- **Rotation**: Keeps max N files (default 20), deletes older
|
||||
- **Timing**: Production captures when display process is active (unless `SCREENSHOT_ALWAYS=1`); development allows periodic idle captures to keep dashboard fresh
|
||||
- **Reliability**: Stale/invalid pending trigger metadata is ignored automatically to avoid lock-up of periodic updates
|
||||
- **Event-triggered captures**: `_trigger_event_screenshot(type, delay)` arms a one-shot `threading.Timer` after event start/stop; timer is cancelled and replaced on rapid event switches; default delays: presentation=4s, video=2s, web=5s (env-configurable)
|
||||
- **IPC signal file** (`screenshots/meta.json`): written atomically by `display_manager` after each capture; contains `type`, `captured_at`, `file`, `send_immediately`; `send_immediately=true` for event-triggered, `false` for periodic
|
||||
|
||||
### Transmission Strategy (simclient.py)
|
||||
- **Source**: Prefers `screenshots/latest.jpg` if present, falls back to newest timestamped file
|
||||
- **Topic**: `infoscreen/{client_id}/dashboard`
|
||||
- **Format**: JSON with base64-encoded image data
|
||||
- **Payload Structure**:
|
||||
- **Format**: JSON with base64-encoded image data, grouped v2 schema
|
||||
- **Schema version**: `"2.0"` (legacy flat fields removed; all fields grouped)
|
||||
- **Payload builder**: `_build_dashboard_payload()` in `simclient.py` — single source of truth
|
||||
- **Payload Structure** (v2):
|
||||
```json
|
||||
{
|
||||
"timestamp": "ISO datetime",
|
||||
"client_id": "UUID",
|
||||
"status": "alive",
|
||||
"screenshot": {
|
||||
"filename": "latest.jpg",
|
||||
"data": "base64...",
|
||||
"timestamp": "ISO datetime",
|
||||
"size": 12345
|
||||
"message": { "client_id": "UUID", "status": "alive" },
|
||||
"content": {
|
||||
"screenshot": {
|
||||
"filename": "latest.jpg",
|
||||
"data": "base64...",
|
||||
"timestamp": "ISO datetime",
|
||||
"size": 12345
|
||||
}
|
||||
},
|
||||
"system_info": {
|
||||
"hostname": "...",
|
||||
"ip": "...",
|
||||
"uptime": 123456.78
|
||||
"runtime": {
|
||||
"system_info": { "hostname": "...", "ip": "...", "uptime": 123456.78 },
|
||||
"process_health": { "event_type": "...", "process_status": "...", ... }
|
||||
},
|
||||
"metadata": {
|
||||
"schema_version": "2.0",
|
||||
"producer": "simclient",
|
||||
"published_at": "ISO datetime",
|
||||
"capture": {
|
||||
"type": "periodic | event_start | event_stop",
|
||||
"captured_at": "ISO datetime",
|
||||
"age_s": 0.9,
|
||||
"triggered": false,
|
||||
"send_immediately": false
|
||||
},
|
||||
"transport": { "topic": "infoscreen/.../dashboard", "qos": 0, "publisher": "simclient" }
|
||||
}
|
||||
}
|
||||
```
|
||||
- **Logging**: Logs publish success/failure with file size for monitoring
|
||||
- **Capture types**: `periodic` (interval-based), `event_start` (N seconds after event launch), `event_stop` (1s after process killed)
|
||||
- **Triggered send**: `display_manager` sets `send_immediately=true` in `meta.json`; simclient 1-second tick detects and fires within ≤1s
|
||||
- **Logging**: `Dashboard published: schema=2.0 type=<type> screenshot=<file> (<bytes>) age=<s>`
|
||||
|
||||
### Scalability Considerations
|
||||
- **Client-side resize/compress**: Reduces bandwidth and broker load (recommended for 50+ clients)
|
||||
|
||||
Reference in New Issue
Block a user