Commit Graph
18 Commits
Author SHA1 Message Date
fototeddyandClaude Sonnet 5 e9b9c5bcd5 Solar-Integration und dev_watch-Geräte zusammenführen
solar-integration (aus dem separaten VanAligneiOS-Repo) und dev_watch
haben unabhängige Git-Historien, decken aber überlappende und sich
ergänzende Funktionen ab. Übernommen aus solar-integration: Votronic-
Solar-ESP-Anbindung samt Geräterolle, die Live-Activity/Widget-Extension
fürs Sperrbildschirm/Dynamic-Island/CarPlay, das Querformat-Layout für
Libelle/Fahrzeug-Ansicht und Ausrichtungs-Assistent, sowie die
mehreren Fahrzeuggrafik-Stile (Vanster/California). Beibehalten aus
dev_watch: alle zusätzlichen Geräteprotokolle (Daly-/JBD-BMS, Alpicool-
Kühlbox, WattCycle, Victron), die dort zwischenzeitlich entstanden.

Die Xcode-Projektdatei wurde von Hand um die neue Widget-Extension samt
SharedActivity-Gruppe erweitert (Datei-synchronisierte Gruppen, kein
App-Group-Entitlement nötig). Build für App, Watch und Widget-Extension
geprüft (Debug und Release).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 21:00:14 +02:00
BiasFandClaude Opus 5 812874baef Kühlbox-Kachel: "Soll" dazuschreiben, Betriebsart gross, Hinweis nach vorn
Auf der Kachel stand eine nackte Zahl, und das ist genau die Zahl, die
man für die Innentemperatur hält. Jetzt steht "Soll" darüber – bei zwei
Zonen "Soll links", mit "Soll rechts" gleich daneben statt in der
Nebenwertzeile.

Die Betriebsart bekommt ein eigenes Schild in Titelgrösse, rechts auf
Höhe des Sollwerts: Eco oder Max in der Akzentfarbe hinterlegt, Aus grau.
Ob die Box überhaupt läuft, ist die zweite Frage nach dem Sollwert, und
Platz ist auf der Kachel reichlich.

In der Fusszeile steht der Hinweis aufs Verbinden jetzt vorn: "Verbindet
erst beim Öffnen · zuletzt gestellt vor 12 Minuten". Er erklärt, warum
hier kein Messwert steht – das ist die Frage, die sich zuerst stellt, das
Alter kommt danach.

Im Vorführbetrieb steht die Kühlbox ebenfalls auf "zuletzt gestellt"
statt live. Sonst zeigt er ein Verhalten, das es nicht mehr gibt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 22:21:09 +02:00
BiasFandClaude Opus 5 5fec4a55dd Kühlbox nur verbinden, während man sie ansieht
Jede Verbindung meldet sich am Display der Box an – sie piept, und wer
gerade davorsteht, wird gestört. Dauerhaft verbunden zu sein ist dort
also nicht unsichtbar wie beim BMS, sondern lästig.

Die Kühlbox wird deshalb nur noch verbunden, solange ihre Ansicht offen
ist: am iPhone über die Detailansicht, an der Uhr über einen eigenen
Befehl, den sie beim Öffnen und Schliessen schickt. Ein Stellbefehl geht
weiterhin immer durch – ist die Box nicht verbunden, wird er gemerkt und
löst den Verbindungsaufbau aus.

Abgeriegelt sind alle drei Wege, über die bisher verbunden wurde: beim
Start, im Takt des Wiederverbindens, und – das war das eigentliche Loch –
sobald das Gerät in den Werbedaten auftaucht. Da die App dauerhaft
scannt, hätte allein dieser Weg die Box weiter angefunkt. Dass sie in
Reichweite ist, ist kein Grund, sie anzufassen.

Auf der Übersicht steht dafür der zuletzt gestellte Stand statt der
Messwerte: Sollwert, Ein/Aus, Eco oder Max, dazu wann er gestellt wurde.
Das bleibt richtig, auch wenn es von gestern ist – ein Sollwert ändert
sich nur, wenn jemand ihn ändert. Eine Innentemperatur von gestern sähe
dagegen aus wie eine von jetzt, und man würde ihr glauben. Genau das
sichern die neuen Prüfungen ab: Hauptwert ist der Sollwert, gemessene
Temperatur und Bordspannung kommen nicht vor.

