USB-Meter / USB Meter / Model / MeterCapabilities.swift
Newer Older
146 lines | 4.342kb
Bogdan Timofte authored 2 weeks ago
1
//
2
//  MeterCapabilities.swift
3
//  USB Meter
4
//
5
//  Created by Codex on 23/03/2026.
6
//
7

            
8
import SwiftUI
9

            
10
struct MeterCapabilities {
11
    let availableDataGroupIDs: [UInt8]
12
    let supportsDataGroupCommands: Bool
Bogdan Timofte authored 2 weeks ago
13
    let supportsRecordingView: Bool
Bogdan Timofte authored 2 weeks ago
14
    let supportsScreenSettings: Bool
15
    let supportsRecordingThreshold: Bool
Bogdan Timofte authored 2 weeks ago
16
    let reportsCurrentScreenIndex: Bool
17
    let showsDataGroupEnergy: Bool
18
    let highlightsActiveDataGroup: Bool
Bogdan Timofte authored 2 weeks ago
19
    let supportsFahrenheit: Bool
20
    let supportsChargerDetection: Bool
Bogdan Timofte authored 2 weeks ago
21
    let primaryTemperatureUnitSymbol: String?
22
    let dataGroupsTitle: String
Bogdan Timofte authored 2 weeks ago
23
    let documentedWorkingVoltage: String
Bogdan Timofte authored 2 weeks ago
24
    let chargerTypeDescriptions: [UInt16: String]
Bogdan Timofte authored 2 weeks ago
25
    let screenDescriptions: [UInt16: String]
Bogdan Timofte authored 2 weeks ago
26
    let dataGroupsHint: String?
27
    let recordingThresholdHint: String?
Bogdan Timofte authored 2 weeks ago
28

            
29
    func chargerTypeDescription(for index: UInt16) -> String {
30
        guard supportsChargerDetection else { return "-" }
31
        if let label = chargerTypeDescriptions[index] {
32
            return label
33
        }
34
        return index == 0 ? "Unknown" : "Unknown (\(index))"
35
    }
Bogdan Timofte authored 2 weeks ago
36

            
37
    func screenDescription(for index: UInt16) -> String? {
38
        screenDescriptions[index]
39
    }
Bogdan Timofte authored 2 weeks ago
40
}
41

            
42
extension MeterCapabilities {
43
    static let umFamily = MeterCapabilities(
44
        availableDataGroupIDs: Array(0...9),
45
        supportsDataGroupCommands: true,
Bogdan Timofte authored 2 weeks ago
46
        supportsRecordingView: true,
Bogdan Timofte authored 2 weeks ago
47
        supportsScreenSettings: true,
48
        supportsRecordingThreshold: true,
Bogdan Timofte authored 2 weeks ago
49
        reportsCurrentScreenIndex: true,
50
        showsDataGroupEnergy: true,
51
        highlightsActiveDataGroup: true,
Bogdan Timofte authored 2 weeks ago
52
        supportsFahrenheit: true,
53
        supportsChargerDetection: true,
Bogdan Timofte authored 2 weeks ago
54
        primaryTemperatureUnitSymbol: "℃",
55
        dataGroupsTitle: "Data Groups",
Bogdan Timofte authored 2 weeks ago
56
        documentedWorkingVoltage: "4-24 V",
Bogdan Timofte authored 2 weeks ago
57
        chargerTypeDescriptions: [
58
            1: "QC2",
59
            2: "QC3",
60
            3: "Apple 2.4A",
61
            4: "Apple 2.1A",
62
            5: "Apple 1.0A",
63
            6: "Apple 0.5A",
64
            7: "DCP 1.5A",
65
            8: "Samsung"
Bogdan Timofte authored 2 weeks ago
66
        ],
67
        screenDescriptions: [
68
            0: "Main Measurement",
69
            1: "Quick Charge",
70
            2: "Charging Record",
71
            3: "Cable Impedance",
72
            4: "Graphing",
73
            5: "System Settings"
Bogdan Timofte authored 2 weeks ago
74
        ],
Bogdan Timofte authored 2 weeks ago
75
        dataGroupsHint: "The active group is reported by the meter. Group 0 is temporary. Groups 1-9 persist across power cycles.",
76
        recordingThresholdHint: "The meter starts its built-in charge record when current rises above this threshold."
Bogdan Timofte authored 2 weeks ago
77
    )
78

            
79
    static let tc66c = MeterCapabilities(
80
        availableDataGroupIDs: [0, 1],
81
        supportsDataGroupCommands: false,
Bogdan Timofte authored 2 weeks ago
82
        supportsRecordingView: true,
Bogdan Timofte authored 2 weeks ago
83
        supportsScreenSettings: false,
84
        supportsRecordingThreshold: false,
Bogdan Timofte authored 2 weeks ago
85
        reportsCurrentScreenIndex: false,
86
        showsDataGroupEnergy: true,
87
        highlightsActiveDataGroup: false,
Bogdan Timofte authored 2 weeks ago
88
        supportsFahrenheit: false,
89
        supportsChargerDetection: false,
Bogdan Timofte authored 2 weeks ago
90
        primaryTemperatureUnitSymbol: nil,
91
        dataGroupsTitle: "Memory Totals",
Bogdan Timofte authored 2 weeks ago
92
        documentedWorkingVoltage: "3.5-24 V",
Bogdan Timofte authored 2 weeks ago
93
        chargerTypeDescriptions: [:],
Bogdan Timofte authored 2 weeks ago
94
        screenDescriptions: [:],
Bogdan Timofte authored 2 weeks ago
95
        dataGroupsHint: "The device exposes two read-only memories with charge and energy totals. The active memory is not reported.",
Bogdan Timofte authored 2 weeks ago
96
        recordingThresholdHint: nil
Bogdan Timofte authored 2 weeks ago
97
    )
98
}
99

            
100
extension Model {
101
    static let byPeripheralName = Dictionary(
102
        uniqueKeysWithValues: allCases.flatMap { model in
103
            model.peripheralNames.map { ($0, model) }
104
        }
105
    )
106

            
107
    var radio: BluetoothRadio {
108
        switch self {
109
        case .UM25C, .UM34C:
110
            return .BT18
111
        case .TC66C:
112
            return .PW0316
113
        }
114
    }
115

            
116
    var peripheralNames: [String] {
117
        switch self {
118
        case .UM25C:
119
            return ["UM25C"]
120
        case .UM34C:
121
            return ["UM34C"]
122
        case .TC66C:
123
            return ["TC66C", "PW0316"]
124
        }
125
    }
126

            
127
    var color: Color {
128
        switch self {
129
        case .UM25C:
130
            return .blue
131
        case .UM34C:
132
            return .yellow
133
        case .TC66C:
134
            return .black
135
        }
136
    }
137

            
138
    var capabilities: MeterCapabilities {
139
        switch self {
140
        case .UM25C, .UM34C:
141
            return .umFamily
142
        case .TC66C:
143
            return .tc66c
144
        }
145
    }
146
}