10-04-2026
This commit is contained in:
parent
4d6b4930b2
commit
4bb89aad8c
836 changed files with 52961 additions and 5950 deletions
274
public/_cabinet/_docs/CABINET_PROJECT.md
Normal file
274
public/_cabinet/_docs/CABINET_PROJECT.md
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
# 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
|
||||
480
public/_cabinet/_docs/KIOSK_MODE_SETUP.md
Normal file
480
public/_cabinet/_docs/KIOSK_MODE_SETUP.md
Normal file
|
|
@ -0,0 +1,480 @@
|
|||
# Chrome Kiosk-Mode Setup für Android Digital Signage
|
||||
|
||||
## 🎯 Problem
|
||||
|
||||
Bei einem Page-Reload (z.B. nach 6h automatisch) wird der Vollbildmodus beendet - das ist eine Browser-Sicherheitsmaßnahme. Der Vollbildmodus kann nicht automatisch per Script reaktiviert werden.
|
||||
|
||||
## ✅ Die Lösung: Chrome Kiosk-Mode
|
||||
|
||||
Der **Kiosk-Mode** ist die professionelle Lösung für Digital Signage. Chrome läuft dabei permanent im Vollbild ohne Browser-UI.
|
||||
|
||||
---
|
||||
|
||||
## 📱 Option 1: Chrome Kiosk-Mode (Empfohlen für Android)
|
||||
|
||||
### Voraussetzungen:
|
||||
- Android-Gerät (Tablet/Display)
|
||||
- Chrome Browser installiert
|
||||
- ADB (Android Debug Bridge) für Setup
|
||||
|
||||
### Setup-Schritte:
|
||||
|
||||
#### 1. **Developer-Optionen aktivieren**
|
||||
|
||||
1. Gehe zu **Einstellungen** → **Über das Telefon/Tablet**
|
||||
2. Tippe **7x auf "Build-Nummer"**
|
||||
3. Developer-Optionen sind jetzt aktiv
|
||||
|
||||
#### 2. **USB-Debugging aktivieren**
|
||||
|
||||
1. Gehe zu **Einstellungen** → **Entwickleroptionen**
|
||||
2. Aktiviere **"USB-Debugging"**
|
||||
3. Verbinde Gerät per USB mit Computer
|
||||
|
||||
#### 3. **ADB installieren (auf Computer)**
|
||||
|
||||
**Windows:**
|
||||
```bash
|
||||
# Download Android Platform Tools
|
||||
https://developer.android.com/studio/releases/platform-tools
|
||||
|
||||
# Entpacken und zu PATH hinzufügen
|
||||
```
|
||||
|
||||
**macOS:**
|
||||
```bash
|
||||
brew install android-platform-tools
|
||||
```
|
||||
|
||||
**Linux:**
|
||||
```bash
|
||||
sudo apt install android-tools-adb
|
||||
```
|
||||
|
||||
#### 4. **Chrome im Kiosk-Mode starten**
|
||||
|
||||
```bash
|
||||
# Verbindung testen
|
||||
adb devices
|
||||
|
||||
# Chrome beenden
|
||||
adb shell am force-stop com.android.chrome
|
||||
|
||||
# Chrome im Kiosk-Mode starten
|
||||
adb shell am start \
|
||||
-n com.android.chrome/com.google.android.apps.chrome.Main \
|
||||
-a android.intent.action.VIEW \
|
||||
-d "https://cabinet.b2in.eu" \
|
||||
--ez create_new_tab true \
|
||||
--activity-clear-task \
|
||||
--activity-clear-top \
|
||||
--activity-single-top
|
||||
|
||||
# Optional: Vollbild erzwingen
|
||||
adb shell settings put global policy_control immersive.full=*
|
||||
```
|
||||
|
||||
#### 5. **Auto-Start beim Boot (Optional)**
|
||||
|
||||
Erstelle eine Boot-App oder nutze Automate-Apps:
|
||||
|
||||
**Mit MacroDroid (kostenlose App):**
|
||||
1. Installiere MacroDroid aus Play Store
|
||||
2. Erstelle Macro:
|
||||
- **Trigger:** "Device Boot"
|
||||
- **Action:** "Launch Application" → Chrome
|
||||
- **Action:** "Load Webpage" → https://cabinet.b2in.eu
|
||||
3. Speichern und aktivieren
|
||||
|
||||
---
|
||||
|
||||
## 📱 Option 2: Dedicated Kiosk-Browser Apps
|
||||
|
||||
### Empfohlene Apps für Android Digital Signage:
|
||||
|
||||
### **1. Fully Kiosk Browser** (⭐ Empfohlen)
|
||||
|
||||
**Features:**
|
||||
- ✅ Echter Kiosk-Modus (keine UI, kein Zurück-Button)
|
||||
- ✅ Auto-Start beim Boot
|
||||
- ✅ Remote-Management
|
||||
- ✅ Screensaver-Funktion
|
||||
- ✅ Keep Screen On
|
||||
- ✅ Remote-Config via Web-Interface
|
||||
|
||||
**Installation:**
|
||||
```
|
||||
1. Download: https://www.fully-kiosk.com
|
||||
2. Installiere APK auf Android
|
||||
3. Öffne App
|
||||
4. Settings:
|
||||
- Start URL: https://cabinet.b2in.eu
|
||||
- Kiosk Mode: ON
|
||||
- Launch on Boot: ON
|
||||
- Hide System UI: ON
|
||||
- Keep Screen On: ON
|
||||
- Reload on Network Restore: ON
|
||||
5. Lock App (Admin Pin setzen)
|
||||
```
|
||||
|
||||
**Kosten:**
|
||||
- Kostenlos für Single-Device
|
||||
- Plus Version: ~€20 (einmalig) für erweiterte Features
|
||||
|
||||
### **2. Kiosk Browser Lockdown**
|
||||
|
||||
**Features:**
|
||||
- ✅ Einfaches Setup
|
||||
- ✅ Kiosk-Mode
|
||||
- ✅ Auto-Start
|
||||
- ✅ Kostenlos
|
||||
|
||||
**Installation:**
|
||||
```
|
||||
1. Play Store: "Kiosk Browser Lockdown"
|
||||
2. URL setzen: https://cabinet.b2in.eu
|
||||
3. Kiosk Mode aktivieren
|
||||
4. PIN setzen
|
||||
```
|
||||
|
||||
### **3. Chrome mit Custom Launcher**
|
||||
|
||||
**Features:**
|
||||
- ✅ Nutzt Chrome Engine
|
||||
- ✅ Custom Launcher ersetzt Home-Screen
|
||||
- ✅ Kostenlos
|
||||
|
||||
**Apps:**
|
||||
- "Screen On" (Play Store)
|
||||
- "Stay Alive!" (Play Store)
|
||||
- "Screen Alive" (Play Store)
|
||||
|
||||
---
|
||||
|
||||
## 💻 Option 3: Chrome Flags (Desktop/Android)
|
||||
|
||||
### Für Desktop-Testing:
|
||||
|
||||
**Chrome starten mit Flags:**
|
||||
|
||||
**Windows:**
|
||||
```powershell
|
||||
"C:\Program Files\Google\Chrome\Application\chrome.exe" ^
|
||||
--kiosk "https://cabinet.b2in.eu" ^
|
||||
--disable-session-crashed-bubble ^
|
||||
--disable-infobars ^
|
||||
--noerrdialogs ^
|
||||
--disable-translate ^
|
||||
--no-first-run ^
|
||||
--fast-start ^
|
||||
--disable-features=TranslateUI ^
|
||||
--disk-cache-dir=NUL ^
|
||||
--overscroll-history-navigation=0
|
||||
```
|
||||
|
||||
**macOS:**
|
||||
```bash
|
||||
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
|
||||
--kiosk "https://cabinet.b2in.eu" \
|
||||
--disable-session-crashed-bubble \
|
||||
--disable-infobars \
|
||||
--noerrdialogs
|
||||
```
|
||||
|
||||
**Linux:**
|
||||
```bash
|
||||
google-chrome \
|
||||
--kiosk "https://cabinet.b2in.eu" \
|
||||
--disable-session-crashed-bubble \
|
||||
--disable-infobars \
|
||||
--noerrdialogs \
|
||||
--disable-translate \
|
||||
--no-first-run
|
||||
```
|
||||
|
||||
### Flags Erklärung:
|
||||
- `--kiosk` - Vollbild-Modus ohne UI
|
||||
- `--disable-session-crashed-bubble` - Keine "Chrome wurde nicht korrekt beendet" Meldung
|
||||
- `--disable-infobars` - Keine Info-Leisten
|
||||
- `--noerrdialogs` - Keine Error-Dialoge
|
||||
- `--disable-translate` - Keine Übersetzungs-Popups
|
||||
- `--no-first-run` - Kein First-Run-Dialog
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Option 4: Unsere Fallback-Lösung (bereits implementiert)
|
||||
|
||||
### Was haben wir implementiert:
|
||||
|
||||
#### 1. **LocalStorage-Tracking**
|
||||
```javascript
|
||||
// Beim Aktivieren merken
|
||||
localStorage.setItem('cabinet_fullscreen_was_active', 'true');
|
||||
|
||||
// Nach Reload prüfen
|
||||
if (wasFullscreen) {
|
||||
// Auffälliger Reminder anzeigen
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. **Visueller Reminder**
|
||||
- **Orange pulsierender Button** nach Reload
|
||||
- Text: "⚠️ Vollbild aktivieren!"
|
||||
- Automatisch sichtbar wenn Fullscreen vorher aktiv war
|
||||
|
||||
#### 3. **Auto-Retry (30s Delay)**
|
||||
```javascript
|
||||
// Nach 30s automatisch versuchen (falls Kiosk-Mode aktiv)
|
||||
setTimeout(() => {
|
||||
enterFullscreen(); // Wird ignoriert wenn keine User-Geste
|
||||
}, 30000);
|
||||
```
|
||||
|
||||
#### 4. **Logging**
|
||||
```javascript
|
||||
✅ "Fullscreen aktiviert"
|
||||
⚠️ "Fullscreen-Reminder angezeigt"
|
||||
ℹ️ "Fullscreen verlassen"
|
||||
```
|
||||
|
||||
### Vorteile:
|
||||
- ✅ Funktioniert ohne zusätzliche Apps
|
||||
- ✅ Visueller Hinweis dass Fullscreen reaktiviert werden muss
|
||||
- ✅ Nutzer wird "erinnert" nach Reload
|
||||
- ✅ Logging für Monitoring
|
||||
|
||||
### Nachteile:
|
||||
- ❌ Erfordert manuellen Klick nach Reload
|
||||
- ❌ Nicht vollautomatisch
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Empfohlenes Setup für Production
|
||||
|
||||
### Für Android Digital Signage Displays:
|
||||
|
||||
#### **Best Practice:**
|
||||
|
||||
```
|
||||
1. Hardware: Android Tablet/Display
|
||||
└─ Empfohlen: Android 9+ mit min 2GB RAM
|
||||
|
||||
2. Software: Fully Kiosk Browser (Plus)
|
||||
├─ Start URL: https://cabinet.b2in.eu
|
||||
├─ Kiosk Mode: ON
|
||||
├─ Launch on Boot: ON
|
||||
├─ Hide System UI: ON
|
||||
├─ Keep Screen On: ON
|
||||
├─ Reload on Network Restore: ON
|
||||
└─ Remote Management: ON
|
||||
|
||||
3. Network: Kabelgebunden (LAN)
|
||||
└─ Fallback: 5GHz WiFi mit statischer IP
|
||||
|
||||
4. Power: USV/Surge Protection
|
||||
└─ Auto Power-On nach Stromausfall
|
||||
|
||||
5. Monitoring:
|
||||
├─ Fully Kiosk Remote Admin
|
||||
└─ Unsere Logs: view-logs.php
|
||||
```
|
||||
|
||||
### Setup-Checklist:
|
||||
|
||||
- [ ] Android-Gerät vorbereitet
|
||||
- [ ] Fully Kiosk Browser installiert
|
||||
- [ ] Kiosk-Mode konfiguriert
|
||||
- [ ] Auto-Start aktiviert
|
||||
- [ ] System-UI versteckt
|
||||
- [ ] Keep-Screen-On aktiviert
|
||||
- [ ] Remote-Management aktiviert (Optional)
|
||||
- [ ] PIN-Schutz gesetzt
|
||||
- [ ] Display-Helligkeit eingestellt
|
||||
- [ ] Netzwerk getestet (LAN bevorzugt)
|
||||
- [ ] Power-Management konfiguriert
|
||||
- [ ] Test-Lauf 24h durchgeführt
|
||||
- [ ] Monitoring aktiv (Logs checken)
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Troubleshooting
|
||||
|
||||
### Problem: Kiosk-Mode wird nicht aktiviert
|
||||
|
||||
**Lösung 1: Developer-Optionen**
|
||||
```
|
||||
Settings → Developer Options → "Stay Awake" ON
|
||||
```
|
||||
|
||||
**Lösung 2: App-Berechtigungen**
|
||||
```
|
||||
Settings → Apps → Fully Kiosk → Permissions
|
||||
- Display over other apps: ALLOW
|
||||
- Auto-start: ALLOW
|
||||
```
|
||||
|
||||
**Lösung 3: Device Admin**
|
||||
```
|
||||
Settings → Security → Device Administrators
|
||||
- Fully Kiosk Browser: ENABLE
|
||||
```
|
||||
|
||||
### Problem: Display schaltet sich ab
|
||||
|
||||
**Lösung:**
|
||||
```
|
||||
1. Fully Kiosk Settings:
|
||||
- Keep Screen On: ON
|
||||
- Screen Saver: OFF
|
||||
- Prevent Sleep: ON
|
||||
|
||||
2. Android Settings:
|
||||
- Display → Sleep: NEVER
|
||||
- Display → Adaptive Brightness: OFF
|
||||
```
|
||||
|
||||
### Problem: Chrome Exit nach Reload
|
||||
|
||||
**Lösung:**
|
||||
```
|
||||
Nutze Fully Kiosk Browser statt Chrome!
|
||||
- Fully ist speziell für Kiosk designed
|
||||
- Kein ungewolltes Exit möglich
|
||||
- Automatischer Neustart bei Crash
|
||||
```
|
||||
|
||||
### Problem: Zurück-Button verlässt App
|
||||
|
||||
**Lösung:**
|
||||
```
|
||||
Fully Kiosk Settings:
|
||||
- Disable Back Button: ON
|
||||
- Disable Home Button: ON (Device Admin nötig)
|
||||
- Kiosk Mode: Advanced
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Vergleich der Optionen
|
||||
|
||||
| Option | Kosten | Komplexität | Zuverlässigkeit | Empfehlung |
|
||||
|--------|--------|-------------|-----------------|------------|
|
||||
| **Fully Kiosk** | €20 | ⭐⭐ | ⭐⭐⭐⭐⭐ | 🥇 **BEST** |
|
||||
| **Chrome Kiosk (ADB)** | Kostenlos | ⭐⭐⭐⭐ | ⭐⭐⭐ | OK für Tech-Versierte |
|
||||
| **Kiosk Browser Free** | Kostenlos | ⭐⭐ | ⭐⭐⭐ | OK für Testing |
|
||||
| **Unsere Fallback-Lösung** | Kostenlos | ⭐ | ⭐⭐ | Fallback |
|
||||
| **Chrome + Custom Launcher** | Kostenlos | ⭐⭐⭐ | ⭐⭐⭐ | Mittel |
|
||||
|
||||
---
|
||||
|
||||
## 🎬 Quick Start: Fully Kiosk (Empfohlen)
|
||||
|
||||
### 5-Minuten-Setup:
|
||||
|
||||
```bash
|
||||
1. Download: https://www.fully-kiosk.com
|
||||
└─ APK auf Android-Gerät installieren
|
||||
|
||||
2. App öffnen → Settings:
|
||||
Start URL: https://cabinet.b2in.eu
|
||||
|
||||
3. Advanced Settings:
|
||||
[x] Kiosk Mode
|
||||
[x] Launch on Boot
|
||||
[x] Hide System UI
|
||||
[x] Keep Screen On
|
||||
[x] Prevent Sleep
|
||||
|
||||
4. Lock Settings (+ Button):
|
||||
└─ PIN setzen (z.B. 1234)
|
||||
|
||||
5. ✅ Fertig! Display läuft 24/7 im Kiosk-Mode
|
||||
```
|
||||
|
||||
### Remote-Management aktivieren:
|
||||
|
||||
```
|
||||
1. Settings → Remote Administration:
|
||||
[x] Enable Remote Administration
|
||||
[x] Remote Admin from Local Network
|
||||
|
||||
2. Notiere IP-Adresse:
|
||||
z.B. http://192.168.1.100:2323
|
||||
|
||||
3. Öffne vom PC:
|
||||
http://192.168.1.100:2323
|
||||
└─ Password: (Dein PIN)
|
||||
|
||||
4. ✅ Remote-Control aktiv!
|
||||
- Screenshots
|
||||
- Reload
|
||||
- Settings ändern
|
||||
- Screen On/Off
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 Pro-Tipps
|
||||
|
||||
### 1. **Netzwerk-Stabilität**
|
||||
```
|
||||
- LAN bevorzugen (kein WiFi)
|
||||
- Statische IP vergeben
|
||||
- Router/Switch mit QoS
|
||||
- Fully Kiosk: "Reload on Network Restore" ON
|
||||
```
|
||||
|
||||
### 2. **Power-Management**
|
||||
```
|
||||
- USV verwenden
|
||||
- BIOS: "AC Power Recovery" → ON
|
||||
- Android: "Auto Power On" → ON
|
||||
- Fully Kiosk: "Restart on Crash" → ON
|
||||
```
|
||||
|
||||
### 3. **Display-Pflege**
|
||||
```
|
||||
- Bildschirmschoner nach 22:00 Uhr
|
||||
- Helligkeit reduzieren nachts
|
||||
- Pixel-Shift aktivieren (gegen Burn-In)
|
||||
- Display-Timeout: NEVER
|
||||
```
|
||||
|
||||
### 4. **Monitoring**
|
||||
```
|
||||
- Fully Kiosk Remote Admin
|
||||
- Unsere Logs: view-logs.php
|
||||
- Ping-Monitoring (Nagios/Zabbix)
|
||||
- Wöchentliche Checks
|
||||
```
|
||||
|
||||
### 5. **Security**
|
||||
```
|
||||
- Fully Kiosk mit PIN schützen
|
||||
- Device Administrator aktivieren
|
||||
- USB-Debugging OFF (nach Setup)
|
||||
- Unknown Sources OFF
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📞 Support
|
||||
|
||||
### Fully Kiosk Support:
|
||||
- Website: https://www.fully-kiosk.com
|
||||
- Forum: https://www.fully-kiosk.com/forum
|
||||
- Email: support@fully-kiosk.com
|
||||
|
||||
### Unsere Logs:
|
||||
- URL: https://cabinet.b2in.eu/view-logs.php
|
||||
- Check: Fullscreen-Events
|
||||
- Monitor: Memory & Errors
|
||||
|
||||
---
|
||||
|
||||
**Empfehlung:** Investiere die €20 für **Fully Kiosk Browser Plus** - es spart viele Stunden Troubleshooting und ist die stabilste Lösung für Digital Signage! 🎯
|
||||
|
||||
---
|
||||
|
||||
**Last Update:** 2026-01-19
|
||||
**Version:** 1.3
|
||||
215
public/_cabinet/_docs/LOGGING_README.md
Normal file
215
public/_cabinet/_docs/LOGGING_README.md
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
# Cabinet Digital Signage - Logging System
|
||||
|
||||
## 📋 Übersicht
|
||||
|
||||
Dieses erweiterte Logging-System ermöglicht es dir, alle Fehler und Events von den Android-Displays remote zu überwachen, ohne physischen Zugriff auf die Geräte zu benötigen.
|
||||
|
||||
## 🎯 Features
|
||||
|
||||
### Automatisches Logging von:
|
||||
- ✅ **JavaScript-Fehler** (Runtime Errors)
|
||||
- ✅ **Unhandled Promise Rejections** (async/await Fehler)
|
||||
- ✅ **Console Errors & Warnings**
|
||||
- ✅ **Resource Loading Failures** (Videos, Bilder)
|
||||
- ✅ **Video Playback Errors** (mit Media Error Codes)
|
||||
- ✅ **Network Status** (Online/Offline Events)
|
||||
- ✅ **Video Stalling** (Buffering-Probleme)
|
||||
- ✅ **Configuration Loading** (API-Fehler)
|
||||
- ✅ **Heartbeat** (alle 5 Minuten - zeigt dass Display läuft)
|
||||
|
||||
### Log-Levels:
|
||||
- `FATAL` - Kritische JavaScript-Fehler
|
||||
- `ERROR` - Fehler (Video-Loading, Network, etc.)
|
||||
- `WARNING` - Warnungen (Buffering, Connection Lost)
|
||||
- `INFO` - Informationen (Heartbeat, Video Started, Config Loaded)
|
||||
|
||||
## 📂 Dateistruktur
|
||||
|
||||
```
|
||||
public/_cabinet/
|
||||
├── index.html # Haupt-Display-Datei (mit Logging)
|
||||
├── logger.php # Backend-Endpoint für Logs
|
||||
├── view-logs.php # Web-Interface zum Ansehen der Logs
|
||||
├── logs/ # Log-Verzeichnis (wird automatisch erstellt)
|
||||
│ ├── all_2026-01-19.log # Alle Logs des Tages
|
||||
│ ├── error_2026-01-19.log # Nur Errors
|
||||
│ ├── fatal_2026-01-19.log # Nur Fatal Errors
|
||||
│ ├── warning_2026-01-19.log # Nur Warnings
|
||||
│ ├── info_2026-01-19.log # Nur Info
|
||||
│ └── json_2026-01-19.log # JSON Format (für Parsing)
|
||||
└── LOGGING_README.md # Diese Datei
|
||||
```
|
||||
|
||||
## 🚀 Setup
|
||||
|
||||
### 1. Logs-Verzeichnis erstellen (falls nicht automatisch erstellt)
|
||||
```bash
|
||||
mkdir -p public/_cabinet/logs
|
||||
chmod 755 public/_cabinet/logs
|
||||
```
|
||||
|
||||
### 2. PHP-Konfiguration (falls nötig)
|
||||
Stelle sicher, dass PHP Schreibrechte auf das `logs/` Verzeichnis hat:
|
||||
```bash
|
||||
chown -R www-data:www-data public/_cabinet/logs
|
||||
# ODER
|
||||
chmod 777 public/_cabinet/logs # Nur für Development!
|
||||
```
|
||||
|
||||
### 3. Logs ansehen
|
||||
Öffne im Browser:
|
||||
```
|
||||
https://cabinet.b2in.eu/view-logs.php
|
||||
```
|
||||
|
||||
## 📊 Log-Viewer Features
|
||||
|
||||
Der `view-logs.php` bietet:
|
||||
- 📈 **Statistiken** (Anzahl Fatal/Error/Warning/Info)
|
||||
- 🎨 **Farbcodierung** nach Log-Level
|
||||
- 🔍 **Dateiauswahl** (verschiedene Log-Dateien)
|
||||
- ⚡ **Auto-Refresh** (alle 10 Sekunden)
|
||||
- 📏 **Zeilenanzahl** wählbar (50/100/500/1000/alle)
|
||||
|
||||
## 🔒 Sicherheit
|
||||
|
||||
**WICHTIG:** Der Log-Viewer sollte in Produktion geschützt werden!
|
||||
|
||||
### Option 1: .htaccess Passwortschutz
|
||||
```apache
|
||||
# In public/_cabinet/.htaccess
|
||||
<Files "view-logs.php">
|
||||
AuthType Basic
|
||||
AuthName "Restricted Access"
|
||||
AuthUserFile /pfad/zu/.htpasswd
|
||||
Require valid-user
|
||||
</Files>
|
||||
```
|
||||
|
||||
### Option 2: PHP Session-basiert
|
||||
Füge am Anfang von `view-logs.php` hinzu:
|
||||
```php
|
||||
<?php
|
||||
session_start();
|
||||
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
|
||||
// Login-Formular oder Redirect
|
||||
header('Location: /login.php');
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
```
|
||||
|
||||
## 📝 Kontext-Informationen
|
||||
|
||||
Jeder Log-Eintrag enthält automatisch:
|
||||
- **Timestamp** (ISO 8601)
|
||||
- **IP-Adresse** des Displays
|
||||
- **User Agent** (Browser/OS Info)
|
||||
- **Viewport** (Display-Auflösung)
|
||||
- **Connection Status** (online/offline)
|
||||
- **Aktuelles Video** (Dateiname)
|
||||
- **Video Index** (Position in Playlist)
|
||||
- **Footer Index** (Aktueller Footer-Content)
|
||||
- **Playlist-Länge** (Anzahl Videos)
|
||||
|
||||
## 🎮 Manuelle Logs
|
||||
|
||||
Du kannst auch manuell Logs aus dem JavaScript senden:
|
||||
|
||||
```javascript
|
||||
// Info Log
|
||||
window.displayLogger.log('Meine Info-Nachricht', {
|
||||
customData: 'wert'
|
||||
});
|
||||
|
||||
// Warning
|
||||
window.displayLogger.warn('Warnung', {
|
||||
reason: 'Irgendwas ist komisch'
|
||||
});
|
||||
|
||||
// Error
|
||||
window.displayLogger.error('Fehler aufgetreten', {
|
||||
errorCode: 123
|
||||
});
|
||||
|
||||
// Kontext setzen
|
||||
window.displayLogger.setContext('customKey', 'customValue');
|
||||
```
|
||||
|
||||
## 🔄 Log-Rotation
|
||||
|
||||
Logs werden automatisch rotiert:
|
||||
- Separate Dateien pro Tag
|
||||
- Automatische Löschung von Logs älter als 30 Tage
|
||||
- Verschiedene Dateien pro Log-Level
|
||||
|
||||
## 📱 Debugging-Workflow
|
||||
|
||||
1. **Problem entdeckt** → Öffne `view-logs.php`
|
||||
2. **Wähle Log-Datei** → z.B. `error_2026-01-19.log`
|
||||
3. **Schaue Statistiken** → Wie viele Fehler pro Level?
|
||||
4. **Analysiere Logs** → Welches Video? Welcher Footer? Welche IP?
|
||||
5. **Problem beheben** → Update CMS oder Code
|
||||
6. **Monitoring** → Aktiviere Auto-Refresh zum Live-Monitoring
|
||||
|
||||
## 🐛 Häufige Fehlertypen
|
||||
|
||||
### MEDIA_ERR_NETWORK (Code 2)
|
||||
- **Ursache:** Netzwerkprobleme beim Video-Laden
|
||||
- **Lösung:** Prüfe Internetverbindung, Video-URL, Server-Erreichbarkeit
|
||||
|
||||
### MEDIA_ERR_DECODE (Code 3)
|
||||
- **Ursache:** Video-Codec nicht unterstützt oder Datei korrupt
|
||||
- **Lösung:** Video neu encodieren (H.264, AAC)
|
||||
|
||||
### MEDIA_ERR_SRC_NOT_SUPPORTED (Code 4)
|
||||
- **Ursache:** Video-Format nicht unterstützt
|
||||
- **Lösung:** Format zu MP4/WebM ändern
|
||||
|
||||
### Promise Rejection
|
||||
- **Ursache:** Async-Fehler (meist API-Calls)
|
||||
- **Lösung:** Prüfe API-Endpoint, CORS-Settings
|
||||
|
||||
### Stalled Video
|
||||
- **Ursache:** Buffering-Probleme
|
||||
- **Lösung:** Video-Bitrate reduzieren, Netzwerk prüfen
|
||||
|
||||
## 💡 Best Practices
|
||||
|
||||
1. **Regelmäßig Logs checken** - Mindestens 1x pro Woche
|
||||
2. **Statistiken beachten** - Viele Errors/Warnings? → Aktion nötig
|
||||
3. **Heartbeat überwachen** - Kommt alle 5 Min? Display läuft
|
||||
4. **JSON-Logs für Analyse** - Nutze `json_*.log` für automatische Auswertung
|
||||
5. **Log-Level richtig nutzen**:
|
||||
- `FATAL` → Sofort reagieren
|
||||
- `ERROR` → Zeitnah prüfen
|
||||
- `WARNING` → Im Auge behalten
|
||||
- `INFO` → Für Debugging
|
||||
|
||||
## 🔗 Integration mit Monitoring-Tools
|
||||
|
||||
Die JSON-Logs können einfach in Monitoring-Tools integriert werden:
|
||||
|
||||
```bash
|
||||
# Alle Fatal Errors der letzten 24h
|
||||
grep '"level":"FATAL"' public/_cabinet/logs/json_*.log
|
||||
|
||||
# Errors nach IP gruppieren
|
||||
jq -r '.ip' public/_cabinet/logs/json_*.log | sort | uniq -c
|
||||
|
||||
# Häufigste Fehler
|
||||
jq -r '.message' public/_cabinet/logs/json_*.log | sort | uniq -c | sort -rn
|
||||
```
|
||||
|
||||
## 📞 Support
|
||||
|
||||
Bei Fragen oder Problemen:
|
||||
1. Prüfe die Logs in `view-logs.php`
|
||||
2. Schaue dir die Kontext-Informationen an
|
||||
3. Prüfe ob andere Displays gleichen Fehler haben
|
||||
4. Kontaktiere den Support mit Log-Auszug
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.2
|
||||
**Letztes Update:** 2026-01-19
|
||||
292
public/_cabinet/_docs/QUICK_START.md
Normal file
292
public/_cabinet/_docs/QUICK_START.md
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
# Cabinet Digital Signage - Quick Start Guide
|
||||
|
||||
## 🚀 Schnellstart nach Video-Optimierung
|
||||
|
||||
### Was wurde geändert?
|
||||
|
||||
Die Display-Software wurde **massiv optimiert** um das Problem mit schwarzen Bildschirmen nach längerer Laufzeit zu beheben.
|
||||
|
||||
### ✅ Version 1.3 Features:
|
||||
|
||||
1. **Video-Cleanup** - Speicher wird nach jedem Video freigegeben
|
||||
2. **Watchdog** - Überwacht ob Videos laufen und recovered automatisch
|
||||
3. **Start-Timeout** - Videos die nicht starten werden übersprungen
|
||||
4. **Error Recovery** - Automatischer Skip bei defekten Videos
|
||||
5. **Memory-Monitoring** - Speicherüberwachung alle 10 Minuten
|
||||
6. **Präventiver Reload** - Automatischer Neustart alle 6 Stunden
|
||||
7. **Performance-Boost** - CSS Hardware-Beschleunigung aktiviert
|
||||
|
||||
---
|
||||
|
||||
## 📱 Display Setup
|
||||
|
||||
### 1. Display aufrufen
|
||||
```
|
||||
https://cabinet.b2in.eu
|
||||
```
|
||||
|
||||
### 2. Vollbild aktivieren
|
||||
- Klicke auf **"V 1.3"** Button oben links
|
||||
- Display wechselt in Vollbildmodus
|
||||
- Button verschwindet automatisch
|
||||
|
||||
⚠️ **WICHTIG:** Bei einem Page-Reload (nach 6h oder bei Fehlern) wird der Vollbildmodus beendet. Du siehst dann einen **orange pulsierenden Button** mit "⚠️ Vollbild aktivieren!". Einfach erneut klicken.
|
||||
|
||||
💡 **Besser:** Nutze **Fully Kiosk Browser** für permanenten Vollbild ohne manuelles Klicken. Siehe `KIOSK_MODE_SETUP.md`
|
||||
|
||||
### 3. Laufen lassen
|
||||
- Display läuft jetzt automatisch 24/7
|
||||
- Automatischer Reload alle 6 Stunden
|
||||
- Watchdog überwacht Video-Playback
|
||||
- Bei Problemen: Automatische Self-Recovery
|
||||
|
||||
---
|
||||
|
||||
## 📊 Monitoring
|
||||
|
||||
### Log-Viewer öffnen:
|
||||
```
|
||||
https://cabinet.b2in.eu/view-logs.php
|
||||
```
|
||||
|
||||
### Was solltest du sehen:
|
||||
|
||||
#### ✅ Normale Logs (alles OK):
|
||||
```
|
||||
[INFO] Video started: video1.mp4
|
||||
[INFO] Video cleanup durchgeführt
|
||||
[INFO] Heartbeat - Display is running
|
||||
[INFO] Memory Status: 45% (230MB / 512MB)
|
||||
[INFO] Playlist-Loop abgeschlossen
|
||||
```
|
||||
|
||||
#### ⚠️ Warnungen (beobachten):
|
||||
```
|
||||
[WARNING] Video stalled (buffering)
|
||||
[WARNING] Hohe Speicherauslastung (85%)
|
||||
[WARNING] Überspringe zum nächsten Video
|
||||
```
|
||||
|
||||
#### ❌ Fehler (Action nötig):
|
||||
```
|
||||
[ERROR] Video start timeout
|
||||
[ERROR] Video Error: MEDIA_ERR_NETWORK
|
||||
[ERROR] Kritischer Zustand erkannt
|
||||
[FATAL] JavaScript Error
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎬 Video-Upload Checklist
|
||||
|
||||
Beim Hochladen neuer Videos beachten:
|
||||
|
||||
### ✅ Must-Have:
|
||||
- [ ] Format: **MP4** (H.264 + AAC)
|
||||
- [ ] Auflösung: **Max 1920x1080**
|
||||
- [ ] Bitrate: **5-10 Mbps**
|
||||
- [ ] Dateigröße: **Max 100 MB**
|
||||
- [ ] Länge: **15-60 Sekunden** (optimal)
|
||||
|
||||
### ⚠️ Vermeiden:
|
||||
- ❌ Zu große Dateien (>100MB)
|
||||
- ❌ Zu hohe Bitrate (>10 Mbps)
|
||||
- ❌ Zu lange Videos (>3 Min)
|
||||
- ❌ Exotische Formate (MOV, AVI, WMV)
|
||||
- ❌ 4K Videos (overkill für Display)
|
||||
|
||||
### 🔧 Video optimieren (FFmpeg):
|
||||
```bash
|
||||
ffmpeg -i input.mp4 \
|
||||
-c:v libx264 -preset slow -crf 23 \
|
||||
-c:a aac -b:a 128k \
|
||||
-vf scale=1920:1080 \
|
||||
-movflags +faststart \
|
||||
output.mp4
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Problem: Schwarzer Bildschirm
|
||||
|
||||
#### Schritt 1: Logs checken
|
||||
```
|
||||
→ Öffne view-logs.php
|
||||
→ Schaue nach ERROR oder FATAL Logs
|
||||
```
|
||||
|
||||
#### Schritt 2: Was sagt das Log?
|
||||
|
||||
**"Video start timeout"**
|
||||
- Video lädt nicht → Check Video-URL
|
||||
- Video zu groß → Komprimieren
|
||||
- Netzwerkproblem → Check Internet
|
||||
|
||||
**"Video Error: MEDIA_ERR_NETWORK"**
|
||||
- Netzwerk-Issue → Check Router/Internet
|
||||
- Server down → Check b2in.eu erreichbar
|
||||
|
||||
**"Video definitiv stuck"**
|
||||
- ✅ Watchdog hat recovered!
|
||||
- Video wurde übersprungen
|
||||
- Nächstes Video sollte laufen
|
||||
|
||||
**"Hohe Speicherauslastung"**
|
||||
- Videos zu groß → Komprimieren
|
||||
- Zu viele Videos → Playlist verkleinern
|
||||
- Warte auf automatischen Reload (alle 6h)
|
||||
|
||||
#### Schritt 3: Manuelle Actions
|
||||
|
||||
**Display neu laden:**
|
||||
```javascript
|
||||
// In Browser-Console (F12):
|
||||
location.reload();
|
||||
```
|
||||
|
||||
**Display komplett neustarten:**
|
||||
```
|
||||
1. Browser schließen
|
||||
2. Warten 10 Sekunden
|
||||
3. Browser neu öffnen
|
||||
4. URL aufrufen
|
||||
5. Vollbild aktivieren
|
||||
```
|
||||
|
||||
### Problem: Video buffert ständig
|
||||
|
||||
#### Ursachen:
|
||||
- Internetverbindung zu langsam
|
||||
- Video-Bitrate zu hoch
|
||||
- Netzwerk überlastet
|
||||
|
||||
#### Lösung:
|
||||
1. **Check Internet:** Speedtest machen
|
||||
2. **Videos optimieren:** Bitrate reduzieren (5 Mbps)
|
||||
3. **Playlist reduzieren:** Weniger Videos = weniger Daten
|
||||
4. **Router prüfen:** Neustart? Kabel OK?
|
||||
|
||||
### Problem: Footer läuft, Video nicht
|
||||
|
||||
#### Das war das Haupt-Problem! Jetzt gefixt durch:
|
||||
- ✅ Video-Cleanup nach jedem Video
|
||||
- ✅ Watchdog erkennt stuck Videos
|
||||
- ✅ Automatischer Skip/Recovery
|
||||
- ✅ Memory-Management
|
||||
- ✅ Präventiver Reload alle 6h
|
||||
|
||||
#### Falls es DOCH noch passiert:
|
||||
```
|
||||
1. Logs checken: view-logs.php
|
||||
2. Memory-Status prüfen
|
||||
3. Watchdog-Logs suchen
|
||||
4. Falls >3 Fehler: Display reload automatisch
|
||||
5. Falls nicht: Manuell reloaden
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📞 Support
|
||||
|
||||
### Bei Problemen:
|
||||
|
||||
1. **Logs sichern:**
|
||||
- Öffne view-logs.php
|
||||
- Download/Screenshot der Fehler
|
||||
- Besonders ERROR und FATAL Logs
|
||||
|
||||
2. **Info sammeln:**
|
||||
- Welches Display (IP/Standort)?
|
||||
- Wann trat Problem auf?
|
||||
- Was zeigen die Logs?
|
||||
- Memory-Status?
|
||||
|
||||
3. **Kontakt:**
|
||||
- Mit Log-Auszug
|
||||
- Screenshots
|
||||
- Display-Info
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Monitoring-Routine
|
||||
|
||||
### Täglich (optional):
|
||||
- [ ] Kurzer Blick auf Display (läuft es?)
|
||||
- [ ] Bei Problemen: Logs checken
|
||||
|
||||
### Wöchentlich:
|
||||
- [ ] Logs checken (view-logs.php)
|
||||
- [ ] Statistiken ansehen (Fatal/Error/Warning)
|
||||
- [ ] Memory-Status prüfen
|
||||
- [ ] Watchdog-Interventionen zählen
|
||||
|
||||
### Monatlich:
|
||||
- [ ] Alte Logs aufräumen (>30 Tage automatisch)
|
||||
- [ ] Video-Performance überprüfen
|
||||
- [ ] Playlist aktualisieren
|
||||
- [ ] Display-Uptime checken
|
||||
|
||||
---
|
||||
|
||||
## 💡 Tipps & Tricks
|
||||
|
||||
### Performance optimieren:
|
||||
- Halte Playlist klein (5-10 Videos)
|
||||
- Optimiere Videos vor Upload
|
||||
- Nutze konsistente Video-Auflösung
|
||||
- Vermeide sehr lange Videos (>2 Min)
|
||||
|
||||
### Zuverlässigkeit erhöhen:
|
||||
- Lass präventiven Reload aktiv (6h)
|
||||
- Check Logs wöchentlich
|
||||
- Halte Internet-Verbindung stabil
|
||||
- Nutze kabelgebundenes Netzwerk statt WiFi
|
||||
|
||||
### Memory sparen:
|
||||
- Videos komprimieren (H.264, CRF 23)
|
||||
- Playlist auf 10 Videos limitieren
|
||||
- Preload='metadata' (bereits aktiv)
|
||||
- Automatischer Cleanup (bereits aktiv)
|
||||
|
||||
---
|
||||
|
||||
## ✨ Neue Features nutzen
|
||||
|
||||
### Auto-Recovery:
|
||||
```
|
||||
Display recovered jetzt automatisch von:
|
||||
✅ Stuck Videos (Watchdog)
|
||||
✅ Video-Ladefehlern (Skip)
|
||||
✅ Start-Timeouts (Skip)
|
||||
✅ Memory-Problemen (Reload nach 6h)
|
||||
✅ Kritischen Fehlern (Reload)
|
||||
```
|
||||
|
||||
### Logging:
|
||||
```
|
||||
Alle Events werden geloggt:
|
||||
📊 Video-Start/Ende
|
||||
📊 Memory-Status
|
||||
📊 Fehler und Warnungen
|
||||
📊 Watchdog-Interventionen
|
||||
📊 Heartbeats (Display läuft)
|
||||
```
|
||||
|
||||
### Monitoring:
|
||||
```
|
||||
Live-Überwachung möglich:
|
||||
🔍 view-logs.php
|
||||
🔍 Auto-Refresh alle 10s
|
||||
🔍 Statistiken (Fatal/Error/Warning)
|
||||
🔍 Farbcodierung nach Schwere
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.3
|
||||
**Release:** 2026-01-19
|
||||
**Status:** ✅ Production Ready
|
||||
|
||||
🎉 **Viel Erfolg mit dem optimierten Display!**
|
||||
368
public/_cabinet/_docs/VIDEO_OPTIMIZATION_README.md
Normal file
368
public/_cabinet/_docs/VIDEO_OPTIMIZATION_README.md
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
# Cabinet Digital Signage - Video-Optimierung & Robustness
|
||||
|
||||
## 🔧 Problem
|
||||
|
||||
Nach einer gewissen Laufzeit wurden die Videos nicht mehr angezeigt (schwarzer Bildschirm), obwohl der Footer weiterhin funktionierte. Dies deutet auf Memory-Leaks oder einen fehlerhaften Video-Loop hin.
|
||||
|
||||
## ✅ Implementierte Lösungen
|
||||
|
||||
### 1. **Robuster Video-Cleanup** (Memory-Management)
|
||||
|
||||
#### Was wurde gemacht:
|
||||
- **Explizites Video-Cleanup** vor jedem neuen Video:
|
||||
```javascript
|
||||
videoElement.pause();
|
||||
videoElement.removeAttribute('src');
|
||||
videoElement.load(); // Triggert Garbage Collection
|
||||
```
|
||||
- **100ms Delay** nach Cleanup, bevor neues Video geladen wird
|
||||
- **Preload auf 'metadata'** gesetzt (statt 'auto') → weniger Memory-Verbrauch
|
||||
|
||||
#### Warum das hilft:
|
||||
- Browser gibt Speicher des alten Videos frei
|
||||
- Verhindert Memory-Leaks bei langen Laufzeiten
|
||||
- Reduziert gleichzeitig geladene Video-Daten
|
||||
|
||||
### 2. **Video Watchdog** (Überwachung)
|
||||
|
||||
#### Was wurde gemacht:
|
||||
- **Watchdog läuft alle 5 Sekunden**
|
||||
- Prüft ob Video noch läuft (vergleicht `currentTime`)
|
||||
- Erkennt wenn Video "stecken bleibt"
|
||||
- Automatischer Skip zum nächsten Video nach 2x "stuck"
|
||||
|
||||
#### Was wird überwacht:
|
||||
```javascript
|
||||
- currentTime (bewegt sich das Video?)
|
||||
- isPaused (ist Video pausiert?)
|
||||
- hasEnded (ist Video zu Ende?)
|
||||
- isStuck (currentTime ändert sich nicht)
|
||||
```
|
||||
|
||||
#### Warum das hilft:
|
||||
- Erkennt frozen Videos automatisch
|
||||
- Verhindert dass Display hängen bleibt
|
||||
- Selbstheilende Funktion ohne manuellen Eingriff
|
||||
|
||||
### 3. **Start-Timeout** (10 Sekunden)
|
||||
|
||||
#### Was wurde gemacht:
|
||||
- Timeout von 10 Sekunden für Video-Start
|
||||
- Falls Video nicht innerhalb von 10s startet → Skip zum nächsten
|
||||
- Timeout wird geclearet wenn Video erfolgreich startet
|
||||
|
||||
#### Warum das hilft:
|
||||
- Verhindert endloses Warten bei defekten Videos
|
||||
- Display bleibt nicht schwarz wenn Video nicht lädt
|
||||
- Automatische Recovery
|
||||
|
||||
### 4. **Error Recovery** (Fehlerbehandlung)
|
||||
|
||||
#### Was wurde gemacht:
|
||||
- **Automatischer Skip** bei Video-Fehlern
|
||||
- **Consecutive Error Tracking** (zählt aufeinanderfolgende Fehler)
|
||||
- **Max 3 aufeinanderfolgende Fehler** → dann Page-Reload nach 30s
|
||||
- **Error-Logging** mit detaillierten Media Error Codes
|
||||
|
||||
#### Error Codes:
|
||||
- `MEDIA_ERR_ABORTED` (1) - Video-Laden abgebrochen
|
||||
- `MEDIA_ERR_NETWORK` (2) - Netzwerkfehler
|
||||
- `MEDIA_ERR_DECODE` (3) - Dekodierungsfehler
|
||||
- `MEDIA_ERR_SRC_NOT_SUPPORTED` (4) - Format nicht unterstützt
|
||||
|
||||
#### Warum das hilft:
|
||||
- Display recovered automatisch von Fehlern
|
||||
- Verhindert dass ein defektes Video alles blockiert
|
||||
- Bei wiederholten Problemen: Komplett-Neustart
|
||||
|
||||
### 5. **Memory-Monitoring** (Performance-Überwachung)
|
||||
|
||||
#### Was wurde gemacht:
|
||||
- **Memory-Check alle 10 Minuten**
|
||||
- Loggt Speicherverbrauch in MB und Prozent
|
||||
- **Warnung bei >80% Speicherauslastung**
|
||||
- Loggt Video-Buffer-Status
|
||||
|
||||
#### Beispiel-Log:
|
||||
```json
|
||||
{
|
||||
"message": "Memory Status",
|
||||
"context": {
|
||||
"usedMB": 245,
|
||||
"limitMB": 512,
|
||||
"percentUsed": 48
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Warum das hilft:
|
||||
- Frühzeitiges Erkennen von Memory-Problemen
|
||||
- Daten für Troubleshooting und Optimierung
|
||||
- Proaktives Monitoring statt reaktives Debugging
|
||||
|
||||
### 6. **Präventive Maßnahmen**
|
||||
|
||||
#### A) Präventiver Page-Reload (alle 6 Stunden)
|
||||
```javascript
|
||||
setTimeout(() => {
|
||||
location.reload();
|
||||
}, 6 * 60 * 60 * 1000);
|
||||
```
|
||||
- Verhindert Memory-Leaks über sehr lange Laufzeit
|
||||
- Fresh Start alle 6 Stunden
|
||||
- Erfolgt automatisch im Hintergrund
|
||||
|
||||
#### B) Critical Error Check (alle 30 Sekunden)
|
||||
- Überwacht kritische Zustände
|
||||
- Bei 3 kritischen Fehlern → Reload nach 5s
|
||||
- Selbstheilende Funktion
|
||||
|
||||
#### C) CSS Performance-Optimierungen
|
||||
```css
|
||||
#video-player {
|
||||
will-change: transform;
|
||||
transform: translateZ(0);
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
```
|
||||
- Aktiviert Hardware-Beschleunigung
|
||||
- Reduziert Rendering-Last
|
||||
- Optimiert für Video-Playback
|
||||
|
||||
### 7. **Erweiterte Video-Events**
|
||||
|
||||
#### Neue Events die geloggt werden:
|
||||
- `ended` - Video zu Ende
|
||||
- `error` - Video-Fehler (mit Error Code)
|
||||
- `stalled` - Buffering (Video hängt)
|
||||
- `waiting` - Waiting for data
|
||||
- `playing` - Video spielt ab
|
||||
- `canplay` - Video kann abgespielt werden
|
||||
|
||||
#### Warum das hilft:
|
||||
- Vollständige Transparenz über Video-Status
|
||||
- Erkennen von Buffering-Problemen
|
||||
- Debuggen von Playback-Issues
|
||||
|
||||
## 📊 Monitoring & Debugging
|
||||
|
||||
### Was wird jetzt geloggt:
|
||||
|
||||
#### Erfolgreiche Events:
|
||||
```
|
||||
✅ Video cleanup durchgeführt
|
||||
✅ Video started: video1.mp4
|
||||
✅ Video läuft wieder normal
|
||||
✅ Playlist-Loop abgeschlossen, starte von vorne
|
||||
```
|
||||
|
||||
#### Warnungen:
|
||||
```
|
||||
⚠️ Video scheint stecken geblieben zu sein
|
||||
⚠️ Hohe Speicherauslastung (85%)
|
||||
⚠️ Video stalled (buffering)
|
||||
⚠️ Überspringe zum nächsten Video
|
||||
```
|
||||
|
||||
#### Fehler:
|
||||
```
|
||||
❌ Video start timeout (10s überschritten)
|
||||
❌ Video definitiv stuck - starte nächstes
|
||||
❌ Video Error: MEDIA_ERR_NETWORK
|
||||
❌ Kritischer Zustand erkannt
|
||||
```
|
||||
|
||||
### Log-Analyse:
|
||||
|
||||
#### Beispiel 1: Memory-Problem
|
||||
```
|
||||
[INFO] Memory Status: 420MB / 512MB (82%)
|
||||
[WARNING] Hohe Speicherauslastung
|
||||
→ Action: Beobachten, evtl. Videos optimieren
|
||||
```
|
||||
|
||||
#### Beispiel 2: Stuck Video
|
||||
```
|
||||
[WARNING] Video scheint stecken geblieben (2x)
|
||||
[ERROR] Video definitiv stuck - starte nächstes
|
||||
[WARNING] Überspringe zum nächsten Video: watchdog_stuck
|
||||
→ Action: Watchdog hat Recovery durchgeführt ✓
|
||||
```
|
||||
|
||||
#### Beispiel 3: Netzwerkprobleme
|
||||
```
|
||||
[ERROR] Video Error: MEDIA_ERR_NETWORK
|
||||
[WARNING] Überspringe zum nächsten Video: error_MEDIA_ERR_NETWORK
|
||||
[INFO] Video started: video2.mp4
|
||||
→ Action: Netzwerk kurz unterbrochen, automatisch recovered ✓
|
||||
```
|
||||
|
||||
## 🎯 Best Practices für Videos
|
||||
|
||||
### 1. **Video-Format**
|
||||
- **Container:** MP4 (H.264 + AAC)
|
||||
- **Codec:** H.264 (High Profile, Level 4.0)
|
||||
- **Audio:** AAC, 128-256 kbps
|
||||
- **Auflösung:** Max 1920x1080 (Full HD)
|
||||
- **Framerate:** 25 oder 30 fps
|
||||
- **Bitrate:** 5-10 Mbps (nicht höher!)
|
||||
|
||||
### 2. **Video-Länge**
|
||||
- **Optimal:** 15-60 Sekunden
|
||||
- **Maximum:** 2-3 Minuten
|
||||
- **Warum:** Kürzere Videos = weniger Memory-Verbrauch
|
||||
|
||||
### 3. **Dateigrößen**
|
||||
- **Optimal:** 10-50 MB pro Video
|
||||
- **Maximum:** 100 MB pro Video
|
||||
- **Warum:** Schnelleres Laden, weniger Buffering
|
||||
|
||||
### 4. **Playlist-Größe**
|
||||
- **Optimal:** 5-10 Videos
|
||||
- **Maximum:** 20 Videos
|
||||
- **Warum:** Übersichtlich, nicht zu viel Content im Loop
|
||||
|
||||
### 5. **Video-Optimierung**
|
||||
Nutze Tools wie:
|
||||
- **FFmpeg** für Re-Encoding
|
||||
- **HandBrake** für Kompression
|
||||
- **Adobe Media Encoder** für Profis
|
||||
|
||||
#### FFmpeg Beispiel:
|
||||
```bash
|
||||
ffmpeg -i input.mp4 \
|
||||
-c:v libx264 -preset slow -crf 23 \
|
||||
-c:a aac -b:a 128k \
|
||||
-vf scale=1920:1080 \
|
||||
-movflags +faststart \
|
||||
output.mp4
|
||||
```
|
||||
|
||||
## 🔍 Troubleshooting
|
||||
|
||||
### Problem: Videos werden nach einiger Zeit schwarz
|
||||
|
||||
#### Mögliche Ursachen:
|
||||
1. **Memory-Leak** → Check Memory-Logs
|
||||
2. **Video zu groß** → Komprimieren
|
||||
3. **Netzwerkprobleme** → Check Network-Logs
|
||||
4. **Browser-Cache voll** → Wird jetzt automatisch gecleart
|
||||
|
||||
#### Lösung:
|
||||
- ✅ Implementiert: Automatischer Cleanup
|
||||
- ✅ Implementiert: Watchdog erkennt Problem
|
||||
- ✅ Implementiert: Automatischer Skip/Recovery
|
||||
- ✅ Implementiert: Präventiver Reload nach 6h
|
||||
|
||||
### Problem: Video startet nicht
|
||||
|
||||
#### Check in Logs:
|
||||
```
|
||||
[ERROR] Video start timeout
|
||||
[ERROR] Video play failed: MEDIA_ERR_SRC_NOT_SUPPORTED
|
||||
```
|
||||
|
||||
#### Lösung:
|
||||
1. **Video-Format prüfen** (MP4 H.264?)
|
||||
2. **Video-Pfad prüfen** (erreichbar?)
|
||||
3. **Video neu encodieren**
|
||||
4. **Watchdog springt automatisch zum nächsten**
|
||||
|
||||
### Problem: Video buffert ständig
|
||||
|
||||
#### Check in Logs:
|
||||
```
|
||||
[WARNING] Video stalled (buffering)
|
||||
[WARNING] Video waiting (buffering)
|
||||
```
|
||||
|
||||
#### Lösung:
|
||||
1. **Netzwerkverbindung prüfen**
|
||||
2. **Video-Bitrate reduzieren**
|
||||
3. **Preload auf 'metadata'** (bereits implementiert)
|
||||
4. **Video komprimieren**
|
||||
|
||||
### Problem: Hohe Speicherauslastung
|
||||
|
||||
#### Check in Logs:
|
||||
```
|
||||
[WARNING] Hohe Speicherauslastung (85%)
|
||||
```
|
||||
|
||||
#### Lösung:
|
||||
1. **Videos komprimieren**
|
||||
2. **Playlist verkleinern**
|
||||
3. **Präventiver Reload** (bereits aktiv nach 6h)
|
||||
4. **Browser-Cache leeren** (manuell)
|
||||
|
||||
## 📈 Performance-Metriken
|
||||
|
||||
### Empfohlene Werte:
|
||||
- **Memory Usage:** < 70% des Heap-Limits
|
||||
- **Video Start Time:** < 2 Sekunden
|
||||
- **Buffering Events:** < 1 pro Stunde
|
||||
- **Consecutive Errors:** 0
|
||||
- **Watchdog Interventions:** < 1 pro Tag
|
||||
|
||||
### Critical Werte (Action required):
|
||||
- **Memory Usage:** > 85%
|
||||
- **Video Start Time:** > 10 Sekunden (Timeout!)
|
||||
- **Buffering Events:** > 5 pro Stunde
|
||||
- **Consecutive Errors:** ≥ 3
|
||||
- **Watchdog Interventions:** > 10 pro Tag
|
||||
|
||||
## 🚀 Testing
|
||||
|
||||
### 1. **Test im Browser**
|
||||
```
|
||||
1. Öffne https://cabinet.b2in.eu
|
||||
2. Öffne Developer Tools (F12)
|
||||
3. Console Tab öffnen
|
||||
4. Logs beobachten:
|
||||
- "Video cleanup durchgeführt"
|
||||
- "Video started: ..."
|
||||
- Memory-Status nach 30s
|
||||
```
|
||||
|
||||
### 2. **Stress-Test**
|
||||
```
|
||||
1. Lass Display 24h laufen
|
||||
2. Check Logs auf Probleme
|
||||
3. Memory-Status nach 24h prüfen
|
||||
4. Watchdog-Interventionen zählen
|
||||
```
|
||||
|
||||
### 3. **Network-Test**
|
||||
```
|
||||
1. Simuliere schlechte Verbindung (DevTools → Network → Throttling)
|
||||
2. Beobachte Error-Recovery
|
||||
3. Check ob automatischer Skip funktioniert
|
||||
```
|
||||
|
||||
### 4. **Memory-Test**
|
||||
```
|
||||
1. Lass Display 6h laufen
|
||||
2. Check Memory-Logs alle 10 Min
|
||||
3. Sollte < 70% bleiben
|
||||
4. Nach 6h: automatischer Reload
|
||||
```
|
||||
|
||||
## 📋 Changelog
|
||||
|
||||
### Version 1.3 (2026-01-19)
|
||||
- ✅ Video-Cleanup vor jedem neuen Video
|
||||
- ✅ Video Watchdog (5s Interval)
|
||||
- ✅ Start-Timeout (10s)
|
||||
- ✅ Error Recovery mit Consecutive Error Tracking
|
||||
- ✅ Memory-Monitoring (alle 10 Min)
|
||||
- ✅ Präventiver Reload (alle 6h)
|
||||
- ✅ Critical Error Check (alle 30s)
|
||||
- ✅ CSS Performance-Optimierungen
|
||||
- ✅ Erweiterte Video-Events (playing, canplay, waiting)
|
||||
- ✅ Detaillierte Error-Codes mit Logging
|
||||
|
||||
---
|
||||
|
||||
**Status:** ✅ Ready for Production
|
||||
**Tested on:** Chrome 120+ / Android 11+
|
||||
**Last Update:** 2026-01-19
|
||||
175
public/_cabinet/_docs/b2in-display-implementation.md
Normal file
175
public/_cabinet/_docs/b2in-display-implementation.md
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
# B2in Display – Frontend-Implementation
|
||||
|
||||
**Ziel:** Frontend-Webapp für das B2in Schaufenster-Display (9:16 Portrait, 43–55 Zoll).
|
||||
**Pfad:** `public/_cabinet/b2in/index.html`
|
||||
**Konzept-Basis:** `public/_cabinet/_docs/b2in-displays.md`
|
||||
|
||||
---
|
||||
|
||||
## Ist-Zustand
|
||||
|
||||
Es gibt bereits drei Display-Typen unter `public/_cabinet/`:
|
||||
|
||||
| Typ | Pfad | Status | Beschreibung |
|
||||
|-----|------|--------|-------------|
|
||||
| **Video-Display** | `index.html` | Live, stabil | CABINET-Branding. Videos + Footer-Rotation. API: `/api/display/config` |
|
||||
| **Offers** | `offers/index.html` | Entwickelt, nicht live | CABINET-Branding. iFrame-basierte Slide-Rotation mit `config.json` |
|
||||
| **Info-Tablet** | `info/index.html` | Entwickelt | CABINET-Branding. Store-Status/Öffnungszeiten. API: `/api/cabinet-tablet/status` |
|
||||
| **B2in Display** | `b2in/` | **Neu – wird jetzt gebaut** | B2in-Branding. Playlist mit Videos/Bildern + Text. API: `/api/b2in-display/playlist` |
|
||||
|
||||
---
|
||||
|
||||
## Architektur-Übersicht
|
||||
|
||||
```
|
||||
public/_cabinet/b2in/
|
||||
├── index.html ← Haupt-Webapp (Playlist-Engine + UI)
|
||||
├── b2in-styles.css ← Display-spezifische Styles
|
||||
└── (assets/) ← Medien werden per API/URL referenziert, nicht lokal
|
||||
```
|
||||
|
||||
Shared CSS aus `public/_cabinet/shared/cabinet-base.css` wird **nicht** importiert – das B2in-Display hat ein eigenständiges Branding (dunkel, B2in statt CABINET). Es ist ein komplett eigenes Design-System.
|
||||
|
||||
---
|
||||
|
||||
## Schritte
|
||||
|
||||
### Schritt 1: HTML-Grundgerüst + CSS
|
||||
|
||||
**Datei:** `public/_cabinet/b2in/index.html` + `b2in-styles.css`
|
||||
|
||||
Layout gemäß Konzept (Abschnitt 2.1):
|
||||
|
||||
```
|
||||
┌─────────────────────────┐
|
||||
│ HEADER │ ← B2in-Logo (links) + Claim (rechts)
|
||||
│ B2in · Claim │ Fest, immer sichtbar
|
||||
├─────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────┐ │ ← Gradient oben (dunkel → transparent)
|
||||
│ │ VIDEO / BILD │ │ 16:9 Content-Bereich
|
||||
│ │ (16:9 Media) │ │ object-fit: cover
|
||||
│ └─────────────────┘ │ ← Gradient unten (transparent → dunkel)
|
||||
│ │
|
||||
├─────────────────────────┤
|
||||
│ TEXTFELD │ ← Headline (max 40 Zeichen)
|
||||
│ Headline + Subline │ Subline (max 80 Zeichen)
|
||||
├─────────────────────────┤ Wechselt synchron mit Media
|
||||
│ FOOTER │ ← "Marcel Scheibe" + "b2in.de" + QR-Code
|
||||
│ Name · URL · QR │ Fest, immer sichtbar
|
||||
└─────────────────────────┘
|
||||
```
|
||||
|
||||
**Design-Entscheidungen:**
|
||||
- Dunkler Hintergrund (#0a0a0a) – B2in-Branding, nicht CABINET-weiß
|
||||
- 9:16 Aspect Ratio Container (wie bestehende Displays)
|
||||
- Gradient-Overlays oben/unten über dem Media-Bereich
|
||||
- IBM Plex Sans Font (wie alle Cabinet-Displays)
|
||||
- Akzentfarbe: B2in-Blau (wird aus Branding-Guide übernommen)
|
||||
- Kein CABINET-Logo, kein Accent #009FE3
|
||||
|
||||
### Schritt 2: Playlist-Engine (JavaScript)
|
||||
|
||||
**Klasse:** `B2inDisplayApp`
|
||||
|
||||
Kernfunktionalität:
|
||||
1. **API laden** → `GET /api/b2in-display/playlist` (wird später gebaut, erstmal Mock/Fallback)
|
||||
2. **Playlist sortieren** → nach `sort_order`, nur `is_active === true`
|
||||
3. **Gewichtung anwenden** → 70/30 Immobilien/Möbel-Verteilung berechnen
|
||||
4. **Rotation starten** → Item für Item durchspielen
|
||||
|
||||
Item-Wechsel-Logik:
|
||||
- **Video:** Abspielen bis Ende → nächstes Item
|
||||
- **Bild:** `duration_seconds` abwarten → nächstes Item
|
||||
- **Am Ende der Playlist:** Von vorne beginnen
|
||||
|
||||
### Schritt 3: Video-Handling
|
||||
|
||||
Bewährtes Pattern aus dem bestehenden `index.html` übernehmen:
|
||||
- `autoplay muted playsinline` für Browser-Autoplay-Policy
|
||||
- Memory-Management: `src` leeren + `load()` nach jedem Video
|
||||
- Preloading: Nächstes Item im Hintergrund vorladen
|
||||
- Start-Timeout (10s) → bei Timeout überspringen
|
||||
- Watchdog: Prüft alle 5s ob Video noch läuft
|
||||
- Error-Handling: Bei Fehler → Item überspringen, nie schwarzer Screen
|
||||
|
||||
### Schritt 4: Bild-Handling
|
||||
|
||||
- `<img>` Element mit `object-fit: cover`
|
||||
- Duration aus Item oder globaler `default_image_duration`
|
||||
- Ken-Burns-Effekt (optionaler langsamer Zoom per CSS)
|
||||
- Preload via `new Image()` im Hintergrund
|
||||
|
||||
### Schritt 5: Transitions
|
||||
|
||||
Drei Typen (per CMS-Setting steuerbar):
|
||||
|
||||
| Typ | Umsetzung |
|
||||
|-----|-----------|
|
||||
| `fade` | Opacity 1→0, dann 0→1 |
|
||||
| `crossfade` | Neues Element über dem alten einblenden (empfohlen, Standard) |
|
||||
| `slide` | CSS transform translateX |
|
||||
|
||||
Text-Synchronisation:
|
||||
1. Text fade-out (400ms)
|
||||
2. Neuen Text setzen
|
||||
3. Text fade-in (400ms)
|
||||
4. Startet 200ms vor Media-Wechsel
|
||||
|
||||
### Schritt 6: Polling + Stabilität
|
||||
|
||||
Gleicher Ansatz wie Info-Tablet, aber mit 60s Intervall:
|
||||
|
||||
- **Lightweight Check** alle 60s → `GET /api/b2in-display/check`
|
||||
- **Full Fetch** nur bei Timestamp-Änderung
|
||||
- Laufendes Video/Bild wird zu Ende gespielt, dann neue Playlist
|
||||
- localStorage-Cache als Offline-Fallback
|
||||
- Auto-Reload alle 6 Stunden
|
||||
- Connection-Recovery: 3 Fehler → 5 Min Pause → Retry
|
||||
- 30 Min offline → Page-Reload
|
||||
|
||||
### Schritt 7: Standby-Modus
|
||||
|
||||
Wenn `display_active === false`:
|
||||
- Nur B2in-Logo auf dunklem Hintergrund
|
||||
- Kein Content, kein Textfeld, kein Footer-Text
|
||||
- Polling läuft weiter (wartet auf Aktivierung)
|
||||
|
||||
### Schritt 8: Error-Overlay
|
||||
|
||||
Bei kritischen Fehlern (keine Playlist, kein Media):
|
||||
- Dezentes B2in-Logo auf dunklem Hintergrund
|
||||
- Niemals Browser-Fehler oder weißer Screen
|
||||
- Automatischer Retry im Hintergrund
|
||||
|
||||
---
|
||||
|
||||
## API-Abhängigkeit
|
||||
|
||||
Das Frontend wird **zunächst mit Mock-Daten** gebaut. Die API (`/api/b2in-display/playlist` + `/check`) wird als separater Schritt im Backend implementiert. Das Frontend erkennt automatisch, ob die API verfügbar ist, und fällt auf eingebettete Demo-Daten zurück.
|
||||
|
||||
**Mock-Playlist für Entwicklung:**
|
||||
```javascript
|
||||
const MOCK_PLAYLIST = {
|
||||
settings: {
|
||||
display_active: true,
|
||||
footer_name: "Marcel Scheibe",
|
||||
footer_url: "b2in.de",
|
||||
transition: { type: "crossfade", duration_ms: 800 },
|
||||
default_image_duration: 10
|
||||
},
|
||||
items: [
|
||||
// Demo-Items mit Platzhalter-Medien
|
||||
],
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Abgrenzung (was NICHT in diesem Schritt passiert)
|
||||
|
||||
- Kein CMS-Backend (Model, Migration, Controller, Admin-UI) → separater Schritt
|
||||
- Kein Media-Upload → Videos/Bilder werden per URL referenziert
|
||||
- Keine Gewichtungs-Logik im Backend → wird im Frontend berechnet
|
||||
- Keine Änderung am bestehenden Video-Display (`index.html`) → bleibt unberührt
|
||||
386
public/_cabinet/_docs/b2in-displays.md
Normal file
386
public/_cabinet/_docs/b2in-displays.md
Normal file
|
|
@ -0,0 +1,386 @@
|
|||
# B2in Schaufenster-Display – Entwicklungskonzept
|
||||
|
||||
**Status:** Entwicklungsvorlage | Februar 2026
|
||||
|
||||
---
|
||||
|
||||
## 1. Projektübersicht
|
||||
|
||||
### 1.1 Zweck
|
||||
|
||||
Ein großformatiges Display im Schaufenster des CABINET Stores in Bielefeld zeigt B2in-Content im Hochformat (9:16). Ziel: Laufkundschaft in 3–5 Sekunden eine klare Botschaft vermitteln – B2in als Marke für internationale Immobilien und exklusive Einrichtungskonzepte. Das Display läuft parallel zum CABINET-Schaufenster und ist eigenständig gebrandet.
|
||||
|
||||
### 1.2 Technischer Ansatz
|
||||
|
||||
Die Anzeige wird als Webapp unter einer Subdomain ( Subdomain (`cabinet.b2in.eu/info <- live / [`https://b2in.test/_cabinet](https://b2in.test/_cabinet)/info ← testserver) bereitgestellt. Ein Smart TV mit android greift im Vollbildmodus über den Browser darauf zu. Inhalte (Videos, Bilder, Texte) werden über das B2in-Backend (CMS) gepflegt und rotieren automatisch.
|
||||
|
||||
### 1.3 Branding
|
||||
|
||||
Ausschließlich B2in-Branding. Kein CABINET-Logo, kein Azizi, keine Partnerlogos. Der Frame zeigt: B2in-Logo, Claim "Connecting Design & Property", Marcel Scheibe als Person, b2in.de und QR-Code.
|
||||
|
||||
---
|
||||
|
||||
## 2. Display-Architektur
|
||||
|
||||
### 2.1 Formatierung
|
||||
|
||||
Das Display steht im **9:16 Hochformat (Portrait)**. Das Videomaterial liegt im **16:9 Querformat** vor. Daraus ergibt sich ein natürlicher Split:
|
||||
|
||||
`┌─────────────────────────┐
|
||||
│ HEADER │ ← Fester Bereich: Logo + Claim
|
||||
│ B2in · Claim │
|
||||
├─────────────────────────┤
|
||||
│ │
|
||||
│ │ ← Oberer Leerraum (Gradient zum Video)
|
||||
│ ┌───────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ VIDEO / BILD │ │ ← 16:9 Content-Bereich (rotierend)
|
||||
│ │ (16:9) │ │
|
||||
│ │ │ │
|
||||
│ └───────────────────┘ │
|
||||
│ │ ← Unterer Leerraum (Gradient zum Text)
|
||||
│ │
|
||||
├─────────────────────────┤
|
||||
│ TEXTFELD │ ← Rotierender Text (Headline + Subline)
|
||||
│ Headline + Subline │
|
||||
├─────────────────────────┤
|
||||
│ FOOTER │ ← Fester Bereich: Name + URL + QR
|
||||
│ Marcel Scheibe · QR │
|
||||
└─────────────────────────┘`
|
||||
|
||||
### 2.2 Bereiche im Detail
|
||||
|
||||
| # | Bereich | Inhalt | Verhalten |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | **Header** | B2in-Logo (links) + Claim "Connecting Design & Property" (rechts). | Fest. Steht permanent, unabhängig vom Content. |
|
||||
| 2 | **Content-Bereich** | 16:9 Video (MP4) oder Einzelbild (JPG/PNG). Nimmt ca. 50–60% der Screenhöhe ein. Oben und unten Gradient-Übergang zum dunklen Hintergrund. | Rotiert automatisch. Reihenfolge und Dauer per CMS steuerbar. |
|
||||
| 3 | **Textfeld** | Headline (max. 40 Zeichen) + Subline (max. 80 Zeichen). Passt sich dem aktuellen Content an. | Wechselt synchron mit dem Video/Bild. Sanfte Fade-Transition. |
|
||||
| 4 | **Footer** | "Marcel Scheibe" (Name) + "b2in.de" (URL) + QR-Code (rechts). | Fest. Steht permanent. |
|
||||
|
||||
---
|
||||
|
||||
## 3. Content-Rotation (Playlist-System)
|
||||
|
||||
### 3.1 Konzept
|
||||
|
||||
Das Display zeigt eine Playlist von Content-Items, die automatisch durchrotieren. Jedes Item besteht aus einem Medienelement (Video oder Bild) plus passendem Text.
|
||||
|
||||
### 3.2 Gewichtung
|
||||
|
||||
Die Rotation folgt einer definierten Gewichtung:
|
||||
|
||||
| Kategorie | Anteil | Beispiel-Content |
|
||||
| --- | --- | --- |
|
||||
| **Immobilien** | ~70% | Dubai-Projekte, internationale Lifestyle-Aufnahmen, Architektur |
|
||||
| **Möbel / Einrichtung** | ~30% | Lokale Händler-Highlights, Einrichtungskonzepte, Interior-Design |
|
||||
|
||||
Die Gewichtung wird über ein `category`-Feld pro Item gesteuert. Das Frontend berechnet die Rotation so, dass die Verteilung über einen Durchlauf eingehalten wird (z. B. bei 10 Items: 7× Immobilien, 3× Möbel).
|
||||
|
||||
### 3.3 Content-Item Struktur
|
||||
|
||||
Jedes Playlist-Item hat folgende Eigenschaften:
|
||||
|
||||
| Feld | Typ | Beschreibung |
|
||||
| --- | --- | --- |
|
||||
| `id` | Auto | Eindeutige ID |
|
||||
| `title` | Text (intern) | Interner Name zur Identifikation im CMS (wird nicht angezeigt) |
|
||||
| `category` | Dropdown | `immobilien` | `moebel` – bestimmt die Gewichtung in der Rotation |
|
||||
| `media_type` | Dropdown | `video` | `image` |
|
||||
| `media_file` | Upload (MP4/JPG/PNG) | Mediendatei. Videos: MP4, H.264, max. 1080p. Bilder: JPG/PNG, min. 1920x1080. |
|
||||
| `media_url` | URL (optional) | Alternative zu Upload: Externe Video-/Bild-URL. Wird bevorzugt wenn vorhanden. |
|
||||
| `headline` | Text | Max. 40 Zeichen. Wird im Textfeld angezeigt. |
|
||||
| `subline` | Text | Max. 80 Zeichen. Erklärender Text unter der Headline. |
|
||||
| `duration_seconds` | Zahl | Anzeigedauer in Sekunden. Für Bilder: empfohlen 8–12 Sek. Für Videos: wird ignoriert, Dauer ergibt sich aus Videolänge. |
|
||||
| `sort_order` | Zahl | Reihenfolge in der Playlist. Niedrigste Zahl zuerst. |
|
||||
| `is_active` | Toggle | Aktiv/Inaktiv. Inaktive Items werden übersprungen. |
|
||||
|
||||
### 3.4 Beispiel-Playlist
|
||||
|
||||
| # | Titel (intern) | Kategorie | Typ | Headline | Subline | Dauer |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| 1 | Dubai Skyline Video | immobilien | video | Internationale Immobilien — Ihr Einstieg. | Beratung, Begleitung und Vermittlung. Persönlich. Transparent. | (Video) |
|
||||
| 2 | Dubai Villa Rendering | immobilien | image | Ihr Zuhause. Weltweit. | Von Dubai bis Europa – wir finden Ihre Immobilie. | 10s |
|
||||
| 3 | Möbel Showroom | moebel | image | Exklusive Einrichtung — Lokal. Für Sie. | Kuratierte Möbelkonzepte von lokalen Fachhändlern. | 10s |
|
||||
| 4 | Dubai Pool Lifestyle | immobilien | video | Dubai. Lissabon. Und morgen? | Internationale Immobilien als Kapitalanlage. | (Video) |
|
||||
| 5 | Dubai Apartment Tour | immobilien | video | Neubau ab 3.000 €/m² | Wertsteigerung. Steuervorteile. Persönliche Begleitung. | (Video) |
|
||||
| 6 | Interior Design Mood | moebel | image | Lokale Händler. Echte Stücke. | Ausstellungsstücke und Designmöbel aus Ihrer Region. | 10s |
|
||||
| 7 | Dubai Cityscape Drone | immobilien | video | Ihr Immobilien-Dolmetscher. | Marcel Scheibe begleitet Sie durch den gesamten Kaufprozess. | (Video) |
|
||||
|
||||
---
|
||||
|
||||
## 4. CMS-Felder (B2in-Backend)
|
||||
|
||||
Im B2in-Backend wird ein eigener Bereich „B2in Display" angelegt mit zwei Ebenen: globale Einstellungen und die Playlist-Items.
|
||||
|
||||
### 4.1 Globale Einstellungen
|
||||
|
||||
| Feldname | Typ | Beschreibung |
|
||||
| --- | --- | --- |
|
||||
| `display_active` | Toggle | Master-Schalter. Wenn deaktiviert, zeigt das Display einen Standby-Screen (nur Logo). |
|
||||
| `footer_name` | Text | Name im Footer. Standard: "Marcel Scheibe" |
|
||||
| `footer_url` | Text | URL im Footer. Standard: "b2in.de" |
|
||||
| `qr_code_image` | Upload (PNG/SVG) | QR-Code Asset für den Footer. |
|
||||
| `rotation_weight_immobilien` | Zahl (%) | Soll-Anteil Immobilien-Content. Standard: 70. |
|
||||
| `rotation_weight_moebel` | Zahl (%) | Soll-Anteil Möbel-Content. Standard: 30. |
|
||||
| `default_image_duration` | Zahl (Sek.) | Standard-Anzeigedauer für Bilder, wenn beim Item nichts eingetragen. Standard: 10. |
|
||||
| `transition_type` | Dropdown | `fade` | `slide` | `crossfade` – Übergangseffekt zwischen Items. Standard: crossfade. |
|
||||
| `transition_duration_ms` | Zahl | Dauer der Transition in Millisekunden. Standard: 800. |
|
||||
|
||||
### 4.2 Playlist-Items
|
||||
|
||||
Wiederholbare Einträge (Repeater-Feld oder eigene Collection), Felder wie in Abschnitt 3.3 definiert.
|
||||
|
||||
### 4.3 Zeichenlimit-Hinweise für Marcel
|
||||
|
||||
Im CMS sollten bei den Textfeldern visuelle Hinweise erscheinen:
|
||||
|
||||
- **Headline:** Zähler „12/40 Zeichen" – wird rot ab 35
|
||||
- **Subline:** Zähler „45/80 Zeichen" – wird rot ab 70
|
||||
- **Begründung:** Auf dem Display müssen die Texte in 3 Sekunden lesbar sein. Längere Texte werden nicht gelesen.
|
||||
|
||||
---
|
||||
|
||||
## 5. API-Endpoint
|
||||
|
||||
### 5.1 Endpoint-Struktur
|
||||
|
||||
`GET /api/b2in-display/playlist`
|
||||
|
||||
**Response (JSON):**
|
||||
|
||||
json
|
||||
|
||||
`{
|
||||
"settings": {
|
||||
"display_active": true,
|
||||
"footer_name": "Marcel Scheibe",
|
||||
"footer_url": "b2in.de",
|
||||
"qr_code_url": "/assets/qr-b2in.svg",
|
||||
"rotation_weights": {
|
||||
"immobilien": 70,
|
||||
"moebel": 30
|
||||
},
|
||||
"default_image_duration": 10,
|
||||
"transition": {
|
||||
"type": "crossfade",
|
||||
"duration_ms": 800
|
||||
}
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"id": 1,
|
||||
"category": "immobilien",
|
||||
"media_type": "video",
|
||||
"media_url": "/media/display/dubai-skyline.mp4",
|
||||
"headline": "Internationale Immobilien — Ihr Einstieg.",
|
||||
"subline": "Beratung, Begleitung und Vermittlung. Persönlich. Transparent.",
|
||||
"duration_seconds": null,
|
||||
"sort_order": 1,
|
||||
"is_active": true
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"category": "moebel",
|
||||
"media_type": "image",
|
||||
"media_url": "/media/display/showroom-lokal.jpg",
|
||||
"headline": "Exklusive Einrichtung — Lokal. Für Sie.",
|
||||
"subline": "Kuratierte Möbelkonzepte von lokalen Fachhändlern.",
|
||||
"duration_seconds": 10,
|
||||
"sort_order": 3,
|
||||
"is_active": true
|
||||
}
|
||||
],
|
||||
"updated_at": "2026-02-26T14:30:00Z"
|
||||
}`
|
||||
|
||||
### 5.2 Update-Mechanismus (Polling)
|
||||
|
||||
Gleicher Ansatz wie beim CABINET Info-Tablet:
|
||||
|
||||
**1. Lightweight Check (alle 60 Sekunden):**
|
||||
|
||||
`GET /api/b2in-display/check`
|
||||
|
||||
json
|
||||
|
||||
`{ "updated_at": "2026-02-26T14:30:00Z" }`
|
||||
|
||||
**2. Full Fetch (nur bei Änderung):**
|
||||
Wenn Timestamp abweicht → komplette Playlist neu laden. Laufendes Video wird zu Ende gespielt, dann greift die neue Playlist.
|
||||
|
||||
**Warum 60 statt 30 Sekunden?** Das Display zeigt eine Playlist, keine Echtzeit-Infos. Wenn Marcel ein neues Video hochlädt, ist eine Verzögerung von maximal 60 Sekunden völlig akzeptabel.
|
||||
|
||||
---
|
||||
|
||||
## 6. Frontend-Logik
|
||||
|
||||
### 6.1 Playlist-Engine
|
||||
|
||||
Das Frontend implementiert eine einfache Playlist-Engine:
|
||||
|
||||
`Ablauf:
|
||||
1. Playlist laden (API-Call)
|
||||
2. Nur aktive Items filtern (is_active === true)
|
||||
3. Items nach sort_order sortieren
|
||||
4. Gewichtung anwenden:
|
||||
- Items nach Kategorie gruppieren
|
||||
- Rotation so mischen, dass die %-Verteilung eingehalten wird
|
||||
- Beispiel bei 70/30: I, I, M, I, I, I, M, I, I, M (bei 10 Items)
|
||||
5. Erstes Item anzeigen
|
||||
6. Bei Video: Warten bis Video endet → nächstes Item
|
||||
7. Bei Bild: duration_seconds abwarten → nächstes Item
|
||||
8. Am Ende der Playlist: Von vorne beginnen
|
||||
9. Zwischen Items: Transition (crossfade/fade/slide)`
|
||||
|
||||
### 6.2 Video-Handling
|
||||
|
||||
| Aspekt | Spezifikation |
|
||||
| --- | --- |
|
||||
| **Format** | MP4, H.264 Codec, max. 1080p (1920x1080) |
|
||||
| **Autoplay** | Videos starten automatisch, gemutet (Browser-Policy). Ton ist nicht relevant für Schaufenster-Display. |
|
||||
| **Ladezeit** | Videos werden im Hintergrund vorgeladen (nächstes Item in der Playlist wird gepreloaded während das aktuelle läuft). |
|
||||
| **Fehlerfälle** | Wenn ein Video nicht lädt (404, Netzwerkfehler): Item überspringen, nächstes anzeigen. Fehler loggen. |
|
||||
| **Loop** | Kein Loop pro Video. Jedes Video spielt einmal, dann kommt das nächste Playlist-Item. |
|
||||
|
||||
### 6.3 Bild-Handling
|
||||
|
||||
| Aspekt | Spezifikation |
|
||||
| --- | --- |
|
||||
| **Format** | JPG oder PNG, min. 1920x1080 Pixel |
|
||||
| **Skalierung** | `object-fit: cover` – Bild füllt den 16:9-Bereich, wird bei Bedarf beschnitten. |
|
||||
| **Dauer** | Aus `duration_seconds` des Items oder `default_image_duration` aus den globalen Settings. |
|
||||
| **Ken-Burns-Effekt (optional)** | Langsamer Zoom-In während der Anzeigedauer. Macht statische Bilder lebendiger. Per CSS-Animation, kein JavaScript nötig. |
|
||||
|
||||
### 6.4 Text-Synchronisation
|
||||
|
||||
Headline und Subline wechseln synchron mit dem Media-Content:
|
||||
|
||||
1. Aktuelles Textfeld ausblenden (fade-out, 400ms)
|
||||
2. Neuen Text setzen
|
||||
3. Neues Textfeld einblenden (fade-in, 400ms)
|
||||
4. Timing: Text-Transition startet 200ms vor dem Media-Wechsel, damit beides gleichzeitig erscheint.
|
||||
|
||||
---
|
||||
|
||||
## 7. Technische Stabilität & Kiosk-Betrieb
|
||||
|
||||
### 7.1 Hardware-Setup
|
||||
|
||||
| Komponente | Empfehlung |
|
||||
| --- | --- |
|
||||
| **Display** | TV/Monitor im Hochformat (9:16), 43–55 Zoll. Full HD ausreichend (1080x1920 in Portrait). LED/LCD mit hoher Helligkeit (min. 350 nits, ideal 500+ nits für Schaufenster mit Sonneneinstrahlung). |
|
||||
| **Media Player** | Dedizierter Android-Stick oder -Box (z. B. Amazon Fire TV Stick 4K, Xiaomi Mi Box, oder professionell: BrightSign). Alternativ: Smart TV mit Browser. |
|
||||
| **Kiosk-Software** | Fully Kiosk Browser (wenn Android). Bei BrightSign: eigene Kiosk-Funktionalität. |
|
||||
| **Halterung** | VESA-Wandhalterung, Portrait-Montage. Ggf. mit Blickwinkelschutz-Folie wenn das Display zu nah an der Scheibe steht. |
|
||||
| **Stromversorgung** | Dauerstrom. Optional: Zeitschaltuhr oder Smart Plug für automatisches Ein/Aus (z. B. 07:00–22:00). |
|
||||
| **WLAN** | Stabiles Store-WLAN. Bei Verbindungsproblemen: LAN-Adapter als Fallback. |
|
||||
|
||||
### 7.2 Webapp-seitige Stabilität
|
||||
|
||||
| Maßnahme | Beschreibung |
|
||||
| --- | --- |
|
||||
| **Auto-Reload** | Kompletter Page-Reload alle 6 Stunden. Räumt Speicher auf – besonders wichtig bei Video-Wiedergabe, die Memory Leaks verursachen kann. |
|
||||
| **Video-Memory-Management** | Nach jedem Video: `src` des Video-Elements leeren und neu setzen, damit der Browser den Speicher freigibt. Kein Stapeln von Video-Elementen. |
|
||||
| **Offline-Fallback** | Wenn API nicht erreichbar: Letzte Playlist aus localStorage abspielen. Kein schwarzer Bildschirm. |
|
||||
| **Connection-Recovery** | Polling-Fehler 3x hintereinander → 5 Min. Pause → erneut versuchen. Nach 30 Min. ohne Verbindung → Page-Reload. |
|
||||
| **Lokaler Cache** | Playlist-JSON wird in localStorage gespeichert. Mediendateien werden im Browser-Cache gehalten (Cache-Control Headers serverseitig setzen, z. B. `max-age=86400`). |
|
||||
| **Standby-Modus** | Optionaler CMS-Toggle: Wenn `display_active = false`, zeigt die Webapp nur das B2in-Logo auf dunklem Hintergrund. Kein Content, kein Textfeld. |
|
||||
| **Error-Overlay** | Bei kritischen Fehlern (keine Playlist, kein Media): Dezentes B2in-Logo auf dunklem Hintergrund. Niemals ein Browser-Fehlerbild oder weißer Screen. |
|
||||
| **Automatischer Playlist-Neustart** | Wenn die Playlist durchgelaufen ist und das nächste Polling eine Änderung zeigt: Neue Playlist nahtlos übernehmen. |
|
||||
|
||||
### 7.3 Performance-Hinweise
|
||||
|
||||
- Videos sollten für Web optimiert sein: MP4, H.264, AAC Audio (auch wenn gemutet), `moov atom` am Anfang der Datei (für schnellen Start)
|
||||
- Empfohlene Bitrate: 5–8 Mbit/s für 1080p
|
||||
- Bilder sollten als WebP oder komprimiertes JPG vorliegen (max. 500 KB pro Bild)
|
||||
- Preloading: Immer das nächste Item vorladen, während das aktuelle abgespielt wird
|
||||
|
||||
---
|
||||
|
||||
## 8. Frontend-Spezifikation
|
||||
|
||||
### 8.1 Technologie
|
||||
|
||||
- HTML/CSS/JS (Vanilla). Kein Framework nötig.
|
||||
- Responsive für gängige Display-Auflösungen im 9:16 Portrait (1080x1920, 720x1280)
|
||||
|
||||
### 8.3 Transitions zwischen Items
|
||||
|
||||
| Transition-Typ | Beschreibung |
|
||||
| --- | --- |
|
||||
| `fade` | Aktuelles Item blendet aus (opacity 1→0), neues blendet ein (opacity 0→1). |
|
||||
| `crossfade` | Neues Item blendet über dem aktuellen ein. Sanfter, da kein schwarzer Zwischenzustand. **Empfohlen.** |
|
||||
| `slide` | Aktuelles Item gleitet nach links raus, neues kommt von rechts rein. |
|
||||
|
||||
Standard: **crossfade** mit 800ms. Per CMS änderbar.
|
||||
|
||||
---
|
||||
|
||||
## 9. Leitplanken für Content-Pflege
|
||||
|
||||
**Diese Regeln sollten im CMS als Hinweistext sichtbar sein:**
|
||||
|
||||
### ✓ Ja, so machen wir es:
|
||||
|
||||
- **Ein Item, eine Botschaft.** Jedes Playlist-Item hat eine klare Aussage: Immobilien ODER Möbel.
|
||||
- **Texte kurz halten.** Headline max. 40 Zeichen, Subline max. 80 Zeichen. Was in 3 Sekunden nicht gelesen werden kann, wird nicht gelesen.
|
||||
- **Nur B2in-Content.** Keine Partnerlogos im Video/Bild. Kein Azizi-Branding. Kein CABINET.
|
||||
- **Hochwertige Medien.** Nur professionelles Video-/Bildmaterial. Keine Handy-Fotos, keine Screenshots.
|
||||
- **Regelmäßig aktualisieren.** Playlist mindestens quartalsweise prüfen. Abgelaufene Projekte rausnehmen.
|
||||
|
||||
### ✗ Das vermeiden wir:
|
||||
|
||||
- **Zu viele Items.** Max. 8–10 Items in der Playlist. Mehr führt zu langer Rotation, Wiederholung wird selten.
|
||||
- **Text im Video.** Wenn das Video bereits Text enthält, Headline und Subline reduzieren oder leer lassen – sonst doppelt sich die Information.
|
||||
- **Preislisten oder Grundrisse.** Das Display weckt Neugier, es informiert nicht. Details gehören auf die Website.
|
||||
- **Verschiedene Botschaften mischen.** Kein Item, das gleichzeitig Dubai, Möbel und CABINET bewirbt.
|
||||
|
||||
---
|
||||
|
||||
## 10. Umsetzungs-Checkliste
|
||||
|
||||
| # | Aufgabe | Verantwortlich | Status |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | CMS-Bereich "B2in Display" anlegen: Globale Settings + Playlist-Repeater (Abschnitt 4) | Backend-Entwicklung | Offen |
|
||||
| 2 | API-Endpoint `/api/b2in-display/playlist` + `/check` implementieren (Abschnitt 5) | Backend-Entwicklung | Offen |
|
||||
| 3 | Media-Upload-Funktion im CMS (MP4 + JPG/PNG) mit Größen-Validierung | Backend-Entwicklung | Offen |
|
||||
| 4 | Frontend-Webapp mit Playlist-Engine bauen (Abschnitt 6) | Frontend-Entwicklung | Offen |
|
||||
| 5 | Video-Preloading + Memory-Management implementieren (Abschnitt 6.2 + 7.2) | Frontend-Entwicklung | Offen |
|
||||
| 6 | Polling-Mechanismus + Offline-Fallback + Auto-Reload (Abschnitt 5.2 + 7.2) | Frontend-Entwicklung | Offen |
|
||||
| 7 | Subdomain einrichten + SSL + Deployment | DevOps | Offen |
|
||||
| 8 | Display-Hardware beschaffen + montieren (Abschnitt 7.1) | Marcel / Hardware | Offen |
|
||||
| 9 | Kiosk-Software einrichten (Fully Kiosk oder BrightSign) | Technik | Offen |
|
||||
| 10 | QR-Code generieren (Ziel: b2in.de) + als Asset hinterlegen | Design | Offen |
|
||||
| 11 | Initiales Video-/Bildmaterial aufbereiten (Format, Komprimierung, Qualität) | Content / Design | Offen |
|
||||
| 12 | Beispiel-Playlist im CMS anlegen + End-to-End-Test | QA | Offen |
|
||||
| 13 | Installation im Store: Position, Helligkeit, Blickwinkel, WLAN-Stabilität | Marcel + Technik | Offen |
|
||||
|
||||
---
|
||||
|
||||
## Anhang A: Zusammenfassung der Auto-Logiken
|
||||
|
||||
Folgende Dinge passieren automatisch, ohne dass Marcel etwas pflegen muss:
|
||||
|
||||
- Playlist rotiert endlos durch alle aktiven Items
|
||||
- Gewichtung (70/30) wird automatisch aus den Kategorien berechnet
|
||||
- Videos starten automatisch (gemutet) und gehen nach Ende zum nächsten Item
|
||||
- Bilder werden nach definierter Dauer gewechselt
|
||||
- Polling prüft alle 60 Sekunden auf CMS-Änderungen
|
||||
- Bei Playlist-Änderung: Laufendes Item wird zu Ende gespielt, dann greift neue Playlist
|
||||
- Auto-Reload alle 6 Stunden für Speicher-Hygiene
|
||||
- Offline: Letzte Playlist läuft weiter aus dem Cache
|
||||
- Bei Video-Fehler: Item wird übersprungen, kein schwarzer Screen
|
||||
- Standby-Modus bei `display_active = false`: Nur Logo auf dunklem Hintergrund
|
||||
|
||||
## Anhang B: Unterschiede zum CABINET Info-Tablet
|
||||
|
||||
| Aspekt | CABINET Info-Tablet | B2in Display |
|
||||
| --- | --- | --- |
|
||||
| **Zweck** | Store-Information | Marken-/Content-Anzeige |
|
||||
| **Branding** | CABINET | B2in |
|
||||
| **Content-Typ** | Text/Daten (statisch) | Video/Bild (Playlist) |
|
||||
| **Interaktion** | Keine | Keine |
|
||||
| **Update-Frequenz** | Bei Bedarf (1–2x/Tag) | Playlist rotiert dauerhaft |
|
||||
| **Polling-Intervall** | 30 Sekunden | 60 Sekunden |
|
||||
| **Hardware** | Android-Tablet 8–10" | TV/Monitor 43–55" + Media Player |
|
||||
| **CMS-Komplexität** | 12 einfache Felder | Globale Settings + Playlist-Repeater |
|
||||
200
public/_cabinet/_docs/infotablet.md
Normal file
200
public/_cabinet/_docs/infotablet.md
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
# CABINET Info-Tablet – Entwicklungskonzept
|
||||
|
||||
**Status:** Entwicklungsvorlage | Februar 2026
|
||||
|
||||
---
|
||||
|
||||
## 1. Projektübersicht
|
||||
|
||||
### 1.1 Zweck
|
||||
|
||||
Ein kleines Tablet im Schaufenster neben dem Eingang des CABINET Stores in Bielefeld zeigt Passanten und Kunden auf einen Blick die wichtigsten Store-Informationen: aktueller Öffnungsstatus, Öffnungszeiten, Sonderhinweise und den nächsten freien Beratungstermin.
|
||||
|
||||
### 1.2 Technischer Ansatz
|
||||
|
||||
Die Anzeige wird als responsive Webapp unter einer Subdomain (`cabinet.b2in.eu/info <- live / [`https://b2in.test/_cabinet](https://b2in.test/_cabinet)/info ← testserver) bereitgestellt. Das Tablet greift im Vollbild-Kioskmodus über den Browser darauf zu. Die Inhalte werden über das bestehende B2in-Backend (CMS) gepflegt.
|
||||
Ordner /info
|
||||
### 1.3 Branding
|
||||
|
||||
Ausschließlich CABINET-Branding. Kein B2in-Logo, kein Hinweis auf andere Marken. Das Tablet ist ein reines Store-Informationstool.
|
||||
|
||||
---
|
||||
|
||||
## 2. Content-Struktur & Layout
|
||||
|
||||
Das Display ist in fünf feste Bereiche unterteilt, von oben nach unten:
|
||||
|
||||
| # | Bereich | Inhalt | Verhalten |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | **Header** | CABINET Logo (links) + aktuelles Datum mit Wochentag (rechts). | Datum aktualisiert sich automatisch um Mitternacht. |
|
||||
| 2 | **Status-Banner** | Drei Zustände: **Geöffnet** (grün): „Wir sind geöffnet" + „Heute bis [Uhrzeit] für Sie da." · **Hinweis** (gelb): Frei definierbare Headline + Subtext. Z. B. „Heute erst ab 11:00 Uhr" · **Geschlossen** (rot): Frei definierbare Headline + Subtext. Z. B. „Betriebsurlaub bis 03.03." | Farbe, Icon und Text wechseln je nach Status. CMS-gesteuert. |
|
||||
| 3 | **Öffnungszeiten** | Wochenansicht Mo–So. Heutiger Tag visuell hervorgehoben (fetter Text, leichter Hintergrund). Wenn Sonderöffnung aktiv: heutige Zeit wird in Orange angezeigt. | Heutiger Tag wird automatisch erkannt. Sonderöffnung überschreibt Standard-Zeit für heute. |
|
||||
| 4 | **Termin-Karte** | Dunkle Karte mit Kalender-Icon. Zeigt: „Nächster freier Termin" + Datum/Uhrzeit + „Beratung – ca. 45 Min." | CMS-gesteuert. Optional: Kann später an Kalendersystem angebunden werden. |
|
||||
| 5 | **Footer** | Telefonnummer (links) + E-Mail (links) + QR-Code (rechts). QR-Code führt zur Website oder Terminbuchung. | Statisch. QR-Code wird einmalig generiert und als Asset hinterlegt. |
|
||||
|
||||
---
|
||||
|
||||
## 3. CMS-Felder (B2in-Backend)
|
||||
|
||||
Folgende Felder werden im B2in-Backend als eigener Bereich „CABINET Info-Tablet" angelegt. Alle Felder sind einfache Eingabefelder ohne komplexe Logik.
|
||||
|
||||
| Feldname | Typ | Validierung | Beschreibung |
|
||||
| --- | --- | --- | --- |
|
||||
| `store_status` | Dropdown | `open` | `notice` | `closed` | Bestimmt Farbe und Grundtext des Status-Banners. |
|
||||
| `notice_headline` | Text | Max. 40 Zeichen | Headline im Status-Banner bei Status „notice" oder „closed". Wird bei „open" ignoriert. |
|
||||
| `notice_subtext` | Text | Max. 80 Zeichen | Erklärender Subtext unter der Headline. Optional. |
|
||||
| `override_open_today` | Zeit (HH:MM) | Optional, Format HH:MM | Sonder-Öffnungszeit für heute. Überschreibt die Standard-Öffnungszeit in der Wochenansicht. |
|
||||
| `override_close_today` | Zeit (HH:MM) | Optional, Format HH:MM | Sonder-Schlusszeit für heute. |
|
||||
| `next_appointment_date` | Datum | TT.MM.JJJJ | Datum des nächsten freien Beratungstermins. |
|
||||
| `next_appointment_time` | Zeit (HH:MM) | Format HH:MM | Uhrzeit des nächsten freien Termins. |
|
||||
| `hours_monday` – `hours_sunday` | Text | z. B. „10:00–18:00" oder „Geschlossen" | Standard-Öffnungszeiten pro Wochentag. 7 Felder. |
|
||||
| `contact_phone` | Text | Freitext | Telefonnummer im Footer. |
|
||||
| `contact_email` | Text | E-Mail-Format | E-Mail-Adresse im Footer. |
|
||||
|
||||
**Wichtig:** Die Felder `override_open_today` und `override_close_today` sollten sich automatisch um Mitternacht zurücksetzen (auf leer), damit die Sonderöffnung nicht versehentlich am nächsten Tag weiterläuft.
|
||||
|
||||
---
|
||||
|
||||
## 4. API-Endpoint
|
||||
|
||||
Das Backend stellt einen einfachen JSON-Endpoint bereit, den die Webapp abfragt.
|
||||
|
||||
### 4.1 Endpoint-Struktur
|
||||
|
||||
`GET /api/cabinet-tablet/status`
|
||||
|
||||
**Response (JSON):**
|
||||
|
||||
json
|
||||
|
||||
`{
|
||||
"store_status": "notice",
|
||||
"notice_headline": "Heute erst ab 11:00 Uhr",
|
||||
"notice_subtext": "Wegen eines Kundentermins öffnen wir heute später.",
|
||||
"override_open_today": "11:00",
|
||||
"override_close_today": null,
|
||||
"next_appointment": {
|
||||
"date": "2026-02-27",
|
||||
"time": "14:00"
|
||||
},
|
||||
"hours": {
|
||||
"monday": "10:00 – 18:00",
|
||||
"tuesday": "10:00 – 18:00",
|
||||
"wednesday": "10:00 – 18:00",
|
||||
"thursday": "10:00 – 18:00",
|
||||
"friday": "10:00 – 18:00",
|
||||
"saturday": "10:00 – 14:00",
|
||||
"sunday": "Geschlossen"
|
||||
},
|
||||
"contact": {
|
||||
"phone": "0521 – 123 456 0",
|
||||
"email": "info@cabinet-bielefeld.de"
|
||||
},
|
||||
"updated_at": "2026-02-26T09:15:00Z"
|
||||
}`
|
||||
|
||||
### 4.2 Update-Mechanismus (Polling)
|
||||
|
||||
Die Webapp fragt den Endpoint in zwei Stufen ab:
|
||||
|
||||
**1. Lightweight Check (alle 30 Sekunden):**
|
||||
Die Webapp ruft einen minimalen Endpoint ab, der nur den `updated_at` Timestamp zurückgibt.
|
||||
|
||||
`GET /api/cabinet-tablet/check`
|
||||
|
||||
json
|
||||
|
||||
`{ "updated_at": "2026-02-26T09:15:00Z" }`
|
||||
|
||||
**2. Full Fetch (nur bei Änderung):**
|
||||
Wenn der Timestamp sich vom lokal gespeicherten unterscheidet, wird der komplette Status-Endpoint abgerufen und die Anzeige aktualisiert – kein Page-Reload, nur DOM-Update per JavaScript.
|
||||
|
||||
**Warum Polling statt WebSockets?** Für ein einzelnes Tablet, das auf ein CMS reagiert, das vielleicht 1–2x am Tag geändert wird, ist Polling robuster und einfacher zu warten. WebSockets wären Overkill und eine zusätzliche Fehlerquelle.
|
||||
|
||||
---
|
||||
|
||||
## 5. Technische Stabilität & Kiosk-Betrieb
|
||||
|
||||
### 5.1 Kiosk-App (Android)
|
||||
|
||||
**Empfehlung: Fully Kiosk Browser** (ca. 7 € einmalig pro Gerät, Industriestandard für Digital Signage).
|
||||
|
||||
Funktionen, die wir nutzen:
|
||||
|
||||
- Vollbild-/Kioskmodus: Kein Zugriff auf Android-UI, Statusbar ausgeblendet
|
||||
- Auto-Restart bei Browser-Absturz: App startet sich automatisch neu und lädt die URL
|
||||
- Zeitsteuerung: Tablet geht nachts (z. B. 22:00) in Standby, wacht morgens (z. B. 07:00) auf
|
||||
- Remote-Management: Über Fully Cloud kann die URL und Einstellungen remote geändert werden
|
||||
- Bildschirm-Timeout: Screen bleibt dauerhaft an während der definierten Betriebszeit
|
||||
- Motion Detection (optional): Bildschirm wird heller wenn jemand davor steht
|
||||
|
||||
### 5.2 Webapp-seitige Stabilität
|
||||
|
||||
Zusätzlich zur Kiosk-App bauen wir folgende Sicherheiten direkt in die Webapp ein:
|
||||
|
||||
| Maßnahme | Beschreibung |
|
||||
| --- | --- |
|
||||
| **Auto-Reload** | Kompletter Page-Reload alle 6 Stunden (z. B. um 03:00, 09:00, 15:00, 21:00). Räumt Speicher auf und verhindert Memory Leaks durch langlebige Browser-Sessions. |
|
||||
| **Offline-Fallback** | Wenn die API nicht erreichbar ist, zeigt die Webapp den letzten bekannten Stand an + dezenten Hinweis „Stand: [Zeitpunkt]". Kein Fehlerbildschirm, der Passanten verwirrt. |
|
||||
| **Connection-Recovery** | Wenn das Polling 3x hintereinander fehlschlägt, wartet die Webapp 5 Minuten, dann versucht sie es erneut. Nach 30 Minuten ohne Verbindung: automatischer Page-Reload. |
|
||||
| **Lokaler Cache** | Die letzte API-Response wird im localStorage gespeichert. Bei Neustart (z. B. nach Browser-Crash) wird sofort der Cache angezeigt, während im Hintergrund frische Daten geladen werden. |
|
||||
| **Keine Interaktion** | Die Webapp hat keine klickbaren Elemente (außer dem QR-Code, der ohnehin nur visuell ist). Kein Scrollen, kein Touch-Event. Verhindert versehentliche Bedienung. |
|
||||
| **Automatische Datumsaktualisierung** | Um Mitternacht: Neuen Wochentag setzen, heutigen Tag in der Öffnungszeiten-Liste aktualisieren, Sonderöffnungszeiten zurücksetzen. |
|
||||
|
||||
---
|
||||
|
||||
## 6. Frontend-Spezifikation
|
||||
|
||||
### 6.1 Technologie
|
||||
|
||||
- Einfache statische HTML/CSS/JS-Seite (kein Framework notwendig)
|
||||
- Responsive für Tablet-Größen hochkannt (ca. 1.600 x 2.456** Pixel **, 256 PPI**)
|
||||
- Keine externen Abhängigkeiten außer einer Google-Fonts-Einbindung (Fallback auf System-Fonts)
|
||||
- JavaScript Vanilla – kein React, Vue o. Ä. nötig
|
||||
|
||||
### 6.3 Animations & Transitions
|
||||
|
||||
Wenn sich der Status ändert (z. B. von „open" zu „notice"), soll der Übergang sanft per CSS-Transition (300ms ease) erfolgen – kein harter Wechsel. Gleiches gilt für Änderungen an Öffnungszeiten oder Termin.
|
||||
|
||||
---
|
||||
|
||||
## 7. Hardware-Empfehlung
|
||||
|
||||
| Komponente | Empfehlung |
|
||||
| --- | --- |
|
||||
| **Tablet** | Android-Tablet, 8–10 Zoll, min. 2 GB RAM. Muss nicht high-end sein – es zeigt nur eine Webseite. HUAWEI MatePad T |
|
||||
| **Kiosk-App** | Fully Kiosk Browser (ca. 7 € Lizenz). |
|
||||
| **Halterung** | Wandhalterung oder Standfuß mit Diebstahlschutz. Hochkant montiert. |
|
||||
| **Stromversorgung** | Dauerhaft am Strom (Ladekabel mit Kabelkanal). Akku-Ladung auf 80 % begrenzen (Fully Kiosk unterstützt das), um Akku-Verschleiß zu minimieren. |
|
||||
| **WLAN** | Stabiles Store-WLAN. Empfehlung: Festes WLAN-Profil im Tablet hinterlegen, Auto-Reconnect aktivieren. |
|
||||
|
||||
---
|
||||
|
||||
## 8. Umsetzungs-Checkliste
|
||||
|
||||
| # | Aufgabe | Verantwortlich | Status |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | CMS-Felder im B2in-Backend anlegen (Abschnitt 3) | Backend-Entwicklung | Offen |
|
||||
| 2 | API-Endpoint implementieren (Abschnitt 4) | Backend-Entwicklung | Offen |
|
||||
| 3 | Frontend-Webapp bauen (Abschnitt 2 + 6) | Frontend-Entwicklung | Offen |
|
||||
| 4 | Polling-Mechanismus + Stabilität implementieren (Abschnitt 4.2 + 5.2) | Frontend-Entwicklung | Offen |
|
||||
| 5 | Subdomain einrichten + Deployment | DevOps | Offen |
|
||||
| 6 | Tablet beschaffen + Fully Kiosk einrichten (Abschnitt 7) | Marcel / Hardware | Offen |
|
||||
| 7 | QR-Code generieren + als Asset hinterlegen | Design | Offen |
|
||||
| 8 | End-to-End-Test: CMS-Änderung → Tablet zeigt Update | QA | Offen |
|
||||
| 9 | Installation im Store + Feintuning Helligkeit/Position | Marcel + Technik | Offen |
|
||||
|
||||
---
|
||||
|
||||
## Anhang: Zusammenfassung der Auto-Logiken
|
||||
|
||||
Folgende Dinge passieren automatisch, ohne dass Marcel etwas pflegen muss:
|
||||
|
||||
- Datum und Wochentag im Header aktualisieren sich um Mitternacht
|
||||
- Heutiger Tag in der Öffnungszeitenliste wird automatisch hervorgehoben
|
||||
- Sonderöffnungszeiten (override-Felder) setzen sich um Mitternacht zurück
|
||||
- Bei Status „open": Banner-Text generiert sich automatisch aus der heutigen Schlusszeit
|
||||
- Polling läuft im Hintergrund (alle 30 Sek.), DOM-Updates ohne Flackern
|
||||
- Auto-Reload alle 6 Stunden für Speicher-Hygiene
|
||||
- Offline-Fallback: Letzter Stand wird angezeigt, kein leerer Bildschirm
|
||||
- Fully Kiosk: Auto-Restart bei Crash, Standby-Zeiten, Bildschirm-Management
|
||||
Loading…
Add table
Add a link
Reference in a new issue