Der Stand liegt in den Einstellungen (FridgeSettings) mit einem
Zeitstempel, der „zuletzt geändert" bedeutet und nicht „zuletzt gesehen" –
sonst behauptete die Kachel Frische, wo sich nichts getan hat. Die Uhr
bekommt dasselbe Bild: WatchFridge trägt jetzt ein Kennzeichen isLive.

BMS und Neigungsmesser bleiben dauerhaft verbunden. Sie stören nicht, und
ihre Werte will man laufend sehen.

Nicht nachgezogen ist die Android-App – dort verbindet der
BluetoothManager weiterhin dauerhaft.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 22:00:10 +02:00
BiasFandClaude Opus 5 f0df433421 Kalibrierung und Einbaulage gehören in den Sensor, nicht in die Apps
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>
2026-08-31 20:50:23 +02:00
BiasFandClaude Opus 5 8f8edb137b Kühlbox: weniger Piepen, Diagnose zum Weitergeben
Dein Befund grenzt es ein: die Solltemperatur lässt sich stellen, also
kommen Schreibvorgänge an. Es scheitert nur am Einstellungsblock.

Das mehrfache Piepen war meine Schuld. Beantwortet die Box die Anmeldung
nicht, habe ich sie vor jedem Stellbefehl erneut angemeldet - und die Box
quittiert jede Anmeldung mit einem Ton. Jetzt geschieht das höchstens
einmal je Verbindung.

Weiter komme ich nicht ohne die Antwort deiner Box. Ihre Länge entscheidet
darüber, wie lang der Stellbefehl sein muss, und sie steht jetzt als
"Statusdaten der Box" in der Diagnose. Dazu ein Knopf, der alles zusammen
in die Zwischenablage legt - Merkmalsbaum, Weg, Schreibart, letzten Befehl
und letzte Antwort. Das abzutippen wäre zuviel verlangt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 09:08:43 +02:00
BiasFandClaude Opus 5 8b1e2ac39d Kühlbox: Schreibweg absichern und selbst nachbessern
Vier Anläufe ohne Erfolg heisst: die Annahme, der Schreibvorgang komme an,
trägt nicht mehr. Also wird sie geprüft, statt weiter darauf zu bauen.

Drei Dinge am Schreibweg waren wirklich falsch.

Die Reihenfolge der Kandidaten war nicht festgelegt. Bietet ein Merkmal
beide Schreibarten an, sind beide Einträge gleichwertig - und `sorted`
sichert für gleichwertige Einträge keine Reihenfolge zu. Ob mit oder ohne
Bestätigung geschrieben wurde, entschied damit der Zufall, von Start zu
Start womöglich verschieden. Jetzt bleibt die Fundreihenfolge erhalten.

Ein Schreibvorgang ohne Bestätigung wird von iOS stillschweigend verworfen,
wenn der Sendepuffer voll ist. Das wurde nirgends beachtet. Jetzt wartet,
was nicht sofort rausgeht, auf die Bereitschaftsmeldung.

Schreibfehler waren unsichtbar: für Schreibvorgänge mit Bestätigung gab es
gar keine Rückmeldung. Jetzt werden sie gezählt und Fehler gemeldet, beides
steht in der Diagnose.

Dazu bessert die Sitzung selbst nach. Nach einem Stellbefehl wird geprüft,
ob sich die Einstellungen der Box überhaupt geändert haben - an den
Einstellungsbytes, nicht an Temperatur und Spannung, die ohnehin schwanken.
Bleibt alles gleich, wird einmal mit der anderen Schreibart nachgesetzt.
Nimmt die Box nur eine der beiden an, findet die App das jetzt allein.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 09:03:22 +02:00
BiasFandClaude Opus 5 568662fd5e Kühlbox: Stellbefehl in der Länge, die die Box erwartet
Diesmal gegen die Referenzimplementierung geprüft statt geraten. Rahmen,
Längenbyte, Prüfsumme, Anmelde- und Abfragepaket stimmen dort byteweise
mit unseren überein. Ein Unterschied blieb: die Länge des Einstellungs-
blocks.

