@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,342 @@
1
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // RaftChannelWebBLE
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 { RaftConnEvent, RaftConnEventFn } from "./RaftConnEvents";
13
+ import RaftLog from "./RaftLog";
14
+ import RaftMsgHandler from "./RaftMsgHandler";
15
+ import { ConnectorOptions } from "./RaftSystemType";
16
+ import RaftUtils from "./RaftUtils";
17
+
18
+ export default class RaftChannelWebBLE implements RaftChannel {
19
+ // BLE UUIDS
20
+ public static ServiceUUID = "aa76677e-9cfd-4626-a510-0d305be57c8d";
21
+ public static CmdUUID = "aa76677e-9cfd-4626-a510-0d305be57c8e";
22
+ public static RespUUID = "aa76677e-9cfd-4626-a510-0d305be57c8f";
23
+
24
+ // Device and characteristics
25
+ private _bleDevice: BluetoothDevice | null = null;
26
+ private _characteristicTx: BluetoothRemoteGATTCharacteristic | null = null;
27
+ private _characteristicRx: BluetoothRemoteGATTCharacteristic | null = null;
28
+
29
+ // Message handler
30
+ private _raftMsgHandler: RaftMsgHandler | null = null;
31
+
32
+ // Conn event fn
33
+ private _onConnEvent: RaftConnEventFn | null = null;
34
+
35
+ // Last message tx time
36
+ private _msgTxTimeLast = Date.now();
37
+ private _msgTxMinTimeBetweenMs = 1;
38
+ private readonly maxRetries = 1;
39
+
40
+ // Connected flag and retries
41
+ private _isConnected = false;
42
+ private readonly _maxConnRetries = 3;
43
+
44
+ // Event listener fn
45
+ private _eventListenerFn: ((event: Event) => void) | null = null;
46
+
47
+ // File Handler parameters
48
+ private _requestedBatchAckSize = 10;
49
+ private _requestedFileBlockSize = 500;
50
+
51
+ fhBatchAckSize(): number {
52
+ return this._requestedBatchAckSize;
53
+ }
54
+ fhFileBlockSize(): number {
55
+ return this._requestedFileBlockSize;
56
+ }
57
+
58
+ // Set message handler
59
+ setMsgHandler(raftMsgHandler: RaftMsgHandler): void {
60
+ this._raftMsgHandler = raftMsgHandler;
61
+ }
62
+
63
+ requiresSubscription(): boolean {
64
+ return true;
65
+ }
66
+
67
+ // RICREST command before disconnect
68
+ ricRestCmdBeforeDisconnect(): string | null {
69
+ return "blerestart";
70
+ }
71
+
72
+ // isEnabled
73
+ isEnabled() {
74
+ if (navigator.bluetooth) {
75
+ RaftLog.error("Web Bluetooth is supported in your browser.");
76
+ return true;
77
+ } else {
78
+ window.alert(
79
+ "Web Bluetooth API is not available.\n" +
80
+ 'Please make sure the "Experimental Web Platform features" flag is enabled.'
81
+ );
82
+ return false;
83
+ }
84
+ }
85
+
86
+ // isConnected
87
+ isConnected(): boolean {
88
+ return this._bleDevice !== null && this._isConnected;
89
+ }
90
+
91
+ // Set onConnEvent handler
92
+ setOnConnEvent(connEventFn: RaftConnEventFn): void {
93
+ this._onConnEvent = connEventFn;
94
+ }
95
+
96
+ // Disconnection event
97
+ onDisconnected(event: Event): void {
98
+ const device = event.target as BluetoothDevice;
99
+ RaftLog.debug(`RaftChannelWebBLE.onDisconnected ${device.name}`);
100
+ if (this._bleDevice) {
101
+ this._bleDevice.removeEventListener(
102
+ "gattserverdisconnected",
103
+ this._eventListenerFn
104
+ );
105
+ }
106
+ this._isConnected = false;
107
+ if (this._onConnEvent) {
108
+ this._onConnEvent(RaftConnEvent.CONN_DISCONNECTED);
109
+ }
110
+ }
111
+
112
+ // Get connected locator
113
+ getConnectedLocator(): string | object {
114
+ return this._bleDevice || "";
115
+ }
116
+
117
+ // Connect to a device
118
+ async connect(locator: string | object, _connectorOptions: ConnectorOptions): Promise<boolean> {
119
+ // RaftLog.debug(`Selected device: ${deviceID}`);
120
+ this._bleDevice = locator as BluetoothDevice;
121
+ if (this._bleDevice && this._bleDevice.gatt) {
122
+ try {
123
+ // Connect
124
+ for (let connRetry = 0; connRetry < this._maxConnRetries; connRetry++) {
125
+ // Connect
126
+ const connTimeoutMs = _connectorOptions.connTimeoutMs || 5000;
127
+ await RaftUtils.withTimeout(connTimeoutMs, this._bleDevice.gatt.connect());
128
+ RaftLog.debug(
129
+ `RaftChannelWebBLE.connect - ${
130
+ this._bleDevice.gatt.connected ? "OK" : "FAILED"
131
+ } attempt ${connRetry+1} connection to device ${this._bleDevice.name}`
132
+ );
133
+
134
+ if (this._bleDevice.gatt.connected) {
135
+
136
+ // Delay a bit
137
+ await new Promise(resolve => setTimeout(resolve, 100));
138
+
139
+ // Get service
140
+ try {
141
+
142
+ const service = await this._bleDevice.gatt.getPrimaryService(
143
+ RaftChannelWebBLE.ServiceUUID
144
+ );
145
+ RaftLog.debug(
146
+ `RaftChannelWebBLE.connect - found service: ${service.uuid}`
147
+ );
148
+
149
+ try {
150
+ // Get Tx and Rx characteristics
151
+ this._characteristicTx = await service.getCharacteristic(
152
+ RaftChannelWebBLE.CmdUUID
153
+ );
154
+ RaftLog.debug(
155
+ `RaftChannelWebBLE.connect - found char ${this._characteristicTx.uuid}`
156
+ );
157
+ this._characteristicRx = await service.getCharacteristic(
158
+ RaftChannelWebBLE.RespUUID
159
+ );
160
+ RaftLog.debug(
161
+ `RaftChannelWebBLE.connect - found char ${this._characteristicRx.uuid}`
162
+ );
163
+
164
+ // Notifications of received messages
165
+ try {
166
+ await this._characteristicRx.startNotifications();
167
+ RaftLog.debug(
168
+ "RaftChannelWebBLE.connect - notifications started"
169
+ );
170
+ this._characteristicRx.addEventListener(
171
+ "characteristicvaluechanged",
172
+ this._onMsgRx.bind(this)
173
+ );
174
+ } catch (error) {
175
+ RaftLog.debug(
176
+ "RaftChannelWebBLE.connnect - addEventListener failed " + error
177
+ );
178
+ }
179
+
180
+ // Connected ok
181
+ RaftLog.debug(`RaftChannelWebBLE.connect ${this._bleDevice.name}`);
182
+
183
+ // Add disconnect listener
184
+ this._eventListenerFn = this.onDisconnected.bind(this);
185
+ this._bleDevice.addEventListener(
186
+ "gattserverdisconnected",
187
+ this._eventListenerFn
188
+ );
189
+
190
+ // Connected
191
+ this._isConnected = true;
192
+ return true;
193
+ } catch (error) {
194
+ RaftLog.error(
195
+ `RaftChannelWebBLE.connect - cannot find characteristic: ${error}`
196
+ );
197
+ }
198
+ } catch (error) {
199
+ if (connRetry === this._maxConnRetries - 1) {
200
+ RaftLog.error(
201
+ `RaftChannelWebBLE.connect - cannot get primary service ${error} - attempt #${connRetry+1} - giving up`
202
+ );
203
+ } else {
204
+ RaftLog.debug(
205
+ `RaftChannelWebBLE.connect - cannot get primary service - attempt #${connRetry+1} ${error}`
206
+ );
207
+ }
208
+ }
209
+ }
210
+ }
211
+ } catch (error: unknown) {
212
+ RaftLog.warn(`RaftChannelWebBLE.connect - cannot connect ${error}`);
213
+ }
214
+
215
+ // Disconnect
216
+ if (
217
+ this._bleDevice &&
218
+ this._bleDevice.gatt &&
219
+ this._bleDevice.gatt.connected
220
+ ) {
221
+ try {
222
+ await this._bleDevice.gatt.disconnect();
223
+ } catch (error) {
224
+ RaftLog.warn(`RaftChannelWebBLE.connect - cannot disconnect ${error}`);
225
+ }
226
+ }
227
+ }
228
+
229
+ return false;
230
+ }
231
+
232
+ // Disconnect
233
+ async disconnect(): Promise<void> {
234
+ if (this._bleDevice && this._bleDevice.gatt) {
235
+ try {
236
+ RaftLog.debug(`RaftChannelWebBLE.disconnect GATT`);
237
+ await this._bleDevice.gatt.disconnect();
238
+ } catch (error) {
239
+ RaftLog.debug(`RaftChannelWebBLE.disconnect ${error}`);
240
+ }
241
+ }
242
+ }
243
+
244
+ pauseConnection(pause: boolean): void {
245
+ RaftLog.verbose(
246
+ `pauseConnection ${pause} - no effect for this channel type`
247
+ );
248
+ return;
249
+ }
250
+
251
+ // Handle notifications
252
+ _onMsgRx(event: Event): void {
253
+ // Get characteristic
254
+ const characteristic = event.target as BluetoothRemoteGATTCharacteristic;
255
+
256
+ // Get value
257
+ const value = characteristic.value;
258
+ if (value !== undefined) {
259
+ const msg = new Uint8Array(value.buffer);
260
+
261
+ // Handle message
262
+ if (this._raftMsgHandler) {
263
+ try {
264
+ this._raftMsgHandler.handleNewRxMsg(msg);
265
+ } catch (error) {
266
+ RaftLog.debug(`RaftChannelWebBLE.onMsgRx ${error}`);
267
+ }
268
+ }
269
+ }
270
+ }
271
+
272
+ // Send a message
273
+ async sendTxMsg(
274
+ msg: Uint8Array
275
+ // _sendWithResponse: boolean
276
+ ): Promise<boolean> {
277
+ // Check valid
278
+ if (this._bleDevice === null) {
279
+ return false;
280
+ }
281
+
282
+ // Retry upto maxRetries
283
+ for (let retryIdx = 0; retryIdx < this.maxRetries; retryIdx++) {
284
+ // Check for min time between messages
285
+ while (Date.now() - this._msgTxTimeLast < this._msgTxMinTimeBetweenMs) {
286
+ await new Promise((resolve) => setTimeout(resolve, 5));
287
+ }
288
+ this._msgTxTimeLast = Date.now();
289
+
290
+ // Write to the characteristic
291
+ try {
292
+ if (this._characteristicTx) {
293
+ if (this._characteristicTx.writeValueWithoutResponse) {
294
+ await this._characteristicTx.writeValueWithoutResponse(msg);
295
+ } else if (this._characteristicTx.writeValue) {
296
+ await this._characteristicTx.writeValue(msg);
297
+ } else if (this._characteristicTx.writeValueWithResponse) {
298
+ await this._characteristicTx.writeValueWithResponse(msg);
299
+ }
300
+ }
301
+ break;
302
+ } catch (error) {
303
+ if (retryIdx === this.maxRetries - 1) {
304
+ RaftLog.info(
305
+ `RaftChannelWebBLE.sendTxMsg ${error} retried ${retryIdx} times`
306
+ );
307
+ }
308
+ }
309
+ }
310
+ return true;
311
+ }
312
+
313
+ // Send message without awaiting response
314
+ async sendTxMsgNoAwait(
315
+ msg: Uint8Array
316
+ // _sendWithResponse: boolean
317
+ ): Promise<boolean> {
318
+ // Check valid
319
+ if (this._bleDevice === null) {
320
+ return false;
321
+ }
322
+
323
+ // Check for min time between messages
324
+ while (Date.now() - this._msgTxTimeLast < this._msgTxMinTimeBetweenMs) {
325
+ await new Promise((resolve) => setTimeout(resolve, 5));
326
+ }
327
+ this._msgTxTimeLast = Date.now();
328
+
329
+ // Write to the characteristic
330
+ if (this._characteristicTx) {
331
+ if (this._characteristicTx.writeValueWithoutResponse) {
332
+ this._characteristicTx.writeValueWithoutResponse(msg);
333
+ } else if (this._characteristicTx.writeValue) {
334
+ this._characteristicTx.writeValue(msg);
335
+ } else if (this._characteristicTx.writeValueWithResponse) {
336
+ this._characteristicTx.writeValueWithResponse(msg);
337
+ }
338
+ return true;
339
+ }
340
+ return false;
341
+ }
342
+ }