@bota.dev/react-native-app-sdk 2.0.0-beta.1 → 2.0.0-beta.10
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 +104 -4
- package/android/build.gradle +1 -0
- package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidDevices.kt +22 -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 +86 -3
- package/android/src/test/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidDevicesTest.kt +35 -0
- 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 +568 -8
- package/ios/BotaDeviceSDK.mm +114 -0
- package/ios/BotaDeviceSDKAppleBridge.swift +141 -4
- package/ios/BotaDeviceSDKAppleDevices.swift +11 -0
- 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 +16 -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 +183 -28
- package/lib/commonjs/client.js.map +1 -1
- package/lib/commonjs/clientPresence.js +26 -0
- package/lib/commonjs/clientPresence.js.map +1 -0
- package/lib/commonjs/index.js +29 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/managers/DeviceManager.js +23 -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/sdkIdentity.js +10 -0
- package/lib/commonjs/sdkIdentity.js.map +1 -0
- package/lib/commonjs/specs/NativeBotaDeviceSDK.js.map +1 -1
- package/lib/commonjs/uploadRecovery.js +68 -0
- package/lib/commonjs/uploadRecovery.js.map +1 -0
- package/lib/module/BotaClient.js +16 -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 +183 -28
- package/lib/module/client.js.map +1 -1
- package/lib/module/clientPresence.js +22 -0
- package/lib/module/clientPresence.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/managers/DeviceManager.js +23 -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/sdkIdentity.js +6 -0
- package/lib/module/sdkIdentity.js.map +1 -0
- package/lib/module/specs/NativeBotaDeviceSDK.js.map +1 -1
- package/lib/module/uploadRecovery.js +64 -0
- package/lib/module/uploadRecovery.js.map +1 -0
- package/lib/typescript/BotaClient.d.ts +2 -0
- 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 +24 -3
- package/lib/typescript/client.d.ts.map +1 -1
- package/lib/typescript/clientPresence.d.ts +26 -0
- package/lib/typescript/clientPresence.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +10 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/managers/DeviceManager.d.ts +5 -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/sdkIdentity.d.ts +3 -0
- package/lib/typescript/sdkIdentity.d.ts.map +1 -0
- package/lib/typescript/specs/NativeBotaDeviceSDK.d.ts +70 -0
- package/lib/typescript/specs/NativeBotaDeviceSDK.d.ts.map +1 -1
- package/lib/typescript/uploadRecovery.d.ts +27 -0
- package/lib/typescript/uploadRecovery.d.ts.map +1 -0
- package/package.json +1 -1
- package/scripts/bota_device_sdk_spm_workaround.rb +26 -15
- package/src/BotaClient.ts +17 -3
- package/src/ble/constants.ts +5 -0
- package/src/ble/deviceDiagnostics.ts +238 -0
- package/src/client.ts +189 -18
- package/src/clientPresence.ts +33 -0
- package/src/index.ts +18 -0
- package/src/managers/DeviceManager.ts +23 -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/sdkIdentity.ts +3 -0
- package/src/specs/NativeBotaDeviceSDK.ts +66 -0
- package/src/uploadRecovery.ts +66 -0
package/ios/BotaDeviceSDK.mm
CHANGED
|
@@ -569,6 +569,46 @@ RCT_EXPORT_MODULE(BotaDeviceSDK)
|
|
|
569
569
|
}];
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
+
- (void)listPendingRecordings:(JS::NativeBotaDeviceSDK::NativeConnectedDevice &)device
|
|
573
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
574
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
575
|
+
{
|
|
576
|
+
[[BotaDeviceSDKAppleBridge shared]
|
|
577
|
+
listPendingRecordingsWithID:device.id_()
|
|
578
|
+
serialNumber:device.serialNumber()
|
|
579
|
+
deviceType:device.deviceType()
|
|
580
|
+
firmwareVersion:device.firmwareVersion()
|
|
581
|
+
hardwareRevision:device.hardwareRevision()
|
|
582
|
+
isProvisioned:device.isProvisioned()
|
|
583
|
+
connectionState:device.connectionState()
|
|
584
|
+
mtu:device.mtu()
|
|
585
|
+
completion:^(NSArray<NSDictionary *> *_Nullable values, NSError *_Nullable error) {
|
|
586
|
+
if (error != nil) { BotaRejectEncryptedUploadV2Error(reject); return; }
|
|
587
|
+
resolve(values);
|
|
588
|
+
}];
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
- (void)cancelEncryptedRecordingV2:(NSString *)operationId
|
|
592
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
593
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
594
|
+
{
|
|
595
|
+
[[BotaDeviceSDKAppleBridge shared]
|
|
596
|
+
cancelEncryptedRecordingV2WithOperationID:operationId
|
|
597
|
+
completion:^(NSError *_Nullable error) {
|
|
598
|
+
if (error != nil) { BotaRejectEncryptedUploadV2Error(reject); return; }
|
|
599
|
+
resolve(nil);
|
|
600
|
+
}];
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
- (void)releaseEncryptedUploadV2Material:(NSString *)materialRegistrationId
|
|
604
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
605
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
606
|
+
{
|
|
607
|
+
[[BotaDeviceSDKAppleBridge shared]
|
|
608
|
+
releaseEncryptedUploadV2MaterialWithRegistrationID:materialRegistrationId
|
|
609
|
+
completion:^{ resolve(nil); }];
|
|
610
|
+
}
|
|
611
|
+
|
|
572
612
|
- (void)syncRecording:(JS::NativeBotaDeviceSDK::NativeConnectedDevice &)device
|
|
573
613
|
recording:(JS::NativeBotaDeviceSDK::NativeDeviceRecording &)recording
|
|
574
614
|
sinkId:(NSString *)sinkId
|
|
@@ -626,6 +666,10 @@ RCT_EXPORT_MODULE(BotaDeviceSDK)
|
|
|
626
666
|
generation:recording.generation()
|
|
627
667
|
ciphertextLength:recording.ciphertextLength()
|
|
628
668
|
ciphertextSHA256:recording.ciphertextSha256()
|
|
669
|
+
startedAtMs:recording.startedAtMs()
|
|
670
|
+
durationMs:recording.durationMs()
|
|
671
|
+
plaintextLength:recording.plaintextLength()
|
|
672
|
+
storageFormat:recording.storageFormat().has_value() ? @(recording.storageFormat().value()) : nil
|
|
629
673
|
operationID:operationId
|
|
630
674
|
onProfileRequest:^(NSDictionary *request) {
|
|
631
675
|
[weakSelf emitOnEncryptedUploadV2ProfileRequested:request];
|
|
@@ -807,6 +851,7 @@ RCT_EXPORT_MODULE(BotaDeviceSDK)
|
|
|
807
851
|
uploadRecordingFileWithTaskID:request.taskId()
|
|
808
852
|
recordingID:request.recordingId()
|
|
809
853
|
localPath:request.localPath()
|
|
854
|
+
fileSizeBytes:request.fileSizeBytes().has_value() ? @(request.fileSizeBytes().value()) : nil
|
|
810
855
|
uploadURL:request.uploadUrl()
|
|
811
856
|
uploadToken:request.uploadToken()
|
|
812
857
|
completeURL:request.completeUrl()
|
|
@@ -826,6 +871,23 @@ RCT_EXPORT_MODULE(BotaDeviceSDK)
|
|
|
826
871
|
}];
|
|
827
872
|
}
|
|
828
873
|
|
|
874
|
+
- (void)releaseRecordingFile:(NSString *)taskId
|
|
875
|
+
localPath:(NSString *)localPath
|
|
876
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
877
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
878
|
+
{
|
|
879
|
+
[[BotaDeviceSDKAppleBridge shared]
|
|
880
|
+
releaseRecordingFileWithTaskID:taskId
|
|
881
|
+
localPath:localPath
|
|
882
|
+
completion:^(NSError *error) {
|
|
883
|
+
if (error != nil) {
|
|
884
|
+
BotaRejectAppleError(error, reject);
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
resolve(nil);
|
|
888
|
+
}];
|
|
889
|
+
}
|
|
890
|
+
|
|
829
891
|
- (void)cancelRecordingUpload:(NSString *)taskId
|
|
830
892
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
831
893
|
reject:(__unused RCTPromiseRejectBlock)reject
|
|
@@ -966,6 +1028,46 @@ RCT_EXPORT_MODULE(BotaDeviceSDK)
|
|
|
966
1028
|
}];
|
|
967
1029
|
}
|
|
968
1030
|
|
|
1031
|
+
- (void)readDiagnosticEvents:(JS::NativeBotaDeviceSDK::NativeConnectedDevice &)device
|
|
1032
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
1033
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
1034
|
+
{
|
|
1035
|
+
[[BotaDeviceSDKAppleBridge shared]
|
|
1036
|
+
readDiagnosticEventsWithID:device.id_()
|
|
1037
|
+
serialNumber:device.serialNumber()
|
|
1038
|
+
deviceType:device.deviceType()
|
|
1039
|
+
firmwareVersion:device.firmwareVersion()
|
|
1040
|
+
hardwareRevision:device.hardwareRevision()
|
|
1041
|
+
isProvisioned:device.isProvisioned()
|
|
1042
|
+
connectionState:device.connectionState()
|
|
1043
|
+
mtu:device.mtu()
|
|
1044
|
+
completion:^(NSDictionary *_Nullable batch, NSError *_Nullable error) {
|
|
1045
|
+
if (error != nil) { BotaRejectAppleError(error, reject); return; }
|
|
1046
|
+
resolve(batch);
|
|
1047
|
+
}];
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
- (void)acknowledgeDiagnosticEvents:(JS::NativeBotaDeviceSDK::NativeConnectedDevice &)device
|
|
1051
|
+
acceptedEventIds:(NSArray *)acceptedEventIds
|
|
1052
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
1053
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
1054
|
+
{
|
|
1055
|
+
[[BotaDeviceSDKAppleBridge shared]
|
|
1056
|
+
acknowledgeDiagnosticEventsWithID:device.id_()
|
|
1057
|
+
serialNumber:device.serialNumber()
|
|
1058
|
+
deviceType:device.deviceType()
|
|
1059
|
+
firmwareVersion:device.firmwareVersion()
|
|
1060
|
+
hardwareRevision:device.hardwareRevision()
|
|
1061
|
+
isProvisioned:device.isProvisioned()
|
|
1062
|
+
connectionState:device.connectionState()
|
|
1063
|
+
mtu:device.mtu()
|
|
1064
|
+
acceptedEventIds:acceptedEventIds
|
|
1065
|
+
completion:^(NSError *_Nullable error) {
|
|
1066
|
+
if (error != nil) { BotaRejectAppleError(error, reject); return; }
|
|
1067
|
+
resolve(nil);
|
|
1068
|
+
}];
|
|
1069
|
+
}
|
|
1070
|
+
|
|
969
1071
|
- (void)stopDeviceLogs:(RCTPromiseResolveBlock)resolve
|
|
970
1072
|
reject:(__unused RCTPromiseRejectBlock)reject
|
|
971
1073
|
{
|
|
@@ -974,6 +1076,18 @@ RCT_EXPORT_MODULE(BotaDeviceSDK)
|
|
|
974
1076
|
}];
|
|
975
1077
|
}
|
|
976
1078
|
|
|
1079
|
+
- (void)nextClientPresence:(NSString *)deviceId resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
|
1080
|
+
{
|
|
1081
|
+
[[BotaDeviceSDKAppleBridge shared] nextClientPresenceWithDeviceID:deviceId
|
|
1082
|
+
completion:^(NSDictionary *_Nullable report, NSError *_Nullable error) {
|
|
1083
|
+
if (error != nil) {
|
|
1084
|
+
reject(@"client_presence_failed", error.localizedDescription, error);
|
|
1085
|
+
} else {
|
|
1086
|
+
resolve(report);
|
|
1087
|
+
}
|
|
1088
|
+
}];
|
|
1089
|
+
}
|
|
1090
|
+
|
|
977
1091
|
- (void)readStatus:(RCTPromiseResolveBlock)resolve
|
|
978
1092
|
reject:(RCTPromiseRejectBlock)reject
|
|
979
1093
|
{
|
|
@@ -801,6 +801,48 @@ public final class BotaDeviceSDKAppleBridge: NSObject, @unchecked Sendable {
|
|
|
801
801
|
}
|
|
802
802
|
}
|
|
803
803
|
|
|
804
|
+
@objc(listPendingRecordingsWithID:serialNumber:deviceType:firmwareVersion:hardwareRevision:isProvisioned:connectionState:mtu:completion:)
|
|
805
|
+
public func listPendingRecordings(
|
|
806
|
+
id: String, serialNumber: String, deviceType: String, firmwareVersion: String,
|
|
807
|
+
hardwareRevision: String?, isProvisioned: Bool, connectionState: String, mtu: Double,
|
|
808
|
+
completion: @escaping @Sendable ([[String: Any]]?, NSError?) -> Void
|
|
809
|
+
) {
|
|
810
|
+
Task {
|
|
811
|
+
do {
|
|
812
|
+
let values = try await recordings.listPendingRecordings(Self.connectedDevice(
|
|
813
|
+
id: id, serialNumber: serialNumber, deviceType: deviceType,
|
|
814
|
+
firmwareVersion: firmwareVersion, hardwareRevision: hardwareRevision,
|
|
815
|
+
isProvisioned: isProvisioned, connectionState: connectionState, mtu: mtu
|
|
816
|
+
))
|
|
817
|
+
completion(values.map { value in
|
|
818
|
+
switch value {
|
|
819
|
+
case let .legacy(recording):
|
|
820
|
+
["profile": "legacy", "legacy": Self.recording(recording)]
|
|
821
|
+
case let .encryptedV2(recording):
|
|
822
|
+
["profile": "encrypted_upload_v2", "encrypted": BotaDeviceSDKAppleRecordings.encryptedUploadV2Recording(recording)]
|
|
823
|
+
}
|
|
824
|
+
}, nil)
|
|
825
|
+
} catch { completion(nil, error as NSError) }
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
@objc(cancelEncryptedRecordingV2WithOperationID:completion:)
|
|
830
|
+
public func cancelEncryptedRecordingV2(
|
|
831
|
+
operationID: String, completion: @escaping @Sendable (NSError?) -> Void
|
|
832
|
+
) {
|
|
833
|
+
Task {
|
|
834
|
+
do { try await recordings.cancelEncryptedRecordingV2(operationID); completion(nil) }
|
|
835
|
+
catch { completion(error as NSError) }
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
@objc(releaseEncryptedUploadV2MaterialWithRegistrationID:completion:)
|
|
840
|
+
public func releaseEncryptedUploadV2Material(
|
|
841
|
+
registrationID: String, completion: @escaping @Sendable () -> Void
|
|
842
|
+
) {
|
|
843
|
+
Task { await BotaDeviceSDKEncryptedUploadV2Materials.release(registrationID); completion() }
|
|
844
|
+
}
|
|
845
|
+
|
|
804
846
|
@objc(syncRecordingWithID:serialNumber:deviceType:firmwareVersion:hardwareRevision:isProvisioned:connectionState:mtu:recordingUUID:startedAtMilliseconds:durationMilliseconds:fileSize:codec:isEncrypted:sinkID:onProgress:completion:)
|
|
805
847
|
public func syncRecording(
|
|
806
848
|
id: String,
|
|
@@ -855,6 +897,7 @@ public final class BotaDeviceSDKAppleBridge: NSObject, @unchecked Sendable {
|
|
|
855
897
|
var value: [String: Any] = [
|
|
856
898
|
"localPath": result.localPath,
|
|
857
899
|
"e2eEncrypted": result.isE2EEncrypted,
|
|
900
|
+
"fileSizeBytes": result.fileSizeBytes,
|
|
858
901
|
]
|
|
859
902
|
if let contentSHA256Hex = result.contentSHA256Hex {
|
|
860
903
|
value["contentSha256"] = contentSHA256Hex
|
|
@@ -866,7 +909,7 @@ public final class BotaDeviceSDKAppleBridge: NSObject, @unchecked Sendable {
|
|
|
866
909
|
}
|
|
867
910
|
}
|
|
868
911
|
|
|
869
|
-
@objc(syncEncryptedRecordingV2WithID:serialNumber:deviceType:firmwareVersion:hardwareRevision:isProvisioned:connectionState:mtu:recordingUUID:generation:ciphertextLength:ciphertextSHA256:operationID:onProfileRequest:onProgress:completion:)
|
|
912
|
+
@objc(syncEncryptedRecordingV2WithID:serialNumber:deviceType:firmwareVersion:hardwareRevision:isProvisioned:connectionState:mtu:recordingUUID:generation:ciphertextLength:ciphertextSHA256:startedAtMs:durationMs:plaintextLength:storageFormat:operationID:onProfileRequest:onProgress:completion:)
|
|
870
913
|
public func syncEncryptedRecordingV2(
|
|
871
914
|
id: String,
|
|
872
915
|
serialNumber: String,
|
|
@@ -880,6 +923,10 @@ public final class BotaDeviceSDKAppleBridge: NSObject, @unchecked Sendable {
|
|
|
880
923
|
generation: Double,
|
|
881
924
|
ciphertextLength: String,
|
|
882
925
|
ciphertextSHA256: String,
|
|
926
|
+
startedAtMs: String?,
|
|
927
|
+
durationMs: String?,
|
|
928
|
+
plaintextLength: String?,
|
|
929
|
+
storageFormat: NSNumber?,
|
|
883
930
|
operationID: String,
|
|
884
931
|
onProfileRequest: @escaping @Sendable ([String: Any]) -> Void,
|
|
885
932
|
onProgress: @escaping @Sendable ([String: Any]) -> Void,
|
|
@@ -895,6 +942,9 @@ public final class BotaDeviceSDKAppleBridge: NSObject, @unchecked Sendable {
|
|
|
895
942
|
throw BotaDeviceSDKAppleBridgeInputError.invalidUnsignedInteger
|
|
896
943
|
}
|
|
897
944
|
let digest = try Self.sha256Data(ciphertextSHA256)
|
|
945
|
+
guard let format = UInt8(exactly: try Self.unsignedInteger(storageFormat?.doubleValue ?? 3)) else {
|
|
946
|
+
throw BotaDeviceSDKAppleBridgeInputError.invalidUnsignedInteger
|
|
947
|
+
}
|
|
898
948
|
try await recordings.syncEncryptedRecordingV2(
|
|
899
949
|
Self.connectedDevice(
|
|
900
950
|
id: id,
|
|
@@ -910,7 +960,11 @@ public final class BotaDeviceSDKAppleBridge: NSObject, @unchecked Sendable {
|
|
|
910
960
|
uuid: recordingUUID,
|
|
911
961
|
generation: generationValue,
|
|
912
962
|
ciphertextLength: length,
|
|
913
|
-
ciphertextSHA256: digest
|
|
963
|
+
ciphertextSHA256: digest,
|
|
964
|
+
startedAtMs: try Self.catalogDecimal(startedAtMs),
|
|
965
|
+
durationMs: try Self.catalogDecimal(durationMs),
|
|
966
|
+
plaintextLength: try Self.catalogDecimal(plaintextLength),
|
|
967
|
+
storageFormat: format
|
|
914
968
|
),
|
|
915
969
|
operationID: operationID,
|
|
916
970
|
onProfileRequest: onProfileRequest,
|
|
@@ -923,6 +977,14 @@ public final class BotaDeviceSDKAppleBridge: NSObject, @unchecked Sendable {
|
|
|
923
977
|
}
|
|
924
978
|
}
|
|
925
979
|
|
|
980
|
+
private static func catalogDecimal(_ text: String?) throws -> UInt64 {
|
|
981
|
+
guard let text else { return 0 }
|
|
982
|
+
guard let value = UInt64(text), String(value) == text else {
|
|
983
|
+
throw BotaDeviceSDKAppleBridgeInputError.invalidUnsignedInteger
|
|
984
|
+
}
|
|
985
|
+
return value
|
|
986
|
+
}
|
|
987
|
+
|
|
926
988
|
@objc(resolveEncryptedUploadV2ProfileWithRequestID:profile:uploadSessionID:ownerRevision:securityPolicy:materialRegistrationID:completion:)
|
|
927
989
|
public func resolveEncryptedUploadV2Profile(
|
|
928
990
|
requestID: String,
|
|
@@ -1126,11 +1188,12 @@ public final class BotaDeviceSDKAppleBridge: NSObject, @unchecked Sendable {
|
|
|
1126
1188
|
}
|
|
1127
1189
|
}
|
|
1128
1190
|
|
|
1129
|
-
@objc(uploadRecordingFileWithTaskID:recordingID:localPath:uploadURL:uploadToken:completeURL:contentType:contentSHA256:relayURL:relayBearerToken:onProgress:completion:)
|
|
1191
|
+
@objc(uploadRecordingFileWithTaskID:recordingID:localPath:fileSizeBytes:uploadURL:uploadToken:completeURL:contentType:contentSHA256:relayURL:relayBearerToken:onProgress:completion:)
|
|
1130
1192
|
public func uploadRecordingFile(
|
|
1131
1193
|
taskID: String,
|
|
1132
1194
|
recordingID: String,
|
|
1133
1195
|
localPath: String,
|
|
1196
|
+
fileSizeBytes: NSNumber?,
|
|
1134
1197
|
uploadURL: String,
|
|
1135
1198
|
uploadToken: String?,
|
|
1136
1199
|
completeURL: String?,
|
|
@@ -1143,6 +1206,11 @@ public final class BotaDeviceSDKAppleBridge: NSObject, @unchecked Sendable {
|
|
|
1143
1206
|
) {
|
|
1144
1207
|
Task {
|
|
1145
1208
|
do {
|
|
1209
|
+
let expectedSize = try fileSizeBytes.map { value -> Int64 in
|
|
1210
|
+
let integer = try Self.unsignedInteger(value.doubleValue)
|
|
1211
|
+
guard integer <= UInt64(Int64.max) else { throw CocoaError(.fileReadCorruptFile) }
|
|
1212
|
+
return Int64(integer)
|
|
1213
|
+
}
|
|
1146
1214
|
try await recordingUploads.upload(.init(
|
|
1147
1215
|
taskID: taskID,
|
|
1148
1216
|
recordingID: recordingID,
|
|
@@ -1153,7 +1221,8 @@ public final class BotaDeviceSDKAppleBridge: NSObject, @unchecked Sendable {
|
|
|
1153
1221
|
contentType: contentType,
|
|
1154
1222
|
contentSHA256: contentSHA256,
|
|
1155
1223
|
relayURL: relayURL,
|
|
1156
|
-
relayBearerToken: relayBearerToken
|
|
1224
|
+
relayBearerToken: relayBearerToken,
|
|
1225
|
+
fileSizeBytes: expectedSize
|
|
1157
1226
|
)) { progress in
|
|
1158
1227
|
onProgress([
|
|
1159
1228
|
"taskId": progress.taskID,
|
|
@@ -1168,6 +1237,22 @@ public final class BotaDeviceSDKAppleBridge: NSObject, @unchecked Sendable {
|
|
|
1168
1237
|
}
|
|
1169
1238
|
}
|
|
1170
1239
|
|
|
1240
|
+
@objc(releaseRecordingFileWithTaskID:localPath:completion:)
|
|
1241
|
+
public func releaseRecordingFile(
|
|
1242
|
+
taskID: String,
|
|
1243
|
+
localPath: String,
|
|
1244
|
+
completion: @escaping @Sendable (NSError?) -> Void
|
|
1245
|
+
) {
|
|
1246
|
+
Task {
|
|
1247
|
+
do {
|
|
1248
|
+
try await recordingUploads.release(taskID: taskID, localPath: localPath)
|
|
1249
|
+
completion(nil)
|
|
1250
|
+
} catch {
|
|
1251
|
+
completion(error as NSError)
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1171
1256
|
@objc(cancelRecordingUploadWithTaskID:completion:)
|
|
1172
1257
|
public func cancelRecordingUpload(
|
|
1173
1258
|
taskID: String,
|
|
@@ -1359,6 +1444,43 @@ public final class BotaDeviceSDKAppleBridge: NSObject, @unchecked Sendable {
|
|
|
1359
1444
|
}
|
|
1360
1445
|
}
|
|
1361
1446
|
|
|
1447
|
+
@objc(readDiagnosticEventsWithID:serialNumber:deviceType:firmwareVersion:hardwareRevision:isProvisioned:connectionState:mtu:completion:)
|
|
1448
|
+
public func readDiagnosticEvents(
|
|
1449
|
+
id: String, serialNumber: String, deviceType: String, firmwareVersion: String,
|
|
1450
|
+
hardwareRevision: String?, isProvisioned: Bool, connectionState: String, mtu: Double,
|
|
1451
|
+
completion: @escaping @Sendable ([String: Any]?, NSError?) -> Void
|
|
1452
|
+
) {
|
|
1453
|
+
Task {
|
|
1454
|
+
do {
|
|
1455
|
+
let device = try Self.connectedDevice(
|
|
1456
|
+
id: id, serialNumber: serialNumber, deviceType: deviceType,
|
|
1457
|
+
firmwareVersion: firmwareVersion, hardwareRevision: hardwareRevision,
|
|
1458
|
+
isProvisioned: isProvisioned, connectionState: connectionState, mtu: mtu
|
|
1459
|
+
)
|
|
1460
|
+
completion(diagnosticBatchPayload(try await logs.readDiagnosticEvents(device)), nil)
|
|
1461
|
+
} catch { completion(nil, error as NSError) }
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
@objc(acknowledgeDiagnosticEventsWithID:serialNumber:deviceType:firmwareVersion:hardwareRevision:isProvisioned:connectionState:mtu:acceptedEventIds:completion:)
|
|
1466
|
+
public func acknowledgeDiagnosticEvents(
|
|
1467
|
+
id: String, serialNumber: String, deviceType: String, firmwareVersion: String,
|
|
1468
|
+
hardwareRevision: String?, isProvisioned: Bool, connectionState: String, mtu: Double,
|
|
1469
|
+
acceptedEventIds: [String], completion: @escaping @Sendable (NSError?) -> Void
|
|
1470
|
+
) {
|
|
1471
|
+
Task {
|
|
1472
|
+
do {
|
|
1473
|
+
let device = try Self.connectedDevice(
|
|
1474
|
+
id: id, serialNumber: serialNumber, deviceType: deviceType,
|
|
1475
|
+
firmwareVersion: firmwareVersion, hardwareRevision: hardwareRevision,
|
|
1476
|
+
isProvisioned: isProvisioned, connectionState: connectionState, mtu: mtu
|
|
1477
|
+
)
|
|
1478
|
+
try await logs.acknowledgeDiagnosticEvents(device, acceptedEventIds: acceptedEventIds)
|
|
1479
|
+
completion(nil)
|
|
1480
|
+
} catch { completion(error as NSError) }
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1362
1484
|
@objc(stopDeviceLogsWithCompletion:)
|
|
1363
1485
|
public func stopDeviceLogs(completion: @escaping @Sendable () -> Void) {
|
|
1364
1486
|
Task {
|
|
@@ -1367,6 +1489,21 @@ public final class BotaDeviceSDKAppleBridge: NSObject, @unchecked Sendable {
|
|
|
1367
1489
|
}
|
|
1368
1490
|
}
|
|
1369
1491
|
|
|
1492
|
+
@objc(nextClientPresenceWithDeviceID:completion:)
|
|
1493
|
+
public func nextClientPresence(deviceID: String, completion: @escaping @Sendable (NSDictionary?, NSError?) -> Void) {
|
|
1494
|
+
Task {
|
|
1495
|
+
do {
|
|
1496
|
+
guard let report = try await devices.nextClientPresence(deviceID: deviceID) else {
|
|
1497
|
+
completion(nil, nil)
|
|
1498
|
+
return
|
|
1499
|
+
}
|
|
1500
|
+
completion(["schemaVersion": report.schemaVersion, "sessionId": report.sessionID,
|
|
1501
|
+
"sequence": report.sequence, "platform": report.platform,
|
|
1502
|
+
"sdkPackage": report.sdkPackage, "sdkVersion": report.sdkVersion], nil)
|
|
1503
|
+
} catch { completion(nil, error as NSError) }
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1370
1507
|
@objc(readStatusWithCompletion:)
|
|
1371
1508
|
public func readStatus(
|
|
1372
1509
|
completion: @escaping @Sendable ([String: Any]?, NSError?) -> Void
|
|
@@ -14,14 +14,17 @@ protocol BotaDeviceSDKAppleDeviceClient: Sendable {
|
|
|
14
14
|
) async throws -> ConnectedDevice
|
|
15
15
|
func disconnect() async throws
|
|
16
16
|
func readStatus() async throws -> DeviceStatus
|
|
17
|
+
func nextClientPresence(deviceID: String) async throws -> SDKClientContext?
|
|
17
18
|
func statusUpdates() async throws -> AsyncThrowingStream<DeviceStatus, Error>
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
struct BotaDeviceSDKSharedAppleDeviceClient: BotaDeviceSDKAppleDeviceClient {
|
|
21
22
|
private let devices: DeviceManager
|
|
23
|
+
private let presence: ClientPresence
|
|
22
24
|
|
|
23
25
|
init(client: BotaDeviceClient = .shared) {
|
|
24
26
|
devices = client.devices
|
|
27
|
+
presence = client.clientPresence
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
func startScan(
|
|
@@ -57,6 +60,10 @@ struct BotaDeviceSDKSharedAppleDeviceClient: BotaDeviceSDKAppleDeviceClient {
|
|
|
57
60
|
try await devices.readStatus()
|
|
58
61
|
}
|
|
59
62
|
|
|
63
|
+
func nextClientPresence(deviceID: String) async throws -> SDKClientContext? {
|
|
64
|
+
try await presence.nextReport(deviceID: deviceID)
|
|
65
|
+
}
|
|
66
|
+
|
|
60
67
|
func statusUpdates() async throws -> AsyncThrowingStream<DeviceStatus, Error> {
|
|
61
68
|
try await devices.statusUpdates()
|
|
62
69
|
}
|
|
@@ -142,6 +149,10 @@ actor BotaDeviceSDKAppleDevices {
|
|
|
142
149
|
try await client.readStatus()
|
|
143
150
|
}
|
|
144
151
|
|
|
152
|
+
func nextClientPresence(deviceID: String) async throws -> SDKClientContext? {
|
|
153
|
+
try await client.nextClientPresence(deviceID: deviceID)
|
|
154
|
+
}
|
|
155
|
+
|
|
145
156
|
func startStatusUpdates(
|
|
146
157
|
onStatus: @escaping @Sendable (DeviceStatus) -> Void,
|
|
147
158
|
onError: @escaping @Sendable (Error) -> Void = { _ in }
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import BotaAppSDK
|
|
2
|
+
import Foundation
|
|
3
|
+
|
|
4
|
+
func diagnosticBatchPayload(_ batch: DeviceDiagnosticsBatch) -> [String: Any] {
|
|
5
|
+
["schema_version": batch.schemaVersion, "events": batch.events.map(diagnosticEventPayload)]
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
private func diagnosticEventPayload(_ event: DeviceDiagnosticEvent) -> [String: Any] {
|
|
9
|
+
var payload: [String: Any] = [
|
|
10
|
+
"event_id": event.eventId, "event_type": event.eventType,
|
|
11
|
+
"reason_code": event.reasonCode, "uptime_ms": event.uptimeMs,
|
|
12
|
+
"signature": event.signature, "firmware_build_id": event.firmwareBuildId,
|
|
13
|
+
"subsystem": event.subsystem, "state_before_event": event.stateBeforeEvent,
|
|
14
|
+
]
|
|
15
|
+
if let report = event.report {
|
|
16
|
+
var execution: [String: Any] = ["pc_trace": report.execution.pcTrace]
|
|
17
|
+
execution["task"] = report.execution.task
|
|
18
|
+
execution["reti"] = report.execution.reti
|
|
19
|
+
execution["rets"] = report.execution.rets
|
|
20
|
+
var value: [String: Any] = [
|
|
21
|
+
"fault": [
|
|
22
|
+
"cpu_id": report.fault.cpuId, "cpu_emu": report.fault.cpuEmu,
|
|
23
|
+
"core_emu": report.fault.coreEmu, "hsb_emu": report.fault.hsbEmu,
|
|
24
|
+
"audio_emu": report.fault.audioEmu, "wireless_emu": report.fault.wirelessEmu,
|
|
25
|
+
],
|
|
26
|
+
"execution": execution,
|
|
27
|
+
]
|
|
28
|
+
if let runtime = report.runtime {
|
|
29
|
+
var fields: [String: Any] = [:]
|
|
30
|
+
fields["heap_free_bytes"] = runtime.heapFreeBytes
|
|
31
|
+
fields["task_stack_remaining_bytes"] = runtime.taskStackRemainingBytes
|
|
32
|
+
value["runtime"] = fields
|
|
33
|
+
}
|
|
34
|
+
if let breadcrumbs = report.breadcrumbs {
|
|
35
|
+
value["breadcrumbs"] = breadcrumbs.map { ["delta_ms": $0.deltaMs, "code": $0.code, "arg0": $0.arg0] as [String: Any] }
|
|
36
|
+
}
|
|
37
|
+
payload["report"] = value
|
|
38
|
+
}
|
|
39
|
+
return payload
|
|
40
|
+
}
|
|
@@ -2,6 +2,8 @@ import BotaAppSDK
|
|
|
2
2
|
import Foundation
|
|
3
3
|
|
|
4
4
|
protocol BotaDeviceSDKAppleLogClient: Sendable {
|
|
5
|
+
func readDiagnosticEvents(_ device: ConnectedDevice) async throws -> DeviceDiagnosticsBatch
|
|
6
|
+
func acknowledgeDiagnosticEvents(_ device: ConnectedDevice, acceptedEventIds: [String]) async throws
|
|
5
7
|
func streamLogs(
|
|
6
8
|
_ device: ConnectedDevice
|
|
7
9
|
) async throws -> AsyncThrowingStream<DeviceLogLine, Error>
|
|
@@ -24,6 +26,14 @@ struct BotaDeviceSDKSharedAppleLogClient: BotaDeviceSDKAppleLogClient {
|
|
|
24
26
|
func stop() async throws {
|
|
25
27
|
try await logs.stop()
|
|
26
28
|
}
|
|
29
|
+
|
|
30
|
+
func readDiagnosticEvents(_ device: ConnectedDevice) async throws -> DeviceDiagnosticsBatch {
|
|
31
|
+
try await logs.readDiagnosticEvents(device)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
func acknowledgeDiagnosticEvents(_ device: ConnectedDevice, acceptedEventIds: [String]) async throws {
|
|
35
|
+
try await logs.acknowledgeDiagnosticEvents(device, acceptedEventIds: acceptedEventIds)
|
|
36
|
+
}
|
|
27
37
|
}
|
|
28
38
|
|
|
29
39
|
actor BotaDeviceSDKAppleLogs {
|
|
@@ -39,6 +49,14 @@ actor BotaDeviceSDKAppleLogs {
|
|
|
39
49
|
self.client = client
|
|
40
50
|
}
|
|
41
51
|
|
|
52
|
+
func readDiagnosticEvents(_ device: ConnectedDevice) async throws -> DeviceDiagnosticsBatch {
|
|
53
|
+
try await client.readDiagnosticEvents(device)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
func acknowledgeDiagnosticEvents(_ device: ConnectedDevice, acceptedEventIds: [String]) async throws {
|
|
57
|
+
try await client.acknowledgeDiagnosticEvents(device, acceptedEventIds: acceptedEventIds)
|
|
58
|
+
}
|
|
59
|
+
|
|
42
60
|
func start(
|
|
43
61
|
_ device: ConnectedDevice,
|
|
44
62
|
onLine: @escaping @Sendable (DeviceLogLine) -> Void,
|