274 lines
11 KiB
Markdown
274 lines
11 KiB
Markdown
# CABINET Digital Signage System - Projektdokumentation
|
|
|
|
**Stand:** Februar 2026 | **Version:** 1.3
|
|
|
|
---
|
|
|
|
## 1. Projektübersicht
|
|
|
|
Das CABINET Digital Signage System ist ein In-Store-Display-System für den CABINET Store in Bielefeld. Es besteht aus zwei eigenständigen Modulen, die auf hochkant montierten Displays (9:16 Seitenverhältnis, 1080x1920px) im Store laufen:
|
|
|
|
| Modul | Datei | Live-URL | Zweck |
|
|
|-------|-------|----------|-------|
|
|
| **Video-Display** | `index.html` | `cabinet.b2in.eu` | Zeigt eine Endlos-Playlist von Videos mit rotierenden Footer-Inhalten (Headline, Subline, QR-Code) |
|
|
| **Angebots-Display** | `offers/player.html` | (noch nicht live) | Zeigt statische Produkt-Slides (Angebote, Preise, Details) als Slide-Rotation |
|
|
| **Info-Tablet** | (in Planung) | `cabinet.b2in.eu/info` | Zeigt Store-Status, Öffnungszeiten, Termine im Schaufenster |
|
|
|
|
Alle Inhalte werden uber das B2in-Backend (Admin-Portal unter `portal.b2in.test`) gepflegt.
|
|
|
|
---
|
|
|
|
## 2. Architektur
|
|
|
|
```
|
|
public/_cabinet/
|
|
├── index.html # LIVE: Video-Display (Hauptseite)
|
|
├── index_1.html # Ältere Version
|
|
├── index_2.html # Ältere Version
|
|
├── index-dynamic.html # Dynamische Variante
|
|
├── index-static-backup.html # Statisches Fallback
|
|
├── index copy.html # Kopie/Backup
|
|
│
|
|
├── offer.html # Prototyp: Angebots-Slides (all-in-one)
|
|
├── offers/ # NEU: Modulares Angebots-System
|
|
│ ├── player.html # Slide-Player (lädt config.json + iFrames)
|
|
│ ├── config.json # Slide-Konfiguration (Reihenfolge, Dauer, Inhalte)
|
|
│ ├── shared-styles.css # Gemeinsame CSS-Styles für alle Slides
|
|
│ ├── slide-0-intro.html # Intro-Slide (Store-Vorstellung)
|
|
│ ├── slide-1-goya-hero.html # Produkt-Slide: GOYA Sideboard (Hero)
|
|
│ ├── slide-2-goya-details.html# Produkt-Slide: GOYA Details/Konditionen
|
|
│ └── slide-3-tando.html # Produkt-Slide: TANDO Spiegel (Impuls)
|
|
│
|
|
├── assets/ # Medien-Dateien
|
|
│ ├── *.mp4 # Videos (Saison-Spots)
|
|
│ ├── *.jpg # Produkt-/Hintergrundbilder
|
|
│ └── cabinet-intro.jpg # Intro-Bild
|
|
│
|
|
├── go.php # QR-Code Redirect + Klick-Tracking
|
|
├── logger.php # Remote-Logging-Endpoint (CORS-fähig)
|
|
├── view-logs.php # Web-basierter Log-Viewer
|
|
├── setup-logging.sh # Logging-Setup-Skript
|
|
├── test-logging.html # Test-Seite für Logging
|
|
├── logs/ # Log-Dateien (nach Level + Datum)
|
|
├── clicks.log # QR-Code-Klick-Log
|
|
│
|
|
├── logo-cabinet-300.png # CABINET Logo (300px)
|
|
├── logo-cabinet.png.webp # CABINET Logo (WebP)
|
|
├── .htaccess.example # Apache-Konfigurationsvorlage
|
|
│
|
|
├── infotablet.md # Konzept: Info-Tablet für Schaufenster
|
|
├── offer.md # Notizen zum Angebots-System
|
|
├── QUICK_START.md # Bedienungsanleitung
|
|
├── KIOSK_MODE_SETUP.md # Anleitung Kiosk-Modus (Fully Browser)
|
|
├── LOGGING_README.md # Logging-Dokumentation
|
|
├── VIDEO_OPTIMIZATION_README.md# Video-Optimierungstipps
|
|
└── CABINET_PROJECT.md # Diese Datei
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Modul A: Video-Display (`index.html`)
|
|
|
|
### Funktionsweise
|
|
- Lädt die Konfiguration (Video-Playlist + Footer-Inhalte) per API vom Backend
|
|
- Spielt Videos nacheinander in einer Endlosschleife ab
|
|
- Footer rotiert unabhängig alle 30 Sekunden (Headline + Subline + QR-Code)
|
|
|
|
### API-Anbindung
|
|
- **Endpoint:** `GET /api/display/config` (auf `b2in.eu`)
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"videoPlaylist": [
|
|
{ "src": "assets/fruehjahr_2025.mp4", "position": 25 }
|
|
],
|
|
"footerContent": [
|
|
{ "headline": "Text", "subline": "Subtext", "url": "https://..." }
|
|
]
|
|
}
|
|
```
|
|
- **Polling:** Alle 5 Minuten wird die Config neu geladen
|
|
- **Präventiver Reload:** Alle 6 Stunden kompletter Page-Reload
|
|
|
|
### Robustheit
|
|
- **Video-Watchdog:** Prüft alle 5 Sek. ob Video läuft, Recovery bei Stuck
|
|
- **Start-Timeout:** 10 Sek. Timeout, dann Skip zum nächsten Video
|
|
- **Memory-Management:** Cleanup nach jedem Video, Monitoring alle 10 Min.
|
|
- **Error-Recovery:** Nach 3 aufeinanderfolgenden Fehlern → Page-Reload
|
|
- **Remote-Logging:** Alle Events werden an `logger.php` gesendet
|
|
|
|
### Layout
|
|
```
|
|
┌─────────────────┐
|
|
│ │
|
|
│ VIDEO-BEREICH │ flex-grow: 1 (nimmt restliche Höhe ein)
|
|
│ (object-fit: │
|
|
│ cover) │
|
|
│ │
|
|
├──────────────────┤
|
|
│ ▬▬▬ Progress ▬▬ │ 3px Progress-Bar
|
|
│ CTA-TEXT │ QR │ ~10% Höhe
|
|
│ Headline │Code │ Footer mit rotierendem Inhalt
|
|
│ Subline │ │
|
|
└─────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Modul B: Angebots-Display (`offers/`)
|
|
|
|
### Funktionsweise
|
|
- `player.html` ist der Haupt-Player
|
|
- Lädt `config.json` für Slide-Konfiguration
|
|
- Jeder Slide ist ein eigenständiges HTML-Dokument, eingebettet per iFrame
|
|
- Slides rotieren automatisch mit konfigurierbarer Dauer (8-12 Sek.)
|
|
- Fade-Transition (0.6s) zwischen Slides
|
|
|
|
### Slide-Typen
|
|
| Typ | Beschreibung | Beispiel |
|
|
|-----|-------------|---------|
|
|
| `intro` | Store-Vorstellung, allgemeiner Willkommenstext | slide-0-intro.html |
|
|
| `product-hero` | Produkt mit Hero-Bild, Preis, UVP | slide-1-goya-hero.html |
|
|
| `product-details` | Produkt-Details mit Bullet-Liste | slide-2-goya-details.html |
|
|
| `product-impulse` | Impulskauf-Produkt ("Jetzt mitnehmen") | slide-3-tando.html |
|
|
|
|
### Slide-Layout (shared-styles.css)
|
|
```
|
|
┌─────────────────────────────┐
|
|
│ HEADER │ Logo + Tagline
|
|
│ [CABINET Logo] [Tagline] │
|
|
├─────────────────────────────┤
|
|
│ │
|
|
│ HERO-BILD │ flex: 1 (nimmt Hauptfläche ein)
|
|
│ (Produktfoto) │
|
|
│ [Badge] │
|
|
│ │
|
|
├──────────────┬──────────────┤
|
|
│ INFO-BOX │ QR-BOX │ Unterer Bereich
|
|
│ Eyebrow │ Titel │
|
|
│ Titel │ QR-Code │
|
|
│ Preis/UVP │ Kontakt │
|
|
│ Bullets │ │
|
|
└──────────────┴──────────────┘
|
|
```
|
|
|
|
### Design-System
|
|
- **Schrift:** IBM Plex Sans (Google Fonts)
|
|
- **Akzentfarbe:** `#009FE3` (Cabinet Blau)
|
|
- **Safe-Area:** 64px Padding
|
|
- **Max. Auflösung:** 1080x1920px (9:16)
|
|
- **QR-Codes:** Werden live per `api.qrserver.com` generiert
|
|
|
|
### Status
|
|
Die Angebots-Slides sind **fertig entwickelt aber noch nicht live**. Die Inhalte (Produkte, Preise, Bilder) sind statisch in den HTML-Dateien hinterlegt. Eine Backend-Anbindung (wie beim Video-Display) fehlt noch.
|
|
|
|
---
|
|
|
|
## 5. Modul C: Info-Tablet (in Planung)
|
|
|
|
Konzept dokumentiert in `infotablet.md`. Ein kleines Tablet im Schaufenster zeigt:
|
|
- Store-Status (Geöffnet/Hinweis/Geschlossen)
|
|
- Öffnungszeiten (Wochenansicht, heutiger Tag hervorgehoben)
|
|
- Nächster freier Beratungstermin
|
|
- Kontakt + QR-Code
|
|
|
|
**API geplant:** `GET /api/cabinet-tablet/status`
|
|
|
|
---
|
|
|
|
## 6. Backend-Anbindung
|
|
|
|
### Datenbank-Tabellen
|
|
|
|
**`display_videos`** - Video-Playlist
|
|
| Spalte | Typ | Beschreibung |
|
|
|--------|-----|-------------|
|
|
| id | bigint | Primary Key |
|
|
| filename | varchar | Dateiname (z.B. `fruehjahr_2025.mp4`) |
|
|
| title | varchar | Anzeige-Titel (optional) |
|
|
| position | int | Vertikale Position des Videos (0-100, für `object-position`) |
|
|
| sort_order | int | Reihenfolge in der Playlist |
|
|
| is_active | tinyint | Aktiv/Inaktiv |
|
|
|
|
**`display_footer_contents`** - Footer-Inhalte (CTA-Texte + QR-Codes)
|
|
| Spalte | Typ | Beschreibung |
|
|
|--------|-----|-------------|
|
|
| id | bigint | Primary Key |
|
|
| headline | varchar | Überschrift (z.B. "JETZT TERMIN BUCHEN") |
|
|
| subline | varchar | Unterzeile (z.B. "Beratung vor Ort...") |
|
|
| url | varchar | Ziel-URL für QR-Code (optional) |
|
|
| short_code | varchar | 6-stelliger Code für Redirect (unique) |
|
|
| clicks | int | Klick-Zähler (via go.php) |
|
|
| sort_order | int | Reihenfolge |
|
|
| is_active | tinyint | Aktiv/Inaktiv |
|
|
|
|
### Backend-Komponenten
|
|
|
|
| Komponente | Pfad | Funktion |
|
|
|-----------|------|----------|
|
|
| API-Controller | `app/Http/Controllers/Api/DisplayConfigController.php` | Liefert JSON-Config für Video-Display |
|
|
| Video-Model | `app/Models/DisplayVideo.php` | Eloquent-Model mit `active()` Scope |
|
|
| Footer-Model | `app/Models/DisplayFooterContent.php` | Model mit Short-Code-Generierung + Short-URL |
|
|
| Admin-Seite | `app/Livewire/Admin/Cms/CabinetDisplay.php` | Livewire-Verwaltung für Videos + Footer |
|
|
| Admin-Route | `/admin/cms/cabinet` | Admin-Portal-Seite |
|
|
| API-Route | `GET /api/display/config` | Öffentlicher API-Endpoint |
|
|
|
|
### QR-Code / Redirect-System
|
|
1. Backend generiert automatisch einen 6-stelligen `short_code` pro Footer-Inhalt
|
|
2. QR-Code im Display zeigt URL wie `cabinet.b2in.eu/go.php?z=abc123`
|
|
3. `go.php` schlägt den Code in der DB nach, erhöht den Klick-Zähler, und leitet weiter
|
|
4. Fallback: Alte Legacy-Codes (t, t1, p, i, f) für Rückwärtskompatibilität
|
|
|
|
---
|
|
|
|
## 7. Logging & Monitoring
|
|
|
|
### Remote-Logging (`logger.php`)
|
|
- Empfängt POST-Requests mit JSON-Logdaten vom Display
|
|
- CORS-aktiviert für Cross-Origin-Zugriff
|
|
- Speichert Logs in drei Formaten:
|
|
- Pro Level: `logs/info_2026-02-27.log`, `logs/error_2026-02-27.log`
|
|
- Alle zusammen: `logs/all_2026-02-27.log`
|
|
- JSON: `logs/json_2026-02-27.log`
|
|
- Automatische Log-Rotation: Dateien > 30 Tage werden gelöscht
|
|
|
|
### Was wird geloggt
|
|
- Video-Lifecycle: Start, Ende, Error, Stuck, Timeout
|
|
- Heartbeat alle 5 Minuten ("Display läuft")
|
|
- Memory-Status alle 10 Minuten
|
|
- Online/Offline-Status
|
|
- JavaScript-Fehler (global error handler)
|
|
- Resource-Loading-Fehler (Bilder, Videos)
|
|
|
|
### Log-Viewer (`view-logs.php`)
|
|
Web-basierte Oberfläche zum Lesen der Logs mit Auto-Refresh und Farbcodierung.
|
|
|
|
---
|
|
|
|
## 8. Deployment & Betrieb
|
|
|
|
### Live-System
|
|
- **Domain:** `cabinet.b2in.eu` (Subdomain von b2in.eu)
|
|
- **Assets-URL:** `https://b2in.eu/_cabinet/assets/`
|
|
- **API-URL:** `https://b2in.eu/api/display/config`
|
|
|
|
### Test-System
|
|
- **URL:** `b2in.test/_cabinet/`
|
|
- **API:** `b2in.test/api/display/config`
|
|
|
|
### Kiosk-Modus
|
|
Empfohlen: **Fully Kiosk Browser** (Android) - Details in `KIOSK_MODE_SETUP.md`
|
|
- Auto-Start bei Boot
|
|
- Vollbild ohne Statusbar
|
|
- Auto-Restart bei Crash
|
|
- Zeitsteuerung (22:00 Standby, 07:00 Aufwachen)
|
|
|
|
---
|
|
|
|
## 9. Offene Punkte / TODO
|
|
|
|
- [ ] **Offers-System Backend-Anbindung**: `offers/` Slides haben noch keine API-Anbindung - Inhalte sind statisch im HTML
|
|
- [ ] **Offers live schalten**: Player + Slides auf Live-System deployen
|
|
- [ ] **Info-Tablet umsetzen**: Konzept steht (infotablet.md), Implementierung offen
|
|
- [ ] **Offers Config aus DB**: `config.json` sollte dynamisch vom Backend generiert werden
|
|
- [ ] **Bilder-Upload**: Produktbilder für Offers werden noch manuell in `assets/` abgelegt
|