97 lines
3.4 KiB
Swift
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
|
|
}
|
|
}
|