brilliantsole 0.0.26 → 0.0.28

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 (215) hide show
  1. package/README.md +16 -10
  2. package/assets/3d/anchor.glb +0 -0
  3. package/assets/3d/coin.glb +0 -0
  4. package/assets/3d/glasses.glb +0 -0
  5. package/assets/3d/rightHand.glb +0 -0
  6. package/assets/audio/bounceMedium.wav +0 -0
  7. package/assets/audio/bounceStrong.wav +0 -0
  8. package/assets/audio/bounceWeak.wav +0 -0
  9. package/assets/audio/coin.wav +0 -0
  10. package/assets/audio/getUp.wav +0 -0
  11. package/assets/audio/grab.wav +0 -0
  12. package/assets/audio/kick.wav +0 -0
  13. package/assets/audio/platterFadeIn old.wav +0 -0
  14. package/assets/audio/platterFadeIn.wav +0 -0
  15. package/assets/audio/platterFadeOut.wav +0 -0
  16. package/assets/audio/punch.wav +0 -0
  17. package/assets/audio/punchSqueak.wav +0 -0
  18. package/assets/audio/purr.wav +0 -0
  19. package/assets/audio/purrFadeOut.wav +0 -0
  20. package/assets/audio/release.wav +0 -0
  21. package/assets/audio/splat.wav +0 -0
  22. package/assets/audio/stomp.wav +0 -0
  23. package/assets/images/ukaton-pressure-0.svg +9 -0
  24. package/assets/images/ukaton-pressure-1.svg +9 -0
  25. package/assets/images/ukaton-pressure-10.svg +9 -0
  26. package/assets/images/ukaton-pressure-11.svg +9 -0
  27. package/assets/images/ukaton-pressure-12.svg +9 -0
  28. package/assets/images/ukaton-pressure-13.svg +9 -0
  29. package/assets/images/ukaton-pressure-14.svg +9 -0
  30. package/assets/images/ukaton-pressure-15.svg +9 -0
  31. package/assets/images/ukaton-pressure-2.svg +9 -0
  32. package/assets/images/ukaton-pressure-3.svg +9 -0
  33. package/assets/images/ukaton-pressure-4.svg +9 -0
  34. package/assets/images/ukaton-pressure-5.svg +9 -0
  35. package/assets/images/ukaton-pressure-6.svg +9 -0
  36. package/assets/images/ukaton-pressure-7.svg +9 -0
  37. package/assets/images/ukaton-pressure-8.svg +9 -0
  38. package/assets/images/ukaton-pressure-9.svg +9 -0
  39. package/assets/images/ukaton-right-insole.svg +798 -0
  40. package/build/brilliantsole.cjs +2870 -882
  41. package/build/brilliantsole.cjs.map +1 -1
  42. package/build/brilliantsole.js +2477 -782
  43. package/build/brilliantsole.js.map +1 -1
  44. package/build/brilliantsole.ls.js +2260 -592
  45. package/build/brilliantsole.ls.js.map +1 -1
  46. package/build/brilliantsole.min.js +1 -1
  47. package/build/brilliantsole.min.js.map +1 -1
  48. package/build/brilliantsole.module.d.ts +302 -116
  49. package/build/brilliantsole.module.js +2468 -782
  50. package/build/brilliantsole.module.js.map +1 -1
  51. package/build/brilliantsole.module.min.d.ts +302 -116
  52. package/build/brilliantsole.module.min.js +1 -1
  53. package/build/brilliantsole.module.min.js.map +1 -1
  54. package/build/brilliantsole.node.module.d.ts +295 -113
  55. package/build/brilliantsole.node.module.js +2860 -882
  56. package/build/brilliantsole.node.module.js.map +1 -1
  57. package/build/dts/BS-output.d.ts +10 -0
  58. package/build/dts/BS.d.ts +21 -9
  59. package/build/dts/CameraManager.d.ts +72 -0
  60. package/build/dts/Device.d.ts +53 -16
  61. package/build/dts/DeviceInformationManager.d.ts +4 -4
  62. package/build/dts/DeviceManager.d.ts +3 -0
  63. package/build/dts/FileTransferManager.d.ts +18 -8
  64. package/build/dts/InformationManager.d.ts +8 -5
  65. package/build/dts/TfliteManager.d.ts +22 -2
  66. package/build/dts/WifiManager.d.ts +61 -0
  67. package/build/dts/connection/BaseConnectionManager.d.ts +37 -3
  68. package/build/dts/connection/ClientConnectionManager.d.ts +11 -2
  69. package/build/dts/connection/bluetooth/BluetoothConnectionManager.d.ts +1 -0
  70. package/build/dts/connection/bluetooth/NobleConnectionManager.d.ts +3 -1
  71. package/build/dts/connection/bluetooth/WebBluetoothConnectionManager.d.ts +2 -0
  72. package/build/dts/connection/bluetooth/bluetoothUUIDs.d.ts +2 -2
  73. package/build/dts/connection/udp/UDPConnectionManager.d.ts +28 -0
  74. package/build/dts/connection/webSocket/WebSocketConnectionManager.d.ts +25 -0
  75. package/build/dts/devicePair/DevicePair.d.ts +14 -10
  76. package/build/dts/devicePair/DevicePairPressureSensorDataManager.d.ts +8 -4
  77. package/build/dts/devicePair/DevicePairSensorDataManager.d.ts +2 -2
  78. package/build/dts/scanner/BaseScanner.d.ts +4 -1
  79. package/build/dts/scanner/NobleScanner.d.ts +2 -1
  80. package/build/dts/sensor/MotionSensorDataManager.d.ts +5 -2
  81. package/build/dts/sensor/SensorDataManager.d.ts +5 -4
  82. package/build/dts/server/BaseClient.d.ts +6 -3
  83. package/build/dts/server/ServerUtils.d.ts +1 -1
  84. package/build/dts/server/websocket/WebSocketUtils.d.ts +1 -1
  85. package/build/dts/utils/CenterOfPressureHelper.d.ts +2 -2
  86. package/build/dts/utils/Console.d.ts +2 -0
  87. package/build/dts/utils/MathUtils.d.ts +2 -0
  88. package/build/dts/utils/ThrottleUtils.d.ts +2 -0
  89. package/build/dts/vibration/VibrationManager.d.ts +19 -2
  90. package/build/index.d.ts +299 -113
  91. package/build/index.node.d.ts +292 -110
  92. package/examples/3d/scene.html +19 -5
  93. package/examples/3d/script.js +90 -17
  94. package/examples/3d-generic/index.html +144 -0
  95. package/examples/3d-generic/script.js +266 -0
  96. package/examples/balance/script.js +2 -1
  97. package/examples/basic/index.html +232 -18
  98. package/examples/basic/script.js +746 -106
  99. package/examples/bottango/index.html +11 -1
  100. package/examples/bottango/script.js +2 -2
  101. package/examples/center-of-pressure/index.html +114 -114
  102. package/examples/center-of-pressure/script.js +1 -1
  103. package/examples/device-pair/index.html +58 -58
  104. package/examples/device-pair/script.js +12 -8
  105. package/examples/edge-impulse/script.js +135 -44
  106. package/examples/edge-impulse-test/README.md +11 -0
  107. package/examples/edge-impulse-test/edge-impulse-standalone.js +7228 -0
  108. package/examples/edge-impulse-test/edge-impulse-standalone.wasm +0 -0
  109. package/examples/edge-impulse-test/index.html +75 -0
  110. package/examples/edge-impulse-test/run-impulse.js +135 -0
  111. package/examples/edge-impulse-test/script.js +200 -0
  112. package/examples/gloves/edge-impulse-standalone.js +7228 -0
  113. package/examples/gloves/edge-impulse-standalone.wasm +0 -0
  114. package/examples/gloves/index.html +119 -0
  115. package/examples/gloves/run-impulse.js +135 -0
  116. package/examples/gloves/scene.html +124 -0
  117. package/examples/gloves/script.js +931 -0
  118. package/examples/graph/index.html +11 -1
  119. package/examples/graph/script.js +94 -37
  120. package/examples/pressure/index.html +180 -12
  121. package/examples/pressure/script.js +144 -7
  122. package/examples/punch/index.html +135 -0
  123. package/examples/punch/punch.tflite +0 -0
  124. package/examples/punch/script.js +169 -0
  125. package/examples/recording/index.html +191 -183
  126. package/examples/server/index.html +109 -23
  127. package/examples/server/script.js +322 -111
  128. package/examples/ukaton-firmware-update/index.html +20 -0
  129. package/examples/ukaton-firmware-update/manifest.json +11 -0
  130. package/examples/ukaton-firmware-update/merged-firmware.bin +0 -0
  131. package/examples/utils/aframe/aframe-master.min.js +2 -0
  132. package/examples/utils/aframe/bs-vibration.js +150 -0
  133. package/examples/utils/aframe/force-pushable.js +80 -0
  134. package/examples/utils/aframe/grabbable-anchor.js +46 -0
  135. package/examples/utils/aframe/grabbable-listener.js +31 -0
  136. package/examples/utils/aframe/grabbable-physics-body.js +190 -0
  137. package/examples/utils/aframe/grow-shrink.js +25 -0
  138. package/examples/utils/aframe/hand-punch.js +119 -0
  139. package/examples/utils/aframe/my-obb-collider.js +293 -0
  140. package/examples/utils/aframe/occlude-hand-tracking-controls.js +47 -0
  141. package/examples/utils/aframe/occlude-mesh.js +42 -0
  142. package/examples/utils/aframe/palm-up-detector.js +47 -0
  143. package/examples/utils/aframe/shadow-material.js +20 -0
  144. package/examples/utils/aframe/soft-shadow-light.js +9 -0
  145. package/examples/webxr/script.js +3 -3
  146. package/examples/webxr-2/assets/3d/soccerBall.glb +0 -0
  147. package/examples/webxr-2/assets/audio/shellBounce.wav +0 -0
  148. package/examples/webxr-2/assets/audio/shellHit.wav +0 -0
  149. package/examples/webxr-2/assets/audio/shellKick.wav +0 -0
  150. package/examples/webxr-2/assets/audio/soccerBounce.wav +0 -0
  151. package/examples/webxr-2/assets/audio/soccerKick.mp3 +0 -0
  152. package/examples/webxr-2/assets/images/shellTexture.png +0 -0
  153. package/examples/webxr-2/components/bs-ankle.js +337 -0
  154. package/examples/webxr-2/components/coin.js +84 -0
  155. package/examples/webxr-2/components/custom-wrap.js +17 -0
  156. package/examples/webxr-2/components/goomba.js +3250 -0
  157. package/examples/webxr-2/components/init-shell-material.js +215 -0
  158. package/examples/webxr-2/components/platter.js +172 -0
  159. package/examples/webxr-2/components/shell.js +374 -0
  160. package/examples/webxr-2/components/soccer-ball.js +250 -0
  161. package/examples/webxr-2/components/squashed-goomba.js +249 -0
  162. package/examples/webxr-2/edge-impulse-standalone.js +7228 -0
  163. package/examples/webxr-2/edge-impulse-standalone.wasm +0 -0
  164. package/examples/webxr-2/index.html +996 -0
  165. package/examples/webxr-2/kick.tflite +0 -0
  166. package/examples/webxr-2/kick2.tflite +0 -0
  167. package/examples/webxr-2/run-impulse.js +135 -0
  168. package/examples/webxr-2/script.js +384 -0
  169. package/package.json +2 -1
  170. package/src/.prettierrc +4 -0
  171. package/src/BS.ts +66 -9
  172. package/src/CameraManager.ts +499 -0
  173. package/src/Device.ts +620 -92
  174. package/src/DeviceInformationManager.ts +22 -11
  175. package/src/DeviceManager.ts +94 -25
  176. package/src/FileTransferManager.ts +146 -21
  177. package/src/FirmwareManager.ts +1 -1
  178. package/src/InformationManager.ts +62 -20
  179. package/src/TfliteManager.ts +172 -26
  180. package/src/WifiManager.ts +323 -0
  181. package/src/connection/BaseConnectionManager.ts +145 -30
  182. package/src/connection/ClientConnectionManager.ts +47 -11
  183. package/src/connection/bluetooth/BluetoothConnectionManager.ts +14 -3
  184. package/src/connection/bluetooth/NobleConnectionManager.ts +155 -42
  185. package/src/connection/bluetooth/WebBluetoothConnectionManager.ts +104 -35
  186. package/src/connection/bluetooth/bluetoothUUIDs.ts +40 -13
  187. package/src/connection/udp/UDPConnectionManager.ts +356 -0
  188. package/src/connection/websocket/WebSocketConnectionManager.ts +282 -0
  189. package/src/devicePair/DevicePair.ts +145 -49
  190. package/src/devicePair/DevicePairPressureSensorDataManager.ts +72 -24
  191. package/src/devicePair/DevicePairSensorDataManager.ts +5 -5
  192. package/src/scanner/BaseScanner.ts +49 -11
  193. package/src/scanner/NobleScanner.ts +81 -17
  194. package/src/sensor/BarometerSensorDataManager.ts +1 -1
  195. package/src/sensor/MotionSensorDataManager.ts +22 -7
  196. package/src/sensor/PressureSensorDataManager.ts +47 -13
  197. package/src/sensor/SensorConfigurationManager.ts +75 -24
  198. package/src/sensor/SensorDataManager.ts +107 -26
  199. package/src/server/BaseClient.ts +192 -37
  200. package/src/server/BaseServer.ts +201 -43
  201. package/src/server/ServerUtils.ts +39 -9
  202. package/src/server/udp/UDPServer.ts +74 -23
  203. package/src/server/udp/UDPUtils.ts +9 -2
  204. package/src/server/websocket/WebSocketClient.ts +30 -9
  205. package/src/server/websocket/WebSocketServer.ts +1 -1
  206. package/src/server/websocket/WebSocketUtils.ts +4 -2
  207. package/src/utils/CenterOfPressureHelper.ts +5 -5
  208. package/src/utils/Console.ts +62 -9
  209. package/src/utils/MathUtils.ts +31 -1
  210. package/src/utils/ParseUtils.ts +25 -6
  211. package/src/utils/ThrottleUtils.ts +62 -0
  212. package/src/utils/Timer.ts +1 -1
  213. package/src/utils/checksum.ts +1 -1
  214. package/src/utils/mcumgr.js +1 -1
  215. package/src/vibration/VibrationManager.ts +166 -40
