@@ -281,6 +281,7 @@ class Measurements : ObservableObject {
|
||
| 281 | 281 |
private var powerSum: Double = 0 |
| 282 | 282 |
private var voltageSum: Double = 0 |
| 283 | 283 |
private var currentSum: Double = 0 |
| 284 |
+ private var temperatureItemsInSum: Double = 0 |
|
| 284 | 285 |
private var temperatureSum: Double = 0 |
| 285 | 286 |
private var rssiSum: Double = 0 |
| 286 | 287 |
|
@@ -291,6 +292,7 @@ class Measurements : ObservableObject {
|
||
| 291 | 292 |
powerSum = 0 |
| 292 | 293 |
voltageSum = 0 |
| 293 | 294 |
currentSum = 0 |
| 295 |
+ temperatureItemsInSum = 0 |
|
| 294 | 296 |
temperatureSum = 0 |
| 295 | 297 |
rssiSum = 0 |
| 296 | 298 |
} |
@@ -300,7 +302,9 @@ class Measurements : ObservableObject {
|
||
| 300 | 302 |
self.power.addPoint(timestamp: pendingBucketTimestamp, value: powerSum / itemsInSum) |
| 301 | 303 |
self.voltage.addPoint(timestamp: pendingBucketTimestamp, value: voltageSum / itemsInSum) |
| 302 | 304 |
self.current.addPoint(timestamp: pendingBucketTimestamp, value: currentSum / itemsInSum) |
| 303 |
- self.temperature.addPoint(timestamp: pendingBucketTimestamp, value: temperatureSum / itemsInSum) |
|
| 305 |
+ if temperatureItemsInSum > 0 {
|
|
| 306 |
+ self.temperature.addPoint(timestamp: pendingBucketTimestamp, value: temperatureSum / temperatureItemsInSum) |
|
| 307 |
+ } |
|
| 304 | 308 |
self.rssi.addPoint(timestamp: pendingBucketTimestamp, value: rssiSum / itemsInSum) |
| 305 | 309 |
resetPendingAggregation() |
| 306 | 310 |
self.objectWillChange.send() |
@@ -389,24 +393,20 @@ class Measurements : ObservableObject {
|
||
| 389 | 393 |
existing: energy.points, |
| 390 | 394 |
persistedRangeUpperBound: persistedRangeUpperBound |
| 391 | 395 |
) |
| 392 |
- let preservedTemperatureTail = preservedTailPoints( |
|
| 393 |
- from: temperature.points, |
|
| 394 |
- after: persistedRangeUpperBound |
|
| 395 |
- ) |
|
| 396 | 396 |
let preservedRssiTail = preservedTailPoints( |
| 397 | 397 |
from: rssi.points, |
| 398 | 398 |
after: persistedRangeUpperBound |
| 399 | 399 |
) |
| 400 | 400 |
|
| 401 | 401 |
restoreTrace( |
| 402 |
- "measurements-restore-merge session=\(session.id.uuidString) restored=p:\(restoredPowerPoints.count),v:\(restoredVoltagePoints.count),c:\(restoredCurrentPoints.count),e:\(restoredEnergyPoints.count) discontinuities=p:\(restoredPowerPoints.filter(\.isDiscontinuity).count),v:\(restoredVoltagePoints.filter(\.isDiscontinuity).count),c:\(restoredCurrentPoints.filter(\.isDiscontinuity).count),e:\(restoredEnergyPoints.filter(\.isDiscontinuity).count) merged=p:\(mergedPowerPoints.count),v:\(mergedVoltagePoints.count),c:\(mergedCurrentPoints.count),e:\(mergedEnergyPoints.count) tails=t:\(preservedTemperatureTail.count),r:\(preservedRssiTail.count) upperBound=\(persistedRangeUpperBound?.description ?? "nil")" |
|
| 402 |
+ "measurements-restore-merge session=\(session.id.uuidString) restored=p:\(restoredPowerPoints.count),v:\(restoredVoltagePoints.count),c:\(restoredCurrentPoints.count),e:\(restoredEnergyPoints.count) discontinuities=p:\(restoredPowerPoints.filter(\.isDiscontinuity).count),v:\(restoredVoltagePoints.filter(\.isDiscontinuity).count),c:\(restoredCurrentPoints.filter(\.isDiscontinuity).count),e:\(restoredEnergyPoints.filter(\.isDiscontinuity).count) merged=p:\(mergedPowerPoints.count),v:\(mergedVoltagePoints.count),c:\(mergedCurrentPoints.count),e:\(mergedEnergyPoints.count) tails=r:\(preservedRssiTail.count) upperBound=\(persistedRangeUpperBound?.description ?? "nil")" |
|
| 403 | 403 |
) |
| 404 | 404 |
|
| 405 | 405 |
power.replacePoints(mergedPowerPoints) |
| 406 | 406 |
current.replacePoints(mergedCurrentPoints) |
| 407 | 407 |
voltage.replacePoints(mergedVoltagePoints) |
| 408 | 408 |
energy.replacePoints(mergedEnergyPoints) |
| 409 |
- temperature.replacePoints(preservedTemperatureTail) |
|
| 409 |
+ temperature.resetSeries() |
|
| 410 | 410 |
rssi.replacePoints(preservedRssiTail) |
| 411 | 411 |
|
| 412 | 412 |
lastEnergyCounterValue = hasExistingBuffer ? preservedEnergyCounterValue : nil |
@@ -577,7 +577,7 @@ class Measurements : ObservableObject {
|
||
| 577 | 577 |
self.objectWillChange.send() |
| 578 | 578 |
} |
| 579 | 579 |
|
| 580 |
- func addValues(timestamp: Date, power: Double, voltage: Double, current: Double, temperature: Double, rssi: Double) {
|
|
| 580 |
+ func addValues(timestamp: Date, power: Double, voltage: Double, current: Double, temperature: Double?, rssi: Double) {
|
|
| 581 | 581 |
let valuesTimestamp = timestamp.timeIntervalSinceReferenceDate.intValue |
| 582 | 582 |
|
| 583 | 583 |
if pendingBucketSecond == valuesTimestamp {
|
@@ -586,7 +586,10 @@ class Measurements : ObservableObject {
|
||
| 586 | 586 |
powerSum += power |
| 587 | 587 |
voltageSum += voltage |
| 588 | 588 |
currentSum += current |
| 589 |
- temperatureSum += temperature |
|
| 589 |
+ if let temperature {
|
|
| 590 |
+ temperatureItemsInSum += 1 |
|
| 591 |
+ temperatureSum += temperature |
|
| 592 |
+ } |
|
| 590 | 593 |
rssiSum += rssi |
| 591 | 594 |
return |
| 592 | 595 |
} |
@@ -599,7 +602,13 @@ class Measurements : ObservableObject {
|
||
| 599 | 602 |
powerSum = power |
| 600 | 603 |
voltageSum = voltage |
| 601 | 604 |
currentSum = current |
| 602 |
- temperatureSum = temperature |
|
| 605 |
+ if let temperature {
|
|
| 606 |
+ temperatureItemsInSum = 1 |
|
| 607 |
+ temperatureSum = temperature |
|
| 608 |
+ } else {
|
|
| 609 |
+ temperatureItemsInSum = 0 |
|
| 610 |
+ temperatureSum = 0 |
|
| 611 |
+ } |
|
| 603 | 612 |
rssiSum = rssi |
| 604 | 613 |
} |
| 605 | 614 |
|
@@ -818,7 +818,11 @@ class Meter : NSObject, ObservableObject, Identifiable {
|
||
| 818 | 818 |
updateChargeRecord(at: dataDumpRequestTimestamp) |
| 819 | 819 |
captureLiveMeasurements(at: dataDumpRequestTimestamp, in: measurements) |
| 820 | 820 |
if chargeRecordState != .waitingForStart {
|
| 821 |
- captureLiveMeasurements(at: dataDumpRequestTimestamp, in: chargeRecordMeasurements) |
|
| 821 |
+ captureLiveMeasurements( |
|
| 822 |
+ at: dataDumpRequestTimestamp, |
|
| 823 |
+ in: chargeRecordMeasurements, |
|
| 824 |
+ includesTemperature: false |
|
| 825 |
+ ) |
|
| 822 | 826 |
} |
| 823 | 827 |
appData.observeChargeSnapshot(from: self, observedAt: dataDumpRequestTimestamp) |
| 824 | 828 |
// DispatchQueue.global(qos: .userInitiated).asyncAfter( deadline: .now() + 0.33 ) {
|
@@ -1064,7 +1068,11 @@ class Meter : NSObject, ObservableObject, Identifiable {
|
||
| 1064 | 1068 |
} |
| 1065 | 1069 |
} |
| 1066 | 1070 |
|
| 1067 |
- private func captureLiveMeasurements(at timestamp: Date, in destination: Measurements) {
|
|
| 1071 |
+ private func captureLiveMeasurements( |
|
| 1072 |
+ at timestamp: Date, |
|
| 1073 |
+ in destination: Measurements, |
|
| 1074 |
+ includesTemperature: Bool = true |
|
| 1075 |
+ ) {
|
|
| 1068 | 1076 |
if supportsRecordingView {
|
| 1069 | 1077 |
destination.captureEnergyValue( |
| 1070 | 1078 |
timestamp: timestamp, |
@@ -1084,7 +1092,7 @@ class Meter : NSObject, ObservableObject, Identifiable {
|
||
| 1084 | 1092 |
power: power, |
| 1085 | 1093 |
voltage: voltage, |
| 1086 | 1094 |
current: current, |
| 1087 |
- temperature: displayedTemperatureValue, |
|
| 1095 |
+ temperature: includesTemperature ? displayedTemperatureValue : nil, |
|
| 1088 | 1096 |
rssi: Double(btSerial.averageRSSI) |
| 1089 | 1097 |
) |
| 1090 | 1098 |
} |
@@ -166,6 +166,7 @@ struct MeasurementChartView: View {
|
||
| 166 | 166 |
let showsRangeSelector: Bool |
| 167 | 167 |
let rebasesEnergyToVisibleRangeStart: Bool |
| 168 | 168 |
let extendsTimelineToPresent: Bool |
| 169 |
+ let showsTemperatureSeries: Bool |
|
| 169 | 170 |
let rangeSelectorConfiguration: MeasurementChartRangeSelectorConfiguration? |
| 170 | 171 |
|
| 171 | 172 |
@EnvironmentObject private var measurements: Measurements |
@@ -223,6 +224,7 @@ struct MeasurementChartView: View {
|
||
| 223 | 224 |
showsRangeSelector: Bool = true, |
| 224 | 225 |
rebasesEnergyToVisibleRangeStart: Bool = false, |
| 225 | 226 |
extendsTimelineToPresent: Bool = true, |
| 227 |
+ showsTemperatureSeries: Bool = true, |
|
| 226 | 228 |
rangeSelectorConfiguration: MeasurementChartRangeSelectorConfiguration? = nil |
| 227 | 229 |
) {
|
| 228 | 230 |
self.sizing = sizing |
@@ -232,6 +234,7 @@ struct MeasurementChartView: View {
|
||
| 232 | 234 |
self.showsRangeSelector = showsRangeSelector |
| 233 | 235 |
self.rebasesEnergyToVisibleRangeStart = rebasesEnergyToVisibleRangeStart |
| 234 | 236 |
self.extendsTimelineToPresent = extendsTimelineToPresent |
| 237 |
+ self.showsTemperatureSeries = showsTemperatureSeries |
|
| 235 | 238 |
self.rangeSelectorConfiguration = rangeSelectorConfiguration |
| 236 | 239 |
} |
| 237 | 240 |
|
@@ -351,24 +354,35 @@ struct MeasurementChartView: View {
|
||
| 351 | 354 |
} |
| 352 | 355 |
|
| 353 | 356 |
var body: some View {
|
| 354 |
- switch sizing {
|
|
| 355 |
- case .provided: |
|
| 356 |
- chartBody |
|
| 357 |
- case .embedded: |
|
| 358 |
- let chartWidth = max(embeddedWidth, 1) |
|
| 359 |
- chartBody |
|
| 360 |
- .frame(maxWidth: .infinity, alignment: .topLeading) |
|
| 361 |
- .frame(height: Self.embeddedContentHeight(width: chartWidth, showsRangeSelector: showsRangeSelector)) |
|
| 362 |
- .background( |
|
| 363 |
- GeometryReader { geometry in
|
|
| 364 |
- Color.clear.preference(key: EmbeddedWidthKey.self, value: geometry.size.width) |
|
| 357 |
+ Group {
|
|
| 358 |
+ switch sizing {
|
|
| 359 |
+ case .provided: |
|
| 360 |
+ chartBody |
|
| 361 |
+ case .embedded: |
|
| 362 |
+ let chartWidth = max(embeddedWidth, 1) |
|
| 363 |
+ chartBody |
|
| 364 |
+ .frame(maxWidth: .infinity, alignment: .topLeading) |
|
| 365 |
+ .frame(height: Self.embeddedContentHeight(width: chartWidth, showsRangeSelector: showsRangeSelector)) |
|
| 366 |
+ .background( |
|
| 367 |
+ GeometryReader { geometry in
|
|
| 368 |
+ Color.clear.preference(key: EmbeddedWidthKey.self, value: geometry.size.width) |
|
| 369 |
+ } |
|
| 370 |
+ ) |
|
| 371 |
+ .onPreferenceChange(EmbeddedWidthKey.self) { width in
|
|
| 372 |
+ guard width > 0, abs(width - embeddedWidth) > 0.5 else { return }
|
|
| 373 |
+ embeddedWidth = width |
|
| 365 | 374 |
} |
| 366 |
- ) |
|
| 367 |
- .onPreferenceChange(EmbeddedWidthKey.self) { width in
|
|
| 368 |
- guard width > 0, abs(width - embeddedWidth) > 0.5 else { return }
|
|
| 369 |
- embeddedWidth = width |
|
| 370 |
- } |
|
| 375 |
+ } |
|
| 371 | 376 |
} |
| 377 |
+ .onAppear(perform: resetHiddenTemperatureDisplay) |
|
| 378 |
+ .onChange(of: showsTemperatureSeries) { _ in
|
|
| 379 |
+ resetHiddenTemperatureDisplay() |
|
| 380 |
+ } |
|
| 381 |
+ } |
|
| 382 |
+ |
|
| 383 |
+ private func resetHiddenTemperatureDisplay() {
|
|
| 384 |
+ guard !showsTemperatureSeries, displayTemperature else { return }
|
|
| 385 |
+ displayTemperature = false |
|
| 372 | 386 |
} |
| 373 | 387 |
|
| 374 | 388 |
@ViewBuilder |
@@ -665,10 +679,12 @@ struct MeasurementChartView: View {
|
||
| 665 | 679 |
} |
| 666 | 680 |
} |
| 667 | 681 |
|
| 668 |
- seriesToggleButton(title: "Temp", isOn: displayTemperature, condensedLayout: condensedLayout) {
|
|
| 669 |
- displayTemperature.toggle() |
|
| 670 |
- if displayTemperature && displayVoltage && displayCurrent {
|
|
| 671 |
- displayCurrent = false |
|
| 682 |
+ if showsTemperatureSeries {
|
|
| 683 |
+ seriesToggleButton(title: "Temp", isOn: displayTemperature, condensedLayout: condensedLayout) {
|
|
| 684 |
+ displayTemperature.toggle() |
|
| 685 |
+ if displayTemperature && displayVoltage && displayCurrent {
|
|
| 686 |
+ displayCurrent = false |
|
| 687 |
+ } |
|
| 672 | 688 |
} |
| 673 | 689 |
} |
| 674 | 690 |
} |
@@ -1404,6 +1404,7 @@ struct MeterChargeRecordContentView: View {
|
||
| 1404 | 1404 |
showsRangeSelector: hasRangeSelector, |
| 1405 | 1405 |
rebasesEnergyToVisibleRangeStart: true, |
| 1406 | 1406 |
extendsTimelineToPresent: false, |
| 1407 |
+ showsTemperatureSeries: false, |
|
| 1407 | 1408 |
rangeSelectorConfiguration: hasRangeSelector |
| 1408 | 1409 |
? MeasurementChartRangeSelectorConfiguration( |
| 1409 | 1410 |
keepAction: MeasurementChartSelectionAction( |
@@ -134,7 +134,8 @@ struct SessionTrimEditorView: View {
|
||
| 134 | 134 |
sizing: .provided(size: geo.size, compact: true), |
| 135 | 135 |
timeRange: fullStart...fullEnd, |
| 136 | 136 |
showsRangeSelector: false, |
| 137 |
- rebasesEnergyToVisibleRangeStart: false |
|
| 137 |
+ rebasesEnergyToVisibleRangeStart: false, |
|
| 138 |
+ showsTemperatureSeries: false |
|
| 138 | 139 |
) |
| 139 | 140 |
|
| 140 | 141 |
// Dimmed region before trimStart |