Files
Camper-Monitor/README.md
T
BiasFandClaude Opus 5 45d1dc087d Kompressor-Kühlboxen unterstützen, mit Steuerung
Die IceCube-Boxen von Plug-in Festivals sind umgelabelte Alpicool-Boxen –
der Hersteller verweist selbst auf die App "Alpicool T-Series". Bestätigt
am Gerät: die Charakteristiken 00001235 und 00001236 tauchen im GATT-Baum
auf. Dasselbe Protokoll sprechen BrassMonkey und Ocean Comfort.

AlpicoolProtocol baut und liest die Rahmen (FE FE, Länge, Kommando,
Daten, Bytesummen-Prüfsumme) und wertet die Statusantwort aus: Ist- und
Solltemperatur je Zone, Betriebsart, Kompressorstatus, Bedienfeldsperre,
Bordspannung und Batterieanzeige. Zweizonen-Boxen werden an der
Nutzlastlänge erkannt. Auf Stellbefehle antwortet die Box mit Echo und
Status in einer einzigen Benachrichtigung, weshalb der Rahmenleser
weitersucht statt nach dem ersten Treffer abzubrechen; das Echo läuft
mangels Statuslänge ins Leere.

Als bisher einziges Gerät ist die Box auch stellbar: Ein/Aus, Eco/Max,
Solltemperatur je Zone und Bedienfeldsperre. Nach jedem Stellbefehl wird
der Zustand neu abgefragt, sodass die Schalter dem Gerät folgen und nicht
der Eingabe. Ausschalten fragt einmal nach, weil dabei die Kühlung
stoppt. Ein/Aus und Betriebsart brauchen den kompletten
Einstellungsblock: er wird aus dem letzten Status neu aufgebaut und nur
im betroffenen Byte geändert, sonst überschriebe die Box eigene
Einstellungen mit Nullen. Ohne bekannten Status entsteht gar kein
Stellbefehl.

Die Namensprüfung in der Geräteliste hiess bisher looksLikeDaly und
hätte Kühlboxen aus der Vorauswahl geworfen; sie deckt jetzt alle
unterstützten Geräte ab und belegt die Art beim Einrichten vor.

Protokoll und Feldbelegung nach Gruni22/alpicool_ha_ble. Die festen
Anmelde- und Abfragepakete der Referenz sind byteweise abgesichert und
belegen zugleich, dass die allgemeine Prüfsummenregel auch für sie gilt.
139 Prüfungen laufen durch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 14:10:25 +02:00