@@ -0,0 +1,282 @@
1
+ import { DeviceInformationTypes } from "../../DeviceInformationManager.ts";
2
+ import {
3
+ createMessage,
4
+ Message,
5
+ MessageLike,
6
+ } from "../../server/ServerUtils.ts";
7
+ import { webSocketPingTimeout } from "../../server/websocket/WebSocketUtils.ts";
8
+ import { createConsole } from "../../utils/Console.ts";
9
+ import {
10
+ addEventListeners,
11
+ removeEventListeners,
12
+ } from "../../utils/EventUtils.ts";
13
+ import { parseMessage } from "../../utils/ParseUtils.ts";
14
+ import Timer from "../../utils/Timer.ts";
15
+ import BaseConnectionManager, {
16
+ ConnectionType,
17
+ } from "../BaseConnectionManager.ts";
18
+ import type * as ws from "ws";
19
+
20
+ const _console = createConsole("WebSocketConnectionManager", { log: false });
21
+
22
+ const WebSocketMessageTypes = [
23
+ "ping",
24
+ "pong",
25
+ "batteryLevel",
26
+ "deviceInformation",
27
+ "message",
28
+ ] as const;
29
+ type WebSocketMessageType = (typeof WebSocketMessageTypes)[number];
30
+
31
+ type WebSocketMessage = WebSocketMessageType | Message<WebSocketMessageType>;
32
+ function createWebSocketMessage(...messages: WebSocketMessage[]) {
33
+ _console.log("createWebSocketMessage", ...messages);
34
+ return createMessage(WebSocketMessageTypes, ...messages);
35
+ }
36
+
37
+ const WebSocketDeviceInformationMessageTypes: WebSocketMessageType[] = [
38
+ "deviceInformation",
39
+ "batteryLevel",
40
+ ];
41
+
42
+ class WebSocketConnectionManager extends BaseConnectionManager {
43
+ #bluetoothId?: string;
44
+ get bluetoothId() {
45
+ return this.#bluetoothId ?? "";
46
+ }
47
+
48
+ defaultMtu = 2 ** 10;
49
+
50
+ constructor(
51
+ ipAddress: string,
52
+ isSecure: boolean = false,
53
+ bluetoothId?: string
54
+ ) {
55
+ super();
56
+ this.ipAddress = ipAddress;
57
+ this.isSecure = isSecure;
58
+ this.mtu = this.defaultMtu;
59
+ this.#bluetoothId = bluetoothId;
60
+ }
61
+
62
+ get isAvailable() {
63
+ return true;
64
+ }
65
+
66
+ static get isSupported() {
67
+ return true;
68
+ }
69
+ static get type(): ConnectionType {
70
+ return "webSocket";
71
+ }
72
+
73
+ // WEBSOCKET
74
+ #webSocket?: WebSocket;
75
+ get webSocket() {
76
+ return this.#webSocket;
77
+ }
78
+ set webSocket(newWebSocket) {
79
+ if (this.#webSocket == newWebSocket) {
80
+ _console.log("redundant webSocket assignment");
81
+ return;
82
+ }
83
+
84
+ _console.log("assigning webSocket", newWebSocket);
85
+
86
+ if (this.#webSocket) {
87
+ removeEventListeners(this.#webSocket, this.#boundWebSocketEventListeners);
88
+ if (this.#webSocket.readyState == this.#webSocket.OPEN) {
89
+ this.#webSocket.close();
90
+ }
91
+ }
92
+
93
+ if (newWebSocket) {
94
+ addEventListeners(newWebSocket, this.#boundWebSocketEventListeners);
95
+ }
96
+ this.#webSocket = newWebSocket;
97
+
98
+ _console.log("assigned webSocket");
99
+ }
100
+
101
+ // IP ADDRESS
102
+ #ipAddress!: string;
103
+ get ipAddress() {
104
+ return this.#ipAddress;
105
+ }
106
+ set ipAddress(newIpAddress) {
107
+ this.assertIsNotConnected();
108
+ if (this.#ipAddress == newIpAddress) {
109
+ _console.log(`redundnant ipAddress assignment "${newIpAddress}"`);
110
+ return;
111
+ }
112
+ this.#ipAddress = newIpAddress;
113
+ _console.log(`updated ipAddress to "${this.ipAddress}"`);
114
+ }
115
+
116
+ // IS SECURE
117
+ #isSecure = false;
118
+ get isSecure() {
119
+ return this.#isSecure;
120
+ }
121
+ set isSecure(newIsSecure) {
122
+ this.assertIsNotConnected();
123
+ if (this.#isSecure == newIsSecure) {
124
+ _console.log(`redundant isSecure assignment ${newIsSecure}`);
125
+ return;
126
+ }
127
+ this.#isSecure = newIsSecure;
128
+ _console.log(`updated isSecure to "${this.isSecure}"`);
129
+ }
130
+
131
+ // URL
132
+ get url() {
133
+ return `${this.isSecure ? "wss" : "ws"}://${this.ipAddress}/ws`;
134
+ }
135
+
136
+ // CONNECTION
137
+ async connect() {
138
+ await super.connect();
139
+ try {
140
+ this.webSocket = new WebSocket(this.url);
141
+ } catch (error) {
142
+ _console.error("error connecting to webSocket", error);
143
+ this.status = "notConnected";
144
+ }
145
+ }
146
+ async disconnect() {
147
+ await super.disconnect();
148
+ _console.log("closing websocket");
149
+ this.#pingTimer.stop();
150
+ this.#webSocket?.close();
151
+ }
152
+
153
+ get canReconnect() {
154
+ return Boolean(this.webSocket);
155
+ }
156
+ async reconnect() {
157
+ await super.reconnect();
158
+ this.webSocket = new WebSocket(this.url);
159
+ }
160
+
161
+ // BASE CONNECTION MANAGER
162
+ async sendSmpMessage(data: ArrayBuffer) {
163
+ super.sendSmpMessage(data);
164
+ _console.error("smp not supported on webSockets");
165
+ }
166
+
167
+ async sendTxData(data: ArrayBuffer) {
168
+ await super.sendTxData(data);
169
+ if (data.byteLength == 0) {
170
+ return;
171
+ }
172
+ this.#sendWebSocketMessage({ type: "message", data });
173
+ }
174
+
175
+ // WEBSOCKET MESSAGING
176
+ #sendMessage(message: MessageLike) {
177
+ this.assertIsConnected();
178
+ _console.log("sending webSocket message", message);
179
+ this.#webSocket!.send(message);
180
+ this.#pingTimer.restart();
181
+ }
182
+
183
+ #sendWebSocketMessage(...messages: WebSocketMessage[]) {
184
+ this.#sendMessage(createWebSocketMessage(...messages));
185
+ }
186
+
187
+ // WEBSOCKET EVENTS
188
+ #boundWebSocketEventListeners: { [eventType: string]: Function } = {
189
+ open: this.#onWebSocketOpen.bind(this),
190
+ message: this.#onWebSocketMessage.bind(this),
191
+ close: this.#onWebSocketClose.bind(this),
192
+ error: this.#onWebSocketError.bind(this),
193
+ };
194
+
195
+ #onWebSocketOpen(event: ws.Event) {
196
+ _console.log("webSocket.open", event);
197
+ this.#pingTimer.start();
198
+ this.status = "connected";
199
+ this.#requestDeviceInformation();
200
+ }
201
+ async #onWebSocketMessage(event: ws.MessageEvent) {
202
+ // this.#pingTimer.restart();
203
+ //@ts-expect-error
204
+ const arrayBuffer = await event.data.arrayBuffer();
205
+ const dataView = new DataView(arrayBuffer);
206
+ _console.log(`webSocket.message (${dataView.byteLength} bytes)`);
207
+ this.#parseWebSocketMessage(dataView);
208
+ }
209
+ #onWebSocketClose(event: ws.CloseEvent) {
210
+ _console.log("webSocket.close", event);
211
+ this.status = "notConnected";
212
+ this.#pingTimer.stop();
213
+ }
214
+ #onWebSocketError(event: ws.ErrorEvent) {
215
+ _console.error("webSocket.error", event);
216
+ }
217
+
218
+ // PARSING
219
+ #parseWebSocketMessage(dataView: DataView) {
220
+ parseMessage(
221
+ dataView,
222
+ WebSocketMessageTypes,
223
+ this.#onMessage.bind(this),
224
+ null,
225
+ true
226
+ );
227
+ }
228
+
229
+ #onMessage(messageType: WebSocketMessageType, dataView: DataView) {
230
+ _console.log(
231
+ `received "${messageType}" message (${dataView.byteLength} bytes)`
232
+ );
233
+ switch (messageType) {
234
+ case "ping":
235
+ this.#pong();
236
+ break;
237
+ case "pong":
238
+ break;
239
+ case "batteryLevel":
240
+ this.onMessageReceived?.("batteryLevel", dataView);
241
+ break;
242
+ case "deviceInformation":
243
+ parseMessage(
244
+ dataView,
245
+ DeviceInformationTypes,
246
+ (deviceInformationType, dataView) => {
247
+ this.onMessageReceived!(deviceInformationType, dataView);
248
+ }
249
+ );
250
+ break;
251
+ case "message":
252
+ this.parseRxMessage(dataView);
253
+ break;
254
+ default:
255
+ _console.error(`uncaught messageType "${messageType}"`);
256
+ break;
257
+ }
258
+ }
259
+
260
+ // PING
261
+ #pingTimer = new Timer(this.#ping.bind(this), webSocketPingTimeout - 1_000);
262
+ #ping() {
263
+ _console.log("pinging");
264
+ this.#sendWebSocketMessage("ping");
265
+ }
266
+ #pong() {
267
+ _console.log("ponging");
268
+ this.#sendWebSocketMessage("pong");
269
+ }
270
+
271
+ // DEVICE INFORMATION
272
+ #requestDeviceInformation() {
273
+ this.#sendWebSocketMessage(...WebSocketDeviceInformationMessageTypes);
274
+ }
275
+
276
+ remove() {
277
+ super.remove();
278
+ this.webSocket = undefined;
279
+ }
280
+ }
281
+
282
+ export default WebSocketConnectionManager;
@@ -1,6 +1,14 @@
1
1
  import { createConsole } from "../utils/Console.ts";
