Add end-to-end support for video events: server streaming, scheduler metadata, API fields, and dashboard UI. - Server: range-capable streaming endpoint with byte-range support. - Scheduler: emits `video` object; best-effort HEAD probe adds `mime_type`, `size`, `accept_ranges`; placeholders for richer metadata (duration/resolution/bitrate/qualities/thumbnails). - API/DB: accept and persist `event_media_id`, `autoplay`, `loop`, `volume` for video events. - Frontend: Event modal supports video selection + playback options; FileManager increased upload size and client-side duration check (max 10 minutes). - Docs/UX: bumped program-info, added UX-only changelog and updated Copilot instructions for contributors. - Notes: metadata extraction (ffprobe), checksum persistence, and HLS/DASH transcoding are recommended follow-ups (separate changes).
8.5 KiB
MQTT Event Payload Guide
Overview
This document describes the MQTT message structure used by the Infoscreen system to deliver event information from the scheduler to display clients. It covers best practices, payload formats, and versioning strategies.
MQTT Topics
Event Distribution
- Topic:
infoscreen/events/{group_id} - Retained: Yes
- Format: JSON array of event objects
- Purpose: Delivers active events to client groups
Per-Client Configuration
- Topic:
infoscreen/{uuid}/group_id - Retained: Yes
- Format: Integer (group ID)
- Purpose: Assigns clients to groups
Message Structure
General Principles
- Type Safety: Always include
event_typeto allow clients to parse appropriately - Backward Compatibility: Add new fields without removing old ones
- Extensibility: Use nested objects for event-type-specific data
- UTC Timestamps: All times in ISO 8601 format with timezone info
Base Event Structure
Every event includes these common fields:
{
"id": 123,
"title": "Event Title",
"start": "2025-10-19T09:00:00+00:00",
"end": "2025-10-19T09:30:00+00:00",
"group_id": 1,
"event_type": "presentation|website|webuntis|video|message|other",
"recurrence_rule": "FREQ=WEEKLY;BYDAY=MO,WE,FR" or null,
"recurrence_end": "2025-12-31T23:59:59+00:00" or null
}
Event Type-Specific Payloads
Presentation Events
{
"id": 123,
"event_type": "presentation",
"title": "Morning Announcements",
"start": "2025-10-19T09:00:00+00:00",
"end": "2025-10-19T09:30:00+00:00",
"group_id": 1,
"presentation": {
"type": "slideshow",
"files": [
{
"name": "slides.pdf",
"url": "http://server:8000/api/files/converted/abc123.pdf",
"checksum": null,
"size": null
}
],
"slide_interval": 10000,
"auto_advance": true,
"page_progress": true,
"auto_progress": true
}
}
Fields:
type: Always "slideshow" for presentationsfiles: Array of file objects with download URLsslide_interval: Milliseconds between slides (default: 5000)auto_advance: Whether to automatically advance slidespage_progress: Show page number indicatorauto_progress: Enable automatic progression
Website Events
{
"id": 124,
"event_type": "website",
"title": "School Website",
"start": "2025-10-19T09:00:00+00:00",
"end": "2025-10-19T09:30:00+00:00",
"group_id": 1,
"website": {
"type": "browser",
"url": "https://example.com/page"
}
}
Fields:
type: Always "browser" for website displayurl: Full URL to display in embedded browser
WebUntis Events
{
"id": 125,
"event_type": "webuntis",
"title": "Schedule Display",
"start": "2025-10-19T09:00:00+00:00",
"end": "2025-10-19T09:30:00+00:00",
"group_id": 1,
"website": {
"type": "browser",
"url": "https://webuntis.example.com/schedule"
}
}
Note: WebUntis events use the same payload structure as website events. The URL is fetched from system settings (webuntis_url) rather than being specified per-event. Clients treat webuntis and website event types identically—both display a website.
Video Events
{
"id": 126,
"event_type": "video",
"title": "Video Playback",
"start": "2025-10-19T09:00:00+00:00",
"end": "2025-10-19T09:30:00+00:00",
"group_id": 1,
"video": {
"type": "media",
"url": "http://server:8000/api/eventmedia/stream/123/video.mp4",
"autoplay": true,
"loop": false,
"volume": 0.8
}
}
Fields:
type: Always "media" for video playbackurl: Video streaming URL with range request supportautoplay: Whether to start playing automatically (default: true)loop: Whether to loop the video (default: false)volume: Playback volume from 0.0 to 1.0 (default: 0.8)
Message Events (Future)
{
"id": 127,
"event_type": "message",
"title": "Important Announcement",
"start": "2025-10-19T09:00:00+00:00",
"end": "2025-10-19T09:30:00+00:00",
"group_id": 1,
"message": {
"type": "html",
"content": "<h1>Important</h1><p>Message content</p>",
"style": "default"
}
}
Best Practices
1. Type-Based Parsing
Clients should:
- Read the
event_typefield first - Switch/dispatch based on type
- Parse type-specific nested objects (
presentation,website, etc.)
// Example client parsing
function parseEvent(event) {
switch (event.event_type) {
case 'presentation':
return handlePresentation(event.presentation);
case 'website':
case 'webuntis':
return handleWebsite(event.website);
case 'video':
return handleVideo(event.video);
// ...
}
}
2. Graceful Degradation
- Always provide fallback values for optional fields
- Validate URLs before attempting to load
- Handle missing or malformed data gracefully
3. Performance Optimization
- Cache downloaded presentation files
- Use checksums to avoid re-downloading unchanged content
- Preload resources before event start time
4. Time Handling
- Always parse ISO 8601 timestamps with timezone awareness
- Compare event start/end times in UTC
- Account for clock drift on embedded devices
5. Error Recovery
- Retry failed downloads with exponential backoff
- Log errors but continue operation
- Display fallback content if event data is invalid
Message Flow
- Scheduler queries active events from database
- Scheduler formats events with type-specific payloads
- Scheduler publishes JSON array to
infoscreen/events/{group_id}(retained) - Client receives retained message on connect
- Client parses events and schedules display
- Client downloads resources (presentations, etc.)
- Client displays events at scheduled times
Versioning Strategy
Adding New Event Types
- Add enum value to
EventTypeinmodels/models.py - Update scheduler's
format_event_with_media()inscheduler/db_utils.py - Update events API in
server/routes/events.py - Add icon mapping in
get_icon_for_type() - Document payload structure in this guide
Adding Fields to Existing Types
- Safe: Add new optional fields to nested objects
- Unsafe: Remove or rename existing fields
- Migration: Provide both old and new field names during transition
Example: Adding a New Field
{
"event_type": "presentation",
"presentation": {
"type": "slideshow",
"files": [...],
"slide_interval": 10000,
"transition_effect": "fade" // NEW FIELD (optional)
}
}
Old clients ignore unknown fields; new clients use enhanced features.
Common Pitfalls
- Hardcoding Event Types: Use
event_typefield, not assumptions - Timezone Confusion: Always use UTC internally
- Missing Error Handling: Network failures, malformed URLs, etc.
- Resource Leaks: Clean up downloaded files periodically
- Not Handling Recurrence: Events may repeat; check
recurrence_rule
System Settings Integration
Some event types rely on system-wide settings rather than per-event configuration:
WebUntis / Supplement Table URL
- Setting Key:
supplement_table_url - API Endpoint:
GET/POST /api/system-settings/supplement-table - Usage: Automatically applied when creating
webuntisevents - Default: Empty string (must be configured by admin)
- Description: This URL is shared for both Vertretungsplan (supplement table) and WebUntis displays
Presentation Defaults
presentation_interval: Default slide interval (seconds)presentation_page_progress: Show page indicators by defaultpresentation_auto_progress: Auto-advance by default
These are applied when creating new events but can be overridden per-event.
Testing Recommendations
- Unit Tests: Validate payload serialization/deserialization
- Integration Tests: Full scheduler → MQTT → client flow
- Edge Cases: Empty event lists, missing URLs, malformed data
- Performance Tests: Large file downloads, many events
- Time Tests: Events across midnight, timezone boundaries, DST
Related Documentation
AUTH_SYSTEM.md- Authentication and authorizationDATABASE_GUIDE.md- Database schema and models.github/copilot-instructions.md- System architecture overviewscheduler/scheduler.py- Event publishing implementationscheduler/db_utils.py- Event formatting logic
Changelog
- 2025-10-19: Initial documentation
- Documented base event structure
- Added presentation and website/webuntis payload formats
- Established best practices and versioning strategy