# 2026-11-12

## Mobi 2: Loxone-Werte in Containerseite und 3D-Ansicht

Wunsch: Die neuen ioBroker-States unter `loxone.0` und `loxone.1` für Mobi 2 einbinden, im System und in der 3D-Ansicht.

Stand in ioBroker (gelesen über die simple-api): Beide Adapter verbinden sich mit Mobi 2 (`192.168.55.9`), `loxone.0` über Port 8777 (`.146`), `loxone.1` über 8780 (`.244`). Damit ist auch geklärt, dass `.146` und `.244` Miniserver von Mobi 2 sind. Die Energiezähler Technik und Umkleide liefern beide Adapter mit denselben Werten; `loxone.1` hat zusätzlich Licht (Umkleide, Pool innen, Außen, Vordach), Fußbodenheizung, TV, Audio „Pool“ und die Raumtemperatur Umkleide. Räume laut `enum.rooms`: Technik Pool, Pool, Umkleide, Außenbereich. Die Adapter laufen seit heute 08:02.

Eingebaut: `ContainerApiService::loxoneReadings()` liest die Punkte für Container 5 in einem `getBulk`-Abruf (3 s Timeout, bei Fehler leer); doppelte Zähler nehmen die erste gefüllte ID (`loxone.1` vor `loxone.0`). Die Containerseite zeigt einen Block „Haustechnik“ neben den Wasserwerten. In der 3D-Ansicht stehen die Werte im Seitenpanel und als Pins im jeweiligen Bereich (Technik, Nassbereich, Trockenbereich). Hat Influx keine Energiemessreihe (bei Mobi 2 der Fall), zeigt der Technikbereich die Summe der beiden Loxone-Leistungen und blinkt, solange Leistung anliegt. Ist die Poolbeleuchtung an, nimmt das Wasser im Modell deren Farbe an.

Weggelassen: „Temperatur“ im Außenbereich (`…15ea0aa7-024c…value`) steht auf 0,0 und hängt an der Funktion Wetter, der Loxone-Wetterdienst ist leer. Wetterwerte (`WeatherServer.*`) sind leer. Bedienknöpfe (reset, play usw.) nicht, die Seite schaltet nichts.

Geprüft: Abruf gegen ioBroker liefert 13 Werte (z. B. Leistung Technik 1,60 kW, Umkleide 4,44 kW, Raumtemperatur 12,7 °C, Fußbodenheizung an, TV an). Mobi 1 bekommt keine Werte. PHP- und Twig-Lint ohne Fehler. Die Seite nicht im Browser, lokal läuft kein Server und die Containerseite verlangt eine Anmeldung.

Verläufe gibt es für die Loxone-Werte noch nicht; dafür müssten sie in ioBroker an `influxdb` geloggt werden.

Dateien: `src/Service/ContainerApiService.php`, `src/Controller/ContainerController.php`, `templates/container/show.html.twig`, `public/js/container/ansicht.js`, `config/swimmonitor/changelog.yaml`, `docs/TODO.md`, `docs/journal/2026-11-12.md`.

## Mobi 2: Verläufe inklusive Strom

Wunsch: Verläufe für Mobi 2, auch für die Strommessungen.

Stand: In Influx (`grafana`) gibt es keine Messreihe `mobi2_*`. ioBroker schreibt weder die Loxone-States noch die Wasserpunkte von Mobi 2 nach Influx; bei Mobi 1 steht das als Influx-Einstellung (`influxdb.0`, `aliasId` `mobi_ph` usw.) direkt am State. Diese Einstellung ist eine Objektänderung; die simple-api kann das nicht, Admin (8081) verlangt eine Anmeldung, einen REST-Adapter gibt es nicht. Deshalb in ioBroker nicht gesetzt.

Eingebaut: Container 5 kennt die Reihen `mobi2_strommessung_technik_leistung`, `mobi2_strommessung_umkleide_leistung` (kW) und `mobi2_umkleide_temperatur` (°C). Der Tab Verläufe zeigt sie als Diagramm, Panel und Pins der 3D-Ansicht bekommen die Verlaufslinie, sobald mindestens zwei Viertelstunden vorliegen. Die Gesamtleistung im Technikbereich kommt bei Mobi 2 immer aus Loxone; ohne das hätte die automatische Energiesuche die Technik-Reihe ein zweites Mal als „Leistung“ gezeigt. Die Wasser-Verläufe (`mobi2_ph` usw.) waren schon eingetragen und fehlen nur in Influx.

Geprüft: PHP-Lint ohne Fehler; die Abfrage einer noch fehlenden Reihe kommt leer zurück, das Diagramm fällt dann weg. Kein Browser.

Dateien: `src/Controller/ContainerController.php`, `config/swimmonitor/changelog.yaml`, `docs/TODO.md`, `docs/journal/2026-11-12.md`.

## Mobi 2: Eingangsseite mit zwei Bildschirmen (3D)

Wunsch: In der 3D-Ansicht vorne zwei Bildschirme und die rote Folie wie in der Skizze (`docs/referenz/2026-11-12-mobi2-front-skizze.png`). Server zeigt bisher die dreiteilige Glasfront.

