first commit
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
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
|
||||
//case fridge
|
||||
case leveling
|
||||
|
||||
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"
|
||||
//case .fridge: return "Kühlbox"
|
||||
case .leveling: return "Nivellierung"
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
//case .fridge: return "refrigerator"
|
||||
case .leveling: return "level"
|
||||
}
|
||||
}
|
||||
|
||||
/// Es gibt keine Geräte mehr, die nur auf Anforderung verbunden werden –
|
||||
/// der Neigungsmesser bleibt immer verbunden.
|
||||
var connectsOnDemand: Bool { false }
|
||||
/*/// Ob nur verbunden wird, während die Ansicht des Geräts offen ist.
|
||||
///
|
||||
/// Die Kühlbox meldet jede Verbindung an ihrem Display an und verlangt je
|
||||
/// nach Modell sogar einen Tastendruck; dauerhaft verbunden zu sein ist
|
||||
/// dort also nicht unsichtbar, sondern lästig. Ihre Werte ändern sich
|
||||
/// ausserdem langsam, und was auf der Übersicht zählt – der Sollwert –
|
||||
/// ändert sich überhaupt nur, wenn jemand ihn ändert.
|
||||
///
|
||||
/// BMS und Neigungsmesser bleiben dagegen verbunden: Sie stören nicht, und
|
||||
/// ihre Werte will man laufend sehen.
|
||||
var connectsOnDemand: Bool { self == .fridge }*/
|
||||
|
||||
/// Der Neigungsmesser braucht eine echte GATT-Verbindung, um Werte zu liefern.
|
||||
var transport: DeviceTransport {
|
||||
return .connect
|
||||
}
|
||||
/*/// Victron-Geräte werden passiv über das Advertisement gelesen, das Daly BMS
|
||||
/// braucht eine echte GATT-Verbindung.
|
||||
var transport: DeviceTransport {
|
||||
switch self {
|
||||
case .bms, .fridge, .leveling: return .connect
|
||||
default: return .advertisement
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
enum DeviceTransport: Sendable {
|
||||
/// Passives Mitlesen der BLE-Werbedaten (Victron Instant Readout).
|
||||
case advertisement
|
||||
/// Verbindungsaufbau, Kommando schreiben, Antwort per Notify lesen (Daly).
|
||||
case connect
|
||||
}
|
||||
|
||||
/*/// Wie viele Kühlzonen eine Box hat. Manche Einzonen-Boxen senden den langen
|
||||
/// Datensatz einer Doppelzonen-Box mit, weshalb die Erkennung übersteuerbar ist.
|
||||
enum FridgeZoneMode: String, Codable, CaseIterable, Identifiable, Sendable {
|
||||
case automatic
|
||||
case single
|
||||
case dual
|
||||
|
||||
var id: String { rawValue }
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .automatic: return "Automatisch"
|
||||
case .single: return "Eine Zone"
|
||||
case .dual: return "Zwei Zonen"
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/// 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?
|
||||
/// Nur für Kühlboxen.
|
||||
//var fridgeZoneMode: FridgeZoneMode = .automatic
|
||||
/// Nur für den Neigungsmesser: wie er im Fahrzeug sitzt.
|
||||
var sensorOrientation = SensorOrientation.identity
|
||||
|
||||
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)
|
||||
//fridgeZoneMode = try container.decodeIfPresent(FridgeZoneMode.self, forKey: .fridgeZoneMode)
|
||||
// ?? .automatic
|
||||
sensorOrientation = try container.decodeIfPresent(SensorOrientation.self,
|
||||
forKey: .sensorOrientation) ?? .identity
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user