- 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
5.8 KiB
5.8 KiB
Developer Guide
This document is the developer-facing companion to the root README.md. It focuses on code structure, runtime boundaries, MQTT flow, and debugging during implementation work.
For installation, operator usage, and deployment, start at README.md.
Architecture
The client is split into two cooperating processes:
simclient.py: MQTT communication, discovery, group assignment, event intake, heartbeat, dashboard publishing, power-intent intake.display_manager.py: event polling, display orchestration, HDMI-CEC, screenshots, local process health state.
Primary runtime flow:
simclient.pyreceives group and event messages over MQTT.- It writes the active event into
current_event.json. display_manager.pypolls that file and starts or stops the display process.display_manager.pywrites health, screenshot, and power telemetry files.simclient.pypublishes dashboard, health, and power-state messages.
Key Files
display_manager.py: display lifecycle, HDMI-CEC, screenshots, local fallback logic.simclient.py: MQTT callbacks, event persistence, dashboard publishing, power-intent validation, command intake.current_event.json: active event state consumed by the display manager.current_process_health.json: local health bridge for monitoring.power_intent_state.json: latest validated power intent from MQTT.power_state.json: latest applied power action telemetry.screenshots/meta.json: screenshot metadata used by the dashboard path.../scripts/start-simclient.sh: launcher forsimclient.py(used by the systemd unit).../scripts/start-display-manager.sh: launcher fordisplay_manager.py.../scripts/infoscreen-simclient.service: systemd unit forsimclient.py.../scripts/infoscreen-display.service: systemd unit fordisplay_manager.py.../scripts/infoscreen-notify-failure@.service: systemd template unit; fires onOnFailure=.../scripts/infoscreen-notify-failure.sh: publishesservice_failedMQTT alert when a unit gives up.
Developer Workflow
On deployed devices, both processes are managed by systemd:
# Start / stop / restart
sudo systemctl start infoscreen-simclient infoscreen-display
sudo systemctl restart infoscreen-simclient infoscreen-display
# Follow logs
journalctl -u infoscreen-simclient -u infoscreen-display -f
First-time systemd setup:
sudo cp scripts/infoscreen-simclient.service /etc/systemd/system/
sudo cp scripts/infoscreen-display.service /etc/systemd/system/
sudo cp scripts/infoscreen-notify-failure@.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable infoscreen-simclient infoscreen-display
Or run src/pi-setup.sh which includes the above as step 14.
For local development without systemd:
cd ~/infoscreen-dev
source venv/bin/activate
# Terminal 1
./scripts/start-simclient.sh
# Terminal 2
./scripts/start-display-manager.sh
Useful helpers:
./dev-workflow.sh./scripts/test-display-manager.sh./scripts/test-mqtt.sh./scripts/test-screenshot.sh./scripts/test-power-intent.sh./scripts/test-progress-bars.sh
MQTT Topics
Client → Server
infoscreen/discoveryinfoscreen/{client_id}/heartbeatinfoscreen/{client_id}/dashboardinfoscreen/{client_id}/health— includesbroker_connectionblock withreconnect_count,last_disconnect_atinfoscreen/{client_id}/power/stateinfoscreen/{client_id}/commands/ack— command acknowledgement (states:accepted,rejected,execution_started,completed,failed)infoscreen/{client_id}/command/ack— legacy ack topic (also published for compatibility)infoscreen/{client_id}/service_failed— retained alert published byinfoscreen-notify-failure.shwhen systemd gives up restarting a unit
Server → Client
infoscreen/{client_id}/discovery_ackinfoscreen/{client_id}/group_idinfoscreen/events/{group_id}infoscreen/groups/{group_id}/power/intentinfoscreen/{client_id}/commands— remote command intake (reboot,shutdown)
Event and Display Notes
Supported runtime content categories:
- presentation
- video
- web / webpage / website / webuntis
Presentation behavior is documented in ../IMPRESSIVE_INTEGRATION.md.
TV power coordination references:
Debugging
Logs
tail -f ~/infoscreen-dev/logs/display_manager.log ~/infoscreen-dev/src/simclient.log
Runtime Files
cat ~/infoscreen-dev/src/current_event.json
cat ~/infoscreen-dev/src/current_process_health.json
cat ~/infoscreen-dev/src/power_intent_state.json
cat ~/infoscreen-dev/src/power_state.json
MQTT Inspection
mosquitto_sub -h YOUR_BROKER_IP -t 'infoscreen/#'
Screenshots
ls -lh ~/infoscreen-dev/src/screenshots/
cat ~/infoscreen-dev/src/screenshots/meta.json
Environment Notes
ENV=developmentdisables HDMI-CEC in the display manager.POWER_CONTROL_MODEcontrols local vs hybrid vs mqtt power behavior.COMMAND_HELPER_PATHpoints to the shell script that executes privileged commands (reboot/shutdown). Usemock-command-helper.shfor local testing.COMMAND_MOCK_REBOOT_IMMEDIATE_COMPLETE=1makes a mock reboot complete immediately instead of waiting for process restart. Only works when the helper basename ismock-command-helper.sh.- File download host rewriting is handled in
simclient.pyusingFILE_SERVER_*settings.