HealthImport/HealthImport/Model/WorkoutEvent.swift
2024-02-01 15:50:28 +01:00

96 lines
2.6 KiB
Swift

import Foundation
import HealthKit
import SwiftProtobuf
extension HKWorkoutEvent: Identifiable {
public var id: Double {
dateInterval.start.timeIntervalSinceReferenceDate * Double(type.rawValue) * dateInterval.duration
}
}
extension HKWorkoutEventTable {
static func decode(metadata data: Data) -> [String : Any] {
let metadata: WorkoutEventMetadata
do {
metadata = try WorkoutEventMetadata(serializedData: data)
} catch {
print("Failed to decode event metadata: \(error)")
print(data.hex)
return [:]
}
return metadata.elements.reduce(into: [:]) { dict, element in
guard let value = element.value else {
print("No value for metadata element \(element)")
print(data.hex)
return
}
dict[element.key] = value
}
}
static func encode(metadata: [String : Any]) -> Data? {
let wrapper = WorkoutEventMetadata.with {
$0.elements = metadata.compactMap { .from(key: $0.key, value: $0.value) }
}
guard !wrapper.elements.isEmpty else {
return nil
}
do {
return try wrapper.serializedData()
} catch {
print("Failed to encode event metadata: \(error)")
return nil
}
}
}
private extension WorkoutEventMetadata.Element {
var value: Any? {
if hasUnsignedValue {
return unsignedValue
}
if hasQuantity {
return HKQuantity(unit: .init(from: quantity.unit), doubleValue: quantity.value)
}
return UInt(0)
}
static func from(key: String, value: Any) -> Self? {
if let value = value as? UInt {
return .with {
$0.key = key
$0.unsignedValue = UInt64(value)
}
}
guard let value = value as? HKQuantity else {
print("Unknown value type for metadata key \(key): \(value)")
return nil
}
let number: Double
let unit: String
if value.is(compatibleWith: .meter()) {
number = value.doubleValue(for: .meter())
unit = "m"
} else if value.is(compatibleWith: .second()) {
number = value.doubleValue(for: .second())
unit = "s"
} else {
print("Unhandled quantity type for metadata key \(key): \(value)")
return nil
}
return .with { el in
el.key = key
el.quantity = .with {
$0.value = number
$0.unit = unit
}
}
}
}