Older systemd (< 230, common on Pi OS Buster/Bullseye) rejects these keys in [Service] with 'Unknown key' warning and ignores them, meaning no restart rate-limiting was enforced. Also includes pi-setup.sh fix for hardcoded user/home from previous session.
Infoscreen Client
Digital signage client for Raspberry Pi that displays presentations, videos, and web content in kiosk mode. It is managed centrally via MQTT and includes HDMI-CEC TV control, screenshot-based dashboard monitoring, and process health reporting.
Dashboard screenshots can contain visible on-screen content. Keep that in mind when enabling or documenting remote monitoring.
Key Features
- Server-side PPTX to PDF rendering; client displays PDFs with Impressive.
- Presentation auto-advance, loop mode, and progress indicators.
- Video playback with
python-vlcwhen available and external VLC fallback. - Web and WebUntis display in kiosk mode.
- HDMI-CEC TV power control with local fallback and MQTT-coordinated power intent.
- MQTT discovery, heartbeat, group assignment, and event delivery.
- Screenshot dashboard with Wayland/X11 capture tool fallbacks.
- Process health bridge between
display_manager.pyandsimclient.py.
Quick Start
1. Install Dependencies
cd ~/
git clone <repository-url> infoscreen-dev
cd infoscreen-dev
sudo apt-get update
sudo apt-get install -y \
python3 python3-pip python3-venv \
impressive \
chromium-browser vlc \
cec-utils \
scrot imagemagick
# For Wayland systems:
# sudo apt-get install grim gnome-screenshot
python3 -m venv venv
source venv/bin/activate
pip install -r src/requirements.txt
2. Configure .env
Copy .env.template to .env and set at least:
ENV=production
DEBUG_MODE=0
LOG_LEVEL=INFO
MQTT_BROKER=192.168.1.100
MQTT_PORT=1883
MQTT_USER=<broker-username>
MQTT_PASSWORD_BROKER=<broker-password>
MQTT_USERNAME=infoscreen-client-<client-uuid-prefix>
MQTT_PASSWORD=<per-device-random-password>
MQTT_TLS_ENABLED=0
HEARTBEAT_INTERVAL=60
SCREENSHOT_INTERVAL=180
SCREENSHOT_CAPTURE_INTERVAL=180
DISPLAY_CHECK_INTERVAL=15
FILE_SERVER_HOST=
FILE_SERVER_PORT=8000
FILE_SERVER_SCHEME=http
CEC_ENABLED=true
CEC_DEVICE=0
CEC_TURN_OFF_DELAY=30
CEC_POWER_ON_WAIT=5
CEC_POWER_OFF_WAIT=5
POWER_CONTROL_MODE=local
COMMAND_HELPER_PATH=/usr/local/bin/infoscreen-cmd-helper.sh
COMMAND_EXEC_TIMEOUT_SEC=15
COMMAND_DEDUPE_TTL_HOURS=24
COMMAND_DEDUPE_MAX_ENTRIES=5000
COMMAND_MOCK_REBOOT_IMMEDIATE_COMPLETE=0
MQTT auth/TLS notes:
MQTT_USER/MQTT_PASSWORD_BROKERare the broker credentials used at connection time.MQTT_USERNAME/MQTT_PASSWORDare legacy per-device identity fields kept for fallback and identity purposes.- Store real broker credentials only in the local /.env, which is gitignored.
- When TLS is enabled, also set
MQTT_TLS_CA_CERT, and if client certificates are used,MQTT_TLS_CERTandMQTT_TLS_KEY. - Keep the local /.env readable only by the service user and admins, for example mode
600.
Mode summary:
POWER_CONTROL_MODE=local: local event-time CEC only.POWER_CONTROL_MODE=hybrid: prefer fresh MQTT intent, fallback to local timing.POWER_CONTROL_MODE=mqtt: MQTT intent authoritative, with safe fallback behavior.
3. Start Services
The preferred method on deployed devices is systemd:
sudo systemctl start infoscreen-simclient infoscreen-display
sudo systemctl status infoscreen-simclient infoscreen-display
sudo journalctl -u infoscreen-simclient -u infoscreen-display -f
For first-time setup, run src/pi-setup.sh to install and enable the units. See src/README.md for the systemd setup steps.
For local development without systemd:
# Terminal 1
./scripts/start-simclient.sh
# Terminal 2
./scripts/start-display-manager.sh
Runtime Model
The client runs as two cooperating processes:
src/simclient.py: MQTT communication, discovery, heartbeats, event ingestion, dashboard publishing, power intent intake.src/display_manager.py: display orchestration, HDMI-CEC, screenshots, local runtime health state.
Important runtime files:
src/current_event.json: active event from scheduler.src/current_process_health.json: process health bridge for dashboard and monitoring.src/power_intent_state.json: latest validated MQTT power intent.src/power_state.json: last applied power action telemetry.src/screenshots/: shared screenshot directory.
Content Types
Presentations
Presentations are rendered server-side to PDF and displayed with Impressive. Auto-advance, loop, page progress, and auto-progress are supported.
See IMPRESSIVE_INTEGRATION.md for full behavior, event examples, and troubleshooting.
Videos
Video events support:
urlautoplayloopvolume
The Display Manager prefers python-vlc; if unavailable it falls back to the external VLC binary.
Web Pages
Web and WebUntis events are displayed in Chromium kiosk mode.
TV Power Intent
Phase 1 TV power coordination uses the group topic:
infoscreen/groups/{group_id}/power/intent
Key references:
- Frozen contract: TV_POWER_INTENT_SERVER_CONTRACT_V1.md
- Rollout and canary testing: TV_POWER_RUNBOOK.md
- Client implementation handoff: TV_POWER_HANDOFF_CLIENT.md
Testing
Use the helper scripts in scripts/ for focused tests:
./scripts/test-display-manager.sh: event and process testing../scripts/test-impressive.sh: single-play presentation../scripts/test-impressive-loop.sh: looping presentation../scripts/test-mqtt.sh: MQTT broker connectivity../scripts/test-reboot-command.sh: end-to-end reboot/shutdown command lifecycle canary (accepted -> execution_started -> completed/failed)../scripts/test-screenshot.sh: screenshot capture../scripts/test-hdmi-cec.sh: HDMI-CEC diagnostics and runtime state inspection../scripts/test-power-intent.sh: MQTT power intent publishing, rejection tests, and telemetry checks.
Troubleshooting
Use the specialist docs instead of treating this file as the full troubleshooting manual:
- Presentation and Impressive issues: IMPRESSIVE_INTEGRATION.md
- HDMI-CEC setup and TV control: HDMI_CEC_SETUP.md
- Screenshot race condition and metadata sync: SCREENSHOT_MQTT_FIX.md
- Monitoring and dashboard behavior: CLIENT_MONITORING_SETUP.md
- Developer-oriented MQTT/event details: src/README.md
Quick checks:
- Follow logs:
tail -f logs/display_manager.log src/simclient.log - Inspect screenshots:
ls -lh src/screenshots/ - Inspect power state:
cat src/power_intent_state.jsonandcat src/power_state.json - Restart services (systemd):
sudo systemctl restart infoscreen-simclient infoscreen-display - Restart services (dev):
./scripts/restart-all.sh
Deployment
For production you typically run both simclient.py and display_manager.py via systemd or Docker.
- Container setup: src/CONTAINER_TRANSITION.md
- Production compose file: src/docker-compose.production.yml
- Display manager architecture: src/DISPLAY_MANAGER.md
If running directly on the host, ensure:
- the display session is available (
DISPLAY/XAUTHORITYfor X11), - the screenshot tools for your session type are installed,
ENV=productionis set when you want HDMI-CEC active.
Documentation Map
Operator / Deployment
Feature-Specific
- IMPRESSIVE_INTEGRATION.md
- SCREENSHOT_MQTT_FIX.md
- SCHEDULER_FIELDS_SUPPORT.md
- SERVER_VOLUME_CONTROL_SETUP.md
Development / Internal
- src/README.md
- src/DISPLAY_MANAGER.md
- src/IMPLEMENTATION_SUMMARY.md
- TV_POWER_COORDINATION_TASKLIST.md
- TV_POWER_HANDOFF_SERVER.md
- SERVER_TEAM_ACTIONS.md
Contributing
Before changing runtime behavior:
- test with the relevant helper scripts,
- verify logs stay clean,
- update the specialist doc for the feature you changed.
When editing AI assistant guidance files:
- keep
.github/copilot-instructions.mdpolicy-focused, - follow its "Instruction File Design Rules" section,
- avoid turning it into a shadow README.
Recent project history is tracked in CHANGELOG.md.
License
[Add your license here]