App-Namen im iOS-Projekt auf VanControl vereinheitlichen

CamperMonitor (Haupt-Repo) und VanAligneiOS (aus dem gemergten
solar-integration-Branch) liefen unter zwei verschiedenen internen
Namen, obwohl die App nach aussen längst einheitlich "VanControl Pro"
heisst. Jetzt durchgängig VanControl:

- Ordner: CamperMonitor/, CamperMonitorWatch/, CamperMonitorComplication/,
  VanAligneiOSWidget/ → VanControl/, VanControlWatch/,
  VanControlComplication/, VanControlWidget/
- Xcode-Projekt: CamperMonitor.xcodeproj → VanControl.xcodeproj, alle
  Targets/Schemes/Produktnamen entsprechend umbenannt
- Bundle-Identifier auf Wunsch mitgeändert: de.s0.fototeddy.VanControl*
  (App noch nicht veröffentlicht); dabei auch die
  WKCompanionAppBundleIdentifier-Werte korrigiert, die noch das alte
  de.fritob-Präfix statt des tatsächlichen de.s0.fototeddy-Präfixes
  trugen
- Swift-Dateien/Typen: CamperMonitorApp → VanControlApp,
  VanAligneiOSWidget* → VanControlWidget*
- Config/*-Info.plist umbenannt, README.md/Tools/README.md/run-tests.sh
  auf die neuen Pfade angepasst

Bewusst unverändert: firmware/vanalign und alle Bezüge auf "VanAlign"
als Namen der Neigungsmesser-Hardware (eigenständiges Produkt, kein
App-Name) sowie der komplette Android/-Ordner.

Build (App, Watch, Debug) und Protokoll-Testlauf grün.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
fototeddy
2026-09-06 21:25:28 +02:00
co-authored by Claude Sonnet 5
parent 83ea85f3b8
commit 303a9735d0
79 changed files with 190 additions and 190 deletions
+83
View File
@@ -0,0 +1,83 @@
import SwiftUI
/// Eingabe des Victron-Verschlüsselungsschlüssels.
///
/// Der Schlüssel wird einmal eingetragen und danach nie wieder angefasst
/// deshalb steht er hier und nicht in der Geräteübersicht. Nur solange er
/// fehlt oder nicht passt, weist die Übersicht darauf hin.
struct VictronKeyView: View {
let device: ConfiguredDevice
@Environment(DeviceStore.self) private var store
@Environment(BluetoothManager.self) private var bluetooth
@State private var keyInput = ""
var body: some View {
List {
Section {
TextField("32 Hex-Zeichen", text: $keyInput)
.font(.system(.body, design: .monospaced))
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
.onSubmit(save)
Button("Schlüssel speichern", action: save)
.disabled(keyInput.hexBytes?.count != 16)
} footer: {
Text("In VictronConnect: Gerät öffnen → Zahnrad → ⋮ → Produkt-Info → "
+ "„Instant Readout“ einschalten → Verschlüsselungsdaten anzeigen. "
+ "Der Schlüssel ist 16 Byte lang (32 Hex-Zeichen).")
}
// Das erste Byte sendet das Gerät unverschlüsselt mit. Stimmt es
// nicht mit dem eingetragenen überein, gehört der Schlüssel zu
// einem anderen Victron-Gerät der häufigste Fehler überhaupt.
if let expected = bluetooth.diagnostics[device.id]?.expectedKeyText {
Section {
LabeledContent("Gerät sendet") {
Text(expected)
.font(.body.monospaced())
.foregroundStyle(bytesAgree == false ? .red : .primary)
}
LabeledContent("Eingetragen") {
Text(enteredKeyText)
.font(.body.monospaced())
.foregroundStyle(bytesAgree == false ? .red : .secondary)
}
} header: {
Text("Erstes Schlüsselbyte")
} footer: {
if bytesAgree == false {
Text("Die beiden Bytes müssen übereinstimmen. Tun sie das "
+ "nicht, stammt der Schlüssel von einem anderen "
+ "Victron-Gerät in VictronConnect prüfen, ob wirklich "
+ "dieses Gerät geöffnet war.")
} else {
Text("Zum Vergleichen: dieses Byte sendet das Gerät "
+ "unverschlüsselt mit.")
}
}
}
}
.navigationTitle("Verschlüsselung")
.navigationBarTitleDisplayMode(.inline)
.onAppear { keyInput = store.victronKeyText(for: device.id) ?? "" }
}
/// nil, solange kein vollständiger Schlüssel eingetragen ist.
private var bytesAgree: Bool? {
guard let expected = bluetooth.diagnostics[device.id]?.expectedKeyFirstByte,
let entered = keyInput.hexBytes?.first else { return nil }
return expected == entered
}
private var enteredKeyText: String {
guard let byte = keyInput.hexBytes?.first else { return "" }
return String(format: "0x%02X", byte)
}
private func save() {
store.setVictronKey(keyInput, for: device.id)
bluetooth.refreshConfiguration()
}
}