@bota-dev/react-native-sdk 0.0.2

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.
Files changed (177) hide show
  1. package/README.md +279 -0
  2. package/lib/commonjs/BotaClient.js +223 -0
  3. package/lib/commonjs/BotaClient.js.map +1 -0
  4. package/lib/commonjs/ble/BleManager.js +494 -0
  5. package/lib/commonjs/ble/BleManager.js.map +1 -0
  6. package/lib/commonjs/ble/constants.js +166 -0
  7. package/lib/commonjs/ble/constants.js.map +1 -0
  8. package/lib/commonjs/ble/index.js +54 -0
  9. package/lib/commonjs/ble/index.js.map +1 -0
  10. package/lib/commonjs/ble/parsers.js +345 -0
  11. package/lib/commonjs/ble/parsers.js.map +1 -0
  12. package/lib/commonjs/index.js +81 -0
  13. package/lib/commonjs/index.js.map +1 -0
  14. package/lib/commonjs/managers/DeviceManager.js +437 -0
  15. package/lib/commonjs/managers/DeviceManager.js.map +1 -0
  16. package/lib/commonjs/managers/OTAManager.js +227 -0
  17. package/lib/commonjs/managers/OTAManager.js.map +1 -0
  18. package/lib/commonjs/managers/RecordingManager.js +384 -0
  19. package/lib/commonjs/managers/RecordingManager.js.map +1 -0
  20. package/lib/commonjs/managers/index.js +27 -0
  21. package/lib/commonjs/managers/index.js.map +1 -0
  22. package/lib/commonjs/models/Device.js +2 -0
  23. package/lib/commonjs/models/Device.js.map +1 -0
  24. package/lib/commonjs/models/Recording.js +2 -0
  25. package/lib/commonjs/models/Recording.js.map +1 -0
  26. package/lib/commonjs/models/Status.js +6 -0
  27. package/lib/commonjs/models/Status.js.map +1 -0
  28. package/lib/commonjs/models/index.js +39 -0
  29. package/lib/commonjs/models/index.js.map +1 -0
  30. package/lib/commonjs/protocol/ProtocolHandler.js +343 -0
  31. package/lib/commonjs/protocol/ProtocolHandler.js.map +1 -0
  32. package/lib/commonjs/protocol/index.js +13 -0
  33. package/lib/commonjs/protocol/index.js.map +1 -0
  34. package/lib/commonjs/storage/StorageManager.js +333 -0
  35. package/lib/commonjs/storage/StorageManager.js.map +1 -0
  36. package/lib/commonjs/storage/index.js +19 -0
  37. package/lib/commonjs/storage/index.js.map +1 -0
  38. package/lib/commonjs/upload/S3Uploader.js +133 -0
  39. package/lib/commonjs/upload/S3Uploader.js.map +1 -0
  40. package/lib/commonjs/upload/UploadQueue.js +280 -0
  41. package/lib/commonjs/upload/UploadQueue.js.map +1 -0
  42. package/lib/commonjs/upload/index.js +20 -0
  43. package/lib/commonjs/upload/index.js.map +1 -0
  44. package/lib/commonjs/utils/errors.js +187 -0
  45. package/lib/commonjs/utils/errors.js.map +1 -0
  46. package/lib/commonjs/utils/index.js +40 -0
  47. package/lib/commonjs/utils/index.js.map +1 -0
  48. package/lib/commonjs/utils/logger.js +135 -0
  49. package/lib/commonjs/utils/logger.js.map +1 -0
  50. package/lib/commonjs/utils/retry.js +160 -0
  51. package/lib/commonjs/utils/retry.js.map +1 -0
  52. package/lib/module/BotaClient.js +216 -0
  53. package/lib/module/BotaClient.js.map +1 -0
  54. package/lib/module/ble/BleManager.js +484 -0
  55. package/lib/module/ble/BleManager.js.map +1 -0
  56. package/lib/module/ble/constants.js +159 -0
  57. package/lib/module/ble/constants.js.map +1 -0
  58. package/lib/module/ble/index.js +8 -0
  59. package/lib/module/ble/index.js.map +1 -0
  60. package/lib/module/ble/parsers.js +328 -0
  61. package/lib/module/ble/parsers.js.map +1 -0
  62. package/lib/module/index.js +22 -0
  63. package/lib/module/index.js.map +1 -0
  64. package/lib/module/managers/DeviceManager.js +429 -0
  65. package/lib/module/managers/DeviceManager.js.map +1 -0
  66. package/lib/module/managers/OTAManager.js +219 -0
  67. package/lib/module/managers/OTAManager.js.map +1 -0
  68. package/lib/module/managers/RecordingManager.js +376 -0
  69. package/lib/module/managers/RecordingManager.js.map +1 -0
  70. package/lib/module/managers/index.js +8 -0
  71. package/lib/module/managers/index.js.map +1 -0
  72. package/lib/module/models/Device.js +2 -0
  73. package/lib/module/models/Device.js.map +1 -0
  74. package/lib/module/models/Recording.js +2 -0
  75. package/lib/module/models/Recording.js.map +1 -0
  76. package/lib/module/models/Status.js +2 -0
  77. package/lib/module/models/Status.js.map +1 -0
  78. package/lib/module/models/index.js +8 -0
  79. package/lib/module/models/index.js.map +1 -0
  80. package/lib/module/protocol/ProtocolHandler.js +336 -0
  81. package/lib/module/protocol/ProtocolHandler.js.map +1 -0
  82. package/lib/module/protocol/index.js +6 -0
  83. package/lib/module/protocol/index.js.map +1 -0
  84. package/lib/module/storage/StorageManager.js +324 -0
  85. package/lib/module/storage/StorageManager.js.map +1 -0
  86. package/lib/module/storage/index.js +6 -0
  87. package/lib/module/storage/index.js.map +1 -0
  88. package/lib/module/upload/S3Uploader.js +126 -0
  89. package/lib/module/upload/S3Uploader.js.map +1 -0
  90. package/lib/module/upload/UploadQueue.js +272 -0
  91. package/lib/module/upload/UploadQueue.js.map +1 -0
  92. package/lib/module/upload/index.js +7 -0
  93. package/lib/module/upload/index.js.map +1 -0
  94. package/lib/module/utils/errors.js +173 -0
  95. package/lib/module/utils/errors.js.map +1 -0
  96. package/lib/module/utils/index.js +8 -0
  97. package/lib/module/utils/index.js.map +1 -0
  98. package/lib/module/utils/logger.js +129 -0
  99. package/lib/module/utils/logger.js.map +1 -0
  100. package/lib/module/utils/retry.js +149 -0
  101. package/lib/module/utils/retry.js.map +1 -0
  102. package/lib/typescript/src/BotaClient.d.ts +77 -0
  103. package/lib/typescript/src/BotaClient.d.ts.map +1 -0
  104. package/lib/typescript/src/ble/BleManager.d.ts +111 -0
  105. package/lib/typescript/src/ble/BleManager.d.ts.map +1 -0
  106. package/lib/typescript/src/ble/constants.d.ts +111 -0
  107. package/lib/typescript/src/ble/constants.d.ts.map +1 -0
  108. package/lib/typescript/src/ble/index.d.ts +7 -0
  109. package/lib/typescript/src/ble/index.d.ts.map +1 -0
  110. package/lib/typescript/src/ble/parsers.d.ts +100 -0
  111. package/lib/typescript/src/ble/parsers.d.ts.map +1 -0
  112. package/lib/typescript/src/index.d.ts +16 -0
  113. package/lib/typescript/src/index.d.ts.map +1 -0
  114. package/lib/typescript/src/managers/DeviceManager.d.ts +84 -0
  115. package/lib/typescript/src/managers/DeviceManager.d.ts.map +1 -0
  116. package/lib/typescript/src/managers/OTAManager.d.ts +78 -0
  117. package/lib/typescript/src/managers/OTAManager.d.ts.map +1 -0
  118. package/lib/typescript/src/managers/RecordingManager.d.ts +90 -0
  119. package/lib/typescript/src/managers/RecordingManager.d.ts.map +1 -0
  120. package/lib/typescript/src/managers/index.d.ts +7 -0
  121. package/lib/typescript/src/managers/index.d.ts.map +1 -0
  122. package/lib/typescript/src/models/Device.d.ts +139 -0
  123. package/lib/typescript/src/models/Device.d.ts.map +1 -0
  124. package/lib/typescript/src/models/Recording.d.ts +110 -0
  125. package/lib/typescript/src/models/Recording.d.ts.map +1 -0
  126. package/lib/typescript/src/models/Status.d.ts +104 -0
  127. package/lib/typescript/src/models/Status.d.ts.map +1 -0
  128. package/lib/typescript/src/models/index.d.ts +7 -0
  129. package/lib/typescript/src/models/index.d.ts.map +1 -0
  130. package/lib/typescript/src/protocol/ProtocolHandler.d.ts +69 -0
  131. package/lib/typescript/src/protocol/ProtocolHandler.d.ts.map +1 -0
  132. package/lib/typescript/src/protocol/index.d.ts +5 -0
  133. package/lib/typescript/src/protocol/index.d.ts.map +1 -0
  134. package/lib/typescript/src/storage/StorageManager.d.ts +116 -0
  135. package/lib/typescript/src/storage/StorageManager.d.ts.map +1 -0
  136. package/lib/typescript/src/storage/index.d.ts +5 -0
  137. package/lib/typescript/src/storage/index.d.ts.map +1 -0
  138. package/lib/typescript/src/upload/S3Uploader.d.ts +38 -0
  139. package/lib/typescript/src/upload/S3Uploader.d.ts.map +1 -0
  140. package/lib/typescript/src/upload/UploadQueue.d.ts +95 -0
  141. package/lib/typescript/src/upload/UploadQueue.d.ts.map +1 -0
  142. package/lib/typescript/src/upload/index.d.ts +6 -0
  143. package/lib/typescript/src/upload/index.d.ts.map +1 -0
  144. package/lib/typescript/src/utils/errors.d.ts +82 -0
  145. package/lib/typescript/src/utils/errors.d.ts.map +1 -0
  146. package/lib/typescript/src/utils/index.d.ts +7 -0
  147. package/lib/typescript/src/utils/index.d.ts.map +1 -0
  148. package/lib/typescript/src/utils/logger.d.ts +68 -0
  149. package/lib/typescript/src/utils/logger.d.ts.map +1 -0
  150. package/lib/typescript/src/utils/retry.d.ts +53 -0
  151. package/lib/typescript/src/utils/retry.d.ts.map +1 -0
  152. package/package.json +95 -0
  153. package/src/BotaClient.ts +238 -0
  154. package/src/ble/BleManager.ts +573 -0
  155. package/src/ble/constants.ts +158 -0
  156. package/src/ble/index.ts +7 -0
  157. package/src/ble/parsers.ts +395 -0
  158. package/src/index.ts +64 -0
  159. package/src/managers/DeviceManager.ts +545 -0
  160. package/src/managers/OTAManager.ts +263 -0
  161. package/src/managers/RecordingManager.ts +434 -0
  162. package/src/managers/index.ts +12 -0
  163. package/src/models/Device.ts +164 -0
  164. package/src/models/Recording.ts +123 -0
  165. package/src/models/Status.ts +126 -0
  166. package/src/models/index.ts +7 -0
  167. package/src/protocol/ProtocolHandler.ts +459 -0
  168. package/src/protocol/index.ts +5 -0
  169. package/src/storage/StorageManager.ts +343 -0
  170. package/src/storage/index.ts +5 -0
  171. package/src/upload/S3Uploader.ts +164 -0
  172. package/src/upload/UploadQueue.ts +310 -0
  173. package/src/upload/index.ts +6 -0
  174. package/src/utils/errors.ts +310 -0
  175. package/src/utils/index.ts +7 -0
  176. package/src/utils/logger.ts +137 -0
  177. package/src/utils/retry.ts +177 -0
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Protocol Handler - Implements Device-App Protocol for recording transfer
3
+ */
4
+
5
+ import { Buffer } from 'buffer';
6
+ import { getBleManager } from '../ble/BleManager';
7
+ import { SERVICE_BOTA_STORAGE, CHAR_STORAGE_INFO, CHAR_RECORDING_LIST, CHAR_RECORDING_TRANSFER, CHAR_TRANSFER_CONTROL, TRANSFER_PACKET_TIMEOUT } from '../ble/constants';
8
+ import { parseStorageInfo, parseRecordingList, parseTransferPacket, createAckPacket, createTransferCommand } from '../ble/parsers';
9
+ import { TransferError, DeviceError } from '../utils/errors';
10
+ import { logger } from '../utils/logger';
11
+ const log = logger.tag('ProtocolHandler');
12
+
13
+ /**
14
+ * Transfer state for tracking ongoing transfers
15
+ */
16
+
17
+ /**
18
+ * Transfer progress callback
19
+ */
20
+
21
+ /**
22
+ * Protocol Handler class
23
+ */
24
+ export class ProtocolHandler {
25
+ activeTransfers = new Map();
26
+ constructor() {
27
+ this.bleManager = getBleManager();
28
+ }
29
+
30
+ /**
31
+ * Get storage info from device
32
+ */
33
+ async getStorageInfo(deviceId) {
34
+ if (!this.bleManager.isConnected(deviceId)) {
35
+ throw DeviceError.notConnected(deviceId);
36
+ }
37
+ const data = await this.bleManager.readCharacteristic(deviceId, SERVICE_BOTA_STORAGE, CHAR_STORAGE_INFO);
38
+ return parseStorageInfo(data);
39
+ }
40
+
41
+ /**
42
+ * List recordings on device
43
+ */
44
+ async listRecordings(deviceId) {
45
+ if (!this.bleManager.isConnected(deviceId)) {
46
+ throw DeviceError.notConnected(deviceId);
47
+ }
48
+ log.debug('Listing recordings', {
49
+ deviceId
50
+ });
51
+ return new Promise((resolve, reject) => {
52
+ let recordings = [];
53
+ let subscription;
54
+ let timeoutId;
55
+ const cleanup = () => {
56
+ if (timeoutId) clearTimeout(timeoutId);
57
+ subscription?.remove();
58
+ };
59
+
60
+ // Set up timeout
61
+ timeoutId = setTimeout(() => {
62
+ cleanup();
63
+ // If we received some data, return it; otherwise error
64
+ if (recordings.length > 0) {
65
+ resolve(recordings);
66
+ } else {
67
+ reject(new TransferError('Timeout waiting for recording list', 'LIST_TIMEOUT'));
68
+ }
69
+ }, 5000);
70
+
71
+ // Subscribe to recording list notifications
72
+ subscription = this.bleManager.subscribeToCharacteristic(deviceId, SERVICE_BOTA_STORAGE, CHAR_RECORDING_LIST, data => {
73
+ try {
74
+ const parsed = parseRecordingList(data);
75
+ recordings = recordings.concat(parsed);
76
+
77
+ // Check if this is the last packet (could check for end marker)
78
+ // For now, wait for timeout or explicit end
79
+ } catch (error) {
80
+ log.error('Failed to parse recording list', error);
81
+ }
82
+ }, error => {
83
+ cleanup();
84
+ reject(error);
85
+ });
86
+
87
+ // Send list command
88
+ const command = createTransferCommand('list');
89
+ this.bleManager.writeCharacteristic(deviceId, SERVICE_BOTA_STORAGE, CHAR_TRANSFER_CONTROL, command).catch(error => {
90
+ cleanup();
91
+ reject(error);
92
+ });
93
+ });
94
+ }
95
+
96
+ /**
97
+ * Transfer a recording from device
98
+ * Returns the audio data as a Buffer
99
+ */
100
+ async transferRecording(deviceId, recordingUuid, onProgress) {
101
+ if (!this.bleManager.isConnected(deviceId)) {
102
+ throw DeviceError.notConnected(deviceId);
103
+ }
104
+
105
+ // Check if transfer already in progress
106
+ if (this.activeTransfers.has(recordingUuid)) {
107
+ throw new TransferError('Transfer already in progress for this recording', 'TRANSFER_IN_PROGRESS', recordingUuid);
108
+ }
109
+ log.info('Starting recording transfer', {
110
+ deviceId,
111
+ recordingUuid
112
+ });
113
+ return new Promise((resolve, reject) => {
114
+ const state = {
115
+ recordingUuid,
116
+ expectedSequence: 0,
117
+ receivedPackets: new Map(),
118
+ totalBytes: 0,
119
+ isComplete: false
120
+ };
121
+ this.activeTransfers.set(recordingUuid, state);
122
+ const cleanup = () => {
123
+ if (state.timeoutId) clearTimeout(state.timeoutId);
124
+ state.subscription?.remove();
125
+ this.activeTransfers.delete(recordingUuid);
126
+ };
127
+ const resetTimeout = () => {
128
+ if (state.timeoutId) clearTimeout(state.timeoutId);
129
+ state.timeoutId = setTimeout(() => {
130
+ cleanup();
131
+ reject(TransferError.timeout(recordingUuid));
132
+ }, TRANSFER_PACKET_TIMEOUT);
133
+ };
134
+
135
+ // Subscribe to transfer data notifications
136
+ state.subscription = this.bleManager.subscribeToCharacteristic(deviceId, SERVICE_BOTA_STORAGE, CHAR_RECORDING_TRANSFER, async data => {
137
+ try {
138
+ resetTimeout();
139
+ const packet = parseTransferPacket(data);
140
+ await this.handleTransferPacket(deviceId, state, packet, onProgress);
141
+ if (state.isComplete) {
142
+ cleanup();
143
+
144
+ // Assemble the audio data
145
+ const audioData = this.assembleAudioData(state);
146
+
147
+ // Verify checksum if available
148
+ if (state.checksum !== undefined) {
149
+ const calculatedChecksum = this.calculateCrc32(audioData);
150
+ if (calculatedChecksum !== state.checksum) {
151
+ reject(TransferError.checksumMismatch(recordingUuid));
152
+ return;
153
+ }
154
+ }
155
+ log.info('Transfer completed', {
156
+ recordingUuid,
157
+ size: audioData.length
158
+ });
159
+ resolve(audioData);
160
+ }
161
+ } catch (error) {
162
+ cleanup();
163
+ reject(error);
164
+ }
165
+ }, error => {
166
+ cleanup();
167
+ reject(TransferError.interrupted(recordingUuid, error));
168
+ });
169
+
170
+ // Send start transfer command
171
+ const command = createTransferCommand('start', recordingUuid);
172
+ this.bleManager.writeCharacteristic(deviceId, SERVICE_BOTA_STORAGE, CHAR_TRANSFER_CONTROL, command).then(() => {
173
+ resetTimeout();
174
+ }).catch(error => {
175
+ cleanup();
176
+ reject(error);
177
+ });
178
+ });
179
+ }
180
+
181
+ /**
182
+ * Handle a transfer packet from device
183
+ */
184
+ async handleTransferPacket(deviceId, state, packet, onProgress) {
185
+ switch (packet.type) {
186
+ case 'data':
187
+ if (packet.data) {
188
+ // Store packet data
189
+ state.receivedPackets.set(packet.sequenceNumber, Buffer.from(packet.data));
190
+ state.totalBytes += packet.data.length;
191
+
192
+ // Send ACK
193
+ await this.sendAck(deviceId, 'ack', packet.sequenceNumber);
194
+
195
+ // Report progress
196
+ onProgress?.(state.totalBytes);
197
+ log.debug('Received data packet', {
198
+ seq: packet.sequenceNumber,
199
+ size: packet.data.length,
200
+ total: state.totalBytes
201
+ });
202
+ }
203
+ break;
204
+ case 'eof':
205
+ state.checksum = packet.checksum;
206
+ state.isComplete = true;
207
+
208
+ // Send final ACK
209
+ await this.sendAck(deviceId, 'ack', packet.sequenceNumber);
210
+ log.debug('Received EOF packet', {
211
+ seq: packet.sequenceNumber,
212
+ checksum: packet.checksum
213
+ });
214
+ break;
215
+ case 'error':
216
+ throw TransferError.deviceError(state.recordingUuid, packet.errorCode ?? 0xff);
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Send an ACK packet to device
222
+ */
223
+ async sendAck(deviceId, type, sequenceNumber) {
224
+ const ackPacket = createAckPacket(type, sequenceNumber);
225
+ await this.bleManager.writeCharacteristic(deviceId, SERVICE_BOTA_STORAGE, CHAR_RECORDING_TRANSFER, ackPacket, false // Write without response for speed
226
+ );
227
+ }
228
+
229
+ /**
230
+ * Assemble audio data from received packets
231
+ */
232
+ assembleAudioData(state) {
233
+ // Sort packets by sequence number and concatenate
234
+ const sortedSequences = Array.from(state.receivedPackets.keys()).sort((a, b) => a - b);
235
+ const chunks = [];
236
+ for (const seq of sortedSequences) {
237
+ const data = state.receivedPackets.get(seq);
238
+ if (data) {
239
+ chunks.push(data);
240
+ }
241
+ }
242
+ return Buffer.concat(chunks);
243
+ }
244
+
245
+ /**
246
+ * Calculate CRC32 checksum
247
+ */
248
+ calculateCrc32(data) {
249
+ let crc = 0xffffffff;
250
+ const table = this.getCrc32Table();
251
+ for (let i = 0; i < data.length; i++) {
252
+ crc = crc >>> 8 ^ table[(crc ^ data[i]) & 0xff];
253
+ }
254
+ return (crc ^ 0xffffffff) >>> 0;
255
+ }
256
+
257
+ /**
258
+ * Get CRC32 lookup table (lazy initialized)
259
+ */
260
+ crc32Table = null;
261
+ getCrc32Table() {
262
+ if (this.crc32Table) {
263
+ return this.crc32Table;
264
+ }
265
+ const table = [];
266
+ for (let i = 0; i < 256; i++) {
267
+ let crc = i;
268
+ for (let j = 0; j < 8; j++) {
269
+ crc = crc & 1 ? crc >>> 1 ^ 0xedb88320 : crc >>> 1;
270
+ }
271
+ table.push(crc >>> 0);
272
+ }
273
+ this.crc32Table = table;
274
+ return table;
275
+ }
276
+
277
+ /**
278
+ * Confirm sync to device (allows device to delete local copy)
279
+ */
280
+ async confirmSync(deviceId, recordingUuid) {
281
+ if (!this.bleManager.isConnected(deviceId)) {
282
+ throw DeviceError.notConnected(deviceId);
283
+ }
284
+ log.debug('Confirming sync', {
285
+ deviceId,
286
+ recordingUuid
287
+ });
288
+ const command = createTransferCommand('confirm', recordingUuid);
289
+ await this.bleManager.writeCharacteristic(deviceId, SERVICE_BOTA_STORAGE, CHAR_TRANSFER_CONTROL, command);
290
+ }
291
+
292
+ /**
293
+ * Cancel an ongoing transfer
294
+ */
295
+ async cancelTransfer(deviceId, recordingUuid) {
296
+ const state = this.activeTransfers.get(recordingUuid);
297
+ if (!state) {
298
+ return;
299
+ }
300
+ log.info('Cancelling transfer', {
301
+ recordingUuid
302
+ });
303
+
304
+ // Send abort
305
+ try {
306
+ await this.sendAck(deviceId, 'abort', state.expectedSequence);
307
+ } catch {
308
+ // Ignore errors during cancellation
309
+ }
310
+
311
+ // Clean up
312
+ if (state.timeoutId) clearTimeout(state.timeoutId);
313
+ state.subscription?.remove();
314
+ this.activeTransfers.delete(recordingUuid);
315
+ }
316
+
317
+ /**
318
+ * Check if a transfer is in progress
319
+ */
320
+ isTransferInProgress(recordingUuid) {
321
+ return this.activeTransfers.has(recordingUuid);
322
+ }
323
+
324
+ /**
325
+ * Clean up resources
326
+ */
327
+ destroy() {
328
+ // Cancel all active transfers
329
+ for (const [, state] of this.activeTransfers) {
330
+ if (state.timeoutId) clearTimeout(state.timeoutId);
331
+ state.subscription?.remove();
332
+ }
333
+ this.activeTransfers.clear();
334
+ }
335
+ }
336
+ //# sourceMappingURL=ProtocolHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Buffer","getBleManager","SERVICE_BOTA_STORAGE","CHAR_STORAGE_INFO","CHAR_RECORDING_LIST","CHAR_RECORDING_TRANSFER","CHAR_TRANSFER_CONTROL","TRANSFER_PACKET_TIMEOUT","parseStorageInfo","parseRecordingList","parseTransferPacket","createAckPacket","createTransferCommand","TransferError","DeviceError","logger","log","tag","ProtocolHandler","activeTransfers","Map","constructor","bleManager","getStorageInfo","deviceId","isConnected","notConnected","data","readCharacteristic","listRecordings","debug","Promise","resolve","reject","recordings","subscription","timeoutId","cleanup","clearTimeout","remove","setTimeout","length","subscribeToCharacteristic","parsed","concat","error","command","writeCharacteristic","catch","transferRecording","recordingUuid","onProgress","has","info","state","expectedSequence","receivedPackets","totalBytes","isComplete","set","delete","resetTimeout","timeout","packet","handleTransferPacket","audioData","assembleAudioData","checksum","undefined","calculatedChecksum","calculateCrc32","checksumMismatch","size","interrupted","then","type","sequenceNumber","from","sendAck","seq","total","deviceError","errorCode","ackPacket","sortedSequences","Array","keys","sort","a","b","chunks","get","push","crc","table","getCrc32Table","i","crc32Table","j","confirmSync","cancelTransfer","isTransferInProgress","destroy","clear"],"sourceRoot":"../../../src","sources":["protocol/ProtocolHandler.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Protocol module exports
3
+ */
4
+
5
+ export { ProtocolHandler } from './ProtocolHandler';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["ProtocolHandler"],"sourceRoot":"../../../src","sources":["protocol/index.ts"],"mappings":"AAAA;AACA;AACA;;AAEA,SAASA,eAAe,QAAuC,mBAAmB","ignoreList":[]}
@@ -0,0 +1,324 @@
1
+ /**
2
+ * Storage Manager - Local persistence for recordings and upload queue
3
+ */
4
+
5
+ import AsyncStorage from '@react-native-async-storage/async-storage';
6
+ import { Buffer } from 'buffer';
7
+ import { logger } from '../utils/logger';
8
+ const log = logger.tag('StorageManager');
9
+
10
+ // Storage keys
11
+ const STORAGE_PREFIX = '@bota_sdk:';
12
+ const UPLOAD_QUEUE_KEY = `${STORAGE_PREFIX}upload_queue`;
13
+ const SDK_STATE_KEY = `${STORAGE_PREFIX}sdk_state`;
14
+
15
+ /**
16
+ * SDK persistent state
17
+ */
18
+
19
+ /**
20
+ * Storage Manager class
21
+ */
22
+ export class StorageManager {
23
+ uploadQueue = [];
24
+ sdkState = {
25
+ lastSyncTimes: {},
26
+ deviceInfo: {}
27
+ };
28
+ isInitialized = false;
29
+
30
+ /**
31
+ * Initialize storage manager
32
+ */
33
+ async initialize() {
34
+ if (this.isInitialized) {
35
+ return;
36
+ }
37
+ log.debug('Initializing StorageManager');
38
+ try {
39
+ // Load upload queue
40
+ const queueData = await AsyncStorage.getItem(UPLOAD_QUEUE_KEY);
41
+ if (queueData) {
42
+ this.uploadQueue = JSON.parse(queueData);
43
+ // Restore dates
44
+ this.uploadQueue = this.uploadQueue.map(task => ({
45
+ ...task,
46
+ createdAt: new Date(task.createdAt),
47
+ updatedAt: new Date(task.updatedAt)
48
+ }));
49
+ }
50
+
51
+ // Load SDK state
52
+ const stateData = await AsyncStorage.getItem(SDK_STATE_KEY);
53
+ if (stateData) {
54
+ this.sdkState = JSON.parse(stateData);
55
+ }
56
+ this.isInitialized = true;
57
+ log.info('StorageManager initialized', {
58
+ pendingUploads: this.uploadQueue.length
59
+ });
60
+ } catch (error) {
61
+ log.error('Failed to initialize storage', error);
62
+ // Continue with empty state
63
+ this.isInitialized = true;
64
+ }
65
+ }
66
+
67
+ // Upload Queue Methods
68
+
69
+ /**
70
+ * Get all upload tasks
71
+ */
72
+ getUploadQueue() {
73
+ return [...this.uploadQueue];
74
+ }
75
+
76
+ /**
77
+ * Get pending upload tasks
78
+ */
79
+ getPendingUploads() {
80
+ return this.uploadQueue.filter(task => task.status === 'pending' || task.status === 'uploading');
81
+ }
82
+
83
+ /**
84
+ * Get failed upload tasks
85
+ */
86
+ getFailedUploads() {
87
+ return this.uploadQueue.filter(task => task.status === 'failed');
88
+ }
89
+
90
+ /**
91
+ * Add a task to the upload queue
92
+ */
93
+ async addUploadTask(task) {
94
+ log.debug('Adding upload task', {
95
+ taskId: task.id,
96
+ recordingId: task.recordingId
97
+ });
98
+ this.uploadQueue.push(task);
99
+ await this.saveUploadQueue();
100
+ }
101
+
102
+ /**
103
+ * Update an upload task
104
+ */
105
+ async updateUploadTask(taskId, updates) {
106
+ const index = this.uploadQueue.findIndex(t => t.id === taskId);
107
+ if (index === -1) {
108
+ log.warn('Upload task not found', {
109
+ taskId
110
+ });
111
+ return;
112
+ }
113
+ this.uploadQueue[index] = {
114
+ ...this.uploadQueue[index],
115
+ ...updates,
116
+ updatedAt: new Date()
117
+ };
118
+ await this.saveUploadQueue();
119
+ }
120
+
121
+ /**
122
+ * Update task status
123
+ */
124
+ async updateTaskStatus(taskId, status, errorMessage) {
125
+ await this.updateUploadTask(taskId, {
126
+ status,
127
+ errorMessage
128
+ });
129
+ }
130
+
131
+ /**
132
+ * Increment retry count for a task
133
+ */
134
+ async incrementRetryCount(taskId) {
135
+ const task = this.uploadQueue.find(t => t.id === taskId);
136
+ if (task) {
137
+ await this.updateUploadTask(taskId, {
138
+ retryCount: task.retryCount + 1
139
+ });
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Remove a task from the queue
145
+ */
146
+ async removeUploadTask(taskId) {
147
+ log.debug('Removing upload task', {
148
+ taskId
149
+ });
150
+ this.uploadQueue = this.uploadQueue.filter(t => t.id !== taskId);
151
+ await this.saveUploadQueue();
152
+ }
153
+
154
+ /**
155
+ * Clear all completed tasks
156
+ */
157
+ async clearCompletedTasks() {
158
+ this.uploadQueue = this.uploadQueue.filter(t => t.status !== 'completed');
159
+ await this.saveUploadQueue();
160
+ }
161
+
162
+ /**
163
+ * Clear all tasks
164
+ */
165
+ async clearAllTasks() {
166
+ this.uploadQueue = [];
167
+ await this.saveUploadQueue();
168
+ }
169
+
170
+ /**
171
+ * Get a specific upload task
172
+ */
173
+ getUploadTask(taskId) {
174
+ return this.uploadQueue.find(t => t.id === taskId);
175
+ }
176
+
177
+ /**
178
+ * Save upload queue to storage
179
+ */
180
+ async saveUploadQueue() {
181
+ try {
182
+ await AsyncStorage.setItem(UPLOAD_QUEUE_KEY, JSON.stringify(this.uploadQueue));
183
+ } catch (error) {
184
+ log.error('Failed to save upload queue', error);
185
+ }
186
+ }
187
+
188
+ // SDK State Methods
189
+
190
+ /**
191
+ * Get last sync time for a device
192
+ */
193
+ getLastSyncTime(deviceId) {
194
+ const timestamp = this.sdkState.lastSyncTimes[deviceId];
195
+ return timestamp ? new Date(timestamp) : null;
196
+ }
197
+
198
+ /**
199
+ * Set last sync time for a device
200
+ */
201
+ async setLastSyncTime(deviceId, time = new Date()) {
202
+ this.sdkState.lastSyncTimes[deviceId] = time.getTime();
203
+ await this.saveSdkState();
204
+ }
205
+
206
+ /**
207
+ * Get cached device info
208
+ */
209
+ getDeviceInfo(deviceId) {
210
+ return this.sdkState.deviceInfo[deviceId];
211
+ }
212
+
213
+ /**
214
+ * Cache device info
215
+ */
216
+ async setDeviceInfo(deviceId, info) {
217
+ this.sdkState.deviceInfo[deviceId] = info;
218
+ await this.saveSdkState();
219
+ }
220
+
221
+ /**
222
+ * Save SDK state to storage
223
+ */
224
+ async saveSdkState() {
225
+ try {
226
+ await AsyncStorage.setItem(SDK_STATE_KEY, JSON.stringify(this.sdkState));
227
+ } catch (error) {
228
+ log.error('Failed to save SDK state', error);
229
+ }
230
+ }
231
+
232
+ // Recording File Methods
233
+ // Note: For actual file storage, we'd need react-native-fs or similar
234
+ // For now, we'll store base64 encoded audio in AsyncStorage for small files
235
+
236
+ /**
237
+ * Save recording data locally
238
+ */
239
+ async saveRecordingData(deviceId, recordingUuid, data) {
240
+ const key = `${STORAGE_PREFIX}recording:${deviceId}:${recordingUuid}`;
241
+ try {
242
+ // Store as base64 (not ideal for large files, but works for demo)
243
+ await AsyncStorage.setItem(key, data.toString('base64'));
244
+ log.debug('Saved recording data', {
245
+ deviceId,
246
+ recordingUuid,
247
+ size: data.length
248
+ });
249
+ return key;
250
+ } catch (error) {
251
+ log.error('Failed to save recording data', error);
252
+ throw error;
253
+ }
254
+ }
255
+
256
+ /**
257
+ * Load recording data
258
+ */
259
+ async loadRecordingData(localPath) {
260
+ try {
261
+ const data = await AsyncStorage.getItem(localPath);
262
+ if (!data) {
263
+ throw new Error(`Recording not found: ${localPath}`);
264
+ }
265
+ return Buffer.from(data, 'base64');
266
+ } catch (error) {
267
+ log.error('Failed to load recording data', error);
268
+ throw error;
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Delete recording data
274
+ */
275
+ async deleteRecordingData(localPath) {
276
+ try {
277
+ await AsyncStorage.removeItem(localPath);
278
+ log.debug('Deleted recording data', {
279
+ localPath
280
+ });
281
+ } catch (error) {
282
+ log.error('Failed to delete recording data', error);
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Clear all SDK storage
288
+ */
289
+ async clearAll() {
290
+ log.info('Clearing all SDK storage');
291
+ try {
292
+ const keys = await AsyncStorage.getAllKeys();
293
+ const botaKeys = keys.filter(k => k.startsWith(STORAGE_PREFIX));
294
+ await AsyncStorage.multiRemove(botaKeys);
295
+ this.uploadQueue = [];
296
+ this.sdkState = {
297
+ lastSyncTimes: {},
298
+ deviceInfo: {}
299
+ };
300
+ } catch (error) {
301
+ log.error('Failed to clear storage', error);
302
+ }
303
+ }
304
+
305
+ /**
306
+ * Clean up resources
307
+ */
308
+ destroy() {
309
+ this.uploadQueue = [];
310
+ this.sdkState = {
311
+ lastSyncTimes: {},
312
+ deviceInfo: {}
313
+ };
314
+ this.isInitialized = false;
315
+ }
316
+ }
317
+
318
+ /**
319
+ * Generate a unique task ID
320
+ */
321
+ export function generateTaskId() {
322
+ return `task_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
323
+ }
324
+ //# sourceMappingURL=StorageManager.js.map