brilliantsole 0.0.27 → 0.0.29

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 (202) hide show
  1. package/assets/3d/anchor.glb +0 -0
  2. package/assets/3d/coin.glb +0 -0
  3. package/assets/3d/glasses.glb +0 -0
  4. package/assets/audio/bounceMedium.wav +0 -0
  5. package/assets/audio/bounceStrong.wav +0 -0
  6. package/assets/audio/bounceWeak.wav +0 -0
  7. package/assets/audio/coin.wav +0 -0
  8. package/assets/audio/getUp.wav +0 -0
  9. package/assets/audio/grab.wav +0 -0
  10. package/assets/audio/kick.wav +0 -0
  11. package/assets/audio/platterFadeIn old.wav +0 -0
  12. package/assets/audio/platterFadeIn.wav +0 -0
  13. package/assets/audio/platterFadeOut.wav +0 -0
  14. package/assets/audio/punch.wav +0 -0
  15. package/assets/audio/punchSqueak.wav +0 -0
  16. package/assets/audio/purr.wav +0 -0
  17. package/assets/audio/purrFadeOut.wav +0 -0
  18. package/assets/audio/release.wav +0 -0
  19. package/assets/audio/splat.wav +0 -0
  20. package/assets/audio/stomp.wav +0 -0
  21. package/build/brilliantsole.cjs +3091 -741
  22. package/build/brilliantsole.cjs.map +1 -1
  23. package/build/brilliantsole.js +2759 -709
  24. package/build/brilliantsole.js.map +1 -1
  25. package/build/brilliantsole.ls.js +2602 -543
  26. package/build/brilliantsole.ls.js.map +1 -1
  27. package/build/brilliantsole.min.js +1 -1
  28. package/build/brilliantsole.min.js.map +1 -1
  29. package/build/brilliantsole.module.d.ts +295 -65
  30. package/build/brilliantsole.module.js +2749 -710
  31. package/build/brilliantsole.module.js.map +1 -1
  32. package/build/brilliantsole.module.min.d.ts +295 -65
  33. package/build/brilliantsole.module.min.js +1 -1
  34. package/build/brilliantsole.module.min.js.map +1 -1
  35. package/build/brilliantsole.node.module.d.ts +289 -62
  36. package/build/brilliantsole.node.module.js +3080 -742
  37. package/build/brilliantsole.node.module.js.map +1 -1
  38. package/build/dts/BS-output.d.ts +10 -0
  39. package/build/dts/BS.d.ts +21 -8
  40. package/build/dts/CameraManager.d.ts +72 -0
  41. package/build/dts/Device.d.ts +64 -13
  42. package/build/dts/DeviceInformationManager.d.ts +4 -4
  43. package/build/dts/DeviceManager.d.ts +2 -0
  44. package/build/dts/FileTransferManager.d.ts +18 -8
  45. package/build/dts/InformationManager.d.ts +2 -0
  46. package/build/dts/MicrophoneManager.d.ts +88 -0
  47. package/build/dts/TfliteManager.d.ts +22 -2
  48. package/build/dts/WifiManager.d.ts +61 -0
  49. package/build/dts/connection/BaseConnectionManager.d.ts +35 -3
  50. package/build/dts/connection/ClientConnectionManager.d.ts +7 -2
  51. package/build/dts/connection/bluetooth/NobleConnectionManager.d.ts +2 -1
  52. package/build/dts/connection/bluetooth/WebBluetoothConnectionManager.d.ts +1 -0
  53. package/build/dts/connection/bluetooth/bluetoothUUIDs.d.ts +2 -2
  54. package/build/dts/connection/udp/UDPConnectionManager.d.ts +28 -0
  55. package/build/dts/connection/webSocket/WebSocketConnectionManager.d.ts +25 -0
  56. package/build/dts/devicePair/DevicePair.d.ts +5 -5
  57. package/build/dts/scanner/BaseScanner.d.ts +4 -1
  58. package/build/dts/scanner/NobleScanner.d.ts +2 -1
  59. package/build/dts/sensor/MotionSensorDataManager.d.ts +5 -2
  60. package/build/dts/sensor/SensorDataManager.d.ts +5 -4
  61. package/build/dts/server/BaseClient.d.ts +5 -3
  62. package/build/dts/server/ServerUtils.d.ts +1 -1
  63. package/build/dts/server/websocket/WebSocketUtils.d.ts +1 -1
  64. package/build/dts/utils/AudioUtils.d.ts +2 -0
  65. package/build/dts/utils/Console.d.ts +2 -0
  66. package/build/dts/utils/ThrottleUtils.d.ts +2 -0
  67. package/build/dts/vibration/VibrationManager.d.ts +19 -2
  68. package/build/index.d.ts +292 -62
  69. package/build/index.node.d.ts +286 -59
  70. package/examples/3d/scene.html +19 -5
  71. package/examples/3d-generic/index.html +144 -0
  72. package/examples/3d-generic/script.js +266 -0
  73. package/examples/basic/index.html +267 -17
  74. package/examples/basic/script.js +958 -105
  75. package/examples/camera/barcode-detector.js +109 -0
  76. package/examples/camera/depth-estimation.js +71 -0
  77. package/examples/camera/face-detector.js +119 -0
  78. package/examples/camera/face-landmark.js +111 -0
  79. package/examples/camera/gesture-recognition.js +97 -0
  80. package/examples/camera/hand-landmark.js +74 -0
  81. package/examples/camera/image-segmentation.js +98 -0
  82. package/examples/camera/image-to-text.js +43 -0
  83. package/examples/camera/image-upscale.js +75 -0
  84. package/examples/camera/index.html +129 -0
  85. package/examples/camera/object-detection.js +98 -0
  86. package/examples/camera/pose-landmark.js +60 -0
  87. package/examples/camera/script.js +316 -0
  88. package/examples/camera/utils.js +165 -0
  89. package/examples/camera/yolo-tiny.js +54 -0
  90. package/examples/camera/yolo.js +119 -0
  91. package/examples/edge-impulse/script.js +157 -48
  92. package/examples/edge-impulse-test/README.md +11 -0
  93. package/examples/edge-impulse-test/edge-impulse-standalone.js +7228 -0
  94. package/examples/edge-impulse-test/edge-impulse-standalone.wasm +0 -0
  95. package/examples/edge-impulse-test/index.html +75 -0
  96. package/examples/edge-impulse-test/run-impulse.js +135 -0
  97. package/examples/edge-impulse-test/script.js +200 -0
  98. package/examples/glasses-gestures/README.md +11 -0
  99. package/examples/glasses-gestures/edge-impulse-standalone.js +7228 -0
  100. package/examples/glasses-gestures/edge-impulse-standalone.wasm +0 -0
  101. package/examples/glasses-gestures/index.html +69 -0
  102. package/examples/glasses-gestures/run-impulse.js +135 -0
  103. package/examples/glasses-gestures/script.js +226 -0
  104. package/examples/gloves/edge-impulse-standalone.js +7228 -0
  105. package/examples/gloves/edge-impulse-standalone.wasm +0 -0
  106. package/examples/gloves/index.html +4 -1
  107. package/examples/gloves/run-impulse.js +135 -0
  108. package/examples/gloves/script.js +367 -51
  109. package/examples/graph/script.js +94 -37
  110. package/examples/microphone/gender.js +54 -0
  111. package/examples/microphone/index.html +102 -0
  112. package/examples/microphone/script.js +394 -0
  113. package/examples/microphone/utils.js +45 -0
  114. package/examples/microphone/whisper-realtime.js +166 -0
  115. package/examples/microphone/whisper.js +132 -0
  116. package/examples/punch/index.html +135 -0
  117. package/examples/punch/punch.tflite +0 -0
  118. package/examples/punch/script.js +169 -0
  119. package/examples/server/index.html +98 -22
  120. package/examples/server/script.js +317 -109
  121. package/examples/ukaton-firmware-update/merged-firmware.bin +0 -0
  122. package/examples/utils/aframe/aframe-master.min.js +2 -0
  123. package/examples/utils/aframe/bs-vibration.js +150 -0
  124. package/examples/utils/aframe/force-pushable.js +80 -0
  125. package/examples/utils/aframe/grabbable-anchor.js +46 -0
  126. package/examples/utils/aframe/grabbable-listener.js +31 -0
  127. package/examples/utils/aframe/grabbable-physics-body.js +190 -0
  128. package/examples/utils/aframe/grow-shrink.js +25 -0
  129. package/examples/utils/aframe/hand-punch.js +119 -0
  130. package/examples/utils/aframe/my-obb-collider.js +293 -0
  131. package/examples/utils/aframe/occlude-hand-tracking-controls.js +47 -0
  132. package/examples/utils/aframe/occlude-mesh.js +42 -0
  133. package/examples/utils/aframe/palm-up-detector.js +47 -0
  134. package/examples/utils/aframe/shadow-material.js +20 -0
  135. package/examples/utils/aframe/soft-shadow-light.js +9 -0
  136. package/examples/webxr-2/assets/3d/soccerBall.glb +0 -0
  137. package/examples/webxr-2/assets/audio/shellBounce.wav +0 -0
  138. package/examples/webxr-2/assets/audio/shellHit.wav +0 -0
  139. package/examples/webxr-2/assets/audio/shellKick.wav +0 -0
  140. package/examples/webxr-2/assets/audio/soccerBounce.wav +0 -0
  141. package/examples/webxr-2/assets/audio/soccerKick.mp3 +0 -0
  142. package/examples/webxr-2/assets/images/shellTexture.png +0 -0
  143. package/examples/webxr-2/components/bs-ankle.js +337 -0
  144. package/examples/webxr-2/components/coin.js +84 -0
  145. package/examples/webxr-2/components/custom-wrap.js +17 -0
  146. package/examples/webxr-2/components/goomba.js +3250 -0
  147. package/examples/webxr-2/components/init-shell-material.js +215 -0
  148. package/examples/webxr-2/components/platter.js +172 -0
  149. package/examples/webxr-2/components/shell.js +374 -0
  150. package/examples/webxr-2/components/soccer-ball.js +250 -0
  151. package/examples/webxr-2/components/squashed-goomba.js +249 -0
  152. package/examples/webxr-2/edge-impulse-standalone.js +7228 -0
  153. package/examples/webxr-2/edge-impulse-standalone.wasm +0 -0
  154. package/examples/webxr-2/index.html +996 -0
  155. package/examples/webxr-2/kick.tflite +0 -0
  156. package/examples/webxr-2/kick2.tflite +0 -0
  157. package/examples/webxr-2/run-impulse.js +135 -0
  158. package/examples/webxr-2/script.js +384 -0
  159. package/examples/webxr-3/components/bs-camera.js +65 -0
  160. package/examples/webxr-3/index.html +134 -0
  161. package/examples/webxr-3/script.js +432 -0
  162. package/package.json +2 -1
  163. package/src/.prettierrc +4 -0
  164. package/src/BS.ts +79 -8
  165. package/src/CameraManager.ts +497 -0
  166. package/src/Device.ts +691 -86
  167. package/src/DeviceInformationManager.ts +19 -10
  168. package/src/DeviceManager.ts +85 -25
  169. package/src/FileTransferManager.ts +145 -20
  170. package/src/InformationManager.ts +40 -15
  171. package/src/MicrophoneManager.ts +599 -0
  172. package/src/TfliteManager.ts +171 -25
  173. package/src/WifiManager.ts +323 -0
  174. package/src/connection/BaseConnectionManager.ts +130 -30
  175. package/src/connection/ClientConnectionManager.ts +34 -10
  176. package/src/connection/bluetooth/BluetoothConnectionManager.ts +8 -2
  177. package/src/connection/bluetooth/NobleConnectionManager.ts +147 -41
  178. package/src/connection/bluetooth/WebBluetoothConnectionManager.ts +99 -34
  179. package/src/connection/bluetooth/bluetoothUUIDs.ts +40 -13
  180. package/src/connection/udp/UDPConnectionManager.ts +356 -0
  181. package/src/connection/websocket/WebSocketConnectionManager.ts +282 -0
  182. package/src/devicePair/DevicePair.ts +95 -25
  183. package/src/devicePair/DevicePairPressureSensorDataManager.ts +27 -7
  184. package/src/scanner/BaseScanner.ts +49 -11
  185. package/src/scanner/NobleScanner.ts +76 -14
  186. package/src/sensor/MotionSensorDataManager.ts +21 -6
  187. package/src/sensor/PressureSensorDataManager.ts +37 -8
  188. package/src/sensor/SensorConfigurationManager.ts +73 -22
  189. package/src/sensor/SensorDataManager.ts +109 -23
  190. package/src/server/BaseClient.ts +150 -36
  191. package/src/server/BaseServer.ts +50 -2
  192. package/src/server/ServerUtils.ts +39 -9
  193. package/src/server/udp/UDPServer.ts +73 -22
  194. package/src/server/udp/UDPUtils.ts +9 -2
  195. package/src/server/websocket/WebSocketClient.ts +27 -7
  196. package/src/server/websocket/WebSocketUtils.ts +4 -2
  197. package/src/utils/AudioUtils.ts +65 -0
  198. package/src/utils/Console.ts +62 -9
  199. package/src/utils/ParseUtils.ts +24 -5
  200. package/src/utils/ThrottleUtils.ts +62 -0
  201. package/src/utils/Timer.ts +1 -1
  202. package/src/vibration/VibrationManager.ts +166 -40