2
- import EventDispatcher, { BoundEventListeners, Event, EventListenerMap, EventMap } from "../utils/EventDispatcher.ts";
3
- import { addEventListeners, removeEventListeners } from "../utils/EventUtils.ts";
2
+ import EventDispatcher, {
3
+ BoundEventListeners,
4
+ Event,
5
+ EventListenerMap,
6
+ EventMap,
7
+ } from "../utils/EventDispatcher.ts";
8
+ import {
9
+ addEventListeners,
10
+ removeEventListeners,
11
+ } from "../utils/EventUtils.ts";
4
12
  import Device, {
5
13
  DeviceEvent,
6
14
  DeviceEventType,
@@ -9,20 +17,29 @@ import Device, {
9
17
  BoundDeviceEventListeners,
10
18
  DeviceEventMap,
11
19
  } from "../Device.ts";
12
- import DevicePairSensorDataManager, { DevicePairSensorDataEventDispatcher } from "./DevicePairSensorDataManager.ts";
20
+ import DevicePairSensorDataManager, {
21
+ DevicePairSensorDataEventDispatcher,
22
+ } from "./DevicePairSensorDataManager.ts";
13
23
  import { capitalizeFirstCharacter } from "../utils/stringUtils.ts";
14
- import { InsoleSide, InsoleSides } from "../InformationManager.ts";
24
+ import { Side, Sides } from "../InformationManager.ts";
15
25
  import { VibrationConfiguration } from "../vibration/VibrationManager.ts";
16
26
  import { SensorConfiguration } from "../sensor/SensorConfigurationManager.ts";
17
- import { DevicePairSensorDataEventMessages, DevicePairSensorDataEventTypes } from "./DevicePairSensorDataManager.ts";
18
- import { AddPrefixToInterfaceKeys, ExtendInterfaceValues, KeyOf } from "../utils/TypeScriptUtils.ts";
27
+ import {
28
+ DevicePairSensorDataEventMessages,
29
+ DevicePairSensorDataEventTypes,
30
+ } from "./DevicePairSensorDataManager.ts";
31
+ import {
32
+ AddPrefixToInterfaceKeys,
33
+ ExtendInterfaceValues,
34
+ KeyOf,
35
+ } from "../utils/TypeScriptUtils.ts";
19
36
  import DeviceManager from "../DeviceManager.ts";
20
37
 
21
- const _console = createConsole("DevicePair", { log: true });
38
+ const _console = createConsole("DevicePair", { log: false });
22
39
 
23
40
  interface BaseDevicePairDeviceEventMessage {
24
41
  device: Device;
25
- side: InsoleSide;
42
+ side: Side;
26
43
  }
27
44
  type DevicePairDeviceEventMessages = ExtendInterfaceValues<
28
45
  AddPrefixToInterfaceKeys<DeviceEventMessages, "device">,
@@ -30,14 +47,17 @@ type DevicePairDeviceEventMessages = ExtendInterfaceValues<
30
47
  >;
31
48
  type DevicePairDeviceEventType = KeyOf<DevicePairDeviceEventMessages>;
32
49
  function getDevicePairDeviceEventType(deviceEventType: DeviceEventType) {
33
- return `device${capitalizeFirstCharacter(deviceEventType)}` as DevicePairDeviceEventType;
50
+ return `device${capitalizeFirstCharacter(
51
+ deviceEventType
52
+ )}` as DevicePairDeviceEventType;
34
53
  }
35
54
  const DevicePairDeviceEventTypes = DeviceEventTypes.map((eventType) =>
36
55
  getDevicePairDeviceEventType(eventType)
37
56
  ) as DevicePairDeviceEventType[];
38
57
 
39
58
  export const DevicePairConnectionEventTypes = ["isConnected"] as const;
40
- export type DevicePairConnectionEventType = (typeof DevicePairConnectionEventTypes)[number];
59
+ export type DevicePairConnectionEventType =
60
+ (typeof DevicePairConnectionEventTypes)[number];
41
61
 
42
62
  export interface DevicePairConnectionEventMessages {
43
63
  isConnected: { isConnected: boolean };
@@ -54,22 +74,55 @@ export type DevicePairEventMessages = DevicePairConnectionEventMessages &
54
74
  DevicePairSensorDataEventMessages &
55
75
  DevicePairDeviceEventMessages;
56
76
 
57
- export type DevicePairEventDispatcher = EventDispatcher<DevicePair, DevicePairEventType, DevicePairEventMessages>;
58
- export type DevicePairEventMap = EventMap<DevicePair, DeviceEventType, DevicePairEventMessages>;
59
- export type DevicePairEventListenerMap = EventListenerMap<DevicePair, DeviceEventType, DevicePairEventMessages>;
60
- export type DevicePairEvent = Event<DevicePair, DeviceEventType, DevicePairEventMessages>;
61
- export type BoundDevicePairEventListeners = BoundEventListeners<DevicePair, DeviceEventType, DevicePairEventMessages>;
77
+ export type DevicePairEventDispatcher = EventDispatcher<
78
+ DevicePair,
79
+ DevicePairEventType,
80
+ DevicePairEventMessages
81
+ >;
82
+ export type DevicePairEventMap = EventMap<
83
+ DevicePair,
84
+ DeviceEventType,
85
+ DevicePairEventMessages
86
+ >;
87
+ export type DevicePairEventListenerMap = EventListenerMap<
88
+ DevicePair,
89
+ DeviceEventType,
90
+ DevicePairEventMessages
91
+ >;
92
+ export type DevicePairEvent = Event<
93
+ DevicePair,
94
+ DeviceEventType,
95
+ DevicePairEventMessages
96
+ >;
97
+ export type BoundDevicePairEventListeners = BoundEventListeners<
98
+ DevicePair,
99
+ DeviceEventType,
100
+ DevicePairEventMessages
101
+ >;
102
+
103
+ export const DevicePairTypes = ["insoles", "gloves"] as const;
104
+ export type DevicePairType = (typeof DevicePairTypes)[number];
62
105
 
63
106
  class DevicePair {
64
- constructor() {
65
- this.#sensorDataManager.eventDispatcher = this.#eventDispatcher as DevicePairSensorDataEventDispatcher;
107
+ constructor(type: DevicePairType) {
108
+ this.#type = type;
109
+ this.#sensorDataManager.eventDispatcher = this
110
+ .#eventDispatcher as DevicePairSensorDataEventDispatcher;
66
111
  }
67
112
 
68
113
  get sides() {
69
- return InsoleSides;
114
+ return Sides;
70
115
  }
71
116
 
72
- #eventDispatcher: DevicePairEventDispatcher = new EventDispatcher(this as DevicePair, DevicePairEventTypes);
117
+ #type: DevicePairType;
118
+ get type() {
119
+ return this.#type;
120
+ }
121
+
122
+ #eventDispatcher: DevicePairEventDispatcher = new EventDispatcher(
123
+ this as DevicePair,
124
+ DevicePairEventTypes
125
+ );
73
126
  get addEventListener() {
74
127
  return this.#eventDispatcher.addEventListener;
75
128
  }
@@ -101,10 +154,10 @@ class DevicePair {
101
154
  }
102
155
 
103
156
  get isConnected() {
104
- return InsoleSides.every((side) => this[side]?.isConnected);
157
+ return Sides.every((side) => this[side]?.isConnected);
105
158
  }
106
159
  get isPartiallyConnected() {
107
- return InsoleSides.some((side) => this[side]?.isConnected);
160
+ return Sides.some((side) => this[side]?.isConnected);
108
161
  }
109
162
  get isHalfConnected() {
110
163
  return this.isPartiallyConnected && !this.isConnected;
@@ -113,12 +166,23 @@ class DevicePair {
113
166
  _console.assertWithError(this.isConnected, "devicePair must be connected");
114
167
  }
115
168
 
116
- assignInsole(device: Device) {
117
- if (!device.isInsole) {
118
- _console.warn("device is not an insole");
169
+ #isDeviceCorrectType(device: Device) {
170
+ switch (this.type) {
171
+ case "insoles":
172
+ return device.isInsole;
173
+ case "gloves":
174
+ return device.isGlove;
175
+ }
176
+ }
177
+
178
+ assignDevice(device: Device) {
179
+ if (!this.#isDeviceCorrectType(device)) {
180
+ _console.log(
181
+ `device is incorrect type ${device.type} for ${this.type} devicePair`
182
+ );
119
183
  return;
120
184
  }
121
- const side = device.insoleSide;
185
+ const side = device.side;
122
186
 
123
187
  const currentDevice = this[side];
124
188
 
@@ -141,12 +205,16 @@ class DevicePair {
141
205
  break;
142
206
  }
143
207
 
144
- _console.log(`assigned ${side} insole`, device);
208
+ _console.log(`assigned ${side} ${this.type} device`, device);
145
209
 
146
210
  this.resetPressureRange();
147
211
 
148
212
  this.#dispatchEvent("isConnected", { isConnected: this.isConnected });
149
- this.#dispatchEvent("deviceIsConnected", { device, isConnected: device.isConnected, side });
213
+ this.#dispatchEvent("deviceIsConnected", {
214
+ device,
215
+ isConnected: device.isConnected,
216
+ side,
217
+ });
150
218
 
151
219
  return currentDevice;
152
220
  }
@@ -154,27 +222,41 @@ class DevicePair {
154
222
  #addDeviceEventListeners(device: Device) {
155
223
  addEventListeners(device, this.#boundDeviceEventListeners);
156
224
  DeviceEventTypes.forEach((deviceEventType) => {
157
- // @ts-expect-error
158
- device.addEventListener(deviceEventType, this.#redispatchDeviceEvent.bind(this));
225
+ device.addEventListener(
226
+ // @ts-expect-error
227
+ deviceEventType,
228
+ this.#redispatchDeviceEvent.bind(this)
229
+ );
159
230
  });
160
231
  }
161
232
  #removeDeviceEventListeners(device: Device) {
162
233
  removeEventListeners(device, this.#boundDeviceEventListeners);
163
234
  DeviceEventTypes.forEach((deviceEventType) => {
164
- // @ts-expect-error
165
- device.removeEventListener(deviceEventType, this.#redispatchDeviceEvent.bind(this));
235
+ device.removeEventListener(
236
+ // @ts-expect-error
237
+ deviceEventType,
238
+ this.#redispatchDeviceEvent.bind(this)
239
+ );
166
240
  });
167
241
  }
168
242
 
169
- #removeInsole(device: Device) {
170
- const foundDevice = InsoleSides.some((side) => {
243
+ #removeDevice(device: Device) {
244
+ const foundDevice = Sides.some((side) => {
171
245
  if (this[side] != device) {
172
246
  return false;
173
247
  }
174
248
 
175
- _console.log(`removing ${side} insole`, device);
249
+ _console.log(`removing ${side} ${this.type} device`, device);
176
250
  removeEventListeners(device, this.#boundDeviceEventListeners);
177
- delete this[side];
251
+
252
+ switch (side) {
253
+ case "left":
254
+ this.#left = undefined;
255
+ break;
256
+ case "right":
257
+ this.#right = undefined;
258
+ break;
259
+ }
178
260
 
179
261
  return true;
180
262
  });
@@ -195,7 +277,7 @@ class DevicePair {
195
277
  this.#dispatchEvent(getDevicePairDeviceEventType(type), {
196
278
  ...message,
197
279
  device,
198
- side: device.insoleSide,
280
+ side: device.side,
199
281
  });
200
282
  }
201
283
 
@@ -205,20 +287,20 @@ class DevicePair {
205
287
 
206
288
  #onDeviceType(deviceEvent: DeviceEventMap["getType"]) {
207
289
  const { target: device } = deviceEvent;
208
- if (this[device.insoleSide] == device) {
290
+ if (this[device.side] == device) {
209
291
  return;
210
292
  }
211
- const foundDevice = this.#removeInsole(device);
293
+ const foundDevice = this.#removeDevice(device);
212
294
  if (!foundDevice) {
213
295
  return;
214
296
  }
215
- this.assignInsole(device);
297
+ this.assignDevice(device);
216
298
  }
217
299
 
218
300
  // SENSOR CONFIGURATION
219
301
  async setSensorConfiguration(sensorConfiguration: SensorConfiguration) {
220
- for (let i = 0; i < InsoleSides.length; i++) {
221
- const side = InsoleSides[i];
302
+ for (let i = 0; i < Sides.length; i++) {
303
+ const side = Sides[i];
222
304
  if (this[side]?.isConnected) {
223
305
  await this[side].setSensorConfiguration(sensorConfiguration);
224
306
  }
@@ -233,27 +315,41 @@ class DevicePair {
233
315
  }
234
316
  }
235
317
  resetPressureRange() {
318
+ Sides.forEach((side) => this[side]?.resetPressureRange());
236
319
  this.#sensorDataManager.resetPressureRange();
237
320
  }
238
321
 
239
322
  // VIBRATION
240
- async triggerVibration(vibrationConfigurations: VibrationConfiguration[], sendImmediately?: boolean) {
241
- const promises = InsoleSides.map((side) => {
242
- return this[side]?.triggerVibration(vibrationConfigurations, sendImmediately);
323
+ async triggerVibration(
324
+ vibrationConfigurations: VibrationConfiguration[],
325
+ sendImmediately?: boolean
326
+ ) {
327
+ const promises = Sides.map((side) => {
328
+ return this[side]?.triggerVibration(
329
+ vibrationConfigurations,
330
+ sendImmediately
331
+ );
243
332
  }).filter(Boolean);
244
333
  return Promise.allSettled(promises);
245
334
  }
246
335
 
247
- // SHARED INSTANCE
248
- static #shared = new DevicePair();
249
- static get shared() {
250
- return this.#shared;
336
+ // SHARED INSTANCES
337
+ static #insoles = new DevicePair("insoles");
338
+ static get insoles() {
339
+ return this.#insoles;
340
+ }
341
+ static #gloves = new DevicePair("gloves");
342
+ static get gloves() {
343
+ return this.#gloves;
251
344
  }
252
345
  static {
253
346
  DeviceManager.AddEventListener("deviceConnected", (event) => {
254
347
  const { device } = event.message;
255
348
  if (device.isInsole) {
256
- this.#shared.assignInsole(device);
349
+ this.#insoles.assignDevice(device);
350
+ }
351
+ if (device.isGlove) {
352
+ this.#gloves.assignDevice(device);
257
353
  }
258
354
  });
259
355
  }