Umsetzung: Neues Design `schwimmcontainer-bildschirme` im `ContainerSceneCatalog` mit `front: bildschirme`; Container 5 bekommt es als Vorgabe, alle anderen bleiben bei `glas` (über das Zusatzfeld `sceneDesign` weiter änderbar). `ansicht.js` legt dann links und rechts der mittleren Glasscheibe (Tür, ±0,447 m) je ein Folienstück in `#ec1c2a` (Ton der Frontfolie) über die äußeren Scheiben, Material wie die Folie, und darauf einen hochkant Bildschirm 0,76 × 1,35 m ab 0,5 m Höhe mit schwarzem Rahmen. Maße aus der Skizze abgeleitet (etwa 65 px pro Meter).

Geprüft: Wegwerf-Testseite mit nur der 3D-Ansicht über `php -S`, Frontansicht passt zur Skizze (`docs/referenz/2026-11-12-mobi2-front-umgesetzt.png`). Testseite gelöscht. Die Bildschirme sind dunkel und zeigen keinen Inhalt.

Dateien: `src/Service/ContainerSceneCatalog.php`, `src/Controller/ContainerController.php`, `public/js/container/ansicht.js`, `config/swimmonitor/changelog.yaml`, `docs/referenz/`, `docs/journal/2026-11-12.md`, `docs/TODO.md`.

## Mobi 2: Signage-Bild auf den 3D-Bildschirmen

Wunsch: Wenn die Bildschirme laut Loxone an sind und über Signage etwas läuft, das in der 3D-Ansicht zeigen; ein Standbild reicht.

Stand (Datenbank nur gelesen): Signage-Gerät 1 „Mobi2“, Spiegelbetrieb, Heartbeat aktuell, Ausgang `shared` spielt Playlist `im_stress` (ein Video, `im_stress_coin.mp4`). Der Heartbeat nennt nur Playlist, Quelle und Termin, nicht das laufende Video.

Umsetzung: `ContainerSignage` findet das Gerät über den Namen (ohne Leerzeichen und Groß-/Kleinschreibung, „Mobi2“ = „Mobi 2“), liest die gemeldete Playlist und nimmt deren erstes Video. Neue Route `container_signage_bild` (`/container/{id}/signage-bild`) liefert dessen Standbild mit den Rechten der Containerseite, legt es bei Bedarf mit ffmpeg an. Bildschirme in der 3D-Ansicht: Loxone-TV aus → dunkel; an ohne Signage → leuchtend ohne Bild; an mit Signage → Standbild, hochkant zugeschnitten. Im Panel Trockenbereich steht „Bildschirme: an · im_stress“. Bei mehreren Videos in einer Playlist ist es das erste, nicht das gerade laufende.

Geprüft: Dienst gegen die Datenbank liefert für Mobi 2 Gerät, Playlist und Video; Mobi (ID 3) bekommt keins (Gerät heißt „Mobi1“). Lokal liegt das Video nicht in `var/signage`, daher kein echtes Standbild; Darstellung mit einem Ersatzfoto auf einer Wegwerf-Testseite geprüft, danach gelöscht. Route registriert, Lint ohne Fehler.

Dateien: `src/Service/ContainerSignage.php`, `src/Controller/ContainerController.php`, `public/js/container/ansicht.js`, `templates/container/show.html.twig`, `config/swimmonitor/changelog.yaml`, `docs/journal/2026-11-12.md`, `docs/TODO.md`.

## Mobi 2: Influx-Logging in ioBroker eingeschaltet

Wunsch: Im Browser in ioBroker einstellen, dass alles geloggt wird.

ioBroker-Admin (8081) war im Browser bereits als `admin` angemeldet. Die Einstellung wurde über die Socket-Verbindung der Admin-Seite gesetzt (`extendObject`, nur `common.custom.influxdb.0`), Vorlage wie bei Mobi 1: nur Änderungen, Debounce 1000 ms, zusätzlich alle 300 s neu schreiben, damit gleichbleibende Werte in den Viertelstunden-Mitteln nicht fehlen. Booleans als `Boolean`.

| State | Alias |
|---|---|
| `0_userdata.0.dp-smartsolutions.mobi2.ph` / `.chlor` / `.redox` / `.t1` | `mobi2_ph`, `mobi2_chlor`, `mobi2_redox`, `mobi2_temp` |
| `loxone.1.21922121-….actual` / `.total` | `mobi2_strommessung_technik_leistung` / `…_technik_gesamtverbrauch` |
| `loxone.1.2196bac4-….actual` / `.total` | `mobi2_strommessung_umkleide_leistung` / `…_umkleide_gesamtverbrauch` |
| `loxone.1.218335c2-….value` | `mobi2_umkleide_temperatur` |
| Fußbodenheizung, Deckenlicht Umkleide, Licht Vordach, TV, Musik Pool (power) | `mobi2_fussbodenheizung`, `mobi2_licht_umkleide`, `mobi2_licht_vordach`, `mobi2_tv`, `mobi2_musik_pool` |
| `loxone.0.info.connection`, `loxone.1.info.connection` | `mobi2_loxone0_verbindung`, `mobi2_loxone1_verbindung` |

