forked from fritob/Camper-Monitor
Neues Target CamperMonitorWatch, eingebettet in die iPhone-App. Die Uhr zeigt je Gerät den Hauptwert, die Nivellierung mit Libelle und Keilhöhen, den Ausrichtungs-Assistenten und stellt die Kühlbox. Die Uhr funkt nicht selbst, obwohl watchOS das könnte. BMS, Kühlbox und Neigungsmesser lassen jeweils nur eine Verbindung zu – eine mitlesende Uhr würde dem iPhone die Verbindung wegnehmen, statt sie zu ergänzen. Und die Victron-Schlüssel liegen in der Keychain des iPhones; sie ein zweites Mal auf der Uhr aufzubewahren brächte nichts. Das iPhone bleibt also das Funkgerät und reicht fertige Messwerte über WatchConnectivity weiter. Gesendet wird in zwei Takten: ein halber Sekundentakt als Nachricht, solange die Watch-App im Vordergrund ist und das über eine Frist meldet, sonst alle zwei Sekunden als Anwendungskontext und nur bei Änderungen. Läuft die Frist ab, hört das iPhone von selbst wieder auf. Solange die Uhr hinschaut, hält die App das Funkgerät auch im Hintergrund am Leben (UIBackgroundModes in Config/CamperMonitor-Info.plist) – beim Rangieren liegt das iPhone sonst mit dunklem Bildschirm in der Halterung und die Anzeige am Handgelenk wäre genau dann tot. Die verbundenen Geräte liefern dabei weiter, die Victron-Werbedaten nicht: ungefiltertes Suchen lässt iOS im Hintergrund nicht zu. Der plattformneutrale Modellcode wandert nach Shared/ und wird in beide Targets übersetzt; LevelState ist dafür aus VanAlignProtocol.swift herausgelöst. Datensatz und Befehle stehen in Shared/WatchLink und sind in run-tests.sh abgesichert: Rundlauf, Schutz gegen fremde Formatversion, Vergleich ohne Zeitstempel und die Auflösung der Zeitangaben. Geprüft sind der Bau beider Targets samt Einbetten und der Testlauf; auf echter Hardware noch nicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
396 lines
19 KiB
Markdown
396 lines
19 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.
|
||
|
||
Dazu gehört eine **Apple-Watch-App**: Übersicht, Nivellierung samt
|
||
Ausrichtungs-Assistent mit Vibration und die Steuerung der Kühlbox am
|
||
Handgelenk. Sie funkt nicht selbst, sondern hängt am iPhone – warum, steht
|
||
unter [Apple Watch](#apple-watch).
|
||
|
||
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.
|
||
Dasselbe beim Target `CamperMonitorWatch`; dessen Bundle-ID muss die des
|
||
iPhones mit angehängtem `.watchkitapp` bleiben.
|
||
2. iPhone per Kabel anschließen, oben als Ziel wählen, ⌘R.
|
||
|
||
Das Schema `CamperMonitor` baut die Watch-App mit und bettet sie ein. Dafür
|
||
muss die watchOS-Plattform in Xcode installiert sein – sonst bricht schon das
|
||
Übersetzen des Symbolkatalogs ab:
|
||
|
||
```bash
|
||
xcodebuild -downloadPlatform watchOS
|
||
```
|
||
|
||
Auf die Uhr kommt die App danach von selbst: Sie steckt in der iPhone-App und
|
||
taucht in der Watch-App des iPhones unter *Verfügbare Apps* auf.
|
||
|
||
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 die Einbaulage bestimmen.** Sitzt der Sensor quer,
|
||
gedreht oder kopfüber, meldet er längs und quer vertauscht oder mit falschem
|
||
Vorzeichen. Der Assistent unter *Sensor → Einbaulage* klärt das durch zwei
|
||
Kippbewegungen: einmal die Front nach unten, einmal die linke Seite. Aus der
|
||
Reaktion ergibt sich die Zuordnung – geraten wird nichts.
|
||
|
||
**Danach 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.
|
||
|
||
## Apple Watch
|
||
|
||
Die Uhr zeigt dasselbe wie das Dashboard, nur auf das eingedampft, wofür man
|
||
den Arm hebt:
|
||
|
||
* **Übersicht** – je Gerät der Hauptwert und ein Punkt für den Zustand der
|
||
Verbindung. Ganz unten steht, wie alt der Stand ist.
|
||
* **Nivellierung** – Libelle, beide Winkel, was zu tun ist, und die nötige
|
||
Keilhöhe, falls im Fahrzeugprofil Spurweite und Radstand stehen.
|
||
* **Ausrichten** – derselbe Assistent wie am iPhone: Tendenz, Rat und der
|
||
Hinweis auf den flachsten Punkt der letzten anderthalb Minuten. **Steht das
|
||
Fahrzeug in der Toleranz, vibriert die Uhr.** Das ist der eigentliche Gewinn
|
||
gegenüber dem iPhone – beim Rangieren schaut niemand aufs Display, aber die
|
||
Vibration am Handgelenk kommt an.
|
||
* **Kühlbox** – ein/aus, Eco oder Max und die Solltemperatur, über die Krone
|
||
gestellt.
|
||
|
||
### Warum die Uhr nicht selbst funkt
|
||
|
||
watchOS könnte Bluetooth, und trotzdem geht alles über das iPhone. Zwei Gründe,
|
||
beide hart:
|
||
|
||
* BMS, Kühlbox und Neigungsmesser lassen jeweils nur **eine** Verbindung zu.
|
||
Eine mitlesende Uhr würde dem iPhone die Verbindung wegnehmen, statt sie zu
|
||
ergänzen.
|
||
* Die Victron-Schlüssel liegen in der Keychain des iPhones. Sie auf die Uhr zu
|
||
kopieren hiesse, sie ein zweites Mal aufzubewahren, ohne dass der zweite Ort
|
||
irgendetwas brächte.
|
||
|
||
Das iPhone bleibt also das Funkgerät und reicht fertige Messwerte weiter. Was
|
||
die Uhr stellt, stellt in Wahrheit das iPhone – und angezeigt wird auch dort
|
||
nur, was das Gerät zurückmeldet, nicht der Tastendruck.
|
||
|
||
### Was das für den Betrieb heisst
|
||
|
||
Auf dem iPhone muss Camper Monitor laufen. Solange die Uhr meldet, dass jemand
|
||
hinschaut, hält die App das Funkgerät auch im Hintergrund am Leben – sonst wäre
|
||
die Anzeige am Handgelenk beim Rangieren tot, denn dann liegt das iPhone mit
|
||
dunklem Bildschirm in der Halterung. Die verbundenen Geräte liefern dabei
|
||
weiter; die Victron-Werbedaten nicht, weil iOS im Hintergrund kein ungefiltertes
|
||
Suchen erlaubt.
|
||
|
||
Gesendet wird in zwei Takten: ein halber Sekundentakt, solange die Watch-App im
|
||
Vordergrund ist, sonst alle zwei Sekunden und nur bei Änderungen. Der schnelle
|
||
Takt läuft über eine Frist, die die Uhr regelmässig erneuert – schläft sie ein,
|
||
hört das iPhone von selbst wieder auf.
|
||
|
||
Was die Uhr zeigt, ist immer Weitergereichtes. Deshalb steht auf jedem
|
||
Bildschirm das Alter des Standes: Eine abgerissene Strecke zum iPhone sähe sonst
|
||
genauso aus wie ein Fahrzeug, an dem sich nichts tut.
|
||
|
||
## 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.
|
||
|
||
Die Watch-App kennt denselben Schalter und braucht dann kein iPhone: Im Schema
|
||
`CamperMonitorWatch` dieselbe Variable setzen. Die Neigung wandert dort
|
||
langsam hin und her, sonst hätte der Ausrichtungs-Assistent nichts zu zeigen.
|
||
|
||
## 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
|
||
|
||
Shared/ In iPhone- und Watch-App übersetzt
|
||
├── Models/
|
||
│ ├── Profile.swift Fahrzeug samt Maßen
|
||
│ ├── AlignmentAssistant.swift Verlauf, Tendenz und Keilberechnung
|
||
│ ├── SensorOrientation.swift Einbaulage und ihre Erkennung
|
||
│ ├── ConfiguredDevice.swift Eingerichtetes Gerät, Rolle, Transportart
|
||
│ ├── DeviceSnapshot.swift Messwerte in Anzeigeform
|
||
│ ├── LevelState.swift Neigung, Toleranz und Klartext dazu
|
||
│ └── VictronCodes.swift Klartexte für Zustands-/Fehlercodes
|
||
└── WatchLink/
|
||
└── WatchLink.swift Datensatz und Befehle zwischen iPhone und Uhr
|
||
|
||
CamperMonitor/
|
||
├── 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
|
||
├── Watch/
|
||
│ └── PhoneWatchLink.swift Sendet den Stand, nimmt Befehle der Uhr an
|
||
└── 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
|
||
├── SensorSetupView.swift Assistent für die Einbaulage
|
||
└── AddDeviceView.swift Scannen und Einrichten
|
||
|
||
CamperMonitorWatch/ watchOS-App
|
||
├── CamperWatchApp.swift Einstieg, meldet dem iPhone das Hinschauen
|
||
├── PhoneLink.swift Gegenstelle zum iPhone
|
||
├── WatchDemo.swift Erfundene Werte für den Simulator
|
||
└── Views/
|
||
├── WatchRootView.swift Übersicht und Altersangabe
|
||
├── WatchBubble.swift Libelle für den kleinen Bildschirm
|
||
├── WatchLevelView.swift Neigung, Keilhöhe, Kalibrierung
|
||
├── WatchAlignView.swift Ausrichten mit Vibration
|
||
├── WatchDeviceDetailView.swift Alle Werte eines Geräts
|
||
└── WatchFridgeControls.swift Kühlbox stellen
|
||
|
||
Config/
|
||
└── CamperMonitor-Info.plist Nur der Hintergrundbetrieb für die Uhr
|
||
```
|
||
|
||
## Bekannte Grenzen
|
||
|
||
* **Im Hintergrund nur die verbundenen Geräte.** iOS erlaubt das ungefilterte
|
||
Scannen nach Advertisements nur im Vordergrund; die Victron-Werte stehen im
|
||
Hintergrund also still. Verbundene Geräte – Neigungsmesser, BMS, Kühlbox –
|
||
laufen weiter, aber nur solange die Uhr meldet, dass jemand hinschaut. Ohne
|
||
Uhr pausiert die App im Hintergrund vollständig und nimmt beim Zurückkommen
|
||
wieder auf.
|
||
* **Die Uhr braucht das iPhone.** Sie zeigt nur, was von dort kommt. Steckt das
|
||
iPhone ausser Reichweite, steht auf der Uhr, wie alt der letzte Stand ist –
|
||
aber kein neuer.
|
||
* **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.
|