Files
infoscreen-dev/src/DISPLAY_MANAGER.md

12 KiB

Display Manager - Event Display Controller

Overview

The Display Manager is a daemon process that monitors current_event.json and automatically controls display software (LibreOffice, Chromium, VLC) to show the appropriate content based on scheduled events.

Architecture

MQTT Server → simclient.py → current_event.json → display_manager.py → Display Software
                                                                        ├─ LibreOffice (presentations)
                                                                        ├─ Chromium (web pages)
                                                                        └─ VLC/MPV (videos)

How It Works

  1. Event Reception: simclient.py receives events via MQTT and writes them to current_event.json
  2. File Monitoring: display_manager.py continuously monitors this file for changes
  3. Event Processing: When changes detected, manager determines what to display
  4. Time-based Activation: Respects event start and end times
  5. Process Management: Starts appropriate display software and manages its lifecycle
  6. Clean Transitions: Gracefully terminates old software before starting new

Supported Event Types

⚠️ Important: Timestamps are in UTC

All event start and end times must be in UTC format (as stored in the server database). The Display Manager automatically converts these to the local timezone for comparison.

Example format: "2025-10-01 08:00:00" (interpreted as UTC)

1. Presentation Events (PowerPoint/PDF)

{
  "id": 1,
  "title": "Company Overview",
  "start": "2025-10-01 08:00:00",
  "end": "2025-10-01 18:00:00",
  "presentation": {
    "type": "slideshow",
    "files": [
      {
        "name": "presentation.pptx",
        "url": "http://server/files/presentation.pptx"
      }
    ],
    "slide_interval": 10,
    "auto_advance": true
  }
}

Supported Formats:

  • .pptx, .ppt (Microsoft PowerPoint) → LibreOffice Impress
  • .odp (OpenDocument Presentation) → LibreOffice Impress
  • .pdf (PDF documents) → Evince or Okular

Display Behavior:

  • Fullscreen/presentation mode
  • Auto-advance slides (if supported by viewer)
  • Loops through presentation continuously

2. Web Page Events

{
  "id": 2,
  "title": "Dashboard Display",
  "start": "2025-10-01 08:00:00",
  "end": "2025-10-01 18:00:00",
  "web": {
    "url": "https://dashboard.example.com"
  }
}

Display Behavior:

  • Kiosk mode (fullscreen, no UI)
  • Uses Chromium/Chrome browser
  • Disables session restore and crash bubbles

3. Video Events

{
  "id": 3,
  "title": "Promotional Video",
  "start": "2025-10-01 08:00:00",
  "end": "2025-10-01 18:00:00",
  "video": {
    "url": "http://server/videos/promo.mp4",
    "loop": true
  }
}

Supported Formats:

  • Local files or HTTP URLs
  • All formats supported by VLC/MPV (mp4, avi, mkv, etc.)

Display Behavior:

  • Fullscreen playback
  • Optional looping
  • Uses VLC or MPV player

Installation & Setup

Development Setup

  1. Install dependencies:
# Already in requirements.txt, but ensure these system packages are installed:
sudo apt-get update
sudo apt-get install -y \
    libreoffice-impress \
    chromium-browser \
    vlc \
    evince
  1. Start Display Manager:
./scripts/start-display-manager.sh

Production Setup (Systemd Service)

  1. Copy systemd service file:
sudo cp scripts/infoscreen-display.service /etc/systemd/system/
sudo systemctl daemon-reload
  1. Enable and start service:
sudo systemctl enable infoscreen-display.service
sudo systemctl start infoscreen-display.service
  1. Check status:
sudo systemctl status infoscreen-display.service
sudo journalctl -u infoscreen-display.service -f

Configuration

Configure via .env file:

# Display Manager Settings
DISPLAY_CHECK_INTERVAL=5          # How often to check for event changes (seconds)
LOG_LEVEL=INFO                    # Logging level (DEBUG, INFO, WARNING, ERROR)
ENV=production                    # Environment (development, production)

# Display environment
DISPLAY=:0                        # X11 display (usually :0)

Usage

Starting the Display Manager

Development:

./scripts/start-display-manager.sh

Production (systemd):

sudo systemctl start infoscreen-display.service

Testing

Run the interactive test script:

./scripts/test-display-manager.sh

Test menu options:

  1. Check Display Manager status
  2. Create PRESENTATION test event
  3. Create WEBPAGE test event
  4. Create VIDEO test event
  5. Remove event (no display)
  6. Check active display processes
  7. View current event file
  8. Interactive test (cycle through events)

Manual Testing

Create a test event file:

cat > src/current_event.json <<EOF
{
  "id": 999,
  "title": "Test Presentation",
  "start": "2025-01-01 00:00:00",
  "end": "2025-12-31 23:59:59",
  "presentation": {
    "files": [{"name": "test.pptx"}]
  }
}
EOF

Display Manager will detect the change within 5 seconds and start the presentation.

Stopping Display

Remove the event file:

rm src/current_event.json

Or create an empty event:

echo "{}" > src/current_event.json

Best Practices Implemented

1. Separation of Concerns

  • MQTT Client (simclient.py): Handles network communication
  • Display Manager (display_manager.py): Handles display control
  • Communication via file: current_event.json

2. Robust Process Management

  • Clean process lifecycle (start → monitor → terminate)
  • Graceful termination with fallback to force kill
  • Process health monitoring and automatic restart
  • PID tracking for debugging

