USB-Meter / USB Meter / Model / MeterCapabilities.swift
1 contributor
146 lines | 4.342kb
//
//  MeterCapabilities.swift
//  USB Meter
//
//  Created by Codex on 23/03/2026.
//

import SwiftUI

struct MeterCapabilities {
    let availableDataGroupIDs: [UInt8]
    let supportsDataGroupCommands: Bool
    let supportsRecordingView: Bool
    let supportsScreenSettings: Bool
    let supportsRecordingThreshold: Bool
    let reportsCurrentScreenIndex: Bool
    let showsDataGroupEnergy: Bool
    let highlightsActiveDataGroup: Bool
    let supportsFahrenheit: Bool
    let supportsChargerDetection: Bool
    let primaryTemperatureUnitSymbol: String?
    let dataGroupsTitle: String
    let documentedWorkingVoltage: String
    let chargerTypeDescriptions: [UInt16: String]
    let screenDescriptions: [UInt16: String]
    let dataGroupsHint: String?
    let recordingThresholdHint: String?

    func chargerTypeDescription(for index: UInt16) -> String {
        guard supportsChargerDetection else { return "-" }
        if let label = chargerTypeDescriptions[index] {
            return label
        }
        return index == 0 ? "Unknown" : "Unknown (\(index))"
    }

    func screenDescription(for index: UInt16) -> String? {
        screenDescriptions[index]
    }
}

extension MeterCapabilities {
    static let umFamily = MeterCapabilities(
        availableDataGroupIDs: Array(0...9),
        supportsDataGroupCommands: true,
        supportsRecordingView: true,
        supportsScreenSettings: true,
        supportsRecordingThreshold: true,
        reportsCurrentScreenIndex: true,
        showsDataGroupEnergy: true,
        highlightsActiveDataGroup: true,
        supportsFahrenheit: true,
        supportsChargerDetection: true,
        primaryTemperatureUnitSymbol: "℃",
        dataGroupsTitle: "Data Groups",
        documentedWorkingVoltage: "4-24 V",
        chargerTypeDescriptions: [
            1: "QC2",
            2: "QC3",
            3: "Apple 2.4A",
            4: "Apple 2.1A",
            5: "Apple 1.0A",
            6: "Apple 0.5A",
            7: "DCP 1.5A",
            8: "Samsung"
        ],
        screenDescriptions: [
            0: "Main Measurement",
            1: "Quick Charge",
            2: "Charging Record",
            3: "Cable Impedance",
            4: "Graphing",
            5: "System Settings"
        ],
        dataGroupsHint: "The active group is reported by the meter. Group 0 is temporary. Groups 1-9 persist across power cycles.",
        recordingThresholdHint: "The meter starts its built-in charge record when current rises above this threshold."
    )

    static let tc66c = MeterCapabilities(
        availableDataGroupIDs: [0, 1],
        supportsDataGroupCommands: false,
        supportsRecordingView: true,
        supportsScreenSettings: false,
        supportsRecordingThreshold: false,
        reportsCurrentScreenIndex: false,
        showsDataGroupEnergy: true,
        highlightsActiveDataGroup: false,
        supportsFahrenheit: false,
        supportsChargerDetection: false,
        primaryTemperatureUnitSymbol: nil,
        dataGroupsTitle: "Memory Totals",
        documentedWorkingVoltage: "3.5-24 V",
        chargerTypeDescriptions: [:],
        screenDescriptions: [:],
        dataGroupsHint: "The device exposes two read-only memories with charge and energy totals. The active memory is not reported.",
        recordingThresholdHint: nil
    )
}

extension Model {
    static let byPeripheralName = Dictionary(
        uniqueKeysWithValues: allCases.flatMap { model in
            model.peripheralNames.map { ($0, model) }
        }
    )

    var radio: BluetoothRadio {
        switch self {
        case .UM25C, .UM34C:
            return .BT18
        case .TC66C:
            return .PW0316
        }
    }

    var peripheralNames: [String] {
        switch self {
        case .UM25C:
            return ["UM25C"]
        case .UM34C:
            return ["UM34C"]
        case .TC66C:
            return ["TC66C", "PW0316"]
        }
    }

    var color: Color {
        switch self {
        case .UM25C:
            return .blue
        case .UM34C:
            return .yellow
        case .TC66C:
            return .black
        }
    }

    var capabilities: MeterCapabilities {
        switch self {
        case .UM25C, .UM34C:
            return .umFamily
        case .TC66C:
            return .tc66c
        }
    }
}