forked from fritob/Camper-Monitor
Die Geräteansichten zeigten dauerhaft die technischen Angaben: erkanntes Protokoll, Bluetooth-Merkmale samt vollständigem Merkmalsbaum, gesendete Befehle und die Rohdaten der letzten Antwort. Das war zum Einrichten der Geräte nötig - für den Alltag ist es nur Ballast zwischen den Messwerten. Sie sind jetzt ausgeblendet und über Einstellungen → Diagnose anzeigen wieder einzublenden. Die Einstellungen sind neu und sitzen im Fahrzeugmenü des Dashboards. Eine Ausnahme: Meldet ein Gerät einen Fehler oder fehlt ein Victron-Schlüssel, erscheinen die Angaben unabhängig von der Einstellung. Genau dann sind sie das Einzige, was weiterhilft - und niemand denkt in dem Moment daran, sie erst irgendwo einzuschalten. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
287 lines
14 KiB
Markdown
287 lines
14 KiB
Markdown
# 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 |
|
||
| Neigungsmesser (VanAlign Pro) | GATT-Verbindung | Längs- und Querneigung als Libelle, Kalibrierung aus der App |
|
||
|
||
Ein Victron SmartShunt/BMV wird ebenfalls unterstützt, falls später einer dazukommt.
|
||
|
||
Die Firmware des Neigungsmessers liegt mit im Projekt, siehe
|
||
[firmware/vanalign](firmware/vanalign/README.md).
|
||
|
||
## 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).
|
||
|
||
### Nivellierung
|
||
|
||
Der Neigungsmesser [VanAlign Pro](https://github.com/) ist ein ESP32 mit
|
||
MPU6050, der Längs- und Querneigung über Bluetooth bereitstellt. Er bewirbt
|
||
seinen Dienst, wird beim Einrichten also sicher erkannt und die Art
|
||
vorbelegt.
|
||
|
||
Die Detailansicht bietet zwei Darstellungen, umschaltbar und über Starts
|
||
hinweg gemerkt:
|
||
|
||
* **Libelle** – die Blase wandert dorthin, wo das Fahrzeug höher steht, wie bei
|
||
einer echten Wasserwaage. Ringe markieren Toleranz und zwei Grad.
|
||
* **Fahrzeug** – Seitenansicht für längs, Heckansicht für quer, beide gekippt.
|
||
Die Heckansicht teilt die Blickrichtung des Fahrers, links im Bild ist also
|
||
links am Fahrzeug. Die Neigung ist dreifach überhöht dargestellt, sonst wäre
|
||
sie bei zwei Grad kaum zu erkennen; die angezeigten Gradzahlen sind echt.
|
||
|
||
In beiden Fällen: grün heißt eben (bis 0,5°), orange bis zwei Grad, darüber
|
||
rot. Dazu steht in Worten, welche Seite höher steht.
|
||
|
||
Die Fahrzeugzeichnungen stammen aus dem Ursprungsprojekt VanAlign Pro. Sie
|
||
liegen als Schablonen im Asset-Katalog und werden je nach Abweichung
|
||
eingefärbt; die Helligkeit des Originals wurde dafür in Deckkraft übersetzt,
|
||
damit Fenster und Konturen beim Einfärben erhalten bleiben.
|
||
|
||
**Vor der ersten Nutzung kalibrieren:** Fahrzeug eben stellen, dann *Auf
|
||
aktuelle Lage kalibrieren*. Ohne das zeigt die Anzeige die Lage des Sensors,
|
||
nicht die des Fahrzeugs – je nachdem, wie schief er eingebaut ist.
|
||
|
||
Die Werte werden zweimal je Sekunde abgefragt. Bietet ein Gerät `notify` an,
|
||
werden sie stattdessen abonniert – die mitgelieferte Firmware tut das
|
||
allerdings nicht, siehe deren README.
|
||
|
||
Ob bereits kalibriert wurde, meldet nicht jede Firmware zurück. Fehlt die
|
||
Angabe, gilt sie als unbekannt und die App warnt nicht – eine Warnung, die
|
||
sich nie abstellen lässt, wäre schlimmer als keine. Kalibrieren aus der App
|
||
braucht Firmware 1.0.2.
|
||
|
||
### Ausrichtungs-Assistent
|
||
|
||
Von der Nivellierungs-Ansicht aus erreichbar, gedacht fürs Rangieren. Er
|
||
verfolgt die Neigung über die Zeit und sagt, ob es gerade besser oder
|
||
schlechter wird – und wo es am besten stand: *„Vor 4 Sekunden stand das
|
||
Fahrzeug 0,8° flacher."* Steht der Camper in der Toleranz, meldet das Gerät
|
||
sich mit einer Vibration; das Display bleibt solange wach.
|
||
|
||
Bewusst **ohne** Positionsbestimmung. Aus einem MEMS-Beschleunigungssensor
|
||
lässt sich keine brauchbare Strecke ableiten, weil der Fehler beim zweifachen
|
||
Integrieren quadratisch mit der Zeit wächst und die Beschleunigungen im
|
||
Schritttempo ohnehin im Rauschen untergehen. Gebraucht wird das auch nicht:
|
||
Beim Einparken lautet die Frage nie „wo stehe ich", sondern „wird es besser".
|
||
Das steckt vollständig im zeitlichen Verlauf der Neigung – ohne jede Annahme
|
||
über das Gelände.
|
||
|
||
Sind beim Fahrzeug **Spurweite und Radstand** hinterlegt, rechnet der Assistent
|
||
zusätzlich die nötige Höhe der Auffahrkeile aus. Das ist reine Geometrie und
|
||
damit exakt: 2,0° Querneigung bei 2,00 m Spurweite ergeben 7,0 cm unter die
|
||
tieferstehende Seite. Die Maße stehen im Fahrzeugprofil, erreichbar über das
|
||
ⓘ in der Fahrzeugliste.
|
||
|
||
## Diagnose
|
||
|
||
Im Alltag zeigt die App nur Messwerte und Bedienelemente. Die technischen
|
||
Angaben – erkanntes Protokoll, Bluetooth-Merkmale, gesendete Befehle, Rohdaten
|
||
der letzten Antwort – sind ausgeblendet und lassen sich unter *Einstellungen →
|
||
Diagnose anzeigen* einschalten. Die Einstellungen sitzen im Fahrzeugmenü oben
|
||
links im Dashboard.
|
||
|
||
Meldet ein Gerät einen Fehler oder fehlt ein Victron-Schlüssel, werden die
|
||
Angaben unabhängig davon eingeblendet – dann sind sie genau das, was
|
||
weiterhilft.
|
||
|
||
## 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
|
||
|
||
```
|
||
firmware/vanalign/ Firmware des Neigungsmessers (ESPHome)
|
||
├── esp32_ble.yaml Neigungsmessung und Bluetooth-Schnittstelle
|
||
└── experimente/ Nicht für den Betrieb nötig
|
||
|
||
CamperMonitor/
|
||
├── Models/
|
||
│ ├── Profile.swift Fahrzeug samt Maßen
|
||
│ ├── AlignmentAssistant.swift Verlauf, Tendenz und Keilberechnung
|
||
│ ├── 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
|
||
│ ├── VanAlignProtocol.swift Neigungsmesser: Winkel und Kalibrierung
|
||
│ ├── LevelSession.swift Verbindung zum Neigungsmesser
|
||
│ └── 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
|
||
├── LevelView.swift Libelle und Kalibrierung
|
||
├── AlignmentAssistantView.swift Ausrichtungs-Assistent fürs Rangieren
|
||
├── VehicleTiltView.swift Neigung am Fahrzeug dargestellt
|
||
├── SettingsView.swift App-Einstellungen
|
||
└── 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.
|