Fix transfer errors, save raw data

This commit is contained in:
Christoph Hagen
2023-07-03 13:28:51 +02:00
parent 396571fd30
commit d1a24b581d
22 changed files with 369 additions and 1370 deletions

View File

@@ -45,7 +45,7 @@ struct DeviceInfoView: View {
}
private var nextUpdateText: String {
let secs = info.time.nextMeasurement.secondsToNow
let secs = -info.time.nextMeasurement.secondsToNow
guard secs > 1 else {
return "Now"
}
@@ -101,6 +101,9 @@ struct DeviceInfoView: View {
IconAndTextView(
icon: .power,
text: "\(df.string(from: info.time.deviceStartTime)) (\(runTimeString))")
IconAndTextView(
icon: .touchid,
text: "\(info.uniqueIdOfPowerCycle)")
IconAndTextView(
icon: .autostartstop,
text: "Wakeup: \(info.wakeupReason.text)")
@@ -124,6 +127,10 @@ struct DeviceInfoView: View {
IconAndTextView(
icon: .iphoneAndArrowForward,
text: "\(info.transferBlockSize) Byte Block Size")
IconAndTextView(
icon: .externaldriveBadgeCheckmark,
text: String(format: "0x%02X 0x%02X",
UInt8(info.dataChecksum >> 8), UInt8( info.dataChecksum & 0xFF)))
}
sensorView(info.sensor0, id: 0)
sensorView(info.sensor1, id: 1)

View File

@@ -12,16 +12,27 @@ struct LogView: View {
@EnvironmentObject
var log: Log
@EnvironmentObject
var storage: PersistentStorage
var body: some View {
NavigationView {
List(log.logEntries) { entry in
VStack(alignment: .leading) {
HStack {
Text(entry.level.description)
Spacer()
Text(df.string(from: entry.date))
}.font(.footnote)
Text(entry.message)
List {
Text("\(storage.numberOfStoredDeviceInfos) device infos")
.font(.body)
.foregroundColor(.secondary)
Text("\(storage.numberOfStoredTransfers) transfers")
.font(.body)
.foregroundColor(.secondary)
ForEach(log.logEntries) { entry in
VStack(alignment: .leading) {
HStack {
Text(entry.level.description)
Spacer()
Text(df.string(from: entry.date))
}.font(.footnote)
Text(entry.message)
}
}
}
.navigationTitle("Log")

View File

@@ -8,24 +8,17 @@ struct TransferView: View {
let bluetoothClient: BluetoothDevice
@Binding
var info: DeviceInfo?
@EnvironmentObject
var storage: PersistentStorage
@State
var bytesTransferred: Double = 0.0
@State
var totalBytes: Double = 0.0
@State
var measurements: [TemperatureMeasurement] = []
@State
var transferIsRunning = false
@EnvironmentObject
var transfer: TransferHandler
private var storageIcon: SFSymbol {
guard let info = bluetoothClient.lastDeviceInfo else {
guard let info else {
return .externaldrive
}
if info.storageSize - info.numberOfRecordedBytes < storageWarnBytes {
@@ -35,14 +28,14 @@ struct TransferView: View {
}
private var measurementsText: String {
guard let info = bluetoothClient.lastDeviceInfo else {
guard let info else {
return "No measurements"
}
return "\(info.numberOfStoredMeasurements) measurements (\(info.time.totalNumberOfMeasurements) total)"
}
private var storageText: String {
guard let info = bluetoothClient.lastDeviceInfo else {
guard let info else {
return "No data"
}
if info.storageSize <= 0 {
@@ -52,25 +45,25 @@ struct TransferView: View {
}
private var transferSizeText: String {
guard let info = bluetoothClient.lastDeviceInfo else {
guard let info else {
return "No transfer size"
}
return "\(info.transferBlockSize) Byte Block Size"
}
private var transferByteText: String {
let total = Int(totalBytes)
let total = Int(transfer.totalBytes)
guard total > 0 else {
return "No data"
}
return "\(Int(bytesTransferred)) / \(total) Bytes"
return "\(Int(transfer.bytesTransferred)) / \(total) Bytes"
}
private var transferMeasurementText: String {
guard !measurements.isEmpty else {
guard !transfer.measurements.isEmpty else {
return "No measurements"
}
return "\(measurements.count) measurements"
return "\(transfer.measurements.count) measurements"
}
var body: some View {
@@ -93,13 +86,13 @@ struct TransferView: View {
Button(action: clearStorage) {
Text("Remove recorded data")
}
.disabled(transferIsRunning)
.disabled(transfer.transferIsRunning)
.padding()
VStack(alignment: .leading, spacing: 5) {
Text("Transfer")
.font(.headline)
ProgressView(value: bytesTransferred, total: totalBytes)
ProgressView(value: transfer.bytesTransferred, total: transfer.totalBytes)
.progressViewStyle(.linear)
.padding(.vertical, 5)
IconAndTextView(
@@ -113,19 +106,19 @@ struct TransferView: View {
Button(action: transferData) {
Text("Transfer")
}
.disabled(transferIsRunning)
.disabled(transfer.transferIsRunning)
.padding()
Spacer()
Button(action: saveTransfer) {
Text("Save")
}
.disabled(transferIsRunning || measurements.isEmpty)
.disabled(transfer.transferIsRunning || transfer.measurements.isEmpty)
.padding()
Spacer()
Button(action: discardTransfer) {
Text("Discard")
}
.disabled(transferIsRunning || measurements.isEmpty)
.disabled(transfer.transferIsRunning || transfer.measurements.isEmpty)
.padding()
}
Spacer()
@@ -140,80 +133,22 @@ struct TransferView: View {
}
func transferData() {
guard let info = bluetoothClient.lastDeviceInfo else {
guard let info else {
return
}
transferIsRunning = true
let total = info.numberOfRecordedBytes
let chunkSize = info.transferBlockSize
bytesTransferred = 0
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 bluetoothClient.getDeviceData(offset: data.count, count: currentChunkSize) else {
log.warning("Failed to finish transfer")
return
}
data.append(chunk)
DispatchQueue.main.async {
self.bytesTransferred = Double(data.count)
}
}
DispatchQueue.main.async {
self.bytesTransferred = totalBytes
}
var measurementCount = 0
let recordingStart = info.currentMeasurementStartTime
while !data.isEmpty {
let byte = data.removeFirst()
guard (byte == 0xFF) else {
log.error("Expected 0xFF at index \(total - data.count - 1)")
break
}
guard data.count >= 2 else {
log.error("Expected two more bytes after index \(total - data.count - 1)")
break
}
let temp0 = TemperatureValue(byte: data.removeFirst())
let temp1 = TemperatureValue(byte: data.removeFirst())
let date = recordingStart
.addingTimeInterval(TimeInterval(measurementCount * info.measurementInterval))
let measurement = TemperatureMeasurement(
sensor0: temp0,
sensor1: temp1,
date: date)
measurementCount += 1
DispatchQueue.main.async {
self.measurements.append(measurement)
}
}
}
transfer.startTransfer(from: bluetoothClient, with: info, storage: storage)
}
func discardTransfer() {
self.measurements = []
self.bytesTransferred = 0
self.totalBytes = 0
transfer.discardTransfer()
}
func saveTransfer() {
// TODO: Save
discardTransfer()
transfer.saveTransfer(in: storage)
}
func clearStorage() {
guard let byteCount = bluetoothClient.lastDeviceInfo?.numberOfRecordedBytes else {
guard let byteCount = info?.numberOfRecordedBytes else {
return
}
Task {
@@ -229,7 +164,7 @@ struct TransferView: View {
struct TransferView_Previews: PreviewProvider {
static var previews: some View {
let storage = PersistentStorage(lastMeasurements: TemperatureMeasurement.mockData)
TransferView(bluetoothClient: .init())
TransferView(bluetoothClient: .init(), info: .constant(.mock))
.environmentObject(storage)
}
}