@robdobsn/raftjs 1.1.1

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 (149) hide show
  1. package/.editorconfig +14 -0
  2. package/.gitattributes +11 -0
  3. package/.nvmrc +1 -0
  4. package/LICENSE +22 -0
  5. package/README.md +11 -0
  6. package/TODO.md +1 -0
  7. package/dist/RaftAttributeHandler.d.ts +12 -0
  8. package/dist/RaftAttributeHandler.js +241 -0
  9. package/dist/RaftAttributeHandler.js.map +1 -0
  10. package/dist/RaftChannel.d.ts +18 -0
  11. package/dist/RaftChannel.js +12 -0
  12. package/dist/RaftChannel.js.map +1 -0
  13. package/dist/RaftChannelWebBLE.d.ts +38 -0
  14. package/dist/RaftChannelWebBLE.js +274 -0
  15. package/dist/RaftChannelWebBLE.js.map +1 -0
  16. package/dist/RaftChannelWebSerial.d.ts +37 -0
  17. package/dist/RaftChannelWebSerial.js +319 -0
  18. package/dist/RaftChannelWebSerial.js.map +1 -0
  19. package/dist/RaftChannelWebSocket.d.ts +28 -0
  20. package/dist/RaftChannelWebSocket.js +197 -0
  21. package/dist/RaftChannelWebSocket.js.map +1 -0
  22. package/dist/RaftCommsStats.d.ts +39 -0
  23. package/dist/RaftCommsStats.js +128 -0
  24. package/dist/RaftCommsStats.js.map +1 -0
  25. package/dist/RaftConnEvents.d.ts +31 -0
  26. package/dist/RaftConnEvents.js +44 -0
  27. package/dist/RaftConnEvents.js.map +1 -0
  28. package/dist/RaftConnector.d.ts +242 -0
  29. package/dist/RaftConnector.js +613 -0
  30. package/dist/RaftConnector.js.map +1 -0
  31. package/dist/RaftCustomAttrHandler.d.ts +4 -0
  32. package/dist/RaftCustomAttrHandler.js +50 -0
  33. package/dist/RaftCustomAttrHandler.js.map +1 -0
  34. package/dist/RaftDeviceInfo.d.ts +64 -0
  35. package/dist/RaftDeviceInfo.js +36 -0
  36. package/dist/RaftDeviceInfo.js.map +1 -0
  37. package/dist/RaftDeviceManager.d.ts +37 -0
  38. package/dist/RaftDeviceManager.js +450 -0
  39. package/dist/RaftDeviceManager.js.map +1 -0
  40. package/dist/RaftDeviceMsg.d.ts +9 -0
  41. package/dist/RaftDeviceMsg.js +11 -0
  42. package/dist/RaftDeviceMsg.js.map +1 -0
  43. package/dist/RaftDeviceStates.d.ts +33 -0
  44. package/dist/RaftDeviceStates.js +60 -0
  45. package/dist/RaftDeviceStates.js.map +1 -0
  46. package/dist/RaftFileHandler.d.ts +52 -0
  47. package/dist/RaftFileHandler.js +502 -0
  48. package/dist/RaftFileHandler.js.map +1 -0
  49. package/dist/RaftLog.d.ts +22 -0
  50. package/dist/RaftLog.js +63 -0
  51. package/dist/RaftLog.js.map +1 -0
  52. package/dist/RaftMiniHDLC.d.ts +18 -0
  53. package/dist/RaftMiniHDLC.js +383 -0
  54. package/dist/RaftMiniHDLC.js.map +1 -0
  55. package/dist/RaftMsgHandler.d.ts +57 -0
  56. package/dist/RaftMsgHandler.js +480 -0
  57. package/dist/RaftMsgHandler.js.map +1 -0
  58. package/dist/RaftMsgTrackInfo.d.ts +17 -0
  59. package/dist/RaftMsgTrackInfo.js +42 -0
  60. package/dist/RaftMsgTrackInfo.js.map +1 -0
  61. package/dist/RaftProtocolDefs.d.ts +30 -0
  62. package/dist/RaftProtocolDefs.js +48 -0
  63. package/dist/RaftProtocolDefs.js.map +1 -0
  64. package/dist/RaftStreamHandler.d.ts +38 -0
  65. package/dist/RaftStreamHandler.js +257 -0
  66. package/dist/RaftStreamHandler.js.map +1 -0
  67. package/dist/RaftSystemType.d.ts +21 -0
  68. package/dist/RaftSystemType.js +3 -0
  69. package/dist/RaftSystemType.js.map +1 -0
  70. package/dist/RaftSystemUtils.d.ts +136 -0
  71. package/dist/RaftSystemUtils.js +410 -0
  72. package/dist/RaftSystemUtils.js.map +1 -0
  73. package/dist/RaftTypes.d.ts +184 -0
  74. package/dist/RaftTypes.js +157 -0
  75. package/dist/RaftTypes.js.map +1 -0
  76. package/dist/RaftUpdateEvents.d.ts +33 -0
  77. package/dist/RaftUpdateEvents.js +46 -0
  78. package/dist/RaftUpdateEvents.js.map +1 -0
  79. package/dist/RaftUpdateManager.d.ts +61 -0
  80. package/dist/RaftUpdateManager.js +618 -0
  81. package/dist/RaftUpdateManager.js.map +1 -0
  82. package/dist/RaftUtils.d.ts +125 -0
  83. package/dist/RaftUtils.js +454 -0
  84. package/dist/RaftUtils.js.map +1 -0
  85. package/dist/RaftWifiTypes.d.ts +23 -0
  86. package/dist/RaftWifiTypes.js +43 -0
  87. package/dist/RaftWifiTypes.js.map +1 -0
  88. package/dist/TestDataGen.d.ts +7 -0
  89. package/dist/TestDataGen.js +133 -0
  90. package/dist/TestDataGen.js.map +1 -0
  91. package/dist/main.d.ts +18 -0
  92. package/dist/main.js +42 -0
  93. package/dist/main.js.map +1 -0
  94. package/eslint.config.mjs +33 -0
  95. package/examples/dashboard/package.json +39 -0
  96. package/examples/dashboard/src/ConnManager.ts +86 -0
  97. package/examples/dashboard/src/Main.tsx +100 -0
  98. package/examples/dashboard/src/StatusScreen.tsx +72 -0
  99. package/examples/dashboard/src/SystemTypeCog/CogStateInfo.ts +144 -0
  100. package/examples/dashboard/src/SystemTypeCog/SystemTypeCog.ts +77 -0
  101. package/examples/dashboard/src/SystemTypeMarty/RICAddOn.ts +70 -0
  102. package/examples/dashboard/src/SystemTypeMarty/RICAddOnBase.ts +33 -0
  103. package/examples/dashboard/src/SystemTypeMarty/RICAddOnManager.ts +342 -0
  104. package/examples/dashboard/src/SystemTypeMarty/RICCommsStats.ts +170 -0
  105. package/examples/dashboard/src/SystemTypeMarty/RICHWElem.ts +123 -0
  106. package/examples/dashboard/src/SystemTypeMarty/RICLEDPatternChecker.ts +207 -0
  107. package/examples/dashboard/src/SystemTypeMarty/RICROSSerial.ts +464 -0
  108. package/examples/dashboard/src/SystemTypeMarty/RICServoFaultDetector.ts +146 -0
  109. package/examples/dashboard/src/SystemTypeMarty/RICStateInfo.ts +32 -0
  110. package/examples/dashboard/src/SystemTypeMarty/RICSystemUtils.ts +371 -0
  111. package/examples/dashboard/src/SystemTypeMarty/RICTypes.ts +20 -0
  112. package/examples/dashboard/src/SystemTypeMarty/SystemTypeMarty.ts +113 -0
  113. package/examples/dashboard/src/index.html +15 -0
  114. package/examples/dashboard/src/index.tsx +15 -0
  115. package/examples/dashboard/src/styles.css +122 -0
  116. package/examples/dashboard/tsconfig.json +18 -0
  117. package/jest.config.js +11 -0
  118. package/package.json +50 -0
  119. package/src/RaftAttributeHandler.ts +289 -0
  120. package/src/RaftChannel.ts +30 -0
  121. package/src/RaftChannelWebBLE.ts +342 -0
  122. package/src/RaftChannelWebSerial.ts +408 -0
  123. package/src/RaftChannelWebSocket.ts +245 -0
  124. package/src/RaftCommsStats.ts +142 -0
  125. package/src/RaftConnEvents.ts +46 -0
  126. package/src/RaftConnector.ts +745 -0
  127. package/src/RaftCustomAttrHandler.ts +54 -0
  128. package/src/RaftDeviceInfo.ts +104 -0
  129. package/src/RaftDeviceManager.ts +542 -0
  130. package/src/RaftDeviceMsg.ts +20 -0
  131. package/src/RaftDeviceStates.ts +89 -0
  132. package/src/RaftFileHandler.ts +668 -0
  133. package/src/RaftLog.ts +70 -0
  134. package/src/RaftMiniHDLC.ts +396 -0
  135. package/src/RaftMsgHandler.ts +778 -0
  136. package/src/RaftMsgTrackInfo.ts +51 -0
  137. package/src/RaftProtocolDefs.ts +46 -0
  138. package/src/RaftStreamHandler.ts +328 -0
  139. package/src/RaftSystemType.ts +25 -0
  140. package/src/RaftSystemUtils.ts +487 -0
  141. package/src/RaftTypes.ts +250 -0
  142. package/src/RaftUpdateEvents.ts +48 -0
  143. package/src/RaftUpdateManager.ts +778 -0
  144. package/src/RaftUtils.ts +484 -0
  145. package/src/RaftWifiTypes.ts +36 -0
  146. package/src/TestDataGen.ts +157 -0
  147. package/src/main.ts +28 -0
  148. package/testdata/TestDeviceTypeRecs.json +492 -0
  149. package/tsconfig.json +27 -0