200 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Camper Monitor
iOS-App, die per Bluetooth LE die Energieanlage im Wohnmobil ausliest:
| Gerät | Weg | Was ankommt |
|---|---|---|
| Victron Ladebooster (Orion-TR Smart / Orion XS) | Instant Readout im Advertisement | Ein-/Ausgangsspannung, beim XS auch Ströme und Ladeleistung, Zustand, Abschaltgrund |
| Victron Solarladeregler (SmartSolar MPPT) | Instant Readout im Advertisement | PV-Leistung, Batteriespannung, Ladestrom, Tagesertrag, Laststrom, Ladezustand (Bulk/Absorption/Float) |
| Batterie-BMS (Bulltron/Daly, WattCycle) | GATT-Verbindung, alle 5 s abgefragt | SoC, Spannung, Strom, Restkapazität, alle Einzelzellspannungen, Zelldifferenz, Temperaturen, Zyklen, MOSFET-Status |
| Kompressor-Kühlbox (Alpicool und Baugleiche) | GATT-Verbindung, lesen **und** stellen | Ist- und Solltemperatur je Zone, Betriebsart, Kompressorstatus, Bordspannung, Batterieanzeige |
Ein Victron SmartShunt/BMV wird ebenfalls unterstützt, falls später einer dazukommt.
## Bauen und installieren
```bash
open /Users/fritob/GIT/Camper-Management/CamperMonitor.xcodeproj
```
Dann in Xcode:
1. Target `CamperMonitor`**Signing & Capabilities** → dein Apple-Team auswählen.
Die Bundle-ID `de.fritob.CamperMonitor` ggf. anpassen, falls sie schon vergeben ist.
2. iPhone per Kabel anschließen, oben als Ziel wählen, ⌘R.
Wichtig: **Der Simulator hat kein Bluetooth.** Die App startet dort, findet aber
nie ein Gerät. Zum Testen muss sie auf ein echtes iPhone.
Mit einem kostenlosen Apple-Account läuft die App 7 Tage und muss dann neu
installiert werden; mit einem bezahlten Developer-Account ein Jahr.
## Einrichtung in der App
### Victron-Geräte
Victron-Geräte senden ihre Messwerte etwa im Sekundentakt verschlüsselt im
BLE-Advertisement. Es wird nichts verbunden und nichts gestört VictronConnect
kann parallel laufen. Dafür brauchst du pro Gerät einmalig den Schlüssel:
1. VictronConnect öffnen, Gerät anwählen
2. Zahnrad (Einstellungen) → ⋮ oben rechts → **Produkt-Info**
3. **Instant Readout** einschalten
4. **Verschlüsselungsdaten anzeigen** → der Schlüssel sind 32 Hex-Zeichen
In der App: **+** → Gerät aus der Liste wählen (Victron-Geräte werden erkannt
und die Art vorausgefüllt) → Schlüssel einfügen → Sichern.
Der Schlüssel liegt in der iOS-Keychain, nicht in den UserDefaults.
#### Wenn „Schlüssel passt nicht" erscheint
Victron sendet das erste Byte des Schlüssels unverschlüsselt mit, damit sich ein
falscher Schlüssel sofort erkennen lässt. Die Detailansicht des Geräts hat dafür
den Abschnitt **Diagnose**:
* *Gerät sendet als erstes Schlüsselbyte* was das Gerät erwartet
* *Eingetragener Schlüssel beginnt mit* was in der App steht
Stimmen die beiden nicht überein, gehört der Schlüssel zu einem anderen Gerät.
Bei mehreren Victron-Geräten ist das die mit Abstand häufigste Ursache: In
VictronConnect prüfen, dass wirklich dieses Gerät geöffnet war, als der
Schlüssel angezeigt wurde.
Die Diagnose zeigt außerdem Produkt-ID, Datensatztyp und die Rohdaten des
Advertisements letztere lassen sich durch langes Antippen kopieren.
### Batterie / BMS
Kein Schlüssel nötig. Auswählen, Art auf **Batterie / BMS** stellen, Sichern.
Bulltron-Akkus melden sich meist als `DL-…`, WattCycle je nach Charge unter
eigenem Namen findest du nichts, in der Geräteliste auf **Alle** umschalten.
Die App probiert drei Protokolle durch und übernimmt, was antwortet:
| Dialekt | Verbreitung |
|---|---|
| Daly klassisch (`A5`) | Bulltron und viele Daly-BMS |
| Daly Modbus (`D2`) | neuere Daly-Firmware |
| JBD / Xiaoxiang (`DD A5`) | viele LiFePO4-Akkus mit eigener App |
| WattCycle (`1E`/`7E`) | WattCycle-Bluetooth-Serie |
WattCycle-Akkus verlangen eine Besonderheit: vor der ersten Abfrage muss der
Text `HiLink` auf eine eigene Freischalt-Charakteristik (`FFFA`) geschrieben
werden, sonst bleiben sie auf jede Anfrage stumm. Die App macht das
automatisch, sobald ein Gerät diese Charakteristik anbietet. Modell,
Hersteller und Seriennummer liest sie einmalig mit aus und zeigt sie in der
Detailansicht unter *Gerät*.
Protokoll und Feldbelegung stammen aus
[frabnet/esphome-wattcycle-ble](https://github.com/frabnet/esphome-wattcycle-ble);
die Prüfsummen-Variante von dort ist gegen den klassischen Modbus-CRC
nachgerechnet, die Anfragerahmen sind byteweise in `run-tests.sh` abgesichert.
Auch die GATT-Charakteristiken werden gesucht statt vorausgesetzt, weil sich
die BLE-Module zwischen Herstellern und Chargen unterscheiden. Welches
Protokoll erkannt wurde, steht in der Detailansicht unter **Diagnose**
zusammen mit der letzten Rohantwort.
Nur **eine** App gleichzeitig kann mit dem BMS verbunden sein. Wenn die
Hersteller-App offen ist, bekommt Camper Monitor keine Verbindung.
### Kühlbox
Die IceCube-Boxen von Plug-in Festivals sind umgelabelte Alpicool-Boxen
erkennbar daran, dass der Hersteller die App „Alpicool T-Series“ nennt. Dasselbe
Protokoll sprechen auch BrassMonkey und Ocean Comfort.
Beim Einrichten Art auf **Kühlbox** stellen. Die App meldet sich beim Verbinden
selbst an; steht **APP** im Display der Box, verlangt sie dabei einen
Tastendruck am Gerät.
Neben den Messwerten gibt es hier als einzigem Gerät auch Bedienelemente:
Ein/Aus, Eco oder Max, Solltemperatur je Zone und die Bedienfeldsperre. Alle
Schalter zeigen den Stand, den die Box zurückmeldet nach jedem Stellbefehl
wird ihr Zustand neu abgefragt, statt die Eingabe anzunehmen. Das Ausschalten
fragt einmal nach, weil dabei die Kühlung stoppt.
Interessant für die Energieübersicht: Die Box misst die Bordspannung und meldet
sie mit, was einen Quervergleich zu Batterie und Solarregler erlaubt.
Protokoll und Feldbelegung stammen aus
[Gruni22/alpicool_ha_ble](https://github.com/Gruni22/alpicool_ha_ble).
## Mehrere Fahrzeuge
Oben links im Dashboard sitzt der Fahrzeugwechsel. Jedes Profil hat seinen
eigenen Gerätesatz; die App scannt und verbindet immer nur für das gewählte
Fahrzeug. Über *Fahrzeuge verwalten…* lassen sich Profile anlegen, umbenennen,
mit einem Symbol versehen und löschen. Geräte, die vor der Profilverwaltung
eingerichtet wurden, wandern beim Update automatisch ins erste Profil.
## Ohne Fahrzeug ansehen
Ein Demo-Modus füllt die App mit erfundenen Werten, damit sich die Ansichten
ohne Bluetooth prüfen lassen. In Xcode unter *Product → Scheme → Edit Scheme →
Run → Arguments* die Umgebungsvariable `CAMPER_DEMO` auf `1` setzen. Er greift
nur in Debug-Builds.
## Protokolle prüfen
```bash
./run-tests.sh
```
Prüft die Entschlüsselung und die Rahmenverarbeitung ohne Hardware und ohne
Simulator unter anderem AES-CTR gegen den Referenzvektor aus NIST SP 800-38A
und die Prüfsummen beider Daly-Dialekte.
## Aufbau
```
CamperMonitor/
├── Models/
│ ├── Profile.swift Fahrzeug
│ ├── ConfiguredDevice.swift Eingerichtetes Gerät, Rolle, Transportart
│ ├── DeviceSnapshot.swift Messwerte in Anzeigeform
│ └── VictronCodes.swift Klartexte für Zustands-/Fehlercodes
├── Bluetooth/
│ ├── BluetoothManager.swift Zentraler Scan, Verbindungen, Verlauf
│ ├── VictronAdvertisement.swift Advertisement entschlüsseln und auswerten
│ ├── AESCounterMode.swift AES-128-CTR (CommonCrypto)
│ ├── BitReader.swift Bitweises Lesen der gepackten Felder
│ ├── DalyProtocol.swift Daly-Rahmen und Prüfsummen
│ ├── DalyState.swift Sammelt Daly-Antworten zu einem Gesamtbild
│ ├── JBDProtocol.swift JBD/Xiaoxiang, Rahmen und Auswertung
│ ├── WattCycleProtocol.swift WattCycle, Freischaltung und Auswertung
│ ├── AlpicoolProtocol.swift Kühlboxen: Auswertung und Stellbefehle
│ └── BMSSession.swift GATT-Verbindung, Protokollerkennung, Abfrage
├── Store/
│ ├── DeviceStore.swift Geräteliste, Persistenz
│ └── KeychainStore.swift Victron-Schlüssel
└── Views/
├── DashboardView.swift Kachelübersicht
├── DeviceCard.swift Eine Kachel
├── DeviceDetailView.swift Alle Werte, Verlauf, Zellspannungen, Diagnose
├── ProfilesView.swift Fahrzeuge anlegen und verwalten
├── FridgeControls.swift Bedienelemente der Kühlbox
└── AddDeviceView.swift Scannen und Einrichten
```
## Bekannte Grenzen
* **Kein Hintergrundbetrieb.** iOS erlaubt das ungefilterte Scannen nach
Advertisements nur im Vordergrund. Die App pausiert, sobald sie in den
Hintergrund geht, und nimmt beim Zurückkommen wieder auf.
* **Das Modbus-Registerlayout des neuen Daly-Protokolls variiert zwischen
Firmwareständen.** Das klassische `A5`-Protokoll und das JBD-Protokoll sind
gut dokumentiert; falls dein BMS Modbus spricht und Werte unplausibel
aussehen, muss das Mapping in `DalyState.apply(registers:)` am realen Gerät
nachgezogen werden.
* **Die Feldbelegung der BMS-Datensätze ist nicht an jedem Modell geprüft.**
Meldet die Diagnose dauerhaft „wird ermittelt“, spricht der Akku ein
Protokoll, das die App nicht kennt die dort angezeigte Rohantwort ist dann
der Ansatzpunkt.
* Die Feldbelegungen der Victron-Datensätze stammen aus Victrons
„Extra Manufacturer Data“-Beschreibung. Solarladeregler und DC/DC-Wandler
sind die am besten belegten Typen.
* Die Bluetooth-Kennung eines Geräts ist pro iPhone eindeutig. Auf einem
zweiten Gerät müssen die Geräte neu eingerichtet werden.