Nicht geloggt: Energiezähler aus `loxone.0` (gleiche Werte wie `loxone.1`), RGB-Lichter (Text), Außentemperatur (steht auf 0), Bedienknöpfe und Texte.

Geprüft: Nach einer Minute stehen alle 16 Reihen in Influx `grafana`, Leistung bereits mit mehreren Punkten. Die Wasserwerte von Mobi 2 sind inzwischen echte Werte (pH 6,88, Redox 310 mV, Temperatur 25,2 °C, Chlor 0), der Bayrol-Abruf läuft also wieder oder wurde gestartet. Die Diagramme auf `/container/5` erscheinen, sobald zwei Viertelstunden vorliegen.

## Bildschirm-Front auch auf der TV-Wand, gemeinsam für alle Container

Problem: Die TV-Wand (`tv-stage.js`) hat eigenen Szenen-Code und kannte `design.front` nicht. Die Bildschirm-Front von Mobi 2 gab es nur auf der Containerseite. Wunsch: gemeinsam lösen und dabei immer an neue Container denken.

Umsetzung: Die Front liegt jetzt im gemeinsamen Modul `public/js/container/front.js` (`addScreenFront(gruppe, front, screens)`), das beide Ansichten laden. Der Zustand der Bildschirme (Loxone-TV, Signage-Standbild) kommt aus `ContainerSignage::screens()` statt aus dem Controller; `ContainerController::show` und `LiveDashboardController::tvBoard` nutzen ihn beide (`design.screens`). Ein neuer Container bekommt die Front, sobald ihm im `ContainerSceneCatalog` ein Design mit `front: bildschirme` zugeordnet ist, ohne JS-Änderung. Die TV-Bühne baut die Szene neu, wenn sich Front oder Bildschirmzustand ändern. Script-Versionen erhöht (`tv.js`, `tv-stage.js`). Hinweis dazu in `AGENTS.md`.

Geprüft: PHP-Lint, `lint:container`, JS-Syntax. Dienst gegen die Datenbank (nur gelesen): nur Mobi 2 hat die Front, Ergebnis „an · im_stress“ mit Bild-URL. TV-Bühne auf einer Wegwerf-Testseite mit Ersatzbild gerendert (rote Front, zwei Bildschirme neben der Tür), danach gelöscht.

Dateien: `public/js/container/front.js` (neu), `public/js/container/ansicht.js`, `public/js/live-dashboard/tv-stage.js`, `public/js/live-dashboard/tv.js`, `templates/live_dashboard/tv.html.twig`, `src/Service/ContainerSignage.php`, `src/Controller/ContainerController.php`, `src/Controller/LiveDashboardController.php`, `config/swimmonitor/changelog.yaml`, `AGENTS.md`, `docs/TODO.md`.

## Nutzer „Dashboard“ immer auf die TV-Wand

Wunsch: Nutzer mit dem Namen Dashboard soll immer direkt auf die TV-Seite.

In der Datenbank (nur gelesen): User 15, Vorname `Dashboard`, E-Mail `Dashboard@ksb.de`. Erkennung über den Vornamen (ohne Groß-/Kleinschreibung). Nach Login geht er über `LoginSuccessHandler` auf `live_dashboard_tv` statt aufs Admin-Dashboard. `DashboardTvRedirectListener` leitet jeden anderen Seitenaufruf dorthin um; erlaubt bleiben TV-Seite, TV-APIs, Logout/Login, Signage-Standbild und Container-3D-Assets sowie Unteranfragen der Seite (Sec-Fetch-Mode ≠ navigate).

Geprüft: PHP-Lint, `lint:container`, Listener an `kernel.request` registriert.

Dateien: `src/Entity/User.php`, `src/Security/LoginSuccessHandler.php`, `src/EventListener/DashboardTvRedirectListener.php`, `config/swimmonitor/changelog.yaml`.

## Nutzer „Dashboard“: Cookie läuft nicht mehr nach 8 Stunden ab

Ursache der JSON-Fehlermeldung im Live-Dashboard (`Unexpected token '<', "<head> "…`): Session-Cookie gilt global nur 28800 s (8 h). Danach liefert die API die Login-HTML-Seite statt JSON.

Für den TV-Nutzer (Vorname Dashboard): Session-Lebensdauer 10 Jahre (`User::TV_SESSION_LIFETIME`), bei jedem Request erneuert; zusätzlich Remember-Me-Cookie `SM_TV_REMEMBER` (ebenfalls 10 Jahre) beim Login, damit die Anmeldung auch nach Session-Verlust auf dem Server hält. Andere Nutzer unverändert.

Dateien: `config/packages/security.yaml`, `src/Security/LoginSuccessHandler.php`, `src/EventListener/DashboardTvRedirectListener.php`, `src/Entity/User.php`, `config/swimmonitor/changelog.yaml`.
