@bota.dev/react-native-app-sdk 2.0.0-beta.0 → 2.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -2
- package/android/build.gradle +1 -0
- package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidDiagnostics.kt +53 -0
- package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidLogs.kt +16 -0
- package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidRecordingUploads.kt +144 -14
- package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidRecordings.kt +150 -29
- package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKEncryptedUploadV2Materials.kt +27 -0
- package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKModule.kt +68 -3
- package/android/src/test/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidLogsTest.kt +33 -0
- package/android/src/test/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidRecordingUploadsTest.kt +135 -6
- package/android/src/test/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidRecordingsTest.kt +236 -10
- package/generated/codegen-contract.json +495 -8
- package/ios/BotaDeviceSDK.mm +102 -0
- package/ios/BotaDeviceSDKAppleBridge.swift +126 -4
- package/ios/BotaDeviceSDKAppleDiagnostics.swift +40 -0
- package/ios/BotaDeviceSDKAppleLogs.swift +18 -0
- package/ios/BotaDeviceSDKAppleRecordingUploads.swift +138 -6
- package/ios/BotaDeviceSDKAppleRecordings.swift +113 -5
- package/ios/BotaDeviceSDKEncryptedUploadV2Materials.swift +40 -0
- package/lib/commonjs/BotaClient.js +13 -2
- package/lib/commonjs/BotaClient.js.map +1 -1
- package/lib/commonjs/ble/constants.js +5 -1
- package/lib/commonjs/ble/constants.js.map +1 -1
- package/lib/commonjs/ble/deviceDiagnostics.js +240 -0
- package/lib/commonjs/ble/deviceDiagnostics.js.map +1 -0
- package/lib/commonjs/client.js +163 -28
- package/lib/commonjs/client.js.map +1 -1
- package/lib/commonjs/index.js +15 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/managers/DeviceManager.js +8 -0
- package/lib/commonjs/managers/DeviceManager.js.map +1 -1
- package/lib/commonjs/managers/NativeUploadQueue.js +386 -0
- package/lib/commonjs/managers/NativeUploadQueue.js.map +1 -0
- package/lib/commonjs/managers/RecordingManager.js +83 -102
- package/lib/commonjs/managers/RecordingManager.js.map +1 -1
- package/lib/commonjs/managers/uploadRecoveryMetadata.js +83 -0
- package/lib/commonjs/managers/uploadRecoveryMetadata.js.map +1 -0
- package/lib/commonjs/specs/NativeBotaDeviceSDK.js.map +1 -1
- package/lib/module/BotaClient.js +13 -2
- package/lib/module/BotaClient.js.map +1 -1
- package/lib/module/ble/constants.js +4 -0
- package/lib/module/ble/constants.js.map +1 -1
- package/lib/module/ble/deviceDiagnostics.js +234 -0
- package/lib/module/ble/deviceDiagnostics.js.map +1 -0
- package/lib/module/client.js +163 -28
- package/lib/module/client.js.map +1 -1
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/managers/DeviceManager.js +8 -0
- package/lib/module/managers/DeviceManager.js.map +1 -1
- package/lib/module/managers/NativeUploadQueue.js +380 -0
- package/lib/module/managers/NativeUploadQueue.js.map +1 -0
- package/lib/module/managers/RecordingManager.js +83 -102
- package/lib/module/managers/RecordingManager.js.map +1 -1
- package/lib/module/managers/uploadRecoveryMetadata.js +77 -0
- package/lib/module/managers/uploadRecoveryMetadata.js.map +1 -0
- package/lib/module/specs/NativeBotaDeviceSDK.js.map +1 -1
- package/lib/typescript/BotaClient.d.ts.map +1 -1
- package/lib/typescript/ble/constants.d.ts +4 -0
- package/lib/typescript/ble/constants.d.ts.map +1 -1
- package/lib/typescript/ble/deviceDiagnostics.d.ts +10 -0
- package/lib/typescript/ble/deviceDiagnostics.d.ts.map +1 -0
- package/lib/typescript/client.d.ts +18 -2
- package/lib/typescript/client.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +6 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/managers/DeviceManager.d.ts +3 -1
- package/lib/typescript/managers/DeviceManager.d.ts.map +1 -1
- package/lib/typescript/managers/NativeUploadQueue.d.ts +41 -0
- package/lib/typescript/managers/NativeUploadQueue.d.ts.map +1 -0
- package/lib/typescript/managers/RecordingManager.d.ts +3 -8
- package/lib/typescript/managers/RecordingManager.d.ts.map +1 -1
- package/lib/typescript/managers/types.d.ts +6 -1
- package/lib/typescript/managers/types.d.ts.map +1 -1
- package/lib/typescript/managers/uploadRecoveryMetadata.d.ts +6 -0
- package/lib/typescript/managers/uploadRecoveryMetadata.d.ts.map +1 -0
- package/lib/typescript/models/Device.d.ts +42 -0
- package/lib/typescript/models/Device.d.ts.map +1 -1
- package/lib/typescript/models/Recording.d.ts +47 -0
- package/lib/typescript/models/Recording.d.ts.map +1 -1
- package/lib/typescript/models/Status.d.ts +5 -1
- package/lib/typescript/models/Status.d.ts.map +1 -1
- package/lib/typescript/specs/NativeBotaDeviceSDK.d.ts +61 -0
- package/lib/typescript/specs/NativeBotaDeviceSDK.d.ts.map +1 -1
- package/package.json +1 -1
- package/scripts/bota_device_sdk_spm_workaround.rb +26 -15
- package/src/BotaClient.ts +13 -3
- package/src/ble/constants.ts +5 -0
- package/src/ble/deviceDiagnostics.ts +238 -0
- package/src/client.ts +166 -18
- package/src/index.ts +12 -0
- package/src/managers/DeviceManager.ts +11 -0
- package/src/managers/NativeUploadQueue.ts +330 -0
- package/src/managers/RecordingManager.ts +83 -116
- package/src/managers/types.ts +7 -1
- package/src/managers/uploadRecoveryMetadata.ts +59 -0
- package/src/models/Device.ts +43 -0
- package/src/models/Recording.ts +52 -0
- package/src/models/Status.ts +5 -1
- package/src/specs/NativeBotaDeviceSDK.ts +56 -0
|
@@ -5,10 +5,12 @@ struct BotaDeviceSDKAppleRecordingFile: Equatable, Sendable {
|
|
|
5
5
|
let localPath: String
|
|
6
6
|
let isE2EEncrypted: Bool
|
|
7
7
|
let contentSHA256Hex: String?
|
|
8
|
+
let fileSizeBytes: UInt64
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
protocol BotaDeviceSDKAppleRecordingClient: Sendable {
|
|
11
12
|
func listRecordings(_ device: ConnectedDevice) async throws -> [DeviceRecording]
|
|
13
|
+
func listPendingRecordings(_ device: ConnectedDevice) async throws -> [PendingRecording]
|
|
12
14
|
func syncRecording(
|
|
13
15
|
_ device: ConnectedDevice,
|
|
14
16
|
recording: DeviceRecording,
|
|
@@ -18,8 +20,10 @@ protocol BotaDeviceSDKAppleRecordingClient: Sendable {
|
|
|
18
20
|
func syncEncryptedRecordingV2(
|
|
19
21
|
_ device: ConnectedDevice,
|
|
20
22
|
recording: EncryptedUploadV2Recording,
|
|
23
|
+
operationID: UUID,
|
|
21
24
|
provider: @escaping EncryptedUploadV2ProfileProvider
|
|
22
25
|
) async throws
|
|
26
|
+
func cancelEncryptedUploadV2Operation(_ operationID: UUID) async throws
|
|
23
27
|
func confirmRecording(_ device: ConnectedDevice, recordingUUID: String) async throws
|
|
24
28
|
func observeUploadOwnership(
|
|
25
29
|
_ device: ConnectedDevice,
|
|
@@ -50,6 +54,10 @@ struct BotaDeviceSDKSharedAppleRecordingClient: BotaDeviceSDKAppleRecordingClien
|
|
|
50
54
|
try await recordings.listRecordings(device)
|
|
51
55
|
}
|
|
52
56
|
|
|
57
|
+
func listPendingRecordings(_ device: ConnectedDevice) async throws -> [PendingRecording] {
|
|
58
|
+
try await recordings.listPendingRecordings(device)
|
|
59
|
+
}
|
|
60
|
+
|
|
53
61
|
func syncRecording(
|
|
54
62
|
_ device: ConnectedDevice,
|
|
55
63
|
recording: DeviceRecording,
|
|
@@ -70,15 +78,21 @@ struct BotaDeviceSDKSharedAppleRecordingClient: BotaDeviceSDKAppleRecordingClien
|
|
|
70
78
|
func syncEncryptedRecordingV2(
|
|
71
79
|
_ device: ConnectedDevice,
|
|
72
80
|
recording: EncryptedUploadV2Recording,
|
|
81
|
+
operationID: UUID,
|
|
73
82
|
provider: @escaping EncryptedUploadV2ProfileProvider
|
|
74
83
|
) async throws {
|
|
75
84
|
try await recordings.syncEncryptedRecordingV2(
|
|
76
85
|
device,
|
|
77
86
|
recording: recording,
|
|
87
|
+
operationID: operationID,
|
|
78
88
|
provider: provider
|
|
79
89
|
)
|
|
80
90
|
}
|
|
81
91
|
|
|
92
|
+
func cancelEncryptedUploadV2Operation(_ operationID: UUID) async throws {
|
|
93
|
+
try await recordings.cancelEncryptedUploadV2Operation(operationID)
|
|
94
|
+
}
|
|
95
|
+
|
|
82
96
|
func confirmRecording(_ device: ConnectedDevice, recordingUUID: String) async throws {
|
|
83
97
|
try await recordings.confirmRecording(device, recordingUUID: recordingUUID)
|
|
84
98
|
}
|
|
@@ -153,11 +167,16 @@ actor BotaDeviceSDKAppleRecordings {
|
|
|
153
167
|
}
|
|
154
168
|
|
|
155
169
|
private let client: any BotaDeviceSDKAppleRecordingClient
|
|
170
|
+
private let fileSize: @Sendable (String) throws -> UInt64
|
|
156
171
|
private struct EncryptedUploadV2Request {
|
|
172
|
+
let operationID: String
|
|
157
173
|
let recording: EncryptedUploadV2Recording
|
|
158
174
|
let continuation: CheckedContinuation<EncryptedUploadV2Material, Error>
|
|
159
175
|
}
|
|
160
176
|
private var encryptedUploadV2Requests: [String: EncryptedUploadV2Request] = [:]
|
|
177
|
+
private var encryptedUploadV2Operations: [String: UUID] = [:]
|
|
178
|
+
private var encryptedUploadV2Tasks: [String: Task<Void, Error>] = [:]
|
|
179
|
+
private var cancelledEncryptedUploadV2Operations: Set<String> = []
|
|
161
180
|
private var destinationRequests: [
|
|
162
181
|
String: CheckedContinuation<StreamingUploadDestination, Error>
|
|
163
182
|
] = [:]
|
|
@@ -166,15 +185,28 @@ actor BotaDeviceSDKAppleRecordings {
|
|
|
166
185
|
|
|
167
186
|
init(
|
|
168
187
|
client: any BotaDeviceSDKAppleRecordingClient =
|
|
169
|
-
BotaDeviceSDKSharedAppleRecordingClient()
|
|
188
|
+
BotaDeviceSDKSharedAppleRecordingClient(),
|
|
189
|
+
fileSize: @escaping @Sendable (String) throws -> UInt64 = { path in
|
|
190
|
+
let attributes = try FileManager.default.attributesOfItem(atPath: path)
|
|
191
|
+
guard attributes[.type] as? FileAttributeType == .typeRegular,
|
|
192
|
+
let size = attributes[.size] as? NSNumber else {
|
|
193
|
+
throw CocoaError(.fileReadCorruptFile)
|
|
194
|
+
}
|
|
195
|
+
return size.uint64Value
|
|
196
|
+
}
|
|
170
197
|
) {
|
|
171
198
|
self.client = client
|
|
199
|
+
self.fileSize = fileSize
|
|
172
200
|
}
|
|
173
201
|
|
|
174
202
|
func listRecordings(_ device: ConnectedDevice) async throws -> [DeviceRecording] {
|
|
175
203
|
try await client.listRecordings(device)
|
|
176
204
|
}
|
|
177
205
|
|
|
206
|
+
func listPendingRecordings(_ device: ConnectedDevice) async throws -> [PendingRecording] {
|
|
207
|
+
try await client.listPendingRecordings(device)
|
|
208
|
+
}
|
|
209
|
+
|
|
178
210
|
func syncRecording(
|
|
179
211
|
_ device: ConnectedDevice,
|
|
180
212
|
recording: DeviceRecording,
|
|
@@ -200,7 +232,8 @@ actor BotaDeviceSDKAppleRecordings {
|
|
|
200
232
|
return BotaDeviceSDKAppleRecordingFile(
|
|
201
233
|
localPath: path,
|
|
202
234
|
isE2EEncrypted: metadata?.isE2EEncrypted ?? false,
|
|
203
|
-
contentSHA256Hex: metadata?.contentSHA256Hex
|
|
235
|
+
contentSHA256Hex: metadata?.contentSHA256Hex,
|
|
236
|
+
fileSizeBytes: try fileSize(path)
|
|
204
237
|
)
|
|
205
238
|
}
|
|
206
239
|
|
|
@@ -210,11 +243,51 @@ actor BotaDeviceSDKAppleRecordings {
|
|
|
210
243
|
operationID: String,
|
|
211
244
|
onProfileRequest: @escaping @Sendable ([String: Any]) -> Void,
|
|
212
245
|
onProgress: @escaping @Sendable ([String: Any]) -> Void
|
|
246
|
+
) async throws {
|
|
247
|
+
guard encryptedUploadV2Operations[operationID] == nil else {
|
|
248
|
+
throw RecordingError.invalidEncryptedUploadV2Selection
|
|
249
|
+
}
|
|
250
|
+
guard !cancelledEncryptedUploadV2Operations.contains(operationID) else { throw CancellationError() }
|
|
251
|
+
let nativeID = UUID()
|
|
252
|
+
let task = Task {
|
|
253
|
+
try Task.checkCancellation()
|
|
254
|
+
try await self.runEncryptedRecordingV2(
|
|
255
|
+
device,
|
|
256
|
+
recording: recording,
|
|
257
|
+
operationID: operationID,
|
|
258
|
+
nativeID: nativeID,
|
|
259
|
+
onProfileRequest: onProfileRequest,
|
|
260
|
+
onProgress: onProgress
|
|
261
|
+
)
|
|
262
|
+
}
|
|
263
|
+
encryptedUploadV2Operations[operationID] = nativeID
|
|
264
|
+
encryptedUploadV2Tasks[operationID] = task
|
|
265
|
+
defer {
|
|
266
|
+
encryptedUploadV2Operations.removeValue(forKey: operationID)
|
|
267
|
+
encryptedUploadV2Tasks.removeValue(forKey: operationID)
|
|
268
|
+
BotaDeviceSDKEncryptedUploadV2Materials.removeContext(operationID)
|
|
269
|
+
}
|
|
270
|
+
try await withTaskCancellationHandler {
|
|
271
|
+
try await task.value
|
|
272
|
+
} onCancel: {
|
|
273
|
+
task.cancel()
|
|
274
|
+
Task { try? await self.cancelEncryptedRecordingV2(operationID) }
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
private func runEncryptedRecordingV2(
|
|
279
|
+
_ device: ConnectedDevice,
|
|
280
|
+
recording: EncryptedUploadV2Recording,
|
|
281
|
+
operationID: String,
|
|
282
|
+
nativeID: UUID,
|
|
283
|
+
onProfileRequest: @escaping @Sendable ([String: Any]) -> Void,
|
|
284
|
+
onProgress: @escaping @Sendable ([String: Any]) -> Void
|
|
213
285
|
) async throws {
|
|
214
286
|
do {
|
|
215
287
|
try await client.syncEncryptedRecordingV2(
|
|
216
288
|
device,
|
|
217
|
-
recording: recording
|
|
289
|
+
recording: recording,
|
|
290
|
+
operationID: nativeID
|
|
218
291
|
) { context in
|
|
219
292
|
let completedBytes = String(context.checkpoint?.nextCiphertextOffset ?? 0)
|
|
220
293
|
let checkpointRevision = context.checkpoint?.revision
|
|
@@ -264,6 +337,25 @@ actor BotaDeviceSDKAppleRecordings {
|
|
|
264
337
|
}
|
|
265
338
|
}
|
|
266
339
|
|
|
340
|
+
func cancelEncryptedRecordingV2(_ operationID: String) async throws {
|
|
341
|
+
cancelledEncryptedUploadV2Operations.insert(operationID)
|
|
342
|
+
let task = encryptedUploadV2Tasks[operationID]
|
|
343
|
+
task?.cancel()
|
|
344
|
+
let pending = encryptedUploadV2Requests.filter { $0.value.operationID == operationID }
|
|
345
|
+
for (id, request) in pending {
|
|
346
|
+
encryptedUploadV2Requests.removeValue(forKey: id)
|
|
347
|
+
request.continuation.resume(throwing: CancellationError())
|
|
348
|
+
}
|
|
349
|
+
BotaDeviceSDKEncryptedUploadV2Materials.removeContext(operationID)
|
|
350
|
+
var cancellationError: Error?
|
|
351
|
+
if let nativeID = encryptedUploadV2Operations[operationID] {
|
|
352
|
+
do { try await client.cancelEncryptedUploadV2Operation(nativeID) }
|
|
353
|
+
catch { cancellationError = error }
|
|
354
|
+
}
|
|
355
|
+
_ = await task?.result
|
|
356
|
+
if let cancellationError { throw cancellationError }
|
|
357
|
+
}
|
|
358
|
+
|
|
267
359
|
func resolveEncryptedUploadV2Profile(
|
|
268
360
|
requestID: String,
|
|
269
361
|
profile: String,
|
|
@@ -275,6 +367,7 @@ actor BotaDeviceSDKAppleRecordings {
|
|
|
275
367
|
guard let request = encryptedUploadV2Requests.removeValue(forKey: requestID) else {
|
|
276
368
|
throw RecordingError.missingEncryptedUploadV2Request
|
|
277
369
|
}
|
|
370
|
+
BotaDeviceSDKEncryptedUploadV2Materials.removeContext(request.operationID)
|
|
278
371
|
do {
|
|
279
372
|
guard profile == "encrypted_upload_v2",
|
|
280
373
|
let sessionID = UUID(uuidString: uploadSessionID)
|
|
@@ -299,6 +392,7 @@ actor BotaDeviceSDKAppleRecordings {
|
|
|
299
392
|
guard let request = encryptedUploadV2Requests.removeValue(forKey: requestID) else {
|
|
300
393
|
throw RecordingError.missingEncryptedUploadV2Request
|
|
301
394
|
}
|
|
395
|
+
BotaDeviceSDKEncryptedUploadV2Materials.removeContext(request.operationID)
|
|
302
396
|
guard errorCode == "application_material_rejected" else {
|
|
303
397
|
request.continuation.resume(throwing: RecordingError.invalidEncryptedUploadV2Selection)
|
|
304
398
|
throw RecordingError.invalidEncryptedUploadV2Selection
|
|
@@ -453,6 +547,9 @@ actor BotaDeviceSDKAppleRecordings {
|
|
|
453
547
|
}
|
|
454
548
|
|
|
455
549
|
func cancelAll() async {
|
|
550
|
+
let operationIDs = Array(encryptedUploadV2Tasks.keys)
|
|
551
|
+
for id in operationIDs { encryptedUploadV2Tasks[id]?.cancel() }
|
|
552
|
+
for id in operationIDs { try? await cancelEncryptedRecordingV2(id) }
|
|
456
553
|
rejectPendingRequests(message: "recording operations were cancelled")
|
|
457
554
|
try? await client.cancelCurrentOperation()
|
|
458
555
|
}
|
|
@@ -462,9 +559,13 @@ actor BotaDeviceSDKAppleRecordings {
|
|
|
462
559
|
context: EncryptedUploadV2ProviderContext,
|
|
463
560
|
onRequest: @escaping @Sendable ([String: Any]) -> Void
|
|
464
561
|
) async throws -> EncryptedUploadV2Material {
|
|
562
|
+
guard encryptedUploadV2Operations[operationID] != nil,
|
|
563
|
+
!cancelledEncryptedUploadV2Operations.contains(operationID) else { throw CancellationError() }
|
|
465
564
|
let requestID = UUID().uuidString.lowercased()
|
|
565
|
+
try BotaDeviceSDKEncryptedUploadV2Materials.registerContext(operationID, context: context)
|
|
466
566
|
return try await withCheckedThrowingContinuation { continuation in
|
|
467
567
|
encryptedUploadV2Requests[requestID] = .init(
|
|
568
|
+
operationID: operationID,
|
|
468
569
|
recording: context.recording,
|
|
469
570
|
continuation: continuation
|
|
470
571
|
)
|
|
@@ -525,12 +626,15 @@ actor BotaDeviceSDKAppleRecordings {
|
|
|
525
626
|
destinationRequests.removeAll()
|
|
526
627
|
finalizeRequests.removeAll()
|
|
527
628
|
encryptedUploadV2Requests.removeAll()
|
|
528
|
-
encryptedUploadV2.forEach {
|
|
629
|
+
encryptedUploadV2.forEach {
|
|
630
|
+
BotaDeviceSDKEncryptedUploadV2Materials.removeContext($0.operationID)
|
|
631
|
+
$0.continuation.resume(throwing: error)
|
|
632
|
+
}
|
|
529
633
|
destinations.forEach { $0.resume(throwing: error) }
|
|
530
634
|
finalizations.forEach { $0.resume(throwing: error) }
|
|
531
635
|
}
|
|
532
636
|
|
|
533
|
-
|
|
637
|
+
static func encryptedUploadV2Recording(
|
|
534
638
|
_ recording: EncryptedUploadV2Recording
|
|
535
639
|
) -> [String: Any] {
|
|
536
640
|
[
|
|
@@ -538,6 +642,10 @@ actor BotaDeviceSDKAppleRecordings {
|
|
|
538
642
|
"generation": recording.generation,
|
|
539
643
|
"ciphertextLength": String(recording.ciphertextLength),
|
|
540
644
|
"ciphertextSha256": recording.ciphertextSHA256.hexString,
|
|
645
|
+
"startedAtMs": String(recording.startedAtMs),
|
|
646
|
+
"durationMs": String(recording.durationMs),
|
|
647
|
+
"plaintextLength": String(recording.plaintextLength),
|
|
648
|
+
"storageFormat": Int(recording.storageFormat),
|
|
541
649
|
]
|
|
542
650
|
}
|
|
543
651
|
|
|
@@ -15,6 +15,25 @@ public enum BotaDeviceSDKEncryptedUploadV2Materials {
|
|
|
15
15
|
storage.remove(registrationID)
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
public static func readAuthNonce(_ operationID: String) async throws -> Data {
|
|
19
|
+
let entry = try storage.context(operationID)
|
|
20
|
+
let nonce = try await entry.value.readAuthNonce()
|
|
21
|
+
guard try storage.context(operationID).lease == entry.lease else {
|
|
22
|
+
throw CancellationError()
|
|
23
|
+
}
|
|
24
|
+
return nonce
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public static func release(_ registrationID: String) async {
|
|
28
|
+
if let material = storage.remove(registrationID) { await material.cancelPreparation() }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static func registerContext(_ operationID: String, context: EncryptedUploadV2ProviderContext) throws {
|
|
32
|
+
try storage.registerContext(operationID, value: context)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static func removeContext(_ operationID: String) { storage.removeContext(operationID) }
|
|
36
|
+
|
|
18
37
|
static func consume(
|
|
19
38
|
_ registrationID: String,
|
|
20
39
|
recording: EncryptedUploadV2Recording,
|
|
@@ -33,6 +52,10 @@ public enum BotaDeviceSDKEncryptedUploadV2Materials {
|
|
|
33
52
|
}
|
|
34
53
|
|
|
35
54
|
private final class BotaDeviceSDKEncryptedUploadV2MaterialStorage: @unchecked Sendable {
|
|
55
|
+
struct Context: Sendable {
|
|
56
|
+
let lease: UUID
|
|
57
|
+
let value: EncryptedUploadV2ProviderContext
|
|
58
|
+
}
|
|
36
59
|
private enum RegistrationError: LocalizedError {
|
|
37
60
|
case invalidSelection
|
|
38
61
|
case unknownRegistration
|
|
@@ -49,6 +72,23 @@ private final class BotaDeviceSDKEncryptedUploadV2MaterialStorage: @unchecked Se
|
|
|
49
72
|
|
|
50
73
|
private let lock = NSLock()
|
|
51
74
|
private var materials: [String: EncryptedUploadV2Material] = [:]
|
|
75
|
+
private var contexts: [String: Context] = [:]
|
|
76
|
+
|
|
77
|
+
func registerContext(_ operationID: String, value: EncryptedUploadV2ProviderContext) throws {
|
|
78
|
+
try lock.withLock {
|
|
79
|
+
guard contexts[operationID] == nil else { throw RegistrationError.invalidSelection }
|
|
80
|
+
contexts[operationID] = Context(lease: UUID(), value: value)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
func context(_ operationID: String) throws -> Context {
|
|
85
|
+
try lock.withLock {
|
|
86
|
+
guard let context = contexts[operationID] else { throw RegistrationError.unknownRegistration }
|
|
87
|
+
return context
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
func removeContext(_ operationID: String) { _ = lock.withLock { contexts.removeValue(forKey: operationID) } }
|
|
52
92
|
|
|
53
93
|
func register(_ material: EncryptedUploadV2Material) -> String {
|
|
54
94
|
let registrationID = UUID().uuidString.lowercased()
|
|
@@ -9,6 +9,7 @@ var _runtime = require("./compatibility/runtime");
|
|
|
9
9
|
var _DeviceManager = require("./managers/DeviceManager");
|
|
10
10
|
var _OTAManager = require("./managers/OTAManager");
|
|
11
11
|
var _RecordingManager = require("./managers/RecordingManager");
|
|
12
|
+
var _uploadRecoveryMetadata = require("./managers/uploadRecoveryMetadata");
|
|
12
13
|
var _errors = require("./utils/errors");
|
|
13
14
|
var _logger = require("./utils/logger");
|
|
14
15
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -18,7 +19,10 @@ const normalizeConfig = config => ({
|
|
|
18
19
|
backgroundSyncEnabled: config.backgroundSyncEnabled ?? true,
|
|
19
20
|
wifiOnlyUpload: config.wifiOnlyUpload ?? false,
|
|
20
21
|
logLevel: config.logLevel ?? 'warn',
|
|
21
|
-
debug: config.debug ?? false
|
|
22
|
+
debug: config.debug ?? false,
|
|
23
|
+
...(config.uploadRecoveryProvider ? {
|
|
24
|
+
uploadRecoveryProvider: config.uploadRecoveryProvider
|
|
25
|
+
} : {})
|
|
22
26
|
});
|
|
23
27
|
class BotaClientImpl extends _eventemitter.default {
|
|
24
28
|
_config = null;
|
|
@@ -60,6 +64,11 @@ class BotaClientImpl extends _eventemitter.default {
|
|
|
60
64
|
return this._otaManager;
|
|
61
65
|
}
|
|
62
66
|
configure(config = {}) {
|
|
67
|
+
try {
|
|
68
|
+
(0, _uploadRecoveryMetadata.rejectRecordingDataStore)(config.recordingDataStore);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
return Promise.reject(error);
|
|
71
|
+
}
|
|
63
72
|
if (this._configurePromise && !this._destroyPromise) {
|
|
64
73
|
return this._configurePromise;
|
|
65
74
|
}
|
|
@@ -140,7 +149,9 @@ class BotaClientImpl extends _eventemitter.default {
|
|
|
140
149
|
this.setBluetoothState(capabilities.bluetooth ? 'poweredOn' : 'unsupported');
|
|
141
150
|
deviceManager = new _DeviceManager.DeviceManager();
|
|
142
151
|
await deviceManager.initialize();
|
|
143
|
-
recordingManager = new _RecordingManager.RecordingManager(
|
|
152
|
+
recordingManager = new _RecordingManager.RecordingManager({
|
|
153
|
+
uploadRecoveryProvider: config.uploadRecoveryProvider
|
|
154
|
+
});
|
|
144
155
|
await recordingManager.initialize();
|
|
145
156
|
otaManager = new _OTAManager.OTAManager(deviceManager);
|
|
146
157
|
this._deviceManager = deviceManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_eventemitter","_interopRequireDefault","require","_runtime","_DeviceManager","_OTAManager","_RecordingManager","_errors","_logger","e","__esModule","default","log","logger","tag","normalizeConfig","config","environment","backgroundSyncEnabled","wifiOnlyUpload","logLevel","debug","BotaClientImpl","EventEmitter","_config","_state","_bluetoothState","_client","_deviceManager","_recordingManager","_otaManager","_nativeOwned","_operation","Promise","resolve","_configurePromise","_destroyPromise","state","bluetoothState","isBluetoothReady","isInitialized","devices","SdkError","notInitialized","recordings","ota","configure","normalized","operation","enqueue","performConfigure","finally","catch","undefined","waitForBluetooth","timeoutMs","BluetoothError","unavailable","deadline","Date","now","setTimeout","capabilities","getCapabilities","bluetooth","setBluetoothState","timeout","setLogLevel","level","setLevel","setLogHandler","handler","setHandler","destroy","releaseOwnerGraph","removeAllListeners","queued","then","warn","setState","client","getCompatibilityClient","deviceManager","recordingManager","otaManager","nativeState","getState","invalidState","DeviceManager","initialize","RecordingManager","OTAManager","info","
|
|
1
|
+
{"version":3,"names":["_eventemitter","_interopRequireDefault","require","_runtime","_DeviceManager","_OTAManager","_RecordingManager","_uploadRecoveryMetadata","_errors","_logger","e","__esModule","default","log","logger","tag","normalizeConfig","config","environment","backgroundSyncEnabled","wifiOnlyUpload","logLevel","debug","uploadRecoveryProvider","BotaClientImpl","EventEmitter","_config","_state","_bluetoothState","_client","_deviceManager","_recordingManager","_otaManager","_nativeOwned","_operation","Promise","resolve","_configurePromise","_destroyPromise","state","bluetoothState","isBluetoothReady","isInitialized","devices","SdkError","notInitialized","recordings","ota","configure","rejectRecordingDataStore","recordingDataStore","error","reject","normalized","operation","enqueue","performConfigure","finally","catch","undefined","waitForBluetooth","timeoutMs","BluetoothError","unavailable","deadline","Date","now","setTimeout","capabilities","getCapabilities","bluetooth","setBluetoothState","timeout","setLogLevel","level","setLevel","setLogHandler","handler","setHandler","destroy","releaseOwnerGraph","removeAllListeners","queued","then","warn","setState","client","getCompatibilityClient","deviceManager","recordingManager","otaManager","nativeState","getState","invalidState","DeviceManager","initialize","RecordingManager","OTAManager","info","failure","Error","String","emit","BotaClient","exports"],"sourceRoot":"../../src","sources":["BotaClient.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.DEVICE_LOG_FLAG_DROPPED = exports.DEVICE_LOG_FLAG_BACKLOG = exports.BLE_ERROR_STORAGE_KEY_UNAVAILABLE = void 0;
|
|
6
|
+
exports.DEVICE_LOG_FLAG_DROPPED = exports.DEVICE_LOG_FLAG_BACKLOG = exports.DEVICE_DIAGNOSTICS_EVT_SIGNATURE = exports.DEVICE_DIAGNOSTICS_EVT_META = exports.DEVICE_DIAGNOSTICS_EVT_END = exports.DEVICE_DIAGNOSTICS_EVT_DETAIL = exports.BLE_ERROR_STORAGE_KEY_UNAVAILABLE = void 0;
|
|
7
7
|
const DEVICE_LOG_FLAG_BACKLOG = exports.DEVICE_LOG_FLAG_BACKLOG = 0x01;
|
|
8
8
|
const DEVICE_LOG_FLAG_DROPPED = exports.DEVICE_LOG_FLAG_DROPPED = 0x02;
|
|
9
9
|
const BLE_ERROR_STORAGE_KEY_UNAVAILABLE = exports.BLE_ERROR_STORAGE_KEY_UNAVAILABLE = 0x14;
|
|
10
|
+
const DEVICE_DIAGNOSTICS_EVT_META = exports.DEVICE_DIAGNOSTICS_EVT_META = 0x90;
|
|
11
|
+
const DEVICE_DIAGNOSTICS_EVT_SIGNATURE = exports.DEVICE_DIAGNOSTICS_EVT_SIGNATURE = 0x91;
|
|
12
|
+
const DEVICE_DIAGNOSTICS_EVT_END = exports.DEVICE_DIAGNOSTICS_EVT_END = 0x92;
|
|
13
|
+
const DEVICE_DIAGNOSTICS_EVT_DETAIL = exports.DEVICE_DIAGNOSTICS_EVT_DETAIL = 0x95;
|
|
10
14
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["DEVICE_LOG_FLAG_BACKLOG","exports","DEVICE_LOG_FLAG_DROPPED","BLE_ERROR_STORAGE_KEY_UNAVAILABLE"],"sourceRoot":"../../../src","sources":["ble/constants.ts"],"mappings":";;;;;;AAAO,MAAMA,uBAAuB,GAAAC,OAAA,CAAAD,uBAAA,GAAG,IAAI;AACpC,MAAME,uBAAuB,GAAAD,OAAA,CAAAC,uBAAA,GAAG,IAAI;AACpC,MAAMC,iCAAiC,GAAAF,OAAA,CAAAE,iCAAA,GAAG,IAAI","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["DEVICE_LOG_FLAG_BACKLOG","exports","DEVICE_LOG_FLAG_DROPPED","BLE_ERROR_STORAGE_KEY_UNAVAILABLE","DEVICE_DIAGNOSTICS_EVT_META","DEVICE_DIAGNOSTICS_EVT_SIGNATURE","DEVICE_DIAGNOSTICS_EVT_END","DEVICE_DIAGNOSTICS_EVT_DETAIL"],"sourceRoot":"../../../src","sources":["ble/constants.ts"],"mappings":";;;;;;AAAO,MAAMA,uBAAuB,GAAAC,OAAA,CAAAD,uBAAA,GAAG,IAAI;AACpC,MAAME,uBAAuB,GAAAD,OAAA,CAAAC,uBAAA,GAAG,IAAI;AACpC,MAAMC,iCAAiC,GAAAF,OAAA,CAAAE,iCAAA,GAAG,IAAI;AAE9C,MAAMC,2BAA2B,GAAAH,OAAA,CAAAG,2BAAA,GAAG,IAAI;AACxC,MAAMC,gCAAgC,GAAAJ,OAAA,CAAAI,gCAAA,GAAG,IAAI;AAC7C,MAAMC,0BAA0B,GAAAL,OAAA,CAAAK,0BAAA,GAAG,IAAI;AACvC,MAAMC,6BAA6B,GAAAN,OAAA,CAAAM,6BAAA,GAAG,IAAI","ignoreList":[]}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.DeviceDiagnosticsDecoder = void 0;
|
|
7
|
+
exports.diagnosticEventIdCommand = diagnosticEventIdCommand;
|
|
8
|
+
var _buffer = require("buffer");
|
|
9
|
+
var _constants = require("./constants");
|
|
10
|
+
const EVENT_TYPES = {
|
|
11
|
+
1: 'reset',
|
|
12
|
+
2: 'watchdog',
|
|
13
|
+
3: 'hard_fault',
|
|
14
|
+
4: 'storage',
|
|
15
|
+
5: 'power',
|
|
16
|
+
6: 'radio',
|
|
17
|
+
7: 'security'
|
|
18
|
+
};
|
|
19
|
+
const REASONS = {
|
|
20
|
+
1: 'watchdog_timeout',
|
|
21
|
+
2: 'cpu_illegal_instruction',
|
|
22
|
+
3: 'cpu_misaligned_access',
|
|
23
|
+
4: 'cpu_stack_overflow',
|
|
24
|
+
5: 'cpu_usage_fault',
|
|
25
|
+
6: 'memory_protection_fault',
|
|
26
|
+
7: 'invalid_register_read',
|
|
27
|
+
8: 'invalid_register_write',
|
|
28
|
+
9: 'audio_subsystem_fault',
|
|
29
|
+
10: 'wireless_subsystem_fault',
|
|
30
|
+
11: 'flash_mmu_fault',
|
|
31
|
+
12: 'low_voltage_reset',
|
|
32
|
+
255: 'unknown_cpu_exception'
|
|
33
|
+
};
|
|
34
|
+
const SUBSYSTEMS = {
|
|
35
|
+
0: 'system',
|
|
36
|
+
1: 'audio',
|
|
37
|
+
2: 'wireless',
|
|
38
|
+
3: 'storage',
|
|
39
|
+
4: 'power',
|
|
40
|
+
5: 'security'
|
|
41
|
+
};
|
|
42
|
+
const STATES = {
|
|
43
|
+
0: 'boot',
|
|
44
|
+
1: 'deep_standby',
|
|
45
|
+
2: 'recording',
|
|
46
|
+
3: 'upload_preparing',
|
|
47
|
+
4: 'uploading',
|
|
48
|
+
5: 'error_recovery',
|
|
49
|
+
6: 'full_sleep'
|
|
50
|
+
};
|
|
51
|
+
const BREADCRUMBS = {
|
|
52
|
+
1: 'boot',
|
|
53
|
+
2: 'standby_entered',
|
|
54
|
+
3: 'recording_started',
|
|
55
|
+
4: 'upload_preparing',
|
|
56
|
+
5: 'upload_started',
|
|
57
|
+
6: 'error_recovery',
|
|
58
|
+
7: 'full_sleep'
|
|
59
|
+
};
|
|
60
|
+
const DETAIL_WIRE_SIZE = 176;
|
|
61
|
+
function u64LeHex(bytes) {
|
|
62
|
+
return _buffer.Buffer.from(bytes).reverse().toString('hex').padStart(16, '0');
|
|
63
|
+
}
|
|
64
|
+
function diagnosticEventIdCommand(eventId) {
|
|
65
|
+
if (!/^[0-9a-f]{16}$/.test(eventId)) {
|
|
66
|
+
throw new Error('Diagnostic event_id must be 16 lowercase hex characters');
|
|
67
|
+
}
|
|
68
|
+
return _buffer.Buffer.concat([_buffer.Buffer.from([0x11]), _buffer.Buffer.from(eventId, 'hex').reverse()]);
|
|
69
|
+
}
|
|
70
|
+
function normalizedAddress(value) {
|
|
71
|
+
if (value === 0) return undefined;
|
|
72
|
+
const region = (value & 0x80000000) !== 0 ? 'sdram' : (value & 0x40000000) !== 0 ? 'ram' : 'rom';
|
|
73
|
+
const offset = (value & 0x3fffffff).toString(16).padStart(8, '0');
|
|
74
|
+
return `${region}:${offset}`;
|
|
75
|
+
}
|
|
76
|
+
function fixedHex32(value) {
|
|
77
|
+
return value.toString(16).padStart(8, '0');
|
|
78
|
+
}
|
|
79
|
+
function decodeDetail(bytes) {
|
|
80
|
+
if (bytes.length !== DETAIL_WIRE_SIZE || bytes[0] !== 1) {
|
|
81
|
+
throw new Error('Unsupported diagnostic detail payload');
|
|
82
|
+
}
|
|
83
|
+
const hasReport = (bytes[1] & 1) !== 0;
|
|
84
|
+
const firmwareBuildId = _buffer.Buffer.from(bytes.subarray(2, 14)).toString('ascii');
|
|
85
|
+
if (!/^[0-9a-f]{12}$/.test(firmwareBuildId)) {
|
|
86
|
+
throw new Error('Invalid diagnostic firmware build id');
|
|
87
|
+
}
|
|
88
|
+
const common = {
|
|
89
|
+
firmware_build_id: firmwareBuildId,
|
|
90
|
+
subsystem: SUBSYSTEMS[bytes[14]] ?? 'system',
|
|
91
|
+
state_before_event: STATES[bytes[15]] ?? 'unknown'
|
|
92
|
+
};
|
|
93
|
+
if (!hasReport) return common;
|
|
94
|
+
const pcCount = Math.min(bytes[17], 6);
|
|
95
|
+
const breadcrumbCount = Math.min(bytes[18], 8);
|
|
96
|
+
const runtimeMask = bytes[19];
|
|
97
|
+
const pcTrace = [];
|
|
98
|
+
for (let index = 0; index < pcCount; index++) {
|
|
99
|
+
const address = normalizedAddress(bytes.readUInt32LE(48 + index * 4));
|
|
100
|
+
if (address) pcTrace.push(address);
|
|
101
|
+
}
|
|
102
|
+
const task = _buffer.Buffer.from(bytes.subarray(80, 96)).toString('ascii').replace(/\0.*$/, '');
|
|
103
|
+
const breadcrumbs = [];
|
|
104
|
+
for (let index = 0; index < breadcrumbCount; index++) {
|
|
105
|
+
const offset = 96 + index * 10;
|
|
106
|
+
breadcrumbs.push({
|
|
107
|
+
delta_ms: bytes.readInt32LE(offset),
|
|
108
|
+
code: BREADCRUMBS[bytes.readUInt16LE(offset + 4)] ?? 'state_changed',
|
|
109
|
+
arg0: bytes.readInt32LE(offset + 6)
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
const reti = normalizedAddress(bytes.readUInt32LE(40));
|
|
113
|
+
const rets = normalizedAddress(bytes.readUInt32LE(44));
|
|
114
|
+
return {
|
|
115
|
+
...common,
|
|
116
|
+
report: {
|
|
117
|
+
fault: {
|
|
118
|
+
cpu_id: bytes[16],
|
|
119
|
+
cpu_emu: fixedHex32(bytes.readUInt32LE(20)),
|
|
120
|
+
core_emu: fixedHex32(bytes.readUInt32LE(24)),
|
|
121
|
+
hsb_emu: fixedHex32(bytes.readUInt32LE(28)),
|
|
122
|
+
audio_emu: fixedHex32(bytes.readUInt32LE(32)),
|
|
123
|
+
wireless_emu: fixedHex32(bytes.readUInt32LE(36))
|
|
124
|
+
},
|
|
125
|
+
execution: {
|
|
126
|
+
...(task ? {
|
|
127
|
+
task
|
|
128
|
+
} : {}),
|
|
129
|
+
...(reti ? {
|
|
130
|
+
reti
|
|
131
|
+
} : {}),
|
|
132
|
+
...(rets ? {
|
|
133
|
+
rets
|
|
134
|
+
} : {}),
|
|
135
|
+
pc_trace: pcTrace
|
|
136
|
+
},
|
|
137
|
+
...((runtimeMask & 3) !== 0 ? {
|
|
138
|
+
runtime: {
|
|
139
|
+
...((runtimeMask & 1) !== 0 ? {
|
|
140
|
+
heap_free_bytes: bytes.readUInt32LE(72)
|
|
141
|
+
} : {}),
|
|
142
|
+
...((runtimeMask & 2) !== 0 ? {
|
|
143
|
+
task_stack_remaining_bytes: bytes.readUInt32LE(76)
|
|
144
|
+
} : {})
|
|
145
|
+
}
|
|
146
|
+
} : {}),
|
|
147
|
+
...(breadcrumbs.length ? {
|
|
148
|
+
breadcrumbs
|
|
149
|
+
} : {})
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
class DeviceDiagnosticsDecoder {
|
|
154
|
+
events = new Map();
|
|
155
|
+
details = new Map();
|
|
156
|
+
push(packet) {
|
|
157
|
+
if (packet.length === 17 && packet[0] === _constants.DEVICE_DIAGNOSTICS_EVT_META) {
|
|
158
|
+
const type = EVENT_TYPES[packet[2]];
|
|
159
|
+
if (!type) return null;
|
|
160
|
+
this.events.set(packet[1], {
|
|
161
|
+
event_id: u64LeHex(packet.subarray(9, 17)),
|
|
162
|
+
event_type: type,
|
|
163
|
+
reason_code: REASONS[packet.readUInt16LE(3)] ?? 'unknown_cpu_exception',
|
|
164
|
+
uptime_ms: packet.readUInt32LE(5)
|
|
165
|
+
});
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
if (packet.length === 10 && packet[0] === _constants.DEVICE_DIAGNOSTICS_EVT_SIGNATURE) {
|
|
169
|
+
const event = this.events.get(packet[1]);
|
|
170
|
+
if (event) event.signature = u64LeHex(packet.subarray(2, 10));
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
if (packet.length >= 6 && packet.length <= 20 && packet[0] === _constants.DEVICE_DIAGNOSTICS_EVT_DETAIL) {
|
|
174
|
+
const index = packet[1];
|
|
175
|
+
const offset = packet.readUInt16LE(2);
|
|
176
|
+
const total = packet.readUInt16LE(4);
|
|
177
|
+
if (total !== DETAIL_WIRE_SIZE || offset + packet.length - 6 > total) {
|
|
178
|
+
this.reset();
|
|
179
|
+
throw new Error('Invalid diagnostic detail chunk');
|
|
180
|
+
}
|
|
181
|
+
let detail = this.details.get(index);
|
|
182
|
+
if (offset === 0) {
|
|
183
|
+
if (detail) {
|
|
184
|
+
this.reset();
|
|
185
|
+
throw new Error(`Duplicate diagnostic detail at index ${index}`);
|
|
186
|
+
}
|
|
187
|
+
detail = {
|
|
188
|
+
buffer: _buffer.Buffer.alloc(total),
|
|
189
|
+
received: 0
|
|
190
|
+
};
|
|
191
|
+
this.details.set(index, detail);
|
|
192
|
+
}
|
|
193
|
+
if (!detail || detail.received !== offset) {
|
|
194
|
+
this.reset();
|
|
195
|
+
throw new Error(`Out-of-order diagnostic detail at index ${index}`);
|
|
196
|
+
}
|
|
197
|
+
packet.copy(detail.buffer, offset, 6);
|
|
198
|
+
detail.received += packet.length - 6;
|
|
199
|
+
if (detail.received === total) {
|
|
200
|
+
const event = this.events.get(index);
|
|
201
|
+
if (!event) {
|
|
202
|
+
this.reset();
|
|
203
|
+
throw new Error(`Diagnostic detail without metadata at index ${index}`);
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
Object.assign(event, decodeDetail(detail.buffer));
|
|
207
|
+
} catch (error) {
|
|
208
|
+
this.reset();
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
if (packet.length === 2 && packet[0] === _constants.DEVICE_DIAGNOSTICS_EVT_END) {
|
|
215
|
+
const expected = packet[1];
|
|
216
|
+
const events = [];
|
|
217
|
+
for (let index = 0; index < expected; index++) {
|
|
218
|
+
const event = this.events.get(index);
|
|
219
|
+
if (!event?.signature || !event.firmware_build_id || !event.subsystem || !event.state_before_event || this.details.get(index)?.received !== DETAIL_WIRE_SIZE) {
|
|
220
|
+
this.reset();
|
|
221
|
+
throw new Error(`Incomplete diagnostic event at index ${index}`);
|
|
222
|
+
}
|
|
223
|
+
events.push(event);
|
|
224
|
+
}
|
|
225
|
+
const batch = {
|
|
226
|
+
schema_version: 1,
|
|
227
|
+
events
|
|
228
|
+
};
|
|
229
|
+
this.reset();
|
|
230
|
+
return batch;
|
|
231
|
+
}
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
reset() {
|
|
235
|
+
this.events.clear();
|
|
236
|
+
this.details.clear();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
exports.DeviceDiagnosticsDecoder = DeviceDiagnosticsDecoder;
|
|
240
|
+
//# sourceMappingURL=deviceDiagnostics.js.map
|