Ich hatte sie an die Zonenerkennung gehängt. Sendet eine Box den langen
Datensatz, füllt den zweiten Block aber mit Nullen, galt sie als einzonig
und bekam den kurzen Befehl - während sie den langen erwartet. Die Box
verwirft ihn dann wortlos, und Ein- und Ausschalten blieb wirkungslos.
Die Referenz hängt die Länge an die Antwort der Box, nicht an eine
Deutung davon. Jetzt auch hier. Für die Anzeige bleibt die Erkennung
unverändert: ein leerer zweiter Block wird weiterhin nicht als zweite
Zone gezeigt.

Zweitens die Anmeldung. Abfragen beantwortet die Box teils auch
unangemeldet, Stellbefehle nicht. Ob die Anmeldung je bestätigt wurde,
wurde bisher nicht verfolgt. Jetzt schon: fehlt die Bestätigung, wird vor
dem Stellbefehl noch einmal angemeldet. In der Diagnose steht der Stand
als eigene Zeile.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 23:51:38 +02:00
BiasFandClaude Opus 5 270c701ad6 Kühlbox wieder bedienbar, Einbaulage richtig messen
Zwei Fehler aus dem letzten Stand, beide von mir eingebaut.

Die Kühlbox liess sich nicht mehr bedienen. Die Wartesperre gegen den
Verbindungssturm hat nicht unterschieden, warum eine Verbindung endete:
ein Abbruch einer Verbindung, die stand, wurde genauso lange gesperrt wie
ein Fehlschlag. Im Fahrzeug ist so ein Abbruch der Normalfall, und die Box
war danach bis zu einer Minute nicht erreichbar. Ein Tippen ging in dieser
Zeit lautlos verloren, weil es ohne Sitzung ins Leere fiel.

Jetzt zählt die Dauer: was mindestens drei Sekunden stand, gilt als
zustandegekommen und wird nach zwei Sekunden wieder aufgenommen. Nur was
sofort wieder abbricht, zählt als Fehlschlag und wird gestaffelt gesperrt -
gegen das Wechselspiel, wenn eine andere App das Gerät belegt.

Dazu gehen Stellbefehle nicht mehr verloren. Fehlt die Verbindung, wird der
Befehl aufgehoben, die Sperre für dieses Gerät aufgehoben und sofort ein
Versuch angestossen; sobald der Kanal steht, geht er raus. Ein Befehl, der
älter als eine halbe Minute ist, verfällt - ein verspätetes Ausschalten
würde nur überraschen. Die Ansicht sagt es, statt den Schalter stumm
zurückspringen zu lassen.

Zweitens der Assistent für die Einbaulage. Er hat die zweite Bewegung von
der gekippten Lage aus gemessen statt von der Ruhelage. Damit steckte in
jeder zweiten Messung das Zurückkippen aus der ersten, und es schlugen
immer beide Achsen aus. Die Ruhelage ist jetzt der Bezug für beide
Bewegungen, und ein eigener Schritt dazwischen nimmt sie neu auf.

Auch die Auswertung war zu streng: sie hat jede Bewegung für sich
beurteilt und abgelehnt, sobald die andere Achse mitlief. Von Hand gekippt
läuft sie aber immer mit. Beurteilt werden jetzt beide Bewegungen
gemeinsam - es gewinnt die Zuordnung, die zusammen am meisten erklärt.
Zweimal um dieselbe Achse gekippt wird weiterhin erkannt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 23:43:57 +02:00
BiasFandClaude Opus 5 583aa75595 Verbindungssturm abstellen, Einbaulage des Sensors einrichtbar
Zwei Dinge.

Die Kühlbox piepte dauernd und die Bedienung wurde zäh. Ursache war ein
Fehler in der Verbindungslogik: nach einem fehlgeschlagenen Versuch wurde
der Eintrag freigegeben, und das nächste Advertisement löste sofort den
nächsten aus - bei laufendem Scan bis zu einmal je Sekunde. Geräte
quittieren jeden Versuch, Kühlboxen mit einem Piepton. Nebenher wechselte
der Verbindungszustand im selben Takt, was die Oberfläche in eine
Dauerneuzeichnung trieb.

