Files

126 lines
6.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: digital-signage
description: |-
Build and maintain a multi-tenant digital signage CMS platform — Raspberry Pi kiosk players, customer upload portal, playlist management, device registration. Replaces OptiSigns ($15-30/mo).
author: Sho'Nuff
version: 1.0.0
tags: [raspberry-pi, signage, kiosk, multi-tenant, content-management]
platforms: [linux]
---
# Digital Signage CMS
Multi-tenant digital signage platform. Customers upload images/video via a web portal, create playlists, and Raspberry Pi players display content in fullscreen kiosk mode.
## Project Directory
All docs live at `/root/projects/digital-signage/`. Key files:
| File | Contents |
|------|----------|
| `README.md` | Full architecture, multi-tenant hierarchy, Pi registration flow, MVP scope |
| `optisigns-comparison.md` | Feature-by-feature comparison vs OptiSigns (what we build vs what we skip) |
| `cms/customer-setup-guide.md` | Customer-facing 9-step quick-start guide (printable) |
| `player/provisioning.md` | Zero-touch Pi provisioning — first-boot script, SD card imaging, recovery |
| `player/device-identification.md` | Hidden Ctrl+I overlay for support — device name, serial, IP, playlist |
| `mockups/` | Frontend HTML mockups (customer portal) |
## Architecture
```
Customer Web Portal Raspberry Pi Player
┌────────────────────────┐ ┌──────────────────────┐
│ Login (per tenant) │ │ Registration script │
│ Upload images/video │ API │ POST /api/register │
│ Create playlists │ ←───────→ │ Poll /api/playlist │
│ Manage devices │ │ Chromium kiosk mode │
│ Registration codes │ │ Fullscreen playback │
└────────────────────────┘ └──────────────────────┘
FastAPI + SQLite + S3
```
### Multi-tenant hierarchy
```
Platform
├── Tenant: Joe's Diner
│ ├── Users: admin, staff@...
│ ├── Device: Main Lobby Pi
│ ├── Device: Menu Board Pi
│ └── Content: 8 items, 2 playlists
├── Tenant: Main Street Gym
│ └── Device: Front Desk Pi
└── Tenant: Third Coast Dental
├── Device: Waiting Room Pi
├── Device: Exam Room Pi
└── Device: Hallway Pi
```
Key rule: **one customer = one tenant = unlimited devices.** Content libraries are per-tenant. Playlists assignable to one or multiple devices.
## OptiSigns Replication
| Tier | What's Included | Timeline |
|------|----------------|----------|
| **Phase 1 — MVP** | Upload images/video, playlists (ordered + shuffle), multi-tenant, Pi registration, fullscreen kiosk, device identification overlay | ~2 weeks |
| **Phase 2 — Parity** | Content scheduling, multi-user per tenant, thumbnail previews, auto-update on content change | ~1 week |
| **Phase 3 — Surpass** | Sho'Nuff text-to-broadcast integration, ops portal dark theme, no OptiSigns logo, API for remote control | ~1 week |
**What we skip:** Power BI dashboards, touch interactivity, video walls, background music licensing, wireless presentation.
## Pi Provisioning — Zero Touch
1. **Image SD card** with Raspberry Pi OS lite + first-boot script (auto-login, Chromium, player service)
2. **Generate registration code** from CMS
3. **Ship Pi** to customer (HDMI + power cable included)
4. **Customer plugs in** — two cables: HDMI + power
5. **Pi boots**, auto-registers, fetches playlist, plays content
**On power loss/reboot:** Auto-restarts and resumes. Already registered → skips to content.
**On SD card failure:** Flash new card → 5 min fix → re-register from CMS.
**On TV change:** Pi auto-detects resolution via HDMI EDID. No config needed.
## Device Registration Flow
```
1. Customer portal → Devices → Register New Device → code: SIGN-4K7P-M9X2
2. Pi boots → runs registration script → POST /api/register with code + serial
3. Server: creates device under tenant → returns device_id + token
4. Pi stores token locally → starts polling GET /api/playlist/:device_id every 60s
5. CMS playlist change → Pi picks it up on next poll
```
## Device Identification Overlay
Hidden overlay triggered by Ctrl+I pressed 3 times in 2 seconds (or remote API call). Shows device name, serial, IP, playlist, model, last sync. Auto-hides after 30s. No customer sees it in normal operation.
### 3 trigger methods:
1. **Keyboard:** `Ctrl+I` × 3 within 2 seconds
2. **Remote API:** `POST /api/devices/:id/identify` (device polls `/status` every 10s)
3. **Boot flag:** `./kiosk.sh --identify`
## Resolution Handling
**Pi auto-detects via HDMI EDID.** Upload content at highest quality (4K if you have it). Pi scales to whatever display is connected. CMS does NOT need to know or care about output resolution — that's the Pi's job.
| Pi Model | Max Output | Best For |
|----------|-----------|----------|
| Pi 3 | 1080p @ 60fps | Stills, basic slideshows |
| Pi 4 | 4K @ 60fps | Mixed content, smooth video |
| Pi 5 | 4K @ 60fps HDR | Heavy video, multiple layers |
## Frontend Portal Mockup
The customer portal mockup lives at `ops.itpropartner.com/signage-mockup.html` — dark theme, 6 views (login, dashboard, content, playlists, devices, register Pi modal). Demo tenant: Joe's Diner with 3 devices.
## Pitfalls
- **Pi registration code expiry** — codes should auto-expire after 24h to prevent reuse/snooping
- **Offline playback** — player should cache the current playlist locally so it keeps playing if network drops
- **Content moderation** — uploaded files need type/size validation before storage. Allow common image formats (jpg, png, webp) and video (mp4, mov, webm). Reject executables, archives, scripts
- **Multi-user per tenant** — Phase 2 feature but plan the DB schema for it now (users table with tenant_id FK)
- **Scheduling complexity** — time-based playlists need a cron-like scheduler on the backend, not just the player polling interval
- **Player self-healing** — if Chromium crashes (OOM on Pi 3), the service should auto-restart. Player script needs `Restart=always` in the systemd unit
- **Bandwidth** — multiple Pis polling every 60s is negligible. Multiple Pis fetching 140MB video files simultaneously is not. Consider S3 signed URLs or CDN for content delivery at scale