Renames every type and identifier we built for the solar charge controller bridge from generic "Solar" naming to the product name VotronicSolarESP: VanAlignSolarProtocol -> VotronicSolarESPProtocol, SolarSession -> VotronicSolarESPSession, SolarState -> VotronicSolarESPState, plus the dependent properties, parameters, and user-facing discovery/empty-state strings. Purely a Swift-side rename - the underlying BLE service/characteristic UUIDs are untouched, so it has no effect on communicating with the actual firmware. DeviceRole.solar's case name, and DemoData's device instance variables, are left as-is since they describe the role/demo device rather than this specific integration code. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
56 lines
2.3 KiB
Swift
56 lines
2.3 KiB
Swift
import Foundation
|
||
|
||
/// VotronicSolarESP – zweiter ESP32 im Fahrzeug, liest einen
|
||
/// Votronic-Solarladeregler aus und stellt die Werte über einen eigenen
|
||
/// BLE-Dienst bereit. Siehe `firmware/vanalign/esp32_ble_solar.yaml`.
|
||
///
|
||
/// Wie beim Neigungsmesser: kein Rahmenprotokoll, jede Messgrösse liegt in
|
||
/// einer eigenen Charakteristik, alle sind reine Lesewerte, der Client fragt
|
||
/// sie im Takt ab.
|
||
enum VotronicSolarESPProtocol {
|
||
|
||
/// Wird vom Gerät beworben, das Gerät ist darüber auffindbar.
|
||
static let serviceUUID = "05C9A349-2B8E-4B1D-9C9D-C247E9A6A001"
|
||
|
||
static let batteryVoltageUUID = "05C9A349-2B8E-4B1D-9C9D-C247E9A6A101"
|
||
static let pvVoltageUUID = "05C9A349-2B8E-4B1D-9C9D-C247E9A6A102"
|
||
static let pvCurrentUUID = "05C9A349-2B8E-4B1D-9C9D-C247E9A6A103"
|
||
static let pvPowerUUID = "05C9A349-2B8E-4B1D-9C9D-C247E9A6A104"
|
||
static let controllerTempUUID = "05C9A349-2B8E-4B1D-9C9D-C247E9A6A105"
|
||
/// Bit0 Batterie lädt, Bit1 Batterie entlädt, Bit2 PV-Regler aktiv,
|
||
/// Bit3 PV-Strombegrenzung, Bit4 AES aktiv.
|
||
static let statusFlagsUUID = "05C9A349-2B8E-4B1D-9C9D-C247E9A6A106"
|
||
|
||
/// Liest einen Messwert aus vier Bytes, little-endian – wie beim
|
||
/// Neigungsmesser legt die Firmware den Float per `memcpy` ab.
|
||
static func float(from data: Data) -> Double? {
|
||
guard data.count >= 4 else { return nil }
|
||
var raw: UInt32 = 0
|
||
for (index, byte) in data.prefix(4).enumerated() {
|
||
raw |= UInt32(byte) << UInt32(8 * index)
|
||
}
|
||
let value = Float(bitPattern: raw)
|
||
guard value.isFinite else { return nil }
|
||
return Double(value)
|
||
}
|
||
|
||
struct StatusFlags {
|
||
var isBatteryCharging = false
|
||
var isBatteryDischarging = false
|
||
var isControllerActive = false
|
||
var isCurrentLimited = false
|
||
var isAESActive = false
|
||
}
|
||
|
||
static func statusFlags(from data: Data) -> StatusFlags? {
|
||
guard let byte = data.first else { return nil }
|
||
var flags = StatusFlags()
|
||
flags.isBatteryCharging = byte & (1 << 0) != 0
|
||
flags.isBatteryDischarging = byte & (1 << 1) != 0
|
||
flags.isControllerActive = byte & (1 << 2) != 0
|
||
flags.isCurrentLimited = byte & (1 << 3) != 0
|
||
flags.isAESActive = byte & (1 << 4) != 0
|
||
return flags
|
||
}
|
||
}
|