Ein Versuch wird jetzt für eine Weile gesperrt, mit wachsendem Abstand von
fünf bis sechzig Sekunden. Auch nach einem Trennen durch die Gegenseite
wird nicht sofort neu angeklopft - trennt ein Gerät von sich aus, etwa
weil eine andere App verbunden ist, entstünde sonst ein Wechselspiel aus
Verbinden und Trennen. Beim Umkonfigurieren werden die Sperren
zurückgesetzt, damit ein neu eingerichtetes Gerät sofort drankommt.

Dazu entlastet: bei jeder Antwort wurden alle fünf Protokollparser
durchprobiert, auch wenn längst feststand, welches Protokoll gilt. Steht
der Dialekt, läuft nur noch dieser.

Zweitens der Neigungsmesser: je nach Einbaulage meldet er längs und quer
vertauscht oder mit falschem Vorzeichen. Statt die Lage aus einer Liste
raten zu lassen, misst der neue Assistent sie - zweimal kippen, einmal um
jede Achse, und aus der Reaktion ergibt sich die Zuordnung. Schräges oder
zu schwaches Kippen wird erkannt und gemeldet, statt eine zufällige
Zuordnung zu liefern. Die Sitzung führt die Rohwerte des Sensors weiter
mit, weil der Assistent sie unumgerechnet braucht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 23:33:47 +02:00
BiasFandClaude Opus 5 1b9486aad4 Neigungsmesser VanAlign einbinden
Das ESPHome-Projekt VanAlign Pro misst über einen MPU6050 die Längs- und
Querneigung des Fahrzeugs und stellt sie über Bluetooth bereit. Damit
lässt sich der Camper beim Parken ausrichten.

Der Neigungsmesser bewirbt seinen Dienst, wird beim Einrichten also
sicher erkannt und die Geräteart vorbelegt. Anders als bei den übrigen
verbundenen Geräten gibt es hier kein Rahmenprotokoll: jede Messgrösse
liegt in einer eigenen Charakteristik als Float. LevelSession ist deshalb
eine eigene, deutlich einfachere Sitzungsart neben BMSSession - ohne
Protokollerkennung und ohne Kandidatensuche.

Bevorzugt werden die Werte abonniert; bietet das Gerät das nicht an, wird
im Takt abgefragt. Damit läuft die App auch mit der alten Firmware 1.0,
die nur Lesen kennt.

Die Detailansicht zeigt eine Libelle: die Blase wandert dorthin, wo das
Fahrzeug höher steht. Grün bis 0,5 Grad, orange bis zwei, darüber rot -
die Akzentfarbe der App ist selbst grün, "schief" hätte sonst genauso
ausgesehen wie "eben". Die Ringe sind ein echter Massstab (Toleranz und
zwei Grad), sonst sagt die Blasenlage nichts über die verbleibende
Abweichung. Dazu die Ansage in Worten, welche Seite höher steht.

Die Winkel werden fest little-endian gelesen. Die Web-Oberfläche des
Ursprungsprojekts probiert zusätzlich die umgekehrte Reihenfolge, falls
die erste unplausibel wirkt. Das ist nicht nur unnötig, sondern
schädlich: ein vertauschter Float von 4,25 Grad liest sich als etwa 0,0
und wirkt damit völlig plausibel - der Fehler bliebe unbemerkt. Ein Test
hält das fest.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 15:05:34 +02:00
BiasFandClaude Opus 5 1ad476a963 Bluetooth auf eine eigene Queue legen
CoreBluetooth lief auf dem Hauptthread, also demselben, der die
Oberfläche zeichnet. Gescannt wird mit Duplikaten über alle Geräte in
Reichweite, weil Victron seine Werte im Advertisement mitschickt - jedes
einzelne davon kam als Rückruf dort an, samt Entschlüsselung und
Neuzeichnung. Das war die Ursache der trägen Bedienung.

CoreBluetooth arbeitet jetzt auf einer eigenen seriellen Queue. Daraus
folgt eine strikte Trennung:

* Verbindungen, Puffer und Zeitgeber werden ausschliesslich auf dieser
  Queue angefasst. Die Zeitgeber sind deshalb DispatchSourceTimer statt
  Timer, denn auf einer DispatchQueue gibt es keine RunLoop.
* Die veröffentlichten Werte werden ausschliesslich auf dem Hauptthread
  geschrieben, gebündelt über publish().
