This commit is contained in:
BiasF
2026-08-30 10:36:52 +02:00
commit fdcc644828
30 changed files with 4152 additions and 0 deletions
+136
View File
@@ -0,0 +1,136 @@
# 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) |
| Daly BMS (Bulltron) | GATT-Verbindung, alle 5 s abgefragt | SoC, Spannung, Strom, Restkapazität, alle Einzelzellspannungen, Zelldifferenz, Temperaturen, Zyklen, MOSFET-Status |
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.
### Daly BMS
Kein Schlüssel nötig. In der Liste erscheint das BLE-Modul meist als `DL-…`.
Auswählen, Art auf **Batterie / BMS** stellen, Sichern.
Die App erkennt selbst, ob das BMS das klassische `A5`-Protokoll oder das
neuere Modbus-Protokoll (`D2`) spricht, und sucht die passenden GATT-
Charakteristiken automatisch die BLE-Module unterscheiden sich zwischen
Fertigungschargen.
Nur **eine** App gleichzeitig kann mit dem BMS verbunden sein. Wenn die
Bulltron-/Daly-App offen ist, bekommt Camper Monitor keine Verbindung.
## 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/
│ ├── 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 Rahmenbau und Prüfsummen beider Dialekte
│ ├── DalyState.swift Sammelt Antworten zu einem Gesamtbild
│ └── DalySession.swift GATT-Verbindung und Abfragezyklus
├── 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
└── 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 ist gut dokumentiert und
sicher; falls dein BMS Modbus spricht und Werte unplausibel aussehen, muss
das Mapping in `DalyState.apply(registers:)` am realen Gerät nachgezogen
werden.
* 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.