docs: refactor docs structure and tighten assistant instruction policy
shrink root README into a landing page with a docs map and focused contributor guidance add TV_POWER_RUNBOOK as the canonical TV power rollout and canary runbook add CHANGELOG and move project history out of README-style docs refactor src README into a developer-focused guide (architecture, runtime files, MQTT, debugging) prune redundant older HDMI docs and keep a canonical HDMI_CEC_SETUP path update copilot instructions to a high-signal policy format with strict anti-shadow-README design rules align references across docs to current files, scripts, and TV power behavior
This commit is contained in:
311
src/README.md
311
src/README.md
@@ -1,274 +1,129 @@
|
||||
# Infoscreen Client - Raspberry Pi Development
|
||||
# Developer Guide
|
||||
|
||||
A presentation system client for Raspberry Pi that communicates with a server via MQTT to display presentations, videos, and web content in kiosk mode.
|
||||
This document is the developer-facing companion to the root [README.md](../README.md). It focuses on code structure, runtime boundaries, MQTT flow, and debugging during implementation work.
|
||||
|
||||
## Features
|
||||
For installation, operator usage, and deployment, start at [README.md](../README.md).
|
||||
|
||||
- 📡 MQTT communication with server
|
||||
- 📥 Automatic file downloads (presentations, videos)
|
||||
- 🖥️ **Automated display management** with dedicated Display Manager
|
||||
- 🎯 Event-driven content switching (presentations, videos, web pages)
|
||||
- ⏰ Time-based event scheduling with automatic start/stop
|
||||
- 🔄 Graceful application transitions (LibreOffice, Chromium, VLC)
|
||||
- 📸 Screenshot capture for dashboard monitoring
|
||||
- 👥 Group-based content management
|
||||
- 💖 Heartbeat monitoring
|
||||
## Architecture
|
||||
|
||||
## Quick Setup
|
||||
The client is split into two cooperating processes:
|
||||
|
||||
### 1. Flash Raspberry Pi OS
|
||||
- Use **Raspberry Pi OS (64-bit) with Desktop**
|
||||
- Enable SSH and configure WiFi in Pi Imager
|
||||
- Boot Pi and connect to network
|
||||
- `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.
|
||||
|
||||
### 2. Install Development Environment
|
||||
```bash
|
||||
# Run on your Raspberry Pi:
|
||||
curl -sSL https://raw.githubusercontent.com/RobbStarkAustria/infoscreen_client_2025/main/pi-dev-setup.sh | bash
|
||||
```
|
||||
Primary runtime flow:
|
||||
|
||||
1. `simclient.py` receives group and event messages over MQTT.
|
||||
2. It writes the active event into `current_event.json`.
|
||||
3. `display_manager.py` polls that file and starts or stops the display process.
|
||||
4. `display_manager.py` writes health, screenshot, and power telemetry files.
|
||||
5. `simclient.py` publishes 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.
|
||||
- `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.
|
||||
|
||||
## Developer Workflow
|
||||
|
||||
Typical local workflow:
|
||||
|
||||
### 3. Configure MQTT Broker
|
||||
```bash
|
||||
cd ~/infoscreen-dev
|
||||
nano .env
|
||||
# Update MQTT_BROKER=your-server-ip
|
||||
```
|
||||
source venv/bin/activate
|
||||
|
||||
### 4. Test Setup
|
||||
```bash
|
||||
./scripts/test-mqtt.sh # Test MQTT connection
|
||||
./scripts/test-screenshot.sh # Test screenshot capture
|
||||
./scripts/test-presentation.sh # Test presentation tools
|
||||
```
|
||||
# Terminal 1
|
||||
./scripts/start-dev.sh
|
||||
|
||||
### 5. Start Development
|
||||
```bash
|
||||
# Terminal 1: Start MQTT client (receives events)
|
||||
./scripts/start-dev.sh
|
||||
|
||||
# Terminal 2: Start Display Manager (controls screen)
|
||||
# Terminal 2
|
||||
./scripts/start-display-manager.sh
|
||||
|
||||
# Or use interactive menu:
|
||||
./dev-workflow.sh
|
||||
```
|
||||
|
||||
**Important**: You need **both** processes running:
|
||||
- `simclient.py` - Handles MQTT communication and writes events
|
||||
- `display_manager.py` - Reads events and controls display software
|
||||
Useful helpers:
|
||||
|
||||
See [DISPLAY_MANAGER.md](DISPLAY_MANAGER.md) for detailed documentation.
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Daily Development
|
||||
```bash
|
||||
cd ~/infoscreen-dev
|
||||
./dev-workflow.sh # Interactive menu with all options
|
||||
```
|
||||
|
||||
**Menu Options:**
|
||||
1. Start development client (MQTT)
|
||||
2. Start Display Manager
|
||||
3. View live logs
|
||||
4. Test Display Manager
|
||||
5. Test screenshot capture
|
||||
6. Test MQTT connection
|
||||
7. Test presentation tools
|
||||
8. Git status and sync
|
||||
9. Restart systemd services
|
||||
10. Monitor system resources
|
||||
11. Open tmux session
|
||||
|
||||
### Remote Development (Recommended)
|
||||
```bash
|
||||
# From your main computer:
|
||||
# Add to ~/.ssh/config
|
||||
Host pi-dev
|
||||
HostName YOUR_PI_IP
|
||||
User pi
|
||||
|
||||
# Connect with VS Code
|
||||
code --remote ssh-remote+pi-dev ~/infoscreen-dev
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
~/infoscreen-dev/
|
||||
├── .env # Configuration
|
||||
├── src/ # Source code (this repository)
|
||||
│ ├── simclient.py # MQTT client (event receiver)
|
||||
│ ├── display_manager.py # Display controller (NEW!)
|
||||
│ ├── current_event.json # Current active event
|
||||
│ ├── DISPLAY_MANAGER.md # Display Manager documentation
|
||||
│ └── config/ # Client UUID and group ID
|
||||
├── venv/ # Python virtual environment
|
||||
├── presentation/ # Downloaded presentation files
|
||||
├── screenshots/ # Screenshot captures
|
||||
├── logs/ # Application logs
|
||||
│ ├── simclient.log # MQTT client logs
|
||||
│ └── display_manager.log # Display Manager logs
|
||||
└── scripts/ # Development helper scripts
|
||||
├── start-dev.sh # Start MQTT client
|
||||
├── start-display-manager.sh # Start Display Manager (NEW!)
|
||||
├── test-display-manager.sh # Test display events (NEW!)
|
||||
├── test-mqtt.sh # Test MQTT connection
|
||||
├── test-screenshot.sh # Test screenshot capture
|
||||
└── test-presentation.sh # Test presentation tools
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables (.env)
|
||||
```bash
|
||||
# Development settings
|
||||
ENV=development
|
||||
DEBUG_MODE=1
|
||||
LOG_LEVEL=DEBUG
|
||||
|
||||
# MQTT Configuration
|
||||
MQTT_BROKER=192.168.1.100 # Your MQTT server IP
|
||||
MQTT_PORT=1883
|
||||
|
||||
# Intervals (seconds)
|
||||
HEARTBEAT_INTERVAL=10 # Heartbeat frequency
|
||||
SCREENSHOT_INTERVAL=30 # Screenshot capture frequency
|
||||
DISPLAY_CHECK_INTERVAL=5 # Display Manager event check frequency
|
||||
```
|
||||
- `./dev-workflow.sh`
|
||||
- `./scripts/test-display-manager.sh`
|
||||
- `./scripts/test-mqtt.sh`
|
||||
- `./scripts/test-screenshot.sh`
|
||||
- `./scripts/test-power-intent.sh`
|
||||
|
||||
## MQTT Topics
|
||||
|
||||
### Client → Server
|
||||
- `infoscreen/discovery` - Client registration
|
||||
- `infoscreen/{client_id}/heartbeat` - Regular heartbeat
|
||||
- `infoscreen/{client_id}/dashboard` - Screenshot + status
|
||||
|
||||
- `infoscreen/discovery`
|
||||
- `infoscreen/{client_id}/heartbeat`
|
||||
- `infoscreen/{client_id}/dashboard`
|
||||
- `infoscreen/{client_id}/health`
|
||||
- `infoscreen/{client_id}/power/state`
|
||||
|
||||
### Server → Client
|
||||
- `infoscreen/{client_id}/discovery_ack` - Registration acknowledgment
|
||||
- `infoscreen/{client_id}/group_id` - Group assignment
|
||||
- `infoscreen/events/{group_id}` - Event messages with content
|
||||
|
||||
## Event Format
|
||||
- `infoscreen/{client_id}/discovery_ack`
|
||||
- `infoscreen/{client_id}/group_id`
|
||||
- `infoscreen/events/{group_id}`
|
||||
- `infoscreen/groups/{group_id}/power/intent`
|
||||
|
||||
The Display Manager supports three event types:
|
||||
## Event and Display Notes
|
||||
|
||||
**Presentation Event:**
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Company Overview",
|
||||
"start": "2025-10-01 08:00:00",
|
||||
"end": "2025-10-01 18:00:00",
|
||||
"presentation": {
|
||||
"files": [
|
||||
{
|
||||
"url": "https://server/presentations/slide.pptx",
|
||||
"name": "slide.pptx"
|
||||
}
|
||||
],
|
||||
"slide_interval": 10,
|
||||
"auto_advance": true
|
||||
}
|
||||
}
|
||||
```
|
||||
Supported runtime content categories:
|
||||
|
||||
**Web Page Event:**
|
||||
```json
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Dashboard",
|
||||
"start": "2025-10-01 08:00:00",
|
||||
"end": "2025-10-01 18:00:00",
|
||||
"web": {
|
||||
"url": "https://dashboard.example.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
- presentation
|
||||
- video
|
||||
- web / webpage / website / webuntis
|
||||
|
||||
**Video Event:**
|
||||
```json
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Promo Video",
|
||||
"start": "2025-10-01 08:00:00",
|
||||
"end": "2025-10-01 18:00:00",
|
||||
"video": {
|
||||
"url": "https://server/videos/promo.mp4",
|
||||
"loop": true
|
||||
}
|
||||
}
|
||||
```
|
||||
Presentation behavior is documented in [../IMPRESSIVE_INTEGRATION.md](../IMPRESSIVE_INTEGRATION.md).
|
||||
|
||||
See [DISPLAY_MANAGER.md](DISPLAY_MANAGER.md) for complete event documentation.
|
||||
TV power coordination references:
|
||||
|
||||
- [../TV_POWER_INTENT_SERVER_CONTRACT_V1.md](../TV_POWER_INTENT_SERVER_CONTRACT_V1.md)
|
||||
- [../TV_POWER_RUNBOOK.md](../TV_POWER_RUNBOOK.md)
|
||||
|
||||
## Debugging
|
||||
|
||||
### View Logs
|
||||
### Logs
|
||||
|
||||
```bash
|
||||
tail -f ~/infoscreen-dev/logs/simclient.log
|
||||
tail -f ~/infoscreen-dev/logs/display_manager.log ~/infoscreen-dev/src/simclient.log
|
||||
```
|
||||
|
||||
### MQTT Debugging
|
||||
```bash
|
||||
# Subscribe to all infoscreen topics
|
||||
mosquitto_sub -h YOUR_BROKER_IP -t "infoscreen/+/+"
|
||||
### Runtime Files
|
||||
|
||||
# Publish test event
|
||||
mosquitto_pub -h YOUR_BROKER_IP -t "infoscreen/events/test-group" -m '{"web":{"url":"https://google.com"}}'
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
### System Service (Optional)
|
||||
```bash
|
||||
# Enable automatic startup
|
||||
sudo systemctl enable infoscreen-dev
|
||||
sudo systemctl start infoscreen-dev
|
||||
### MQTT Inspection
|
||||
|
||||
# View service logs
|
||||
sudo journalctl -u infoscreen-dev -f
|
||||
```bash
|
||||
mosquitto_sub -h YOUR_BROKER_IP -t 'infoscreen/#'
|
||||
```
|
||||
|
||||
## Hardware Requirements
|
||||
### Screenshots
|
||||
|
||||
- **Raspberry Pi 4 or 5** (recommended Pi 5 for best performance)
|
||||
- **SSD storage** (much faster than SD card)
|
||||
- **Display** connected via HDMI
|
||||
- **Network connection** (WiFi or Ethernet)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Display Issues
|
||||
```bash
|
||||
export DISPLAY=:0
|
||||
echo $DISPLAY
|
||||
ls -lh ~/infoscreen-dev/src/screenshots/
|
||||
cat ~/infoscreen-dev/src/screenshots/meta.json
|
||||
```
|
||||
|
||||
### Screenshot Issues
|
||||
```bash
|
||||
# Test screenshot manually
|
||||
scrot ~/test.png
|
||||
# Check permissions
|
||||
sudo usermod -a -G video pi
|
||||
```
|
||||
## Environment Notes
|
||||
|
||||
### MQTT Connection Issues
|
||||
```bash
|
||||
# Test broker connectivity
|
||||
telnet YOUR_BROKER_IP 1883
|
||||
# Check firewall
|
||||
sudo ufw status
|
||||
```
|
||||
- `ENV=development` disables HDMI-CEC in the display manager.
|
||||
- `POWER_CONTROL_MODE` controls local vs hybrid vs mqtt power behavior.
|
||||
- File download host rewriting is handled in `simclient.py` using `FILE_SERVER_*` settings.
|
||||
|
||||
## Development vs Production
|
||||
## Related Documents
|
||||
|
||||
This setup is optimized for **development**:
|
||||
- ✅ Fast iteration (edit → save → restart)
|
||||
- ✅ Native debugging and logging
|
||||
- ✅ Direct hardware access
|
||||
- ✅ Remote development friendly
|
||||
|
||||
For **production deployment** with multiple clients, consider containerization for easier updates and management.
|
||||
|
||||
## License
|
||||
|
||||
This project is part of the infoscreen presentation system for educational/research purposes.
|
||||
- [../README.md](../README.md)
|
||||
- [DISPLAY_MANAGER.md](DISPLAY_MANAGER.md)
|
||||
- [IMPLEMENTATION_SUMMARY.md](IMPLEMENTATION_SUMMARY.md)
|
||||
- [../CLIENT_MONITORING_SETUP.md](../CLIENT_MONITORING_SETUP.md)
|
||||
- [../SCREENSHOT_MQTT_FIX.md](../SCREENSHOT_MQTT_FIX.md)
|
||||
|
||||
Reference in New Issue
Block a user