@bota.dev/react-native-app-sdk 2.0.0-beta.0 → 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 -3
- 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
|
@@ -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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_buffer","require","_constants","EVENT_TYPES","REASONS","SUBSYSTEMS","STATES","BREADCRUMBS","DETAIL_WIRE_SIZE","u64LeHex","bytes","Buffer","from","reverse","toString","padStart","diagnosticEventIdCommand","eventId","test","Error","concat","normalizedAddress","value","undefined","region","offset","fixedHex32","decodeDetail","length","hasReport","firmwareBuildId","subarray","common","firmware_build_id","subsystem","state_before_event","pcCount","Math","min","breadcrumbCount","runtimeMask","pcTrace","index","address","readUInt32LE","push","task","replace","breadcrumbs","delta_ms","readInt32LE","code","readUInt16LE","arg0","reti","rets","report","fault","cpu_id","cpu_emu","core_emu","hsb_emu","audio_emu","wireless_emu","execution","pc_trace","runtime","heap_free_bytes","task_stack_remaining_bytes","DeviceDiagnosticsDecoder","events","Map","details","packet","DEVICE_DIAGNOSTICS_EVT_META","type","set","event_id","event_type","reason_code","uptime_ms","DEVICE_DIAGNOSTICS_EVT_SIGNATURE","event","get","signature","DEVICE_DIAGNOSTICS_EVT_DETAIL","total","reset","detail","buffer","alloc","received","copy","Object","assign","error","DEVICE_DIAGNOSTICS_EVT_END","expected","batch","schema_version","clear","exports"],"sourceRoot":"../../../src","sources":["ble/deviceDiagnostics.ts"],"mappings":"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","ignoreList":[]}
|
package/lib/commonjs/client.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.createBotaDeviceSDK = exports.BotaNativeModuleError = void 0;
|
|
7
|
+
var _sdkIdentity = require("./sdkIdentity");
|
|
7
8
|
var _runtime = require("./compatibility/runtime");
|
|
8
9
|
class BotaNativeModuleError extends Error {
|
|
9
10
|
code = 'native_module_unavailable';
|
|
@@ -13,12 +14,18 @@ class BotaNativeModuleError extends Error {
|
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
exports.BotaNativeModuleError = BotaNativeModuleError;
|
|
17
|
+
const formatAdvertisedMac = value => {
|
|
18
|
+
if (!value || !/^(?:[0-9a-f]{12}|(?:[0-9a-f]{2}:){5}[0-9a-f]{2})$/i.test(value)) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return value.replace(/:/g, '').toUpperCase().match(/.{2}/g).join(':');
|
|
22
|
+
};
|
|
16
23
|
const mapDiscoveredDevice = device => ({
|
|
17
24
|
id: device.id,
|
|
18
25
|
name: device.name ?? '',
|
|
19
26
|
deviceType: device.deviceType ?? 'bota_pin',
|
|
20
27
|
firmwareVersion: device.firmwareVersion ?? '',
|
|
21
|
-
macAddress: device.macAddress
|
|
28
|
+
macAddress: formatAdvertisedMac(device.macAddress),
|
|
22
29
|
pairingState: device.pairingState ?? 'unpaired',
|
|
23
30
|
rssi: device.rssi,
|
|
24
31
|
discoveredAt: new Date(device.discoveredAtMs)
|
|
@@ -58,6 +65,41 @@ const createOpaqueId = () => 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy
|
|
|
58
65
|
const nibble = value === 'x' ? random : random & 0x3 | 0x8;
|
|
59
66
|
return nibble.toString(16);
|
|
60
67
|
});
|
|
68
|
+
const catalogInteger = (value, maximum = BigInt(Number.MAX_SAFE_INTEGER)) => {
|
|
69
|
+
if (typeof value !== 'string' || !/^(0|[1-9][0-9]{0,19})$/.test(value) || BigInt(value) > maximum) {
|
|
70
|
+
throw new Error('invalid native recording catalog metadata');
|
|
71
|
+
}
|
|
72
|
+
return Number(value);
|
|
73
|
+
};
|
|
74
|
+
const mapPendingRecording = value => {
|
|
75
|
+
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
76
|
+
if (value.profile === 'legacy' && value.legacy && !value.encrypted) {
|
|
77
|
+
const recording = value.legacy;
|
|
78
|
+
if (typeof recording.uuid !== 'string' || !uuidPattern.test(recording.uuid) || !Number.isSafeInteger(recording.startedAtMs) || recording.startedAtMs < 0 || recording.startedAtMs > 8640000000000000 || !Number.isSafeInteger(recording.durationMs) || recording.durationMs < 0 || !Number.isSafeInteger(recording.fileSize) || recording.fileSize < 0 || typeof recording.codec !== 'string' || typeof recording.isEncrypted !== 'boolean') {
|
|
79
|
+
throw new Error('invalid native recording catalog metadata');
|
|
80
|
+
}
|
|
81
|
+
return mapRecording(recording);
|
|
82
|
+
}
|
|
83
|
+
if (value.profile !== 'encrypted_upload_v2' || !value.encrypted || value.legacy) {
|
|
84
|
+
throw new Error('invalid native recording catalog profile');
|
|
85
|
+
}
|
|
86
|
+
const recording = value.encrypted;
|
|
87
|
+
const plaintextLength = recording.plaintextLength;
|
|
88
|
+
if (typeof recording.uuid !== 'string' || !uuidPattern.test(recording.uuid) || recording.storageFormat !== 3 || typeof plaintextLength !== 'string' || !/^(0|[1-9][0-9]{0,19})$/.test(plaintextLength) || BigInt(plaintextLength) > 0xffffffffffffffffn || typeof recording.ciphertextLength !== 'string' || !/^[1-9][0-9]{0,19}$/.test(recording.ciphertextLength) || BigInt(recording.ciphertextLength) > 0xffffffffffffffffn || typeof recording.ciphertextSha256 !== 'string' || !/^[0-9a-f]{64}$/.test(recording.ciphertextSha256) || !Number.isInteger(recording.generation) || recording.generation < 0 || recording.generation > 0xffffffff) {
|
|
89
|
+
throw new Error('invalid native recording catalog identity');
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
uuid: recording.uuid,
|
|
93
|
+
generation: recording.generation,
|
|
94
|
+
ciphertextLength: recording.ciphertextLength,
|
|
95
|
+
ciphertextSha256: recording.ciphertextSha256,
|
|
96
|
+
storageFormat: 3,
|
|
97
|
+
plaintextLength,
|
|
98
|
+
startedAtMs: recording.startedAtMs,
|
|
99
|
+
startedAt: new Date(catalogInteger(recording.startedAtMs, 8640000000000000n)),
|
|
100
|
+
durationMs: catalogInteger(recording.durationMs)
|
|
101
|
+
};
|
|
102
|
+
};
|
|
61
103
|
const bytesToHex = value => Array.from(value, byte => byte.toString(16).padStart(2, '0')).join('');
|
|
62
104
|
const toNativeConnectionSettings = settings => ({
|
|
63
105
|
enabledConnections: settings.enabled_connections,
|
|
@@ -249,6 +291,9 @@ const toNativeRecordingUploadRequest = task => ({
|
|
|
249
291
|
recordingId: task.recordingId,
|
|
250
292
|
deviceId: task.deviceId,
|
|
251
293
|
localPath: task.localPath,
|
|
294
|
+
...(task.fileSizeBytes === undefined ? {} : {
|
|
295
|
+
fileSizeBytes: task.fileSizeBytes
|
|
296
|
+
}),
|
|
252
297
|
uploadUrl: task.uploadUrl,
|
|
253
298
|
...(task.uploadToken ? {
|
|
254
299
|
uploadToken: task.uploadToken
|
|
@@ -268,9 +313,12 @@ const toNativeRecordingUploadRequest = task => ({
|
|
|
268
313
|
} : {})
|
|
269
314
|
});
|
|
270
315
|
const parseUploadQueue = serialized => {
|
|
271
|
-
const value = JSON.parse(serialized
|
|
272
|
-
if (!Array.isArray(value))
|
|
316
|
+
const value = JSON.parse(serialized);
|
|
317
|
+
if (!Array.isArray(value)) throw new Error('Invalid upload recovery journal');
|
|
273
318
|
return value.map(task => {
|
|
319
|
+
if (!task || typeof task !== 'object' || Array.isArray(task) || typeof task.createdAt !== 'string' || typeof task.updatedAt !== 'string') {
|
|
320
|
+
throw new Error('Invalid upload recovery journal');
|
|
321
|
+
}
|
|
274
322
|
const candidate = task;
|
|
275
323
|
return {
|
|
276
324
|
...candidate,
|
|
@@ -280,6 +328,8 @@ const parseUploadQueue = serialized => {
|
|
|
280
328
|
});
|
|
281
329
|
};
|
|
282
330
|
const createBotaDeviceSDK = nativeModule => {
|
|
331
|
+
let presenceStopped = false;
|
|
332
|
+
let presenceGeneration = 0;
|
|
283
333
|
const requireNativeModule = () => {
|
|
284
334
|
if (!nativeModule) throw new BotaNativeModuleError();
|
|
285
335
|
return nativeModule;
|
|
@@ -499,6 +549,10 @@ const createBotaDeviceSDK = nativeModule => {
|
|
|
499
549
|
const values = await requireNativeModule().listRecordings(toNativeConnectedDevice(device));
|
|
500
550
|
return values.map(mapRecording);
|
|
501
551
|
},
|
|
552
|
+
async listPendingRecordings(device) {
|
|
553
|
+
const values = await requireNativeModule().listPendingRecordings(toNativeConnectedDevice(device));
|
|
554
|
+
return values.map(mapPendingRecording);
|
|
555
|
+
},
|
|
502
556
|
async syncRecording(device, recording, onProgress, sinkId) {
|
|
503
557
|
const module = requireNativeModule();
|
|
504
558
|
const subscription = module.onRecordingTransferProgress(progress => {
|
|
@@ -510,38 +564,83 @@ const createBotaDeviceSDK = nativeModule => {
|
|
|
510
564
|
subscription.remove();
|
|
511
565
|
}
|
|
512
566
|
},
|
|
513
|
-
async syncEncryptedRecordingV2(device, recording, provider, onProgress) {
|
|
567
|
+
async syncEncryptedRecordingV2(device, recording, provider, onProgress, options = {}) {
|
|
568
|
+
if (options.signal?.aborted) throw new Error('encrypted upload v2 cancelled');
|
|
514
569
|
const module = requireNativeModule();
|
|
515
|
-
const operationId = createOpaqueId();
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
570
|
+
const operationId = options.operationId ?? createOpaqueId();
|
|
571
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(operationId)) {
|
|
572
|
+
throw new Error('invalid encrypted upload v2 operation ID');
|
|
573
|
+
}
|
|
574
|
+
let active = true;
|
|
575
|
+
let nativeStarted = false;
|
|
576
|
+
let cancellation;
|
|
577
|
+
let cancellationFailed = false;
|
|
578
|
+
const cancel = () => {
|
|
579
|
+
if (nativeStarted && !cancellation) {
|
|
519
580
|
try {
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
capability: request.capability,
|
|
523
|
-
...(request.checkpoint === undefined ? {} : {
|
|
524
|
-
checkpoint: request.checkpoint
|
|
525
|
-
})
|
|
581
|
+
cancellation = module.cancelEncryptedRecordingV2(operationId).catch(() => {
|
|
582
|
+
cancellationFailed = true;
|
|
526
583
|
});
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
}
|
|
530
|
-
await module.resolveEncryptedUploadV2Profile(request.requestId, decision);
|
|
531
|
-
} catch (error) {
|
|
532
|
-
await module.rejectEncryptedUploadV2Profile(request.requestId, 'application_material_rejected');
|
|
584
|
+
} catch {
|
|
585
|
+
cancellationFailed = true;
|
|
533
586
|
}
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
onProgress?.(mapEncryptedUploadV2Progress(progress));
|
|
539
|
-
});
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
let profileSubscription;
|
|
590
|
+
let progressSubscription;
|
|
540
591
|
try {
|
|
592
|
+
options.signal?.addEventListener('abort', cancel, {
|
|
593
|
+
once: true
|
|
594
|
+
});
|
|
595
|
+
profileSubscription = module.onEncryptedUploadV2ProfileRequested(request => {
|
|
596
|
+
if (!active || options.signal?.aborted || request.operationId !== operationId) return;
|
|
597
|
+
void (async () => {
|
|
598
|
+
let decision;
|
|
599
|
+
try {
|
|
600
|
+
decision = await provider({
|
|
601
|
+
operationId,
|
|
602
|
+
recording: request.recording,
|
|
603
|
+
capability: request.capability,
|
|
604
|
+
...(request.checkpoint === undefined ? {} : {
|
|
605
|
+
checkpoint: request.checkpoint
|
|
606
|
+
})
|
|
607
|
+
});
|
|
608
|
+
if (!active || options.signal?.aborted) {
|
|
609
|
+
await module.releaseEncryptedUploadV2Material(decision.materialRegistrationId);
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
if (decision.profile !== 'encrypted_upload_v2') {
|
|
613
|
+
throw new Error('encrypted upload v2 requires an explicit v2 profile');
|
|
614
|
+
}
|
|
615
|
+
await module.resolveEncryptedUploadV2Profile(request.requestId, decision);
|
|
616
|
+
} catch (error) {
|
|
617
|
+
if (decision) await module.releaseEncryptedUploadV2Material(decision.materialRegistrationId).catch(() => {});
|
|
618
|
+
if (active && !options.signal?.aborted) {
|
|
619
|
+
await module.rejectEncryptedUploadV2Profile(request.requestId, 'application_material_rejected');
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
})().catch(() => {});
|
|
623
|
+
});
|
|
624
|
+
progressSubscription = module.onEncryptedUploadV2Progress(progress => {
|
|
625
|
+
if (!active || options.signal?.aborted || progress.operationId !== operationId) return;
|
|
626
|
+
onProgress?.(mapEncryptedUploadV2Progress(progress));
|
|
627
|
+
});
|
|
628
|
+
if (options.signal?.aborted) throw new Error('encrypted upload v2 cancelled');
|
|
629
|
+
nativeStarted = true;
|
|
541
630
|
await module.syncEncryptedRecordingV2(toNativeConnectedDevice(device), recording, operationId);
|
|
542
631
|
} finally {
|
|
543
|
-
|
|
544
|
-
|
|
632
|
+
active = false;
|
|
633
|
+
let cleanupFailed = false;
|
|
634
|
+
for (const remove of [() => options.signal?.removeEventListener('abort', cancel), () => profileSubscription?.remove(), () => progressSubscription?.remove()]) {
|
|
635
|
+
try {
|
|
636
|
+
remove();
|
|
637
|
+
} catch {
|
|
638
|
+
cleanupFailed = true;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
await cancellation;
|
|
642
|
+
if (cancellationFailed) throw new Error('encrypted upload v2 cancellation failed');
|
|
643
|
+
if (cleanupFailed) throw new Error('encrypted upload v2 listener cleanup failed');
|
|
545
644
|
}
|
|
546
645
|
},
|
|
547
646
|
async uploadRecordingFile(task, onProgress) {
|
|
@@ -565,6 +664,9 @@ const createBotaDeviceSDK = nativeModule => {
|
|
|
565
664
|
async cancelRecordingUpload(taskId) {
|
|
566
665
|
await requireNativeModule().cancelRecordingUpload(taskId);
|
|
567
666
|
},
|
|
667
|
+
async releaseRecordingFile(taskId, localPath) {
|
|
668
|
+
await requireNativeModule().releaseRecordingFile(taskId, localPath);
|
|
669
|
+
},
|
|
568
670
|
async loadUploadQueue() {
|
|
569
671
|
return parseUploadQueue(await requireNativeModule().loadCompatibilityUploadQueue());
|
|
570
672
|
},
|
|
@@ -647,6 +749,42 @@ const createBotaDeviceSDK = nativeModule => {
|
|
|
647
749
|
}
|
|
648
750
|
};
|
|
649
751
|
const logs = {
|
|
752
|
+
async readDiagnosticEvents(device) {
|
|
753
|
+
const batch = await requireNativeModule().readDiagnosticEvents(toNativeConnectedDevice(device));
|
|
754
|
+
if (batch.schema_version !== 1) throw new Error('Unsupported diagnostic batch schema');
|
|
755
|
+
return {
|
|
756
|
+
schema_version: 1,
|
|
757
|
+
events: batch.events.map(({
|
|
758
|
+
report,
|
|
759
|
+
...event
|
|
760
|
+
}) => ({
|
|
761
|
+
...event,
|
|
762
|
+
event_type: event.event_type,
|
|
763
|
+
reason_code: event.reason_code,
|
|
764
|
+
...(report ? {
|
|
765
|
+
report: {
|
|
766
|
+
fault: report.fault,
|
|
767
|
+
execution: {
|
|
768
|
+
...report.execution,
|
|
769
|
+
pc_trace: [...report.execution.pc_trace]
|
|
770
|
+
},
|
|
771
|
+
...(report.runtime ? {
|
|
772
|
+
runtime: report.runtime
|
|
773
|
+
} : {}),
|
|
774
|
+
...(report.breadcrumbs ? {
|
|
775
|
+
breadcrumbs: [...report.breadcrumbs]
|
|
776
|
+
} : {})
|
|
777
|
+
}
|
|
778
|
+
} : {})
|
|
779
|
+
}))
|
|
780
|
+
};
|
|
781
|
+
},
|
|
782
|
+
async acknowledgeDiagnosticEvents(device, acceptedEventIds) {
|
|
783
|
+
if (acceptedEventIds.some(id => !/^[0-9a-f]{16}$/.test(id))) {
|
|
784
|
+
throw new Error('Diagnostic event_id must be 16 lowercase hex characters');
|
|
785
|
+
}
|
|
786
|
+
await requireNativeModule().acknowledgeDiagnosticEvents(toNativeConnectedDevice(device), [...acceptedEventIds]);
|
|
787
|
+
},
|
|
650
788
|
async subscribe(device, onLine) {
|
|
651
789
|
const module = requireNativeModule();
|
|
652
790
|
const eventSubscription = module.onDeviceLog(line => {
|
|
@@ -709,6 +847,19 @@ const createBotaDeviceSDK = nativeModule => {
|
|
|
709
847
|
}
|
|
710
848
|
};
|
|
711
849
|
const client = {
|
|
850
|
+
clientPresence: {
|
|
851
|
+
async nextReport(deviceId) {
|
|
852
|
+
if (presenceStopped) return null;
|
|
853
|
+
const generation = presenceGeneration;
|
|
854
|
+
const report = await requireNativeModule().nextClientPresence(deviceId);
|
|
855
|
+
if (presenceStopped || generation !== presenceGeneration) return null;
|
|
856
|
+
return report === null ? null : {
|
|
857
|
+
...report,
|
|
858
|
+
sdkPackage: _sdkIdentity.SDK_PACKAGE,
|
|
859
|
+
sdkVersion: _sdkIdentity.SDK_VERSION
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
},
|
|
712
863
|
controls,
|
|
713
864
|
devices,
|
|
714
865
|
factoryReset,
|
|
@@ -719,6 +870,7 @@ const createBotaDeviceSDK = nativeModule => {
|
|
|
719
870
|
streaming,
|
|
720
871
|
wifi,
|
|
721
872
|
async configure(configuration = {}) {
|
|
873
|
+
const generation = presenceGeneration;
|
|
722
874
|
const nativeConfiguration = {
|
|
723
875
|
logLevel: configuration.logLevel ?? 'warn',
|
|
724
876
|
...(configuration.applicationSupportDirectory ? {
|
|
@@ -726,8 +878,11 @@ const createBotaDeviceSDK = nativeModule => {
|
|
|
726
878
|
} : {})
|
|
727
879
|
};
|
|
728
880
|
await requireNativeModule().configure(nativeConfiguration);
|
|
881
|
+
if (generation === presenceGeneration) presenceStopped = false;
|
|
729
882
|
},
|
|
730
883
|
async destroy() {
|
|
884
|
+
presenceStopped = true;
|
|
885
|
+
presenceGeneration++;
|
|
731
886
|
await requireNativeModule().destroy();
|
|
732
887
|
},
|
|
733
888
|
async getCapabilities() {
|