@@ -22,19 +22,23 @@ export interface DeviceInformation {
22
22
  serialNumber: string;
23
23
  }
24
24
 
25
- export const DeviceInformationMessageTypes = [
25
+ export const DeviceInformationTypes = [
26
26
  "manufacturerName",
27
27
  "modelNumber",
28
- "softwareRevision",
29
28
  "hardwareRevision",
30
29
  "firmwareRevision",
30
+ "softwareRevision",
31
31
  "pnpId",
32
32
  "serialNumber",
33
33
  ] as const;
34
- export type DeviceInformationMessageType = (typeof DeviceInformationMessageTypes)[number];
34
+ export type DeviceInformationType = (typeof DeviceInformationTypes)[number];
35
35
 
36
- export const DeviceInformationEventTypes = [...DeviceInformationMessageTypes, "deviceInformation"] as const;
37
- export type DeviceInformationEventType = (typeof DeviceInformationEventTypes)[number];
36
+ export const DeviceInformationEventTypes = [
37
+ ...DeviceInformationTypes,
38
+ "deviceInformation",
39
+ ] as const;
40
+ export type DeviceInformationEventType =
41
+ (typeof DeviceInformationEventTypes)[number];
38
42
 
39
43
  export interface DeviceInformationEventMessages {
40
44
  manufacturerName: { manufacturerName: string };
@@ -67,18 +71,21 @@ class DeviceInformationManager {
67
71
  this.#information = {};
68
72
  }
69
73
  get #isComplete() {
70
- return DeviceInformationMessageTypes.filter((key) => key != "serialNumber").every(
74
+ return DeviceInformationTypes.filter((key) => key != "serialNumber").every(
71
75
  (key) => key in this.#information
72
76
  );
73
77
  }
74
78
 
75
79
  #update(partialDeviceInformation: Partial<DeviceInformation>) {
76
80
  _console.log({ partialDeviceInformation });
77
- const deviceInformationNames = Object.keys(partialDeviceInformation) as (keyof DeviceInformation)[];
81
+ const deviceInformationNames = Object.keys(
82
+ partialDeviceInformation
83
+ ) as (keyof DeviceInformation)[];
78
84
  deviceInformationNames.forEach((deviceInformationName) => {
79
85
  // @ts-expect-error
80
86
  this.#dispatchEvent(deviceInformationName, {
81
- [deviceInformationName]: partialDeviceInformation[deviceInformationName],
87
+ [deviceInformationName]:
88
+ partialDeviceInformation[deviceInformationName],
82
89
  });
83
90
  });
