Infoscreen 2025
A comprehensive multi-service digital signage solution for educational institutions, featuring client management, event scheduling, presentation conversion, and real-time MQTT communication.
🏗️ Architecture Overview
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Dashboard │ │ API Server │ │ Listener │
│ (React/Vite) │◄──►│ (Flask) │◄──►│ (MQTT Client) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ MariaDB │ │
│ │ (Database) │ │
│ └─────────────────┘ │
│ │
└────────────────────┬───────────────────────────┘
▼
┌─────────────────┐
│ MQTT Broker │
│ (Mosquitto) │
└─────────────────┘
│
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Scheduler │ │ Worker │ │ Infoscreen │
│ (Events) │ │ (Conversions) │ │ Clients │
└─────────────────┘ └─────────────────┘ └─────────────────┘
🌟 Key Features
📊 Dashboard Management
- Modern React-based web interface with Syncfusion components
- Real-time client monitoring and group management
- Event scheduling with academic period support
- Media management with presentation conversion
- Holiday calendar integration
- Visual indicators: TentTree icon next to the main event icon marks events that skip holidays (icon color: black)
🎯 Event System
- Presentations: PowerPoint/LibreOffice → PDF conversion via Gotenberg
- Websites: URL-based content display
- Videos: Media file streaming
- Messages: Text announcements
- WebUntis: Educational schedule integration
- Recurrence & Holidays: Recurring events can be configured to skip holidays. The backend generates EXDATEs (RecurrenceException) for holiday occurrences so the calendar never shows those instances. The "Termine an Ferientagen erlauben" toggle does not affect these events.
- Single Occurrence Editing: Users can edit individual occurrences of recurring events without affecting the master series. The system provides a confirmation dialog to choose between editing a single occurrence or the entire series.
🏫 Academic Period Management
- Support for school years, semesters, and trimesters
- Austrian school system integration
- Holiday calendar synchronization
- Period-based event organization
📡 Real-time Communication
- MQTT-based client discovery and heartbeat monitoring
- Retained topics for reliable state synchronization
- WebSocket support for browser clients
- Automatic client group assignment
🔄 Background Processing
- Redis-based job queues for presentation conversion
- Gotenberg integration for LibreOffice/PowerPoint processing
- Asynchronous file processing with status tracking
- RQ (Redis Queue) worker management
🚀 Quick Start
Prerequisites
- Docker & Docker Compose
- Git
- SSL certificates (for production)
Development Setup
-
Clone the repository
git clone https://github.com/RobbStarkAustria/infoscreen_2025.git cd infoscreen_2025 -
Environment Configuration
cp .env.example .env # Edit .env with your configuration -
Start the development stack
make up # or: docker compose up -d --build -
Initialize the database (first run only)
# One-shot: runs all Alembic migrations, creates default admin/group, and seeds academic periods python server/initialize_database.py -
Access the services
- Dashboard: http://localhost:5173
- API: http://localhost:8000
- Database: localhost:3306
- MQTT: localhost:1883 (WebSocket: 9001)
Production Deployment
-
Build and push images
make build make push -
Deploy on server
make pull-prod make up-prod
For detailed deployment instructions, see:
🛠️ Services
🖥️ Dashboard (dashboard/)
- Technology: React 19 + TypeScript + Vite
- UI Framework: Syncfusion components (Material 3 theme)
- Styling: Centralized Syncfusion Material 3 CSS imports in
dashboard/src/main.tsx - Features: Responsive design, real-time updates, file management
- Port: 5173 (dev), served via Nginx (prod)
🔧 API Server (server/)
- Technology: Flask + SQLAlchemy + Alembic
- Database: MariaDB with timezone-aware timestamps
- Features: RESTful API, file uploads, MQTT integration
- Recurrence/holidays: returns only master events with
RecurrenceRuleandRecurrenceException(EXDATEs) so clients render recurrences and skip holiday instances reliably. - Single occurrence detach:
POST /api/events/<id>/occurrences/<date>/detachcreates standalone events from recurring series without modifying the master event.
- Recurrence/holidays: returns only master events with
- Port: 8000
- Health Check:
/health
👂 Listener (listener/)
- Technology: Python + paho-mqtt
- Purpose: MQTT message processing, client discovery
- Features: Heartbeat monitoring, automatic client registration
⏰ Scheduler (scheduler/)
- Technology: Python + SQLAlchemy
- Purpose: Event publishing, group-based content distribution
- Features: Time-based event activation, MQTT publishing
🔄 Worker (Conversion Service)
- Technology: RQ (Redis Queue) + Gotenberg
- Purpose: Background presentation conversion
- Features: PPT/PPTX/ODP → PDF conversion, status tracking
🗄️ Database (MariaDB 11.2)
- Features: Health checks, automatic initialization
- Migrations: Alembic-based schema management
- Timezone: UTC-aware timestamps
📡 MQTT Broker (Eclipse Mosquitto 2.0.21)
- Features: WebSocket support, health monitoring
- Topics:
infoscreen/discovery- Client registrationinfoscreen/{uuid}/heartbeat- Client alive statusinfoscreen/events/{group_id}- Event distributioninfoscreen/{uuid}/group_id- Client group assignment
📁 Project Structure
infoscreen_2025/
├── dashboard/ # React frontend
│ ├── src/ # React components and logic
│ ├── public/ # Static assets
│ └── Dockerfile # Production build
├── server/ # Flask API backend
│ ├── routes/ # API endpoints
│ ├── alembic/ # Database migrations
│ ├── media/ # File storage
│ ├── initialize_database.py # All-in-one DB initialization (dev)
│ └── worker.py # Background jobs
├── listener/ # MQTT listener service
├── scheduler/ # Event scheduling service
├── models/ # Shared database models
├── mosquitto/ # MQTT broker configuration
├── certs/ # SSL certificates
├── docker-compose.yml # Development setup
├── docker-compose.prod.yml # Production setup
└── Makefile # Development shortcuts
🔧 Development
Available Commands
# Development
make up # Start dev stack
make down # Stop dev stack
make logs # View all logs
make logs-server # View specific service logs
# Building & Deployment
make build # Build all images
make push # Push to registry
make pull-prod # Pull production images
make up-prod # Start production stack
# Maintenance
make health # Health checks
make fix-perms # Fix file permissions
Database Management
# One-shot initialization (schema + defaults + academic periods)
python server/initialize_database.py
# Access database directly
docker exec -it infoscreen-db mysql -u${DB_USER} -p${DB_PASSWORD} ${DB_NAME}
# Run migrations
docker exec -it infoscreen-api alembic upgrade head
# Initialize academic periods (Austrian school system)
docker exec -it infoscreen-api python init_academic_periods.py
MQTT Testing
# Subscribe to all topics
mosquitto_sub -h localhost -t "infoscreen/#" -v
# Publish test message
mosquitto_pub -h localhost -t "infoscreen/test" -m "Hello World"
# Monitor client heartbeats
mosquitto_sub -h localhost -t "infoscreen/+/heartbeat" -v
🌐 API Endpoints
Core Resources
GET /api/clients- List all registered clientsPUT /api/clients/{uuid}/group- Assign client to groupGET /api/groups- List client groups with alive statusGET /api/events- List events with filteringPOST /api/events- Create new eventPOST /api/events/{id}/occurrences/{date}/detach- Detach single occurrence from recurring seriesGET /api/academic_periods- List academic periodsPOST /api/academic_periods/active- Set active period
File Management
POST /api/files- Upload media filesGET /api/files/{path}- Download filesGET /api/files/converted/{path}- Download converted PDFsPOST /api/conversions/{media_id}/pdf- Request conversionGET /api/conversions/{media_id}/status- Check conversion status
Health & Monitoring
GET /health- Service health checkGET /api/screenshots/{uuid}.jpg- Client screenshots
🎨 Frontend Features
Recurrence & holidays
- The frontend manually expands recurring events due to Syncfusion EXDATE handling limitations.
- The API supplies
RecurrenceException(EXDATE) with exact occurrence start times (UTC) so holiday instances are excluded. - Events with "skip holidays" display a TentTree icon next to the main event icon.
- Single occurrence editing: Users can detach individual occurrences via confirmation dialog, creating standalone events while preserving the master series.
Syncfusion Components Used (Material 3)
- Schedule: Event calendar with drag-drop support
- Grid: Data tables with filtering and sorting
- DropDownList: Group and period selectors
- FileManager: Media upload and organization
- Kanban: Task management views
- Notifications: Toast messages and alerts
- Pager: Used on Programinfo changelog for pagination
- Cards (layouts): Programinfo sections styled with Syncfusion card classes
Pages Overview
- Dashboard: System overview and statistics
- Clients: Device management and monitoring
- Groups: Client group organization
- Events: Schedule management
- Media: File upload and conversion
- Settings: System configuration
- Holidays: Academic calendar management
- Program info: Version, build info, tech stack and paginated changelog (reads
dashboard/public/program-info.json)
🔒 Security & Authentication
- Environment Variables: Sensitive data via
.env - SSL/TLS: HTTPS support with custom certificates
- MQTT Security: Username/password authentication
- Database: Parameterized queries, connection pooling
- File Uploads: Type validation, size limits
- CORS: Configured for production deployment
📊 Monitoring & Logging
Health Checks
All services include Docker health checks:
- API: HTTP endpoint monitoring
- Database: Connection and initialization status
- MQTT: Pub/sub functionality test
- Dashboard: Nginx availability
Logging Strategy
- Development: Docker Compose logs with service prefixes
- Production: Centralized logging via Docker log drivers
- MQTT: Message-level debugging available
- Database: Query logging in development mode
🌍 Deployment Options
Development
- Hot Reload: Vite dev server + Flask debug mode
- Volume Mounts: Live code editing
- Debug Ports: Python debugger support (port 5678)
- Local Certificates: Self-signed SSL for testing
Production
- Optimized Builds: Multi-stage Dockerfiles
- Reverse Proxy: Nginx with SSL termination
- Health Monitoring: Comprehensive healthchecks
- Registry: GitHub Container Registry integration
- Scaling: Docker Compose for single-node deployment
🤝 Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
Development Guidelines
- Follow existing code patterns and naming conventions
- Add appropriate tests for new features
- Update documentation for API changes
- Use TypeScript for frontend development
- Follow Python PEP 8 for backend code
📋 Requirements
System Requirements
- CPU: 2+ cores recommended
- RAM: 4GB minimum, 8GB recommended
- Storage: 20GB+ for media files and database
- Network: Reliable internet for client communication
Software Dependencies
- Docker 24.0+
- Docker Compose 2.0+
- Git 2.30+
- Modern web browser (Chrome, Firefox, Safari, Edge)
🐛 Troubleshooting
Common Issues
Services won't start
# Check service health
make health
# View specific service logs
make logs-server
make logs-db
Database connection errors
# Verify database is running
docker exec -it infoscreen-db mysqladmin ping
# Check credentials in .env file
# Restart dependent services
MQTT communication issues
# Test MQTT broker
mosquitto_pub -h localhost -t test -m "hello"
# Check client certificates and credentials
# Verify firewall settings for ports 1883/9001
File conversion problems
# Check Gotenberg service
curl http://localhost:3000/health
# Monitor worker logs
make logs-worker
# Check Redis queue status
docker exec -it infoscreen-redis redis-cli LLEN conversions
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- Syncfusion: UI components for React dashboard
- Eclipse Mosquitto: MQTT broker implementation
- Gotenberg: Document conversion service
- MariaDB: Reliable database engine
- Flask: Python web framework
- React: Frontend user interface library
For detailed technical documentation, deployment guides, and API specifications, please refer to the additional documentation files in this repository.
Notes:
- Tailwind CSS was removed. Styling is managed via Syncfusion Material 3 theme imports in
dashboard/src/main.tsx.
🧭 Changelog Style Guide
When adding entries to dashboard/public/program-info.json (displayed on the Program info page):
-
Structure per release
version(e.g.,2025.1.0-alpha.8)dateinYYYY-MM-DD(ISO format)changes: array of short bullet strings
-
Categories (Keep a Changelog inspired)
- Prefer starting bullets with an implicit category or an emoji, e.g.:
- Added (🆕/✨), Changed (🔧/🛠️), Fixed (🐛/✅), Removed (🗑️), Security (🔒), Deprecated (⚠️)
- Prefer starting bullets with an implicit category or an emoji, e.g.:
-
Writing rules
- Keep bullets concise (ideally one line) and user-facing; avoid internal IDs or jargon
- Put the affected area first when helpful (e.g., “UI: …”, “API: …”, “Scheduler: …”)
- Highlight breaking changes with “BREAKING:”
- Prefer German wording consistently; dates are localized at runtime for display
-
Ordering and size
- Newest release first in the array
- Aim for ≤ 8–10 bullets per release; group or summarize if longer
-
JSON hygiene
- Valid JSON only (no trailing commas); escape quotes as needed
- One release object per version; do not modify historical entries unless to correct typos
The Program info page paginates older entries (default page size 5). Keep highlights at the top of each release for scanability.