* Die Geräteliste wird nicht mehr aus der Funk-Queue heraus im Speicher
  nachgeschlagen. Stattdessen zieht refreshConfiguration auf dem
  Hauptthread eine Momentaufnahme - Kennung, Transportart, Zonenwahl und
  den bereits ausgelesenen Victron-Schlüssel - und reicht sie hinüber.
  Damit greift kein Hintergrundthread mehr auf den beobachteten Speicher
  zu.

Die Stellbefehle der Kühlbox bauen ihren Einstellungsblock ebenfalls auf
der Funk-Queue, weil der zugrundeliegende Zustand dort lebt.

Geprüft im Simulator: der Statuswechsel von CoreBluetooth kommt über die
Funk-Queue und erreicht die Anzeige korrekt, beide Startpfade laufen ohne
Absturz.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 14:39:43 +02:00
BiasFandClaude Opus 5 d7cad6945d Namen leichter ändern, Oberfläche entlasten
Umbenennen war zwar möglich, aber praktisch unauffindbar: das Eingabe-
feld trug nur einen Platzhalter, und übernommen wurde erst über einen
zusätzlichen Knopf. Jetzt steht "Name" als Beschriftung davor, der Knopf
ist weg, gesichert wird beim Abschluss der Eingabe und beim Verlassen der
Ansicht. Der Funkname steht darunter als "Gefunden als", damit das Gerät
weiter zuzuordnen ist.

Beim Einrichten wird nicht mehr der Funkname vorgeschlagen - Namen wie
"WTaEaAA25342229" taugen nicht als Anzeigename -, sondern die Art des
Geräts, sofern der Funkname kryptisch wirkt.

Die Detailansicht arbeitete auf einer Momentaufnahme des Geräts. Nach dem
Umbenennen oder nach dem Umstellen der Kühlzonen zeigte sie deshalb
weiter die alten Werte; sie liest den Stand jetzt aus dem Speicher.

Gegen die träge Oberfläche: CoreBluetooth meldet jedes Advertisement
einzeln und auf dem Hauptthread, und gescannt wird mit Duplikaten über
alle Geräte in Reichweite. Victron sendet mehrmals je Sekunde, dazu
kommt alles andere in Funkreichweite. Ausgewertet wird jetzt höchstens
einmal je Sekunde und Gerät, die Geräteliste beim Einrichten alle zwei
Sekunden, die Rohdaten der Diagnose alle drei. Ein Advertisement mehr
ändert die Anzeige ohnehin nicht, kostet aber Entschlüsselung und eine
Neuzeichnung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 14:34:07 +02:00
BiasFandClaude Opus 5 3bece5b785 Kühlbox: Stellbefehl passend zur Zonenzahl, Schalter ohne Rückfrage
Ausschalten blieb wirkungslos. Zwei Ursachen, beide behoben.

Die Länge des Einstellungsblocks hing an der Länge des empfangenen
Datensatzes statt an der Zonenzahl. Einzonen-Boxen, die den langen
Datensatz trotzdem senden, bekamen so einen 25-Byte-Block für zwei Zonen
und nahmen ihn offenbar nicht an. Jetzt entscheidet die erkannte
Zonenzahl: eine Zone ergibt 20 Byte und passt damit ohne Aufteilen in
einen Schreibvorgang.

Der Bestätigungsdialog beim Ausschalten hing an einer Section, und dort
zeigt SwiftUI ihn nicht zuverlässig an - der Schalter tat dann gar
nichts. Ein und Aus laufen jetzt beide direkt über denselben Weg, ohne
Rückfrage.

Die Diagnose zeigt zusätzlich den zuletzt abgeschickten Stellbefehl mit
Zeitstempel, damit sich unterscheiden lässt, ob ein Befehl das Gerät
nicht erreicht oder von ihm verworfen wird.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 14:27:28 +02:00
BiasFandClaude Opus 5 daea73d649 Kühlbox: Zonen richtig erkennen, Stellbefehle nicht mehr abschneiden
Zwei Fehler am Gerät gefunden.

Einzonen-Boxen als Doppelzone erkannt: Manche senden den langen
Datensatz einer Zweizonen-Box mit, füllen den zweiten Block aber mit
Nullen. Die Nutzlastlänge allein taugt deshalb nicht als Kriterium. Als
zweizonig gilt jetzt nur, wo dieser Block überhaupt Inhalt hat, und in
den Geräteeinstellungen lässt sich die Erkennung auf "Eine Zone" oder
"Zwei Zonen" festnageln.