84
91
 
@@ -86,11 +93,13 @@ class DeviceInformationManager {
86
93
  _console.log({ deviceInformation: this.#information });
87
94
  if (this.#isComplete) {
88
95
  _console.log("completed deviceInformation");
89
- this.#dispatchEvent("deviceInformation", { deviceInformation: this.information });
96
+ this.#dispatchEvent("deviceInformation", {
97
+ deviceInformation: this.information,
98
+ });
90
99
  }
91
100
  }
92
101
 
93
- parseMessage(messageType: DeviceInformationMessageType, dataView: DataView) {
102
+ parseMessage(messageType: DeviceInformationType, dataView: DataView) {
94
103
  _console.log({ messageType });
95
104
 
96
105
  switch (messageType) {
@@ -4,7 +4,12 @@ import Device, { BoundDeviceEventListeners, DeviceEventMap } from "./Device.ts";
4
4
  import { DeviceType } from "./InformationManager.ts";
5
5
  import { createConsole } from "./utils/Console.ts";
6
6
  import { isInBluefy, isInBrowser } from "./utils/environment.ts";
7
- import EventDispatcher, { BoundEventListeners, Event, EventListenerMap, EventMap } from "./utils/EventDispatcher.ts";
7
+ import EventDispatcher, {
8
+ BoundEventListeners,
9
+ Event,
10
+ EventListenerMap,
11
+ EventMap,
12
+ } from "./utils/EventDispatcher.ts";
8
13
  import { addEventListeners } from "./utils/EventUtils.ts";
9
14
 
10
15
  const _console = createConsole("DeviceManager", { log: false });
@@ -12,6 +17,8 @@ const _console = createConsole("DeviceManager", { log: false });
12
17
  export interface LocalStorageDeviceInformation {
13
18
  type: DeviceType;
14
19
  bluetoothId: string;
20
+ ipAddress?: string;
21
+ isWifiSecure?: boolean;
15
22
  }
16
23
 
17
24
  export interface LocalStorageConfiguration {
@@ -43,13 +50,21 @@ export type DeviceManagerEventDispatcher = EventDispatcher<
43
50
  DeviceManagerEventType,
44
51
  DeviceManagerEventMessages
45
52
  >;
46
- export type DeviceManagerEventMap = EventMap<typeof Device, DeviceManagerEventType, DeviceManagerEventMessages>;
53
+ export type DeviceManagerEventMap = EventMap<
54
+ typeof Device,
55
+ DeviceManagerEventType,
56
+ DeviceManagerEventMessages
57
+ >;
47
58
  export type DeviceManagerEventListenerMap = EventListenerMap<
48
59
  typeof Device,
49
60
  DeviceManagerEventType,
50
61
  DeviceManagerEventMessages
51
62
  >;
52
- export type DeviceManagerEvent = Event<typeof Device, DeviceManagerEventType, DeviceManagerEventMessages>;
63
+ export type DeviceManagerEvent = Event<
64
+ typeof Device,
65
+ DeviceManagerEventType,
66
+ DeviceManagerEventMessages
67
+ >;
53
68
  export type BoundDeviceManagerEventListeners = BoundEventListeners<
54
69
  typeof Device,
55
70
  DeviceManagerEventType,
@@ -87,8 +102,15 @@ class DeviceManager {
87
102
 
88
103
  // CONNECTION STATUS
89
104
  /** @private */
90
- OnDeviceConnectionStatusUpdated(device: Device, connectionStatus: ConnectionStatus) {
91
- if (connectionStatus == "notConnected" && !device.canReconnect && this.#AvailableDevices.includes(device)) {
105
+ OnDeviceConnectionStatusUpdated(
106
+ device: Device,
107
+ connectionStatus: ConnectionStatus
108
+ ) {
109
+ if (
110
+ connectionStatus == "notConnected" &&
111
+ !device.canReconnect &&
112
+ this.#AvailableDevices.includes(device)
113
+ ) {
92
114
  const deviceIndex = this.#AvailableDevices.indexOf(device);
93
115
  this.AvailableDevices.splice(deviceIndex, 1);
94
116
  this.#DispatchAvailableDevices();
@@ -125,20 +147,29 @@ class DeviceManager {
125
147
  }
126
148
 
127
149
  #AssertLocalStorage() {
128
- _console.assertWithError(isInBrowser, "localStorage is only available in the browser");
150
+ _console.assertWithError(
151
+ isInBrowser,
152
+ "localStorage is only available in the browser"
153
+ );
129
154
  _console.assertWithError(window.localStorage, "localStorage not found");
130
155
  }
131
156
  #LocalStorageKey = "BS.Device";
132
157
  #SaveToLocalStorage() {
133
158
  this.#AssertLocalStorage();
134
- localStorage.setItem(this.#LocalStorageKey, JSON.stringify(this.#LocalStorageConfiguration));
159
+ localStorage.setItem(
160
+ this.#LocalStorageKey,
161
+ JSON.stringify(this.#LocalStorageConfiguration)
162
+ );
135
163
  }
136
164
  async #LoadFromLocalStorage() {
137
165
  this.#AssertLocalStorage();
138
166
  let localStorageString = localStorage.getItem(this.#LocalStorageKey);
139
167
  if (typeof localStorageString != "string") {
140
168
  _console.log("no info found in localStorage");
141
- this.#LocalStorageConfiguration = Object.assign({}, this.#DefaultLocalStorageConfiguration);
169
+ this.#LocalStorageConfiguration = Object.assign(
170
+ {},
171
+ this.#DefaultLocalStorageConfiguration
172
+ );
142
173
  this.#SaveToLocalStorage();
143
174
  return;
144
175
  }
@@ -160,13 +191,17 @@ class DeviceManager {
160
191
  return;
161
192
  }
162
193
  this.#AssertLocalStorage();
163
- const deviceInformationIndex = this.#LocalStorageConfiguration!.devices.findIndex((deviceInformation) => {
164
- return deviceInformation.bluetoothId == device.bluetoothId;
165
- });
194
+ const deviceInformationIndex =
195
+ this.#LocalStorageConfiguration!.devices.findIndex(
196
+ (deviceInformation) => {
197
+ return deviceInformation.bluetoothId == device.bluetoothId;
198
+ }
199
+ );
166
200
  if (deviceInformationIndex == -1) {
167
201
  return;
168
202
  }
169
- this.#LocalStorageConfiguration!.devices[deviceInformationIndex].type = device.type;
203
+ this.#LocalStorageConfiguration!.devices[deviceInformationIndex].type =
204
+ device.type;
170
205
  this.#SaveToLocalStorage();
171
206
  }
172
207
 
@@ -229,7 +264,8 @@ class DeviceManager {
229
264
  return;
230
265
  }
231
266
  let deviceInformation = configuration.devices.find(
232
- (deviceInformation) => bluetoothDevice.id == deviceInformation.bluetoothId
267
+ (deviceInformation) =>
268
+ bluetoothDevice.id == deviceInformation.bluetoothId
233
269
  );
234
270
  if (!deviceInformation) {
235
271
  return;
@@ -245,10 +281,13 @@ class DeviceManager {
245
281
  if (existingAvailableDevice) {
246
282
  if (
247
283
  existingConnectedDevice &&
248
- existingConnectedDevice?.bluetoothId == existingAvailableDevice.bluetoothId &&
284
+ existingConnectedDevice?.bluetoothId ==
285
+ existingAvailableDevice.bluetoothId &&
249
286
  existingConnectedDevice != existingAvailableDevice
250
287
  ) {
251
- this.AvailableDevices[this.#AvailableDevices.indexOf(existingAvailableDevice)] = existingConnectedDevice;
288
+ this.AvailableDevices[
289
+ this.#AvailableDevices.indexOf(existingAvailableDevice)
290
+ ] = existingConnectedDevice;
252
291
  }
253
292
  return;
254
293
  }
@@ -274,7 +313,10 @@ class DeviceManager {
274
313
 
275
314
  // STATIC EVENTLISTENERS
276
315
 
277
- #EventDispatcher: DeviceManagerEventDispatcher = new EventDispatcher(this as DeviceManager, DeviceManagerEventTypes);
316
+ #EventDispatcher: DeviceManagerEventDispatcher = new EventDispatcher(
317
+ this as DeviceManager,
318
+ DeviceManagerEventTypes
319
+ );
278
320
 
279
321
  get AddEventListener() {
280
322
  return this.#EventDispatcher.addEventListener;
@@ -302,14 +344,19 @@ class DeviceManager {
302
344
  const deviceInformation: LocalStorageDeviceInformation = {
303
345
  type: device.type,
304
346
  bluetoothId: device.bluetoothId!,
347
+ ipAddress: device.ipAddress,
348
+ isWifiSecure: device.isWifiSecure,
305
349
  };
306
- const deviceInformationIndex = this.#LocalStorageConfiguration!.devices.findIndex(
307
- (_deviceInformation) => _deviceInformation.bluetoothId == deviceInformation.bluetoothId
308
- );
350
+ const deviceInformationIndex =
351
+ this.#LocalStorageConfiguration!.devices.findIndex(
352
+ (_deviceInformation) =>
353
+ _deviceInformation.bluetoothId == deviceInformation.bluetoothId
354
+ );
309
355
  if (deviceInformationIndex == -1) {
310
356
  this.#LocalStorageConfiguration!.devices.push(deviceInformation);
311
357
  } else {
312
- this.#LocalStorageConfiguration!.devices[deviceInformationIndex] = deviceInformation;
358
+ this.#LocalStorageConfiguration!.devices[deviceInformationIndex] =
359
+ deviceInformation;
313
360
  }
314
361
  this.#SaveToLocalStorage();
315
362
  }
@@ -322,7 +369,10 @@ class DeviceManager {
322
369
  } else {
323
370
  if (this.#ConnectedDevices.includes(device)) {
324
371
  _console.log("removing device", device);
325
- this.#ConnectedDevices.splice(this.#ConnectedDevices.indexOf(device), 1);
372
+ this.#ConnectedDevices.splice(
373
+ this.#ConnectedDevices.indexOf(device),
374
+ 1
375
+ );
326
376
  this.#DispatchEvent("deviceDisconnected", { device });
327
377
  this.#DispatchEvent("deviceIsConnected", { device });
328
378
  this.#DispatchConnectedDevices();
@@ -339,7 +389,9 @@ class DeviceManager {
339
389
  );
340
390
  _console.log({ existingAvailableDevice });
341
391
  if (existingAvailableDevice) {
342
- this.AvailableDevices[this.AvailableDevices.indexOf(existingAvailableDevice)] = device;
392
+ this.AvailableDevices[
393
+ this.AvailableDevices.indexOf(existingAvailableDevice)
394
+ ] = device;
343
395
  } else {
344
396
  this.AvailableDevices.push(device);
345
397
  }
@@ -349,7 +401,11 @@ class DeviceManager {
349
401
  }
350
402
 
351
403
  _CheckDeviceAvailability(device: Device) {
352
- if (!device.isConnected && !device.isAvailable && this.#AvailableDevices.includes(device)) {
404
+ if (
405
+ !device.isConnected &&
406
+ !device.isAvailable &&
407
+ this.#AvailableDevices.includes(device)
408
+ ) {
353
409
  _console.log("removing device from availableDevices...");
354
410
  this.#AvailableDevices.splice(this.#AvailableDevices.indexOf(device), 1);
355
411
  this.#DispatchAvailableDevices();
@@ -358,11 +414,15 @@ class DeviceManager {
358
414
 
359
415
  #DispatchAvailableDevices() {
360
416
  _console.log({ AvailableDevices: this.AvailableDevices });
361
- this.#DispatchEvent("availableDevices", { availableDevices: this.AvailableDevices });
417
+ this.#DispatchEvent("availableDevices", {
418
+ availableDevices: this.AvailableDevices,
419
+ });
362
420
  }
363
421
  #DispatchConnectedDevices() {
364
422
  _console.log({ ConnectedDevices: this.ConnectedDevices });
365
- this.#DispatchEvent("connectedDevices", { connectedDevices: this.ConnectedDevices });
423
+ this.#DispatchEvent("connectedDevices", {
424
+ connectedDevices: this.ConnectedDevices,
425
+ });
366
426
  }
367
427
  }
368
428
 
@@ -9,6 +9,7 @@ import autoBind from "auto-bind";
9
9
  const _console = createConsole("FileTransferManager", { log: false });
10
10
 
11
11
  export const FileTransferMessageTypes = [
12
+ "getFileTypes",
12
13
  "maxFileLength",
13
14
  "getFileType",
14
15
  "setFileType",
@@ -24,13 +25,17 @@ export const FileTransferMessageTypes = [
24
25
  ] as const;
25
26
  export type FileTransferMessageType = (typeof FileTransferMessageTypes)[number];
26
27
 
27
- export const FileTypes = ["tflite"] as const;
28
+ export const FileTypes = ["tflite", "wifiServerCert", "wifiServerKey"] as const;
28
29
  export type FileType = (typeof FileTypes)[number];
29
30
 
30
31
  export const FileTransferStatuses = ["idle", "sending", "receiving"] as const;
31
32
  export type FileTransferStatus = (typeof FileTransferStatuses)[number];
32
33
 
33
- export const FileTransferCommands = ["startSend", "startReceive", "cancel"] as const;
34
+ export const FileTransferCommands = [
35
+ "startSend",
36
+ "startReceive",
37
+ "cancel",
38
+ ] as const;
34
39
  export type FileTransferCommand = (typeof FileTransferCommands)[number];
35
40
 
36
41
  export const FileTransferDirections = ["sending", "receiving"] as const;
@@ -44,7 +49,21 @@ export const FileTransferEventTypes = [
44
49
  ] as const;
45
50
  export type FileTransferEventType = (typeof FileTransferEventTypes)[number];
46
51
 
52
+ export const RequiredFileTransferMessageTypes: FileTransferMessageType[] = [
53
+ "maxFileLength",
54
+ "getFileLength",
55
+ "getFileChecksum",
56
+ "getFileType",
57
+ "fileTransferStatus",
58
+ ];
59
+
60
+ export interface FileConfiguration {
61
+ file: FileLike;
62
+ type: FileType;
63
+ }
64
+
47
65
  export interface FileTransferEventMessages {
66
+ getFileTypes: { fileTypes: FileType[] };
48
67
  maxFileLength: { maxFileLength: number };
49
68
  getFileType: { fileType: FileType };
50
69
  getFileLength: { fileLength: number };
@@ -56,8 +75,13 @@ export interface FileTransferEventMessages {
56
75
  fileReceived: { file: File | Blob };
57
76
  }
58
77
 
59
- export type FileTransferEventDispatcher = EventDispatcher<Device, FileTransferEventType, FileTransferEventMessages>;
60
- export type SendFileTransferMessageCallback = SendMessageCallback<FileTransferMessageType>;
78
+ export type FileTransferEventDispatcher = EventDispatcher<
79
+ Device,
80
+ FileTransferEventType,
81
+ FileTransferEventMessages
82
+ >;
83
+ export type SendFileTransferMessageCallback =
84
+ SendMessageCallback<FileTransferMessageType>;
61
85
 
62
86
  class FileTransferManager {
63
87
  constructor() {
@@ -82,17 +106,41 @@ class FileTransferManager {
82
106
  #assertValidType(type: FileType) {
83
107
  _console.assertEnumWithError(type, FileTypes);
84
108
  }
109
+ #isValidType(type: FileType) {
110
+ return FileTypes.includes(type);
111
+ }
85
112
  #assertValidTypeEnum(typeEnum: number) {
86
- _console.assertWithError(typeEnum in FileTypes, `invalid typeEnum ${typeEnum}`);
113
+ _console.assertWithError(
114
+ typeEnum in FileTypes,
115
+ `invalid typeEnum ${typeEnum}`
116
+ );
87
117
  }
88
118
 
89
119
  #assertValidStatusEnum(statusEnum: number) {
90
- _console.assertWithError(statusEnum in FileTransferStatuses, `invalid statusEnum ${statusEnum}`);
120
+ _console.assertWithError(
121
+ statusEnum in FileTransferStatuses,
122
+ `invalid statusEnum ${statusEnum}`
123
+ );
91
124
  }
92
125
  #assertValidCommand(command: FileTransferCommand) {
93
126
  _console.assertEnumWithError(command, FileTransferCommands);
94
127
  }
95
128
 
129
+ #fileTypes: FileType[] = [];
130
+ get fileTypes() {
131
+ return this.#fileTypes;
132
+ }
133
+ #parseFileTypes(dataView: DataView) {
134
+ const fileTypes = Array.from(new Uint8Array(dataView.buffer))
135
+ .map((index) => FileTypes[index])
136
+ .filter(Boolean);
137
+ this.#fileTypes = fileTypes;
138
+ _console.log("fileTypes", fileTypes);
139
+ this.#dispatchEvent("getFileTypes", {
140
+ fileTypes: this.#fileTypes,
141
+ });
142
+ }
143
+
96
144
  static #MaxLength = 0; // kB
97
145
  static get MaxLength() {
98
146
  return this.#MaxLength;
@@ -146,7 +194,10 @@ class FileTransferManager {
146
194
  const promise = this.waitForEvent("getFileType");
147
195
 
148
196
  const typeEnum = FileTypes.indexOf(newType);
149
- this.sendMessage([{ type: "setFileType", data: Uint8Array.from([typeEnum]).buffer }], sendImmediately);
197
+ this.sendMessage(
198
+ [{ type: "setFileType", data: Uint8Array.from([typeEnum]).buffer }],
199
+ sendImmediately
200
+ );
150
201
 
151
202
  await promise;
152
203
  }
@@ -178,7 +229,10 @@ class FileTransferManager {
178
229
 
179
230
  const dataView = new DataView(new ArrayBuffer(4));
180
231
  dataView.setUint32(0, newLength, true);
181
- this.sendMessage([{ type: "setFileLength", data: dataView.buffer }], sendImmediately);
232
+ this.sendMessage(
233
+ [{ type: "setFileLength", data: dataView.buffer }],
234
+ sendImmediately
235
+ );
182
236
 
183
237
  await promise;
184
238
  }
@@ -208,7 +262,10 @@ class FileTransferManager {
208
262
 
209
263
  const dataView = new DataView(new ArrayBuffer(4));
210
264
  dataView.setUint32(0, newChecksum, true);
211
- this.sendMessage([{ type: "setFileChecksum", data: dataView.buffer }], sendImmediately);
265
+ this.sendMessage(
266
+ [{ type: "setFileChecksum", data: dataView.buffer }],
267
+ sendImmediately
268
+ );
212
269
 
213
270
  await promise;
214
271
  }
@@ -220,7 +277,12 @@ class FileTransferManager {
220
277
  _console.log(`setting command ${command}`);
221
278
  const commandEnum = FileTransferCommands.indexOf(command);
222
279
  this.sendMessage(
223
- [{ type: "setFileTransferCommand", data: Uint8Array.from([commandEnum]).buffer }],
280
+ [
281
+ {
282
+ type: "setFileTransferCommand",
283
+ data: Uint8Array.from([commandEnum]).buffer,
284
+ },
285
+ ],
224
286
  sendImmediately
225
287
  );
226
288
 
@@ -243,6 +305,7 @@ class FileTransferManager {
243
305
  this.#status = status;
244
306
  this.#dispatchEvent("fileTransferStatus", { fileTransferStatus: status });
245
307
  this.#receivedBlocks.length = 0;
308
+ this.#isCancelling = false;
246
309
  }
247
310
  #assertIsIdle() {
248
311
  _console.assertWithError(this.#status == "idle", "status is not idle");
@@ -259,10 +322,15 @@ class FileTransferManager {
259
322
  _console.log("parseFileBlock", dataView);
260
323
  this.#receivedBlocks.push(dataView.buffer);
261
324
 
262
- const bytesReceived = this.#receivedBlocks.reduce((sum, arrayBuffer) => (sum += arrayBuffer.byteLength), 0);
325
+ const bytesReceived = this.#receivedBlocks.reduce(
326
+ (sum, arrayBuffer) => (sum += arrayBuffer.byteLength),
327
+ 0
328
+ );
263
329
  const progress = bytesReceived / this.#length;
264
330
 
265
- _console.log(`received ${bytesReceived} of ${this.#length} bytes (${progress * 100}%)`);
331
+ _console.log(
332
+ `received ${bytesReceived} of ${this.#length} bytes (${progress * 100}%)`
333
+ );
266
334
 
267
335
  this.#dispatchEvent("fileTransferProgress", { progress });
268
336
 
@@ -273,7 +341,9 @@ class FileTransferManager {
273
341
  if (this.isServerSide) {
274
342
  return;
275
343
  }
276
- await this.sendMessage([{ type: "fileBytesTransferred", data: dataView.buffer }]);
344
+ await this.sendMessage([
345
+ { type: "fileBytesTransferred", data: dataView.buffer },
346
+ ]);
277
347
  return;
278
348
  }
279
349
 
@@ -284,6 +354,12 @@ class FileTransferManager {
284
354
  case "tflite":
285
355
  fileName += ".tflite";
286
356
  break;
357
+ case "wifiServerCert":
358
+ fileName += "_server.crt";
359
+ break;
360
+ case "wifiServerKey":
361
+ fileName += "_server.key";
362
+ break;
287
363
  }
288
364
 
289
365
  let file: File | Blob;
@@ -298,7 +374,9 @@ class FileTransferManager {
298
374
  _console.log({ checksum });
299
375
 
300
376
  if (checksum != this.#checksum) {
301
- _console.error(`wrong checksum - expected ${this.#checksum}, got ${checksum}`);
377
+ _console.error(
378
+ `wrong checksum - expected ${this.#checksum}, got ${checksum}`
379
+ );
302
380
  return;
303
381
  }
304
382
 
@@ -313,6 +391,9 @@ class FileTransferManager {
313
391
  _console.log({ messageType });
314
392
 
315
393
  switch (messageType) {
394
+ case "getFileTypes":
395
+ this.#parseFileTypes(dataView);
396
+ break;
316
397
  case "maxFileLength":
317
398
  this.#parseMaxLength(dataView);
318
399
  break;
@@ -343,17 +424,39 @@ class FileTransferManager {
343
424
  }
344
425
 
345
426
  async send(type: FileType, file: FileLike) {
346
- this.#assertIsIdle();
427
+ if (true) {
428
+ this.#assertIsIdle();
429
+ this.#assertValidType(type);
430
+ } else {
431
+ if (this.status != "idle") {
432
+ _console.warn(`cannot send file - status is ${this.status}`);
433
+ return false;
434
+ }
435
+ if (!this.#isValidType(type)) {
436
+ _console.warn(`invalid fileType ${type}`);
437
+ return false;
438
+ }
439
+ }
347
440
 
348
- this.#assertValidType(type);
349
441
  const fileBuffer = await getFileBuffer(file);
442
+ const fileLength = fileBuffer.byteLength;
443
+ const checksum = crc32(fileBuffer);
444
+
445
+ if (type != this.type) {
446
+ _console.log("different fileTypes - sending");
447
+ } else if (fileLength != this.length) {
448
+ _console.log("different fileLengths - sending");
449
+ } else if (checksum != this.checksum) {
450
+ _console.log("different fileChecksums - sending");
451
+ } else {
452
+ _console.log("already sent file");
453
+ return false;
454
+ }
350
455
 
351
456
  const promises: Promise<any>[] = [];
352
457
 
353
458
  promises.push(this.#setType(type, false));
354
- const fileLength = fileBuffer.byteLength;
355
459
  promises.push(this.#setLength(fileLength, false));
356
- const checksum = crc32(fileBuffer);
357
460
  promises.push(this.#setChecksum(checksum, false));
358
461
  promises.push(this.#setCommand("startSend", false));
359
462
 
@@ -362,6 +465,8 @@ class FileTransferManager {
362
465
  await Promise.all(promises);
363
466
 
364
467
  await this.#send(fileBuffer);
468
+
469
+ return true;
365
470
  }
366
471
 
367
472
  #buffer?: ArrayBuffer;
@@ -377,6 +482,10 @@ class FileTransferManager {
377
482
  if (this.status != "sending") {
378
483
  return;
379
484
  }
485
+ if (this.#isCancelling) {
486
+ _console.error("not sending block - busy cancelling");
487
+ return;
488
+ }
380
489
  if (!this.#buffer) {
381
490
  if (!this.isServerSide) {
382
491
  _console.error("no buffer defined");
@@ -393,7 +502,9 @@ class FileTransferManager {
393
502
 
394
503
  const progress = 1 - bytesLeft / buffer.byteLength;
395
504
  _console.log(
396
- `sending bytes ${offset}-${offset + slicedBuffer.byteLength} of ${buffer.byteLength} bytes (${progress * 100}%)`
505
+ `sending bytes ${offset}-${offset + slicedBuffer.byteLength} of ${
506
+ buffer.byteLength
507
+ } bytes (${progress * 100}%)`
397
508
  );
398
509
  this.#dispatchEvent("fileTransferProgress", { progress });
399
510
  if (slicedBuffer.byteLength == 0) {
@@ -415,7 +526,11 @@ class FileTransferManager {
415
526
  return;
416
527
  }
417
528
  if (!this.isServerSide && this.#bytesTransferred != bytesTransferred) {
418
- _console.error(`bytesTransferred are not equal - got ${bytesTransferred}, expected ${this.#bytesTransferred}`);
529
+ _console.error(
530
+ `bytesTransferred are not equal - got ${bytesTransferred}, expected ${
531
+ this.#bytesTransferred
532
+ }`
533
+ );
419
534
  this.cancel();
420
535
  return;
421
536
  }
@@ -431,9 +546,11 @@ class FileTransferManager {
431
546
  await this.#setCommand("startReceive");
432
547
  }
433
548
 
549
+ #isCancelling = false;
434
550
  async cancel() {
435
551
  this.#assertIsNotIdle();
436
552
  _console.log("cancelling file transfer...");
553
+ this.#isCancelling = true;
437
554
  await this.#setCommand("cancel");
438
555
  }
439
556
 
@@ -450,6 +567,14 @@ class FileTransferManager {
450
567
  _console.log({ newIsServerSide });
451
568
  this.#isServerSide = newIsServerSide;
452
569
  }
570
+
571
+ requestRequiredInformation() {
572
+ _console.log("requesting required fileTransfer information");
573
+ const messages = RequiredFileTransferMessageTypes.map((messageType) => ({
574
+ type: messageType,
575
+ }));
576
+ this.sendMessage(messages, false);
577
+ }
453
578
  }
454
579
 
455
580
  export default FileTransferManager;