Zwei Dinge in einem Commit, weil sie sich dieselben Dateien teilen:
project.pbxproj und WatchRootView.swift tragen beides.
**Komplikation.** Neues Target CamperMonitorComplication, auf watchOS
sind Komplikationen WidgetKit-Widgets. Es wird in die Watch-App
eingebettet (PlugIns) und bietet die vier Zubehör-Familien an. Ein Tipp
öffnet die App direkt auf der Nivellierung statt in der Geräteliste:
Die Komplikation hängt eine Adresse an, die Watch-App führt dafür jetzt
einen Navigationsweg, den sie von aussen setzen kann. Die Adresse steht
in Shared/WatchDeepLink.swift, weil beide Seiten sie brauchen – ein
Tippfehler auf einer Seite bliebe sonst stumm.
Bewusst ohne Messwert: Eine Komplikation läuft in einem eigenen Prozess
und käme an die Werte nur über eine App-Gruppe, und die verlangt eine
bezahlte Mitgliedschaft. Ein Wert, der beim Blick aufs Zifferblatt
Stunden alt sein kann, wäre ohnehin schlimmer als keiner – man glaubt
ihm. Die Komplikation tut deshalb genau eine Sache, und die zuverlässig.
**Rebranding.** Der sichtbare Name ist überall VanControl Pro:
CFBundleDisplayName beider Apple-Targets, Android-Label, die Texte in
beiden Apps, beide READMEs und der Name der APK im Gitea-Ablauf.
Die Kennungen bleiben, wie sie sind – Bundle-IDs, Android-Paket,
Target-, Ordner- und Schemanamen. Eine geänderte Bundle-ID ist für iOS
eine neue App: Geräte, Fahrzeugprofile und Victron-Schlüssel wären weg,
dazu neue Profile und eine neu zu koppelnde Watch-App. Sichtbar ist
davon nichts, also gibt es dafür auch keinen Grund.
Geprüft: alle drei Apple-Targets bauen, die Erweiterung liegt im
Watch-Bundle unter PlugIns, die Anzeigenamen stimmen im gebauten
Bundle, Tests grün. Die neue Bundle-ID der Erweiterung braucht beim
ersten Lauf aus Xcode ein Profil, das Xcode selbst anlegt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Kalibrier-Nullpunkte lagen schon immer im ESP und wurden dort auch
abgezogen – nur verriet die Firmware sie niemandem. Die Einbaulage lag
dagegen in jeder App einzeln, und damit stand sie bei drei Endgeräten
dreimal da, im Zweifel dreimal verschieden. Sie beschreibt aber den
Einbau und nicht das Telefon.
Zwei neue Charakteristiken:
...3426 Nullpunkte, zwei Floats, nur lesen
...3428 Einbaulage, acht Byte, lesen und schreiben
0 Version, 1 = gültig gesetzt, 0 = nie geschrieben
1 Längsachse: 0 = Pitch des Sensors, 1 = Roll
2 längs umgekehrt (0/1)
3 quer umgekehrt (0/1)
4..7 Verdrehung um die Hochachse, float32, Grad
Das Versionsbyte löst die Umstellung: Steht dort 0, hat nie jemand
geschrieben – dann gilt weiter, was die App örtlich gespeichert hat, und
beim nächsten Bestimmen wandert sie hinauf. Mit älterer Firmware ohne die
Charakteristik passiert schlicht nichts.
Angewandt wird die Lage weiterhin in den Apps. Der Sensor verwahrt sie
nur: Meldete er die Winkel bereits umgerechnet, rechnete jede ältere App
die Korrektur ein zweites Mal ein.
Beim Verbinden liest jede App die Lage und übernimmt sie; nach dem
Einbaulage-Assistenten schreibt sie sie hinauf. Die Uhr braucht das
iPhone dafür nicht mehr – sie holt sie sich selbst. Die Android-App
bekommt dabei auch die Verdrehung, die ihrer Fassung bisher ganz fehlte:
Modell, Erkennung und Persistenz nachgezogen.
Geprüft: Firmware übersetzt, im erzeugten Code stehen beide
Charakteristiken mit den richtigen Rechten und der Schreib-Handler;
iPhone- und Watch-Ziel bauen; sieben neue Prüfungen in run-tests.sh
nageln das Byte-Format fest, samt Rundlauf und der Bedeutung von
Version 0. Nicht geprüft ist die Android-Fassung: Auf dieser Maschine
liegt nur Java 8, Gradle verlangt mindestens 11.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Seit dem Neubau mit ESPHome 2026.6.5 lieferte der Sensor bei jeder Abfrage
denselben Wert. Der Grund steht im erzeugten Code: Ein getemplatetes
"value:" an einer Charakteristik wird von der neuen Fassung in eine
Aktion übersetzt, die genau einmal in setup() abläuft.
void setup() {
...
esp32_ble_server_..._setvalueaction_id->play(); // Pitch
esp32_ble_server_..._setvalueaction_id_2->play(); // Roll
Danach stand in der Charakteristik für immer der Wert vom Start – beim
Hochfahren ist das NAN oder die erste Messung. Die Apps lasen also
gewissenhaft eine Zahl, die sich nie mehr änderte; in der Einbaulage-
Bestimmung sah das aus, als merke sich die App sofort einen Wert.
Jetzt setzt jeder Sensor seinen Wert selbst, über on_value. Das
getemplatete "value:" an den Charakteristiken entfällt – ESPHome lehnt
beides nebeneinander ohnehin ab. Im erzeugten Code steht set_value
dadurch nicht mehr in setup(), sondern an den Auslösern der beiden
Sensoren.
Notify bleibt bewusst aus: Die Apps fragen im Takt ab, das funktioniert,
und eine frühere Fassung mit notify liess das Gerät verstummen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die überarbeitete Firmware liess sich prüfen und fehlerfrei übersetzen,
blieb auf dem Gerät aber stumm - keine Werte, keine Ausgabe über die
serielle Schnittstelle. Der Umbau war zu gross für das, was sich ohne
Gerätezugriff absichern lässt: config und compile sagen nichts über das
Laufzeitverhalten.
Die Firmware setzt jetzt wieder auf dem bewährten Stand 1.0 auf und ändert
daran nur zweierlei: die Kalibrierung über Bluetooth funktioniert (die
Charakteristik war beschreibbar, hatte aber keine Aktion hinterlegt und
tat nichts), und der ESP-NOW-Rest ist entfernt, der bei jedem Messwert ein
"hallo" an eine feste MAC schickte. Kein notify, kein aktives Setzen der
Werte, kein Zugriff auf den BLE-Server aus dem Boot-Ablauf heraus.
In der App fällt damit ein Denkfehler auf: fehlende Kalibrier-Offsets
galten als "nicht kalibriert" statt als "unbekannt". Bei Firmware, die
sie nicht meldet, stünde dauerhaft eine Warnung, die sich nicht abstellen
lässt. Gewarnt wird jetzt nur, wenn das Gerät ausdrücklich Nulloffsets
meldet. Der Rücksetz-Knopf hing an derselben Bedingung und wäre sonst
unerreichbar gewesen.
Das Abfragen im Takt war bereits als Rückfallebene eingebaut und trägt
diesen Aufbau ohne Änderung.
Ausserdem nimmt die .gitignore jetzt virtuelle Python-Umgebungen aus. Eine
solche war versehentlich mitversioniert worden - über 14000 Dateien, die
maschinenabhängig sind und im Repo nichts zu suchen haben.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die ESPHome-Firmware lag bisher im eigenständigen Projekt VanAllign-Pro.
Da die App der einzige Client ist, gehören Firmware und App zusammen:
ändert sich die Bluetooth-Schnittstelle, muss beides gemeinsam angefasst
werden.
Übernommen sind die Firmware selbst und die beiden Experimente zu
WLAN/BLE-Umschaltung und ESP-NOW, letztere nach experimente/ einsortiert
und als nicht betriebsnotwendig gekennzeichnet. Die WebBLE-Oberfläche
bleibt im Ursprungsprojekt - sie ist durch die App abgelöst und bringt
2 MB Bilder mit, die in einem iOS-Projekt nichts zu suchen haben.
Die .gitignore schliesst jetzt die ESPHome-Build-Verzeichnisse aus; im
Ursprungsprojekt fehlte das, dort liegen inzwischen 233 MB Bauartefakte
neben den Quellen.
Am neuen Ort mit esphome config gegengeprüft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>