Einschalten reagierte nicht: Ein/Aus und Betriebsart schicken den
kompletten Einstellungsblock, der mit dem langen Datensatz auf 31 Byte
kommt. Ohne ausgehandelte MTU nimmt BLE aber nur 20 Nutzbytes je
Schreibvorgang an, der Rest wurde stillschweigend verworfen. Die
Solltemperatur ging als kurzes Paket durch, alles Längere nicht. Lange
Pakete werden jetzt anhand von maximumWriteValueLength aufgeteilt und
versetzt geschrieben; die Statusabfrage danach wartet entsprechend
länger. Aus dem kurzen Datensatz ist der Befehl übrigens genau 20 Byte
groß und hätte gerade noch gepasst - deshalb trat es nur an dieser Box
auf.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 14:21:28 +02:00
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
BiasFandClaude Opus 5 fc73f730a7 BMS: Warten auf die Notify-Bestätigung nicht mehr endlos
Die Suche nach dem richtigen Verbindungsweg blieb auf dem ersten
Kandidaten stehen: gesendet wurde erst, nachdem iOS das Abonnieren der
Notify-Charakteristik bestätigt hat. Bestätigt ein Modul das nie – bei
der WattCycle-Batterie auf FFF1 der Fall –, wurde weder je eine Anfrage
geschickt noch zum nächsten Kandidaten gewechselt. Die Diagnose zeigte
dauerhaft "1 von 16" und "0 Anfragen / 0 Byte".

Die Aktivierung eines Kandidaten hat jetzt ein Zeitlimit von vier
Sekunden. Läuft es ab, geht es zum nächsten; ist es der einzige Weg,
wird trotzdem gesendet – manche Module antworten auch ohne bestätigtes
Abonnement. Ein Token verhindert, dass verspätete Rückmeldungen eines
bereits verworfenen Kandidaten den aktuellen durcheinanderbringen.

Damit sich Fortschritt überhaupt beobachten lässt, wird die Diagnose
jetzt bei jeder gesendeten Anfrage aktualisiert statt nur am Ende einer
Runde, und zeigt zusätzlich Verbindungszustand, ob der Empfang abonniert
ist, und wann zuletzt gesendet wurde. Die Suche ist enger getaktet, damit
alle Wege in gut zwei Minuten durch sind.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 12:38:31 +02:00
BiasFandClaude Opus 5 b0e7f057b6 BMS: alle Schreib-/Empfangs-Kombinationen durchprobieren
Die WattCycle-Batterie meldete sich am FFF0-Dienst, nahm aber keine
Kommandos an. Grund: dort ist FFF1 die erste beschreibbare
Charakteristik, sie sieht schreibbar aus und bleibt trotzdem stumm –
Kommandos gehören auf FFF2.

Statt die richtige Charakteristik zu raten, stellt BMSSession jetzt alle
Paare aus schreibbarer und benachrichtigender Charakteristik zusammen,
jeweils mit und ohne Schreibbestätigung, und arbeitet sie ab, bis eines
antwortet. Bekannte Paare (FFF2/FFF1, FF02/FF01, Nordic UART) kommen
zuerst dran; ein Kandidat, der sich nicht abonnieren lässt, wird sofort
übersprungen. Auf jedem Weg werden weiterhin Daly klassisch, Daly Modbus
und JBD angefragt.

Die Diagnose zeigt dazu den vollständigen GATT-Baum des Geräts, den
gerade versuchten Weg samt Position in der Kandidatenliste sowie Zähler
für gesendete Anfragen und empfangene Bytes. Damit lässt sich
unterscheiden, ob das BMS die Kommandos gar nicht annimmt oder ein
unbekanntes Protokoll spricht.

Nebenbei: "caravan" existiert nicht als SF-Symbol und ließ SwiftUI
stillschweigend auf Text zurückfallen – in den Demodaten ersetzt.
README auf Profile und WattCycle/JBD nachgezogen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 11:31:16 +02:00
BiasF fdcc644828 init 2026-08-30 10:36:52 +02:00