TempTrack-iOS/TempTrack/Connection/TransferHandler.swift
2023-07-03 13:28:51 +02:00

97 lines
3.4 KiB
Swift

import Foundation
final class TransferHandler: ObservableObject {
@Published
var bytesTransferred: Double = 0.0
@Published
var totalBytes: Double = 0.0
@Published
var measurements: [TemperatureMeasurement] = []
@Published
var transferIsRunning = false
func startTransfer(from device: BluetoothDevice, with info: DeviceInfo, storage: PersistentStorage) {
#warning("Update device info during transfer")
discardTransfer()
transferIsRunning = true
let total = info.numberOfRecordedBytes
let chunkSize = info.transferBlockSize
totalBytes = Double(total)
Task {
defer {
DispatchQueue.main.async {
self.transferIsRunning = false
}
}
var data = Data(capacity: total)
while data.count < total {
let remainingBytes = total - data.count
let currentChunkSize = min(remainingBytes, chunkSize)
guard let chunk = await device.getDeviceData(offset: data.count, count: currentChunkSize) else {
log.warning("Failed to finish transfer")
return
}
guard !chunk.isEmpty else {
break
}
data.append(chunk)
let count = Double(data.count)
DispatchQueue.main.async {
self.bytesTransferred = count
}
}
if data.count != info.numberOfRecordedBytes {
log.warning("Expected \(info.numberOfRecordedBytes) in transfer, got only \(data.count)")
}
let sum = data.reduce(0) { $0 &+ UInt16($1) }
if sum != info.dataChecksum {
log.warning("Checksum does not match")
}
if data.count != 4 * info.numberOfStoredMeasurements {
log.warning("expected \(4 * info.numberOfStoredMeasurements) bytes for \(info.numberOfStoredMeasurements) measurements, got \(data.count)")
}
storage.saveTransferData(data: data, date: info.time.date)
DispatchQueue.main.async {
self.bytesTransferred = self.totalBytes
}
let recordingStart = info.currentMeasurementStartTime
while !data.isEmpty {
guard data.count >= 4 else {
log.error("Expected four bytes at index \(total - data.count - 1)")
break
}
let intervalCount = try! data.decodeUInt16()
let temp0 = TemperatureValue(byte: data.removeFirst())
let temp1 = TemperatureValue(byte: data.removeFirst())
let date = recordingStart
.addingTimeInterval(TimeInterval(intervalCount) * TimeInterval(info.measurementInterval))
let measurement = TemperatureMeasurement(
sensor0: temp0,
sensor1: temp1,
date: date)
DispatchQueue.main.async {
self.measurements.append(measurement)
}
}
}
}
func saveTransfer(in storage: PersistentStorage) {
storage.add(measurements)
discardTransfer()
}
func discardTransfer() {
self.measurements = []
self.bytesTransferred = 0
self.totalBytes = 0
}
}