Initial import: clean snapshot from /home/olafn/infoscreen-dev (2025-10-25)

This commit is contained in:
RobbStarkAustria
2025-10-25 17:42:27 +02:00
commit 8ca9f69f6f
111 changed files with 8612 additions and 0 deletions

457
src/DISPLAY_MANAGER.md Normal file
View File

@@ -0,0 +1,457 @@
# 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)
```json
{
"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
```json
{
"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
```json
{
"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:**
```bash
# 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
```
2. **Start Display Manager:**
```bash
./scripts/start-display-manager.sh
```
### Production Setup (Systemd Service)
1. **Copy systemd service file:**
```bash
sudo cp scripts/infoscreen-display.service /etc/systemd/system/
sudo systemctl daemon-reload
```
2. **Enable and start service:**
```bash
sudo systemctl enable infoscreen-display.service
sudo systemctl start infoscreen-display.service
```
3. **Check status:**
```bash
sudo systemctl status infoscreen-display.service
sudo journalctl -u infoscreen-display.service -f
```
## Configuration
Configure via `.env` file:
```bash
# 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:**
```bash
./scripts/start-display-manager.sh
```
**Production (systemd):**
```bash
sudo systemctl start infoscreen-display.service
```
### Testing
Run the interactive test script:
```bash
./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:
```bash
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:
```bash
rm src/current_event.json
```
Or create an empty event:
```bash
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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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**:
```bash
# 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.