@@ -0,0 +1,745 @@
1
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // RaftConnector
4
+ // Part of RaftJS
5
+ //
6
+ // Rob Dobson & Chris Greening 2020-2024
7
+ // (C) 2020-2024 All rights reserved
8
+ //
9
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10
+
11
+ import RaftChannel from "./RaftChannel";
12
+ import RaftChannelWebBLE from "./RaftChannelWebBLE";
13
+ import RaftMsgHandler, { RaftMsgResultCode } from "./RaftMsgHandler";
14
+ import RaftChannelWebSocket from "./RaftChannelWebSocket";
15
+ import RaftChannelWebSerial from "./RaftChannelWebSerial";
16
+ import RaftCommsStats from "./RaftCommsStats";
17
+ import { RaftEventFn, RaftOKFail, RaftFileSendType, RaftFileDownloadResult, RaftProgressCBType, RaftBridgeSetupResp, RaftFileDownloadFn } from "./RaftTypes";
18
+ import RaftSystemUtils from "./RaftSystemUtils";
19
+ import RaftFileHandler from "./RaftFileHandler";
20
+ import RaftStreamHandler from "./RaftStreamHandler";
21
+ import RaftLog from "./RaftLog";
22
+ import { RaftConnEvent, RaftConnEventNames } from "./RaftConnEvents";
23
+ import { RaftGetSystemTypeCBType, RaftSystemType } from "./RaftSystemType";
24
+ import { RaftUpdateEvent, RaftUpdateEventNames } from "./RaftUpdateEvents";
25
+ import RaftUpdateManager from "./RaftUpdateManager";
26
+
27
+ export default class RaftConnector {
28
+
29
+ // Get system type callback
30
+ private _getSystemTypeCB: RaftGetSystemTypeCBType | null = null;
31
+
32
+ // System type
33
+ private _systemType: RaftSystemType | null = null;
34
+
35
+ // Channel
36
+ private _raftChannel: RaftChannel | null = null;
37
+
38
+ // Channel connection method and locator
39
+ private _channelConnMethod = "";
40
+ private _channelConnLocator: string | object = "";
41
+
42
+ // Comms stats
43
+ private _commsStats: RaftCommsStats = new RaftCommsStats();
44
+
45
+ // Message handler
46
+ private _raftMsgHandler: RaftMsgHandler = new RaftMsgHandler(
47
+ this._commsStats
48
+ );
49
+
50
+ // RaftSystem
51
+ private _raftSystemUtils: RaftSystemUtils = new RaftSystemUtils(this._raftMsgHandler);
52
+
53
+ // Connection performance checker
54
+ private readonly _testConnPerfBlockSize = 500;
55
+ private readonly _testConnPerfNumBlocks = 50;
56
+ private readonly _connPerfRsltDelayMs = 4000;
57
+
58
+ // Retry connection if lost
59
+ private _retryIfLostEnabled = true;
60
+ private _retryIfLostForSecs = 10;
61
+ private _retryIfLostIsConnected = false;
62
+ private _retryIfLostDisconnectTime: number | null = null;
63
+ private readonly _retryIfLostRetryDelayMs = 500;
64
+
65
+ // File handler
66
+ private _raftFileHandler: RaftFileHandler = new RaftFileHandler(
67
+ this._raftMsgHandler,
68
+ this._commsStats,
69
+ );
70
+
71
+ // Stream handler
72
+ private _raftStreamHandler: RaftStreamHandler = new RaftStreamHandler(
73
+ this._raftMsgHandler,
74
+ this._commsStats,
75
+ this
76
+ );
77
+
78
+ // Event listener
79
+ private _onEventFn: RaftEventFn | null = null;
80
+
81
+ // Update manager
82
+ private _raftUpdateManager: RaftUpdateManager | null = null;
83
+
84
+ /**
85
+ * RaftConnector constructor
86
+ * @param getSystemTypeCB - callback to get system type
87
+ */
88
+ public constructor(getSystemTypeCB: RaftGetSystemTypeCBType | null = null) {
89
+
90
+ // Get system type callback
91
+ this._getSystemTypeCB = getSystemTypeCB;
92
+
93
+ // Debug
94
+ RaftLog.debug('RaftConnector starting up');
95
+ }
96
+
97
+ /**
98
+ * Configure the file handler
99
+ * @param fileBlockSize - size of file blocks to send
100
+ * @param batchAckSize - number of blocks to send before waiting for ack
101
+ * @returns void
102
+ */
103
+ configureFileHandler(fileBlockSize: number, batchAckSize: number) {
104
+ this._raftFileHandler.setRequestedFileBlockSize(fileBlockSize);
105
+ this._raftFileHandler.setRequestedBatchAckSize(batchAckSize);
106
+ }
107
+
108
+ /**
109
+ * Set event listener
110
+ * @param onEventFn - event listener
111
+ * @returns void
112
+ * */
113
+ setEventListener(onEventFn: RaftEventFn): void {
114
+ this._onEventFn = onEventFn;
115
+ }
116
+
117
+ /**
118
+ * isConnected
119
+ * @returns boolean - true if connected
120
+ * */
121
+ isConnected() {
122
+ // Check if connected
123
+ const isConnected = this._retryIfLostIsConnected || (this._raftChannel ? this._raftChannel.isConnected() : false);
124
+ return isConnected;
125
+ }
126
+
127
+ /**
128
+ * Set try to reconnect if connection lost
129
+ * @param enableRetry - true to enable retry
130
+ * @param retryForSecs - retry for this many seconds
131
+ * @returns void
132
+ * */
133
+ setRetryConnectionIfLost(enableRetry: boolean, retryForSecs: number): void {
134
+ this._retryIfLostEnabled = enableRetry;
135
+ this._retryIfLostForSecs = retryForSecs;
136
+ if (!this._retryIfLostEnabled) {
137
+ this._retryIfLostIsConnected = false;
138
+ }
139
+ RaftLog.debug(`setRetryConnectionIfLost ${enableRetry} retry for ${retryForSecs}`);
140
+ }
141
+
142
+ /**
143
+ * Get Raft system type (the type of hardware connected to - determined using the getSystemInfo API)
144
+ * @returns RaftSystemType | null - Raft system type
145
+ * */
146
+ getSystemType(): RaftSystemType | null {
147
+ return this._systemType;
148
+ }
149
+
150
+ /**
151
+ * Get connection method
152
+ * @returns string - connection method
153
+ * */
154
+ getConnMethod(): string {
155
+ return this._channelConnMethod;
156
+ }
157
+
158
+ /**
159
+ * Get connection locator
160
+ * @returns string | object - connection locator
161
+ * */
162
+ getConnLocator(): any | null {
163
+ return this._raftChannel ? this._raftChannel.getConnectedLocator() : null;
164
+ }
165
+
166
+ /**
167
+ * Get Raft channel (this is the channel used for commuinications with the Raft application)
168
+ * @returns RaftChannel | null - Raft channel
169
+ * */
170
+ getRaftChannel(): RaftChannel | null {
171
+ return this._raftChannel;
172
+ }
173
+
174
+ /**
175
+ * Get Raft system utils (access to system information and control)
176
+ * @returns RaftSystemUtils - Raft system utils
177
+ * */
178
+ getRaftSystemUtils(): RaftSystemUtils {
179
+ return this._raftSystemUtils;
180
+ }
181
+
182
+ /**
183
+ * Get communication stats
184
+ * @returns RaftCommsStats - communication stats
185
+ * */
186
+ getCommsStats(): RaftCommsStats {
187
+ return this._commsStats;
188
+ }
189
+
190
+ /**
191
+ * Get Raft message handler (to allow message sending and receiving)
192
+ * @returns RaftMsgHandler - Raft message handler
193
+ * */
194
+ getRaftMsgHandler(): RaftMsgHandler {
195
+ return this._raftMsgHandler;
196
+ }
197
+
198
+ /**
199
+ * Pause connection
200
+ * @param pause - true to pause, false to resume
201
+ */
202
+ pauseConnection(pause = true) {
203
+ if (this._raftChannel) this._raftChannel.pauseConnection(pause);
204
+ }
205
+
206
+ /**
207
+ * Connect to a Raft application
208
+ *
209
+ * @param {string} method - can be "WebBLE", "WebSocket" or "WebSerial"
210
+ * @param {string | object} locator - either a string (WebSocket URL or serial port) or an object (WebBLE)
211
+ * @returns Promise<boolean>
212
+ *
213
+ */
214
+ async connect(method: string, locator: string | object): Promise<boolean> {
215
+
216
+ // Ensure disconnected
217
+ try {
218
+ await this.disconnect();
219
+ } catch (err) {
220
+ RaftLog.error('RaftConnector.connect - error: ' + err);
221
+ // Ignore
222
+ }
223
+
224
+ // Check connection method
225
+ let connMethod = "";
226
+ if (method === 'WebBLE' && typeof locator === 'object' && locator !== null) {
227
+
228
+ // Create channel
229
+ this._raftChannel = new RaftChannelWebBLE();
230
+ connMethod = 'WebBLE';
231
+
232
+ } else if (((method === 'WebSocket') || (method === 'wifi')) && (typeof locator === 'string')) {
233
+
234
+ // Create channel
235
+ this._raftChannel = new RaftChannelWebSocket();
236
+ connMethod = 'WebSocket';
237
+ } else if (((method === 'WebSerial'))) {
238
+ this._raftChannel = new RaftChannelWebSerial();
239
+ connMethod = 'WebSerial';
240
+ }
241
+
242
+ RaftLog.debug(`connecting with connMethod ${connMethod}`);
243
+
244
+ // Check channel established
245
+ let connOk = false;
246
+ if (this._raftChannel !== null) {
247
+
248
+ // Connection method and locator
249
+ this._channelConnMethod = connMethod;
250
+ this._channelConnLocator = locator;
251
+
252
+ // Set message handler
253
+ this._raftChannel.setMsgHandler(this._raftMsgHandler);
254
+ this._raftChannel.setOnConnEvent(this.onConnEvent.bind(this));
255
+
256
+ // Message handling in and out
257
+ this._raftMsgHandler.registerForResults(this);
258
+ this._raftMsgHandler.registerMsgSender(this._raftChannel);
259
+
260
+ // Connect
261
+ try {
262
+
263
+ // Event
264
+ this.onConnEvent(RaftConnEvent.CONN_CONNECTING);
265
+
266
+ // Connect
267
+ connOk = await this._connectToChannel();
268
+ } catch (err) {
269
+ RaftLog.error('RaftConnector.connect - error: ' + err);
270
+ }
271
+
272
+ // Check ok
273
+ if (connOk) {
274
+
275
+ // Get system type
276
+ if (this._getSystemTypeCB) {
277
+ // Get system type
278
+ this._systemType = await this._getSystemTypeCB(this._raftSystemUtils);
279
+
280
+ // Set defaults
281
+ if (this._systemType) {
282
+ this._raftSystemUtils.setDefaultWiFiHostname(this._systemType.defaultWiFiHostname);
283
+ }
284
+ }
285
+
286
+ // Setup system type
287
+ if (this._systemType) {
288
+ this._systemType.setup(this._raftSystemUtils, this._onEventFn);
289
+ }
290
+
291
+ // Check if subscription required
292
+ if (this._systemType &&
293
+ this._systemType.subscribeForUpdates &&
294
+ this._raftChannel.requiresSubscription()) {
295
+ try {
296
+ // Subscription
297
+ await this._systemType.subscribeForUpdates(this._raftSystemUtils, true);
298
+ RaftLog.info(`connect subscribed for updates`);
299
+ } catch (error: unknown) {
300
+ RaftLog.warn(`connect subscribe for updates failed ${error}`)
301
+ }
302
+ }
303
+
304
+ // Send connected event
305
+ this.onConnEvent(RaftConnEvent.CONN_CONNECTED);
306
+
307
+ } else {
308
+ // Failed Event
309
+ this.onConnEvent(RaftConnEvent.CONN_CONNECTION_FAILED);
310
+ }
311
+
312
+ // configure file handler
313
+ this.configureFileHandler(this._raftChannel.fhFileBlockSize(), this._raftChannel.fhBatchAckSize());
314
+ } else {
315
+ this._channelConnMethod = "";
316
+ }
317
+
318
+ return connOk;
319
+ }
320
+
321
+ async disconnect(): Promise<void> {
322
+ // Disconnect
323
+ this._retryIfLostIsConnected = false;
324
+ if (this._raftChannel) {
325
+ // Check if there is a RICREST command to send before disconnecting
326
+ const ricRestCommand = this._raftChannel.ricRestCmdBeforeDisconnect();
327
+ console.log(`sending RICREST command before disconnect: ${ricRestCommand}`);
328
+ if (ricRestCommand) {
329
+ await this.sendRICRESTMsg(ricRestCommand, {});
330
+ }
331
+ // await this.sendRICRESTMsg("bledisc", {});
332
+ await this._raftChannel.disconnect();
333
+ this._raftChannel = null;
334
+ }
335
+ }
336
+
337
+ // Mark: Tx Message handling -----------------------------------------------------------------------------------------
338
+
339
+ /**
340
+ *
341
+ * sendRICRESTMsg
342
+ * @param commandName command API string
343
+ * @param params parameters (simple name value pairs only) to parameterize trajectory
344
+ * @returns Promise<RaftOKFail>
345
+ *
346
+ */
347
+ async sendRICRESTMsg(commandName: string, params: object,
348
+ bridgeID: number | undefined = undefined): Promise<RaftOKFail> {
349
+ try {
350
+ // Format the paramList as query string
351
+ const paramEntries = Object.entries(params);
352
+ let paramQueryStr = '';
353
+ for (const param of paramEntries) {
354
+ if (paramQueryStr.length > 0) paramQueryStr += '&';
355
+ paramQueryStr += param[0] + '=' + param[1];
356
+ }
357
+ // Format the url to send
358
+ if (paramQueryStr.length > 0) commandName += '?' + paramQueryStr;
359
+ return await this._raftMsgHandler.sendRICRESTURL<RaftOKFail>(commandName, bridgeID);
360
+ } catch (error) {
361
+ RaftLog.warn(`sendRICRESTMsg failed ${error}`);
362
+ return new RaftOKFail();
363
+ }
364
+ }
365
+
366
+ // Mark: Rx Message handling -----------------------------------------------------------------------------------------
367
+
368
+ /**
369
+ * onRxReply - handle a reply message
370
+ * @param msgHandle number indicating the message that is being replied to (from the original message)
371
+ * @param msgRsltCode result code
372
+ * @param msgRsltJsonObj result object
373
+ */
374
+ onRxReply(
375
+ msgHandle: number,
376
+ msgRsltCode: RaftMsgResultCode,
377
+ msgRsltJsonObj: object | null,
378
+ ): void {
379
+ RaftLog.verbose(
380
+ `onRxReply msgHandle ${msgHandle} rsltCode ${msgRsltCode} obj ${JSON.stringify(
381
+ msgRsltJsonObj,
382
+ )}`,
383
+ );
384
+ }
385
+
386
+ /**
387
+ * onRxUnnumberedMsg - handle an unnumbered message
388
+ * @param msgRsltJsonObj result object
389
+ */
390
+ onRxUnnumberedMsg(msgRsltJsonObj: { [key: string]: number | string }): void {
391
+ RaftLog.verbose(
392
+ `onRxUnnumberedMsg rsltCode obj ${JSON.stringify(msgRsltJsonObj)}`,
393
+ );
394
+
395
+ // Inform the file handler
396
+ if ('okto' in msgRsltJsonObj) {
397
+ this._raftFileHandler.onOktoMsg(msgRsltJsonObj.okto as number);
398
+ } else if ('sokto' in msgRsltJsonObj) {
399
+ this._raftStreamHandler.onSoktoMsg(msgRsltJsonObj.sokto as number);
400
+ }
401
+ }
402
+
403
+ /**
404
+ * onRxFileBlock - handle a file block
405
+ * @param filePos file position
406
+ * @param fileBlockData file block data
407
+ */
408
+ onRxFileBlock(
409
+ filePos: number,
410
+ fileBlockData: Uint8Array
411
+ ): void {
412
+ // RaftLog.info(`onRxFileBlock filePos ${filePos} fileBlockData ${RaftUtils.bufferToHex(fileBlockData)}`);
413
+ this._raftFileHandler.onFileBlock(filePos, fileBlockData);
414
+ }
415
+
416
+
417
+ // Mark: Handling of other message types -----------------------------------------------------------------------------------------
418
+
419
+ /**
420
+ * onRxOtherMsgType - handle other message types
421
+ * @param payload message payload
422
+ * @param frameTimeMs time of frame
423
+ */
424
+ onRxOtherMsgType(payload: Uint8Array, _frameTimeMs: number): void {
425
+ // RaftLog.debug(`onRxOtherMsgType payload ${RaftUtils.bufferToHex(payload)}`);
426
+ RaftLog.verbose(`onRxOtherMsgType payloadLen ${payload.length}`);
427
+
428
+ // Handle other messages
429
+ if (this._systemType && this._systemType.rxOtherMsgType) {
430
+ this._systemType.rxOtherMsgType(payload, _frameTimeMs);
431
+ }
432
+ }
433
+
434
+ // Mark: File sending --------------------------------------------------------------------------------
435
+
436
+ /**
437
+ * sendFile - send a file
438
+ * @param fileName name of file to send
439
+ * @param fileContents file contents
440
+ * @param progressCallback callback to receive progress updates
441
+ * @returns Promise<boolean> - true if file sent successfully
442
+ */
443
+ async sendFile(fileName: string,
444
+ fileContents: Uint8Array,
445
+ progressCallback: ((sent: number, total: number, progress: number) => void) | undefined,
446
+ ): Promise<boolean> {
447
+ return this._raftFileHandler.fileSend(fileName, RaftFileSendType.NORMAL_FILE, "fs", fileContents, progressCallback);
448
+ }
449
+
450
+ // Mark: Streaming --------------------------------------------------------------------------------
451
+
452
+ /**
453
+ * streamAudio - stream audio
454
+ * @param streamContents audio data
455
+ * @param clearExisting true to clear existing audio
456
+ * @param duration duration of audio
457
+ */
458
+ streamAudio(streamContents: Uint8Array, clearExisting: boolean, duration: number): void {
459
+ if (this._raftStreamHandler && this.isConnected()) {
460
+ this._raftStreamHandler.streamAudio(streamContents, clearExisting, duration);
461
+ }
462
+ }
463
+
464
+ /**
465
+ * isStreamStarting - check if stream is starting
466
+ */
467
+ isStreamStarting() {
468
+ return this._raftStreamHandler.isStreamStarting();
469
+ }
470
+
471
+ // Mark: File system --------------------------------------------------------------------------------
472
+
473
+ /**
474
+ * fsGetContents - get file contents
475
+ * @param fileName name of file to get
476
+ * @param fileSource source of file to get (e.g. "fs" or "bridgeserial1", if omitted defaults to "fs")
477
+ * @param progressCallback callback to receive progress updates
478
+ * @returns Promise<RaftFileDownloadResult>
479
+ */
480
+ async fsGetContents(fileName: string,
481
+ fileSource: string,
482
+ progressCallback: RaftProgressCBType | undefined): Promise<RaftFileDownloadResult> {
483
+ return await this._raftFileHandler.fileReceive(fileName, fileSource, progressCallback);
484
+ }
485
+
486
+ /**
487
+ * setLegacySoktoMode - set legacy sokto mode
488
+ * @param legacyMode true to set legacy mode
489
+ */
490
+ setLegacySoktoMode(legacyMode: boolean) {
491
+ return this._raftStreamHandler.setLegacySoktoMode(legacyMode);
492
+ }
493
+
494
+ // Mark: Bridge serial --------------------------------------------------------------------------------
495
+
496
+ /**
497
+ * createCommsBridge - create a comms bridge
498
+ * @param bridgeSource source of bridge (e.g. "Serial1")
499
+ * @param bridgeName name of bridge
500
+ * @param idleCloseSecs idle close time seconds
501
+ * @returns Promise<RaftBridgeSetupResp>
502
+ */
503
+ async createCommsBridge(bridgeSource: string, bridgeName: string, idleCloseSecs = 0): Promise<RaftBridgeSetupResp> {
504
+ return await this._raftMsgHandler.createCommsBridge(bridgeSource, bridgeName, idleCloseSecs);
505
+ }
506
+
507
+ // Mark: Connection performance--------------------------------------------------------------------------
508
+
509
+ /**
510
+ * ParkMiller random number generator
511
+ * @param seed
512
+ * @returns number
513
+ */
514
+ private parkmiller_next(seed: number) {
515
+ const hi = Math.round(16807 * (seed & 0xffff));
516
+ let lo = Math.round(16807 * (seed >> 16));
517
+ lo += (hi & 0x7fff) << 16;
518
+ lo += hi >> 15;
519
+ if (lo > 0x7fffffff)
520
+ lo -= 0x7fffffff;
521
+ return lo;
522
+ }
523
+
524
+ /**
525
+ * checkConnPerformance - check connection performance
526
+ * @returns Promise<number | undefined> - connection performance
527
+ */
528
+ async checkConnPerformance(): Promise<number | undefined> {
529
+
530
+ // Sends a magic sequence of bytes followed by blocks of random data
531
+ // these will be ignored by the Raft library (as it recognises magic sequence)
532
+ // and is used performance evaluation
533
+ let prbsState = 1;
534
+ const testData = new Uint8Array(this._testConnPerfBlockSize);
535
+ for (let i = 0; i < this._testConnPerfNumBlocks; i++) {
536
+ testData.set([0, (i >> 24) & 0xff, (i >> 16) & 0xff, (i >> 8) & 0xff, i & 0xff, 0x1f, 0x9d, 0xf4, 0x7a, 0xb5]);
537
+ for (let j = 10; j < this._testConnPerfBlockSize; j++) {
538
+ prbsState = this.parkmiller_next(prbsState);
539
+ testData[j] = prbsState & 0xff;
540
+ }
541
+ if (this._raftChannel) {
542
+ await this._raftChannel.sendTxMsg(testData, false);
543
+ }
544
+ }
545
+
546
+ // Wait a little to allow the Raft app to process the data
547
+ await new Promise(resolve => setTimeout(resolve, this._connPerfRsltDelayMs));
548
+
549
+ // Get performance
550
+ const blePerf = await this._raftSystemUtils.getSysModInfoBLEMan();
551
+ if (blePerf) {
552
+ console.log(`checkConnPerformance result rate = ${blePerf.tBPS}BytesPS`);
553
+ return blePerf.tBPS;
554
+ } else {
555
+ throw new Error('checkConnPerformance: failed to get BLE performance');
556
+ }
557
+ }
558
+
559
+ // Mark: Connection event --------------------------------------------------------------------------
560
+
561
+ /**
562
+ * onConnEvent - handle connection event
563
+ * @param eventEnum connection event enumeration
564
+ * @param data data associated with event
565
+ * @returns void
566
+ */
567
+ onConnEvent(eventEnum: RaftConnEvent, data: object | string | null | undefined = undefined): void {
568
+
569
+ // Handle information clearing on disconnect
570
+ switch (eventEnum) {
571
+ case RaftConnEvent.CONN_DISCONNECTED:
572
+
573
+ // Disconnect time
574
+ this._retryIfLostDisconnectTime = Date.now();
575
+
576
+ // Check if retry required
577
+ if (this._retryIfLostIsConnected && this._retryIfLostEnabled) {
578
+
579
+ // Indicate connection disrupted
580
+ if (this._onEventFn) {
581
+ this._onEventFn("conn", RaftConnEvent.CONN_ISSUE_DETECTED, RaftConnEventNames[RaftConnEvent.CONN_ISSUE_DETECTED]);
582
+ }
583
+
584
+ // Retry connection
585
+ this._retryConnection();
586
+
587
+ // Don't allow disconnection to propagate until retries have occurred
588
+ return;
589
+
590
+ }
591
+
592
+ // Invalidate connection details
593
+ this._raftSystemUtils.invalidate();
594
+
595
+ // Invalidate system-type info
596
+ if (this._systemType && this._systemType.stateIsInvalid) {
597
+ this._systemType.stateIsInvalid();
598
+ }
599
+ break;
600
+ }
601
+
602
+ // Notify
603
+ if (this._onEventFn) {
604
+ this._onEventFn("conn", eventEnum, RaftConnEventNames[eventEnum], data);
605
+ }
606
+ }
607
+
608
+ /**
609
+ * Retry connection
610
+ */
611
+ private _retryConnection(): void {
612
+
613
+ // Check timeout
614
+ if ((this._retryIfLostDisconnectTime !== null) &&
615
+ (Date.now() - this._retryIfLostDisconnectTime < this._retryIfLostForSecs * 1000)) {
616
+
617
+ // Set timer to try to reconnect
618
+ setTimeout(async () => {
619
+
620
+ // Try to connect
621
+ const isConn = await this._connectToChannel();
622
+ if (!isConn) {
623
+ this._retryConnection();
624
+ } else {
625
+
626
+ // No longer retrying
627
+ this._retryIfLostDisconnectTime = null;
628
+
629
+ // Indicate connection problem resolved
630
+ if (this._onEventFn) {
631
+ this._onEventFn("conn", RaftConnEvent.CONN_ISSUE_RESOLVED, RaftConnEventNames[RaftConnEvent.CONN_ISSUE_RESOLVED]);
632
+ }
633
+
634
+ }
635
+ }, this._retryIfLostRetryDelayMs);
636
+ } else {
637
+
638
+ // No longer connected after retry timeout
639
+ this._retryIfLostIsConnected = false;
640
+
641
+ // Indicate disconnection
642
+ if (this._onEventFn) {
643
+ this._onEventFn("conn", RaftConnEvent.CONN_DISCONNECTED, RaftConnEventNames[RaftConnEvent.CONN_DISCONNECTED]);
644
+ }
645
+
646
+ // Invalidate connection details
647
+ this._raftSystemUtils.invalidate();
648
+
649
+ // Invalidate system-type info
650
+ if (this._systemType && this._systemType.stateIsInvalid) {
651
+ this._systemType.stateIsInvalid();
652
+ }
653
+ }
654
+ }
655
+
656
+ /**
657
+ * Connect to channel
658
+ * @returns Promise<boolean> - true if connected
659
+ */
660
+ private async _connectToChannel(): Promise<boolean> {
661
+ // Connect
662
+ try {
663
+ if (this._raftChannel) {
664
+ const connected = await this._raftChannel.connect(this._channelConnLocator, this._systemType ? this._systemType.connectorOptions : {});
665
+ if (connected) {
666
+ this._retryIfLostIsConnected = true;
667
+ return true;
668
+ }
669
+ }
670
+ } catch (error) {
671
+ RaftLog.error(`RaftConnector.connect() error: ${error}`);
672
+ }
673
+ return false;
674
+ }
675
+
676
+ // Mark: OTA Update -----------------------------------------------------------------------------------------
677
+
678
+ /**
679
+ * onUpdateEvent - handle update event
680
+ * @param eventEnum
681
+ * @param data
682
+ */
683
+ _onUpdateEvent(eventEnum: RaftUpdateEvent, data: object | string | null | undefined = undefined): void {
684
+ // Notify
685
+ if (this._onEventFn) {
686
+ this._onEventFn("ota", eventEnum, RaftUpdateEventNames[eventEnum], data);
687
+ }
688
+ }
689
+
690
+ /**
691
+ * otaUpdateCheck - check for OTA update
692
+ * @returns Promise<RaftUpdateEvent> - update event
693
+ * */
694
+ async otaUpdateCheck(): Promise<RaftUpdateEvent> {
695
+ if (!this._raftUpdateManager)
696
+ return RaftUpdateEvent.UPDATE_NOT_CONFIGURED;
697
+ return await this._raftUpdateManager.checkForUpdate(this._raftSystemUtils.getCachedSystemInfo());
698
+ }
699
+
700
+ /**
701
+ * otaUpdateStart - start OTA update
702
+ * @returns Promise<RaftUpdateEvent> - update event
703
+ * */
704
+ async otaUpdateStart(): Promise<RaftUpdateEvent> {
705
+ if (!this._raftUpdateManager)
706
+ return RaftUpdateEvent.UPDATE_NOT_CONFIGURED;
707
+ return await this._raftUpdateManager.firmwareUpdate();
708
+ }
709
+
710
+ /**
711
+ * otaUpdateCancel - cancel OTA update
712
+ * @returns Promise<void>
713
+ * */
714
+ async otaUpdateCancel(): Promise<void> {
715
+ if (!this._raftUpdateManager)
716
+ return;
717
+ return await this._raftUpdateManager.firmwareUpdateCancel();
718
+ }
719
+
720
+ /**
721
+ * setupUpdateManager - setup the update manager
722
+ * @param appVersion - app version
723
+ * @param appUpdateURL - app update URL
724
+ * @param firmwareBaseURL - firmware base URL
725
+ * @param fileDownloader - file downloader
726
+ * @returns void
727
+ * */
728
+ setupUpdateManager(appVersion: string, appUpdateURL: string, firmwareBaseURL: string, fileDownloader: RaftFileDownloadFn): void {
729
+ // Setup update manager
730
+ const firmwareTypeStrForMainFw = 'main';
731
+ this._raftUpdateManager = new RaftUpdateManager(
732
+ this._systemType,
733
+ this._raftMsgHandler,
734
+ this._raftFileHandler,
735
+ this._raftSystemUtils,
736
+ this._onUpdateEvent.bind(this),
737
+ firmwareTypeStrForMainFw,
738
+ appVersion,
739
+ fileDownloader,
740
+ appUpdateURL,
741
+ firmwareBaseURL,
742
+ this._raftChannel
743
+ );
744
+ }
745
+ }