Files
infoscreen-dev/README.md
RobbStarkAustria 0cd0d95612 feat: remote commands, systemd units, process observability, broker auth split
- Command intake (reboot/shutdown) on infoscreen/{uuid}/commands with ack lifecycle
- MQTT_USER/MQTT_PASSWORD_BROKER split from identity vars; configure_mqtt_security() updated
- infoscreen-simclient.service: Type=notify, WatchdogSec=60, Restart=on-failure
- infoscreen-notify-failure@.service + script: retained MQTT alert when systemd gives up (Gap 3)
- _sd_notify() watchdog keepalive in simclient main loop (Gap 1)
- broker_connection block in health payload: reconnect_count, last_disconnect_at (Gap 2)
- COMMAND_MOCK_REBOOT_IMMEDIATE_COMPLETE canary flag with safety guard
- SERVER_TEAM_ACTIONS.md: server-side integration action items
- Docs: README, CHANGELOG, src/README, copilot-instructions updated
- 43 tests passing
2026-04-05 08:36:50 +02:00

260 lines
8.6 KiB
Markdown

# 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-vlc` when 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.py` and `simclient.py`.
## Quick Start
### 1. Install Dependencies
```bash
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:
```bash
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_BROKER` are the broker credentials used at connection time.
- `MQTT_USERNAME` / `MQTT_PASSWORD` are legacy per-device identity fields kept for fallback and identity purposes.
- Store real broker credentials only in the local [/.env](.env), which is gitignored.
- When TLS is enabled, also set `MQTT_TLS_CA_CERT`, and if client certificates are used, `MQTT_TLS_CERT` and `MQTT_TLS_KEY`.
- Keep the local [/.env](.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:
```bash
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](src/README.md) for the systemd setup steps.
For local development without systemd:
```bash
# 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](IMPRESSIVE_INTEGRATION.md) for full behavior, event examples, and troubleshooting.
### Videos
Video events support:
- `url`
- `autoplay`
- `loop`
- `volume`
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](TV_POWER_INTENT_SERVER_CONTRACT_V1.md)
- Rollout and canary testing: [TV_POWER_RUNBOOK.md](TV_POWER_RUNBOOK.md)
- Client implementation handoff: [TV_POWER_HANDOFF_CLIENT.md](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](IMPRESSIVE_INTEGRATION.md)
- HDMI-CEC setup and TV control: [HDMI_CEC_SETUP.md](HDMI_CEC_SETUP.md)
- Screenshot race condition and metadata sync: [SCREENSHOT_MQTT_FIX.md](SCREENSHOT_MQTT_FIX.md)
- Monitoring and dashboard behavior: [CLIENT_MONITORING_SETUP.md](CLIENT_MONITORING_SETUP.md)
- Developer-oriented MQTT/event details: [src/README.md](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.json` and `cat 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](src/CONTAINER_TRANSITION.md)
- Production compose file: [src/docker-compose.production.yml](src/docker-compose.production.yml)
- Display manager architecture: [src/DISPLAY_MANAGER.md](src/DISPLAY_MANAGER.md)
If running directly on the host, ensure:
- the display session is available (`DISPLAY` / `XAUTHORITY` for X11),
- the screenshot tools for your session type are installed,
- `ENV=production` is set when you want HDMI-CEC active.
## Documentation Map
### Operator / Deployment
- [QUICK_REFERENCE.md](QUICK_REFERENCE.md)
- [HDMI_CEC_SETUP.md](HDMI_CEC_SETUP.md)
- [TV_POWER_RUNBOOK.md](TV_POWER_RUNBOOK.md)
- [CLIENT_MONITORING_SETUP.md](CLIENT_MONITORING_SETUP.md)
- [CHANGELOG.md](CHANGELOG.md)
### Feature-Specific
- [IMPRESSIVE_INTEGRATION.md](IMPRESSIVE_INTEGRATION.md)
- [SCREENSHOT_MQTT_FIX.md](SCREENSHOT_MQTT_FIX.md)
- [SCHEDULER_FIELDS_SUPPORT.md](SCHEDULER_FIELDS_SUPPORT.md)
- [SERVER_VOLUME_CONTROL_SETUP.md](SERVER_VOLUME_CONTROL_SETUP.md)
### Development / Internal
- [src/README.md](src/README.md)
- [src/DISPLAY_MANAGER.md](src/DISPLAY_MANAGER.md)
- [src/IMPLEMENTATION_SUMMARY.md](src/IMPLEMENTATION_SUMMARY.md)
- [TV_POWER_COORDINATION_TASKLIST.md](TV_POWER_COORDINATION_TASKLIST.md)
- [TV_POWER_HANDOFF_SERVER.md](TV_POWER_HANDOFF_SERVER.md)
- [SERVER_TEAM_ACTIONS.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.md` policy-focused,
- follow its "Instruction File Design Rules" section,
- avoid turning it into a shadow README.
Recent project history is tracked in [CHANGELOG.md](CHANGELOG.md).
## License
[Add your license here]