Fix transfer errors, save raw data
This commit is contained in:
@@ -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)
|
||||
|
@@ -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")
|
||||
|
@@ -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)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user