86 lines
3.1 KiB
Swift
86 lines
3.1 KiB
Swift
import Foundation
|
||
|
||
/// Welche Rolle ein Gerät im Camper spielt. Bestimmt Icon, Sortierung und
|
||
/// welche Kennzahl als "Hauptwert" auf der Kachel gross dargestellt wird.
|
||
enum DeviceRole: String, Codable, CaseIterable, Identifiable, Sendable {
|
||
case chargeBooster
|
||
case solarCharger
|
||
case batteryMonitor
|
||
case bms
|
||
|
||
var id: String { rawValue }
|
||
|
||
var title: String {
|
||
switch self {
|
||
case .chargeBooster: return "Ladebooster"
|
||
case .solarCharger: return "Solarladeregler"
|
||
case .batteryMonitor: return "Batteriemonitor"
|
||
case .bms: return "Batterie / BMS"
|
||
}
|
||
}
|
||
|
||
var symbol: String {
|
||
switch self {
|
||
case .chargeBooster: return "bolt.car"
|
||
case .solarCharger: return "sun.max"
|
||
case .batteryMonitor: return "gauge.with.dots.needle.bottom.50percent"
|
||
case .bms: return "battery.100percent.bolt"
|
||
}
|
||
}
|
||
|
||
/// Victron-Geräte werden passiv über das Advertisement gelesen, das Daly BMS
|
||
/// braucht eine echte GATT-Verbindung.
|
||
var transport: DeviceTransport {
|
||
self == .bms ? .connect : .advertisement
|
||
}
|
||
}
|
||
|
||
enum DeviceTransport: Sendable {
|
||
/// Passives Mitlesen der BLE-Werbedaten (Victron Instant Readout).
|
||
case advertisement
|
||
/// Verbindungsaufbau, Kommando schreiben, Antwort per Notify lesen (Daly).
|
||
case connect
|
||
}
|
||
|
||
/// Ein vom Nutzer eingerichtetes Gerät. Der Victron-Schlüssel liegt nicht hier,
|
||
/// sondern in der Keychain (siehe `KeychainStore`).
|
||
struct ConfiguredDevice: Identifiable, Codable, Hashable, Sendable {
|
||
var id: UUID
|
||
var name: String
|
||
var role: DeviceRole
|
||
/// Zu welchem Fahrzeug das Gerät gehört.
|
||
var profileID: UUID
|
||
/// CoreBluetooth-Identifier des Peripherals. Pro iPhone stabil, aber nicht
|
||
/// geräteübergreifend – deshalb wird beim Einrichten neu gescannt.
|
||
var peripheralID: UUID
|
||
/// Zuletzt gesehener Advertised Name, nur zur Wiedererkennung in der UI.
|
||
var advertisedName: String?
|
||
|
||
init(id: UUID = UUID(),
|
||
name: String,
|
||
role: DeviceRole,
|
||
profileID: UUID,
|
||
peripheralID: UUID,
|
||
advertisedName: String? = nil) {
|
||
self.id = id
|
||
self.name = name
|
||
self.role = role
|
||
self.profileID = profileID
|
||
self.peripheralID = peripheralID
|
||
self.advertisedName = advertisedName
|
||
}
|
||
|
||
/// Geräte, die vor der Profilverwaltung angelegt wurden, haben noch keine
|
||
/// Zuordnung – die landen im Standardprofil.
|
||
init(from decoder: Decoder) throws {
|
||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||
id = try container.decode(UUID.self, forKey: .id)
|
||
name = try container.decode(String.self, forKey: .name)
|
||
role = try container.decode(DeviceRole.self, forKey: .role)
|
||
profileID = try container.decodeIfPresent(UUID.self, forKey: .profileID)
|
||
?? Profile.defaultID
|
||
peripheralID = try container.decode(UUID.self, forKey: .peripheralID)
|
||
advertisedName = try container.decodeIfPresent(String.self, forKey: .advertisedName)
|
||
}
|
||
}
|