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>
This commit is contained in:
BiasF
2026-08-30 23:43:57 +02:00
co-authored by Claude Opus 5
parent 583aa75595
commit 270c701ad6
6 changed files with 202 additions and 54 deletions
+24 -8
View File
@@ -15,13 +15,14 @@ struct SensorSetupView: View {
private enum Step {
case intro
case tiltNose
case settle
case tiltSide
case done(SensorOrientation)
case failed(OrientationDetection.Failure)
}
@State private var step: Step = .intro
/// Ruhelage vor der jeweiligen Kippbewegung.
/// Ruhelage, auf die beide Kippbewegungen bezogen werden.
@State private var reference = OrientationDetection.Reading(pitch: 0, roll: 0)
@State private var noseChange: OrientationDetection.Reading?
@@ -83,15 +84,29 @@ struct SensorSetupView: View {
.buttonStyle(.borderedProminent)
.disabled(live == nil)
case .settle:
card(icon: "equal.circle",
title: "Zurück in die Ruhelage",
text: "Stelle den Sensor wieder so hin wie am Anfang und lass "
+ "ihn kurz ruhen.\n\nVon hier aus wird die zweite Bewegung "
+ "gemessen.")
liveReadout
Button("Weiter") {
reference = live ?? reference
step = .tiltSide
}
.buttonStyle(.borderedProminent)
.disabled(live == nil)
case .tiltSide:
card(icon: "arrow.down.left",
title: "Schritt 2 von 2: nach links kippen",
text: "Zurück in die Ausgangslage, dann den Sensor so kippen, als "
+ "würde das Fahrzeug **nach links** hängen die linke Seite "
+ "also nach unten.\n\nWieder deutlich kippen und halten.")
text: "Kippe den Sensor jetzt so, als würde das Fahrzeug **nach "
+ "links** hängen die linke Seite also nach unten.\n\n"
+ "Wieder deutlich kippen und in dieser Lage halten.")
liveReadout
HStack {
Button("Zurück") { step = .tiltNose }
Button("Zurück") { step = .settle }
.buttonStyle(.bordered)
Button("Fertig") { finishSideStep() }
.buttonStyle(.borderedProminent)
@@ -161,13 +176,14 @@ struct SensorSetupView: View {
private func finishNoseStep() {
guard let live else { return }
noseChange = live - reference
reference = live
step = .tiltSide
// Der Bezug bleibt die Ruhelage. Von der gekippten Lage aus zu messen
// wäre falsch: die zweite Messung enthielte dann das Zurückkippen aus
// der ersten, und beide Achsen schlügen aus.
step = .settle
}
private func finishSideStep() {
guard let live, let nose = noseChange else { return }
// Der Bezug ist die Lage aus Schritt 1, deshalb wird von dort gemessen.
let side = live - reference
switch OrientationDetection.orientation(nose: nose, side: side) {
case .success(let orientation): step = .done(orientation)