3. Event State Machine

  • Clear states: NO_EVENT → EVENT_ACTIVE → DISPLAY_RUNNING
  • Proper state transitions
  • Event change detection via file modification time
  • Event deduplication (same event doesn't restart display)

4. Time-based Scheduling

  • Respects event start and end times
  • Automatically stops display when event expires
  • Handles timezone-aware timestamps

5. Application Lifecycle Management

Starting Applications:

  • Detects available software (LibreOffice, Chromium, VLC)
  • Uses appropriate command-line flags for kiosk/fullscreen
  • Sets correct environment variables (DISPLAY, XAUTHORITY)

Stopping Applications:

  • First attempts graceful termination (SIGTERM)
  • Waits 5 seconds for clean shutdown
  • Falls back to force kill (SIGKILL) if needed
  • Cleans up zombie processes

6. Error Handling & Logging

  • Comprehensive error logging with context
  • Rotating log files (2MB per file, 5 backups)
  • Different log levels for development/production
  • Exception handling around all external operations

7. File Watching Strategy

  • Efficient: Only re-reads when file changes (mtime check)
  • Handles missing files gracefully
  • JSON parsing with error recovery
  • Non-blocking I/O

8. Graceful Shutdown

  • Signal handlers (SIGTERM, SIGINT)
  • Stops current display before exiting
  • Clean resource cleanup

9. Development Experience

  • Test scripts for all functionality
  • Interactive testing mode
  • Verbose logging in development
  • Easy manual testing

10. Production Readiness

  • Systemd service integration
  • Auto-restart on failure
  • Resource limits and security settings
  • Journal logging

Troubleshooting

Display Manager not starting

# Check logs
tail -f logs/display_manager.log

# Check if virtual environment activated
source venv/bin/activate

# Verify Python can import required modules
python3 -c "import paho.mqtt.client; print('OK')"

Display software not appearing

# Check DISPLAY variable
echo $DISPLAY

# Verify X11 authentication
xhost +local:

# Check if software is installed
which libreoffice chromium-browser vlc

# Check running processes
ps aux | grep -E 'libreoffice|chromium|vlc'

Events not triggering display changes

# Verify event file exists and is valid JSON
cat src/current_event.json | jq .

# Check file modification time
stat src/current_event.json

# Check Display Manager is running
pgrep -f display_manager.py

# Watch logs in real-time
tail -f logs/display_manager.log

Display software crashes

# Check for error messages
journalctl -xe | grep -E 'libreoffice|chromium|vlc'

# Verify files exist
ls -la src/presentation/

# Test manual start
libreoffice --impress --show src/presentation/test.pptx

Timezone / Event timing issues

Problem: Events not displaying at the expected time

Cause: Event times are in UTC, but you're thinking in local time

Solution:

# Check current UTC time
date -u

# Check current local time
date

# Check timezone offset
date +%Z
date +%z

# Test with UTC timestamp script
./scripts/test-utc-timestamps.sh

# View Display Manager timezone info in logs
tail -f logs/display_manager.log | grep -i "time\|utc"

Understanding UTC timestamps:

  • Server stores times in UTC (database standard)
  • Display Manager compares with current UTC time
  • Events display correctly regardless of client timezone

Example:

  • Event start: 2025-10-01 08:00:00 (UTC)
  • Your timezone: CEST (UTC+2)
  • Event will display at: 10:00:00 local time

Debugging timing issues:

  1. Check Display Manager logs for time comparisons
  2. Logs show: "Current time (UTC): ..." and "Event start time (UTC): ..."
  3. Use test script: ./scripts/test-utc-timestamps.sh
  4. Verify server sends UTC timestamps (not local times)

Architecture Decisions

Why separate processes?

  • Fault isolation: Display crash doesn't affect MQTT client
  • Independent lifecycle: Can restart display without losing connection
  • Simpler debugging: Separate logs and process monitoring

Why file-based communication?

  • Simplicity: No IPC complexity (sockets, pipes, queues)
  • Persistence: Event survives process restarts
  • Debuggability: Can inspect/modify events manually
  • Atomic operations: File writes are atomic

Why polling instead of inotify?

  • Portability: Works on all systems
  • Simplicity: No external dependencies
  • Reliability: Catches events even if filesystem events missed
  • Performance: 5-second interval is sufficient

Why subprocess instead of libraries?

  • Flexibility: Can use any display software
  • Reliability: Process isolation
  • Feature completeness: Full application features (vs. library subset)
  • Maintainability: No need to update when apps change

Performance Characteristics

  • CPU Usage: Minimal when idle (<1%)
  • Memory: ~20-30MB for manager + display software memory
  • Startup Time: <1 second
  • Event Detection: ~5 seconds average, max 5 seconds
  • Display Transition: 1-3 seconds for clean shutdown + start

Future Enhancements

Potential improvements:

  1. Multi-display support: Handle multiple screens
  2. Playlist support: Cycle through multiple presentations
  3. Transition effects: Fade between content
  4. Health checks: Verify display is rendering correctly
  5. Remote control: MQTT commands to pause/resume
  6. Screenshot monitoring: Send actual display output to server
  7. Performance metrics: Track frame rates, response times
  8. Fallback content: Default display when no events active

Integration with MQTT Client

The Display Manager integrates seamlessly with simclient.py:

Server MQTT → simclient.py → current_event.json → display_manager.py → Screen
                    ↓
              Downloads files
              to presentation/

simclient.py responsibilities:

  • MQTT communication
  • Event file downloads
  • Writing current_event.json

display_manager.py responsibilities:

  • Reading current_event.json
  • Time-based event activation
  • Display software control

License & Support

Part of the Infoscreen Client 2025 project. See main README.md for license and contribution guidelines.