TempTrack-iOS/TempTrack/Temperature/TemperatureDataTransfer.swift

165 lines
5.2 KiB
Swift
Raw Normal View History

2023-06-03 08:15:00 +02:00
import Foundation
/*
2023-06-03 08:15:00 +02:00
final class TemperatureDataTransfer {
2023-06-03 08:15:00 +02:00
private let startDateOfCurrentTransfer: Date
private var interval: TimeInterval {
TimeInterval(info.measurementInterval) * dilation
}
2023-06-03 08:15:00 +02:00
private var dataBuffer: Data = Data()
private(set) var currentByteIndex = 0
private var info: DeviceInfo
private let dilation: Double
2023-06-03 08:15:00 +02:00
var size: Int {
info.numberOfRecordedBytes
}
2023-06-03 08:15:00 +02:00
var blockSize: Int {
min(50, info.transferBlockSize)
}
2023-06-03 08:15:00 +02:00
private var numberOfRecordingsInCurrentTransfer: Int {
measurements.count
}
var time: DeviceTime {
info.time
}
2023-06-11 21:57:07 +02:00
var measurements: [TemperatureMeasurement] = []
/// The last temperatures to calculate relative values
private var lastRecording: TemperatureMeasurement = .init(sensor0: .notFound, sensor1: .notFound, date: .now)
2023-06-03 08:15:00 +02:00
private var dateOfNextRecording: Date {
startDateOfCurrentTransfer.addingTimeInterval(TimeInterval(numberOfRecordingsInCurrentTransfer) * interval)
2023-06-03 08:15:00 +02:00
}
var unprocessedByteCount: Int {
dataBuffer.count
}
var remainingBytesToTransfer: Int {
size - currentByteIndex
}
init(info: DeviceInfo, previous: DeviceTime?) {
let (estimatedStart, dilation) = info.estimatedTimeDilation(to: previous)
log.info("Starting transfer")
log.info("Estimated start of recording: \(estimatedStart)")
log.info("Estimated time dilation: \(dilation)")
self.info = info
self.dilation = dilation
self.startDateOfCurrentTransfer = estimatedStart
log.info("True measurement interval: \(interval)")
2023-06-03 08:15:00 +02:00
}
func update(info: DeviceInfo) {
self.info = info
// Possible bug: Device time updated, but new measurement not transferred
// Future transfer will calculate wrong time
2023-06-03 08:15:00 +02:00
}
func nextRequest() -> BluetoothRequest {
guard remainingBytesToTransfer > 0 else {
return .clearRecordingBuffer(byteCount: currentByteIndex)
2023-06-03 08:15:00 +02:00
}
let chunkSize = min(remainingBytesToTransfer, blockSize)
return .getRecordingData(offset: currentByteIndex, count: chunkSize)
}
func add(data: Data, offset: Int, count: Int) -> Bool {
2023-06-13 17:14:57 +02:00
guard currentByteIndex == offset else {
2023-06-14 17:52:43 +02:00
log.warning("Transfer: Discarding \(data.count) bytes at offset \(offset), expected \(currentByteIndex)")
return false
2023-06-13 17:14:57 +02:00
}
guard data.count == count else {
2023-06-14 17:52:43 +02:00
log.warning("Transfer: Expected \(count) bytes, received only \(data.count)")
return false
2023-06-14 17:52:43 +02:00
}
2023-06-03 08:15:00 +02:00
dataBuffer.append(data)
currentByteIndex += data.count
log.info("Transfer: \(currentByteIndex) bytes (added \(data.count))")
return true
2023-06-03 08:15:00 +02:00
}
private func processBytes() {
while !dataBuffer.isEmpty {
let byte = dataBuffer.removeFirst()
guard (byte == 0xFF) else {
addRelative(byte: byte)
continue
}
guard dataBuffer.count >= 2 else {
// Missing data
2023-06-03 08:15:00 +02:00
return
}
let temp0 = TemperatureValue(byte: dataBuffer.removeFirst())
let temp1 = TemperatureValue(byte: dataBuffer.removeFirst())
add(sensor0: temp0, sensor1: temp1)
}
}
func completeTransfer() -> Bool {
let emptyIndices = dataBuffer.enumerated().filter { $0.element == 0 }.map { $0.offset }
2023-06-03 08:15:00 +02:00
processBytes()
guard dataBuffer.isEmpty else {
2023-06-14 17:52:43 +02:00
log.warning("\(dataBuffer.count) bytes remaining in transfer buffer")
return false
}
log.info("Transfer complete: \(currentByteIndex) bytes, \(measurements.count) points")
log.info("Empty bytes: \(emptyIndices)")
if measurements.count != info.numberOfStoredMeasurements {
log.warning("Decoded \(measurements.count) points, but only \(info.numberOfStoredMeasurements) recorded")
2023-06-14 17:52:43 +02:00
}
return true
2023-06-03 08:15:00 +02:00
}
private func addRelative(byte: UInt8) {
add(sensor0: convertTemp(value: (byte >> 4) & 0x0F, relativeTo: lastRecording.sensor0),
2023-06-03 08:15:00 +02:00
sensor1: convertTemp(value: byte & 0x0F, relativeTo: lastRecording.sensor1))
}
private func add(sensor0: TemperatureValue, sensor1: TemperatureValue) {
let measurement = TemperatureMeasurement(
sensor0: sensor0,
sensor1: sensor1,
date: dateOfNextRecording)
2023-06-03 08:15:00 +02:00
if measurement.sensor0.isValid {
lastRecording.sensor0 = measurement.sensor0
}
if measurement.sensor1.isValid {
lastRecording.sensor1 = measurement.sensor1
}
lastRecording.id = measurement.id
2023-06-11 21:57:07 +02:00
measurements.append(measurement)
2023-06-03 08:15:00 +02:00
}
private func convertTemp(value: UInt8, relativeTo previous: TemperatureValue) -> TemperatureValue {
if value == 0 {
return .notFound
}
let newValue = previous.relativeValue - (Double(value) - 8) * 0.5
return .value(newValue)
}
}
private extension TemperatureValue {
var relativeValue: Double {
if case .value(let double) = self {
return double
}
return 0
}
}
*/