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>
This commit is contained in:
BiasF
2026-08-30 11:31:16 +02:00
co-authored by Claude Opus 5
parent fdcc644828
commit b0e7f057b6
5 changed files with 300 additions and 124 deletions
+15 -2
View File
@@ -68,13 +68,26 @@ struct VictronDiagnostics: Hashable {
/// greift, und gibt die letzte Rohantwort zum Nachsehen aus.
struct BMSDiagnostics: Hashable {
var dialect: String
/// Welche Schreib-/Notify-Kombination gerade versucht wird.
var endpointLabel: String?
/// Der wievielte von wie vielen Kandidaten das ist.
var endpointPosition: Pair?
var serviceUUID: String?
var writeUUID: String?
var notifyUUID: String?
/// Vollständiger Dienst-/Merkmalsbaum des Geräts.
var gattSummary: [String]
var sentFrames: Int
var receivedBytes: Int
var lastResponseHex: String?
var updated: Date
struct Pair: Hashable {
var index: Int
var total: Int
init(_ index: Int, _ total: Int) { self.index = index; self.total = total }
}
}
/// Ein Messpunkt für die Verlaufsgrafik.
struct HistorySample: Identifiable, Hashable {
let id = UUID()