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
@@ -67,7 +67,7 @@ addDeviceButton.addEventListener("click", () => {
67
67
  BS.Device.Connect();
68
68
  });
69
69
 
70
- const devicePair = BS.DevicePair.shared;
70
+ const devicePair = BS.DevicePair.insoles;
71
71
  devicePair.addEventListener("isConnected", () => {
72
72
  addDeviceButton.disabled = devicePair.isConnected;
73
73
  });
@@ -86,6 +86,10 @@ const toggleConnectionButtons = {};
86
86
  const togglePressureDataButtons = {};
87
87
  /** @type {Object.<string, HTMLElement[]>} */
88
88
  const pressureSensorElementsContainers = {};
89
+ /** @type {Object.<string, HTMLElement>} */
90
+ const centerOfPressureElementsContainers = {};
91
+ /** @type {Object.<string, HTMLElement>} */
92
+ const devicePairCenterOfPressureElementsContainers = {};
89
93
 
90
94
  devicePair.sides.forEach((side) => {
91
95
  /** @type {HTMLElement} */
@@ -120,24 +124,44 @@ devicePair.sides.forEach((side) => {
120
124
  /** @type {HTMLElement[]} */
121
125
  const pressureSensorElements = Array.from(insoleContainer.querySelectorAll("[data-pressure]"));
122
126
  pressureSensorElementsContainers[side] = pressureSensorElements;
127
+
128
+ centerOfPressureElementsContainers[side] = insoleContainer.querySelector(".center");
129
+ devicePairCenterOfPressureElementsContainers[side] = insoleContainer.querySelector(".devicePairCenter");
123
130
  });
124
131
 
125
132
  devicePair.addEventListener("deviceIsConnected", (event) => {
126
133
  const { device } = event.message;
127
134
 
128
- const toggleConnectionButton = toggleConnectionButtons[device.insoleSide];
135
+ const toggleConnectionButton = toggleConnectionButtons[device.side];
129
136
  if (device.isConnected) {
130
137
  toggleConnectionButton.disabled = false;
131
138
  }
132
139
  toggleConnectionButton.innerText = device.isConnected ? "disconnect" : "reconnect";
133
140
 
134
- togglePressureDataButtons[device.insoleSide].disabled = !device.isConnected;
141
+ togglePressureDataButtons[device.side].disabled = !device.isConnected;
142
+ });
143
+
144
+ devicePair.addEventListener("deviceIsConnected", (event) => {
145
+ const { device, side, isConnected } = event.message;
146
+
147
+ if (!isConnected) {
148
+ return;
149
+ }
150
+
151
+ const insoleContainer = insoleContainers[side];
152
+ const viz = insoleContainer.querySelector(".viz");
153
+ if (device.isUkaton) {
154
+ viz.classList.add("ukaton");
155
+ } else {
156
+ viz.classList.remove("ukaton");
157
+ }
158
+ console.log("insoleContainer", insoleContainer);
135
159
  });
136
160
 
137
161
  devicePair.addEventListener("deviceConnectionStatus", (event) => {
138
162
  const { device } = event.message;
139
163
 
140
- const toggleConnectionButton = toggleConnectionButtons[device.insoleSide];
164
+ const toggleConnectionButton = toggleConnectionButtons[device.side];
141
165
 
142
166
  switch (device.connectionStatus) {
143
167
  case "connected":
@@ -156,7 +180,7 @@ devicePair.addEventListener("deviceConnectionStatus", (event) => {
156
180
  devicePair.addEventListener("deviceGetSensorConfiguration", (event) => {
157
181
  const { device } = event.message;
158
182
 
159
- const togglePressureDataButton = togglePressureDataButtons[device.insoleSide];
183
+ const togglePressureDataButton = togglePressureDataButtons[device.side];
160
184
  const isPressureDataEnabled = device.sensorConfiguration.pressure > 0;
161
185
  if (isPressureDataEnabled) {
162
186
  togglePressureDataButton.innerText = "disable pressure data";
@@ -169,8 +193,85 @@ devicePair.addEventListener("deviceGetSensorConfiguration", (event) => {
169
193
  devicePair.addEventListener("devicePressure", (event) => {
170
194
  const { pressure, side } = event.message;
171
195
 
172
- pressure.sensors.forEach((sensor, index) => {
173
- pressureSensorElementsContainers[side][index].style.opacity = sensor.normalizedValue;
196
+ if (pressureVisualizationMode != "devicePairWeightedValue") {
197
+ pressure.sensors.forEach((sensor, index) => {
198
+ var value = 0;
199
+ switch (pressureVisualizationMode) {
200
+ case "normalizedValue":
201
+ value = sensor.normalizedValue;
202
+ break;
203
+ case "scaledValue":
204
+ value = sensor.scaledValue * pressure.sensors.length;
205
+ break;
206
+ case "weightedValue":
207
+ value = (sensor.weightedValue * pressure.sensors.length) / 2;
208
+ break;
209
+ }
210
+ pressureSensorElementsContainers[side][index].style.opacity = value;
211
+ });
212
+ }
213
+ });
214
+
215
+ devicePair.addEventListener("devicePressure", (event) => {
216
+ const { pressure, side } = event.message;
217
+
218
+ const container = centerOfPressureElementsContainers[side];
219
+ container.style.opacity = pressure.normalizedSum;
220
+
221
+ var center;
222
+ switch (centerOfPressureVisualizationMode) {
223
+ case "center":
224
+ center = pressure.center;
225
+ break;
226
+ case "normalizedCenter":
227
+ center = pressure.normalizedCenter;
228
+ break;
229
+ }
230
+ if (!center) {
231
+ return;
232
+ }
233
+
234
+ container.style.left = `${center.x * 100}%`;
235
+ container.style.bottom = `${center.y * 100}%`;
236
+ });
237
+
238
+ devicePair.addEventListener("pressure", (event) => {
239
+ const { pressure } = event.message;
240
+ if (pressureVisualizationMode == "devicePairWeightedValue") {
241
+ devicePair.sides.forEach((side) => {
242
+ pressure.sensors[side].forEach((sensor, index) => {
243
+ pressureSensorElementsContainers[side][index].style.opacity = sensor.weightedValue / 2;
244
+ });
245
+ });
246
+ }
247
+ });
248
+
249
+ devicePair.addEventListener("pressure", (event) => {
250
+ const { pressure } = event.message;
251
+
252
+ var center;
253
+ switch (centerOfPressureVisualizationMode) {
254
+ case "center":
255
+ center = pressure.center;
256
+ break;
257
+ case "normalizedCenter":
258
+ center = pressure.normalizedCenter;
259
+ break;
260
+ }
261
+ var side;
262
+ if (center) {
263
+ side = center.x < 0.5 ? "left" : "right";
264
+ }
265
+
266
+ devicePair.sides.forEach((_side) => {
267
+ const container = devicePairCenterOfPressureElementsContainers[_side];
268
+ if (side == _side) {
269
+ container.style.opacity = pressure.normalizedSum;
270
+ container.style.left = `${(center.x % 0.5) * 2 * 100}%`;
271
+ container.style.bottom = `${center.y * 100}%`;
272
+ } else {
273
+ container.style.opacity = 0;
274
+ }
174
275
  });
175
276
  });
176
277
 
@@ -199,3 +300,39 @@ websocketClient.addEventListener("connectionStatus", () => {
199
300
  }
200
301
  toggleServerConnectionButton.disabled = disabled;
201
302
  });
303
+
304
+ // PRESSURE VISUALIZATION
305
+
306
+ const pressureVisualizationModes = ["scaledValue", "normalizedValue", "weightedValue", "devicePairWeightedValue"];
307
+ let pressureVisualizationMode = "normalizedValue";
308
+
309
+ /** @type {HTMLSelectElement} */
310
+ const visualizationModeSelect = document.getElementById("pressureVisualizationMode");
311
+ visualizationModeSelect.addEventListener("input", (event) => {
312
+ pressureVisualizationMode = event.target.value;
313
+ console.log({ pressureVisualizationMode });
314
+ });
315
+ /** @type {HTMLOptGroupElement} */
316
+ const visualizationModeOptGroup = visualizationModeSelect.querySelector("optgroup");
317
+ pressureVisualizationModes.forEach((pressureVisualizationMode) => {
318
+ visualizationModeOptGroup.appendChild(new Option(pressureVisualizationMode));
319
+ });
320
+ visualizationModeSelect.value = pressureVisualizationMode;
321
+
322
+ // CENTER OF PRESSURE VISUALIZATION
323
+
324
+ const centerOfPressureVisualizationModes = ["normalizedCenter", "center"];
325
+ let centerOfPressureVisualizationMode = "normalizedCenter";
326
+
327
+ /** @type {HTMLSelectElement} */
328
+ const centerOfPressureVisualizationModeSelect = document.getElementById("centerOfPressureVisualizationMode");
329
+ centerOfPressureVisualizationModeSelect.addEventListener("input", (event) => {
330
+ centerOfPressureVisualizationMode = event.target.value;
331
+ console.log({ centerOfPressureVisualizationMode });
332
+ });
333
+ /** @type {HTMLOptGroupElement} */
334
+ const centerOfPressureVisualizationModeOptGroup = centerOfPressureVisualizationModeSelect.querySelector("optgroup");
335
+ centerOfPressureVisualizationModes.forEach((centerOfPressureVisualizationMode) => {
336
+ centerOfPressureVisualizationModeOptGroup.appendChild(new Option(centerOfPressureVisualizationMode));
337
+ });
338
+ centerOfPressureVisualizationModeSelect.value = centerOfPressureVisualizationMode;
@@ -0,0 +1,135 @@
1
+ <html>
2
+ <head>
3
+ <title>Punch | BrilliantSole JavaScript SDK</title>
4
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
5
+ <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
6
+ <script type="module" src="./script.js"></script>
7
+ <script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
8
+ <script src="../utils/aframe/force-pushable.js"></script>
9
+ <script src="https://cdn.jsdelivr.net/gh/c-frame/aframe-physics-system@v4.2.3/dist/aframe-physics-system.min.js"></script>
10
+ </head>
11
+ <style>
12
+ #scene {
13
+ width: 700px;
14
+ height: 700px;
15
+ margin: auto;
16
+ border-radius: 2rem;
17
+ overflow: hidden;
18
+ border: solid black;
19
+ box-sizing: border-box;
20
+ }
21
+
22
+ #title {
23
+ margin: auto;
24
+ height: 70px;
25
+ display: flex;
26
+ flex-direction: row;
27
+ align-items: center;
28
+ justify-content: center;
29
+
30
+ font-size: xx-large;
31
+ }
32
+ </style>
33
+ <body>
34
+ <nav>
35
+ <a href="../../">home</a>
36
+ </nav>
37
+
38
+ <h1>Punch | BrilliantSole JavaScript SDK</h1>
39
+
40
+ <button id="toggleConnection">connect</button>
41
+
42
+ <progress value="0" id="fileTransferProgress"></progress>
43
+
44
+ <label>
45
+ is model ready <input type="checkbox" disabled id="isModelReady" />
46
+ </label>
47
+
48
+ <div id="title">
49
+ <h1 id="maxClass">Punch</h1>
50
+ </div>
51
+
52
+ <a-scene
53
+ id="scene"
54
+ physics="debug: false"
55
+ embedded
56
+ xr-mode-ui="enabled: false;"
57
+ device-orientation-permission-ui="enabled: false"
58
+ >
59
+ <a-assets></a-assets>
60
+
61
+ <a-camera
62
+ id="camera"
63
+ look-controls="enabled: false;"
64
+ wasd-controls="enabled: false"
65
+ position="0 0.2 0.65"
66
+ rotation="-20 0 0"
67
+ ></a-camera>
68
+ <a-sky></a-sky>
69
+
70
+ <a-entity position="0 -0.55 0">
71
+ <a-sphere
72
+ id="punchingBag2"
73
+ class="punchingBag 2"
74
+ data-section="2"
75
+ radius="0.125"
76
+ color="#777"
77
+ position="0 0.75 0"
78
+ dynamic-body
79
+ force-pushable
80
+ constraint="type: coneTwist;
81
+ target: #punchingBag1;
82
+ pivot: 0 -0.13 0;
83
+ targetPivot: 0 0.13 0;
84
+ axis: 0 1 0;
85
+ targetAxis: 0 1 0"
86
+ ></a-sphere>
87
+ <a-box
88
+ id="punchingBag1"
89
+ class="punchingBag 1"
90
+ data-section="1"
91
+ width="0.5"
92
+ height="0.25"
93
+ depth="0.25"
94
+ color="#B00"
95
+ position="0 0.5 0"
96
+ dynamic-body
97
+ force-pushable
98
+ constraint="type: coneTwist;
99
+ target: #punchingBag0;
100
+ pivot: 0 -0.13 0;
101
+ targetPivot: 0 0.13 0;
102
+ axis: 0 1 0;
103
+ targetAxis: 0 1 0"
104
+ >
105
+ </a-box>
106
+ <a-box
107
+ id="punchingBag0"
108
+ class="punchingBag"
109
+ data-section="0"
110
+ width="0.25"
111
+ height="0.25"
112
+ depth="0.25"
113
+ color="#F00"
114
+ position="0 0.25 0"
115
+ dynamic-body
116
+ force-pushable
117
+ constraint="type: coneTwist;
118
+ target: #punchingBagBase;
119
+ pivot: 0 -0.125 0;
120
+ targetPivot: 0 0.125 0;
121
+ axis: 0 1 0;
122
+ targetAxis: 0 1 0"
123
+ >
124
+ </a-box>
125
+ <a-sphere
126
+ id="punchingBagBase"
127
+ radius="0.125"
128
+ color="#777"
129
+ position="0 0 0"
130
+ static-body
131
+ ></a-sphere>
132
+ </a-entity>
133
+ </a-scene>
134
+ </body>
135
+ </html>
Binary file
@@ -0,0 +1,169 @@
1
+ import * as BS from "../../build/brilliantsole.module.js";
2
+ window.BS = BS;
3
+ console.log(BS);
4
+
5
+ // DEVICE
6
+
7
+ const device = new BS.Device();
8
+ console.log({ device });
9
+ window.device = device;
10
+
11
+ // CONNECT
12
+
13
+ const toggleConnectionButton = document.getElementById("toggleConnection");
14
+ toggleConnectionButton.addEventListener("click", () =>
15
+ device.toggleConnection()
16
+ );
17
+ device.addEventListener("connectionStatus", () => {
18
+ let disabled = false;
19
+ let innerText = device.connectionStatus;
20
+ switch (device.connectionStatus) {
21
+ case "notConnected":
22
+ innerText = "connect";
23
+ break;
24
+ case "connected":
25
+ innerText = "disconnect";
26
+ break;
27
+ }
28
+ toggleConnectionButton.disabled = disabled;
29
+ toggleConnectionButton.innerText = innerText;
30
+ });
31
+
32
+ // FILE TRANSFER
33
+ /** @type {HTMLProgressElement} */
34
+ const fileTransferProgress = document.getElementById("fileTransferProgress");
35
+ device.addEventListener("fileTransferProgress", (event) => {
36
+ const progress = event.message.progress;
37
+ console.log({ progress });
38
+ fileTransferProgress.value = progress == 1 ? 0 : progress;
39
+ });
40
+
41
+ // MODEL
42
+ /** @type {HTMLInputElement} */
43
+ const isModelReadyCheckbox = document.getElementById("isModelReady");
44
+ device.addEventListener("getTfliteInferencingEnabled", () => {
45
+ isModelReadyCheckbox.checked = device.tfliteInferencingEnabled;
46
+ });
47
+ device.addEventListener("fileTransferStatus", () => {
48
+ if (device.fileTransferStatus == "idle") {
49
+ fileTransferProgress.value = 0;
50
+ }
51
+ });
52
+
53
+ /** @type {HTMLSpanElement} */
54
+ const maxClassSpan = document.getElementById("maxClass");
55
+ let gestureTimeout;
56
+ device.addEventListener("tfliteInference", (event) => {
57
+ maxClassSpan.innerText =
58
+ event.message.tfliteInference.maxClass.toUpperCase() + "!";
59
+ if (gestureTimeout) {
60
+ clearTimeout(gestureTimeout);
61
+ }
62
+ gestureTimeout = setTimeout(() => {
63
+ maxClassSpan.innerText = "";
64
+ }, 600);
65
+ });
66
+
67
+ // GLOVE
68
+ /** @type {BS.TfliteFileConfiguration} */
69
+ const punchConfiguration = {
70
+ name: "punch",
71
+ task: "classification",
72
+ sensorTypes: ["gyroscope", "linearAcceleration"],
73
+ sampleRate: 20,
74
+ captureDelay: 200,
75
+ classes: ["idle", "punch", "hook", "uppercut"],
76
+ };
77
+ fetch("./punch.tflite")
78
+ .then((response) => response.arrayBuffer())
79
+ .then((buffer) => {
80
+ punchConfiguration.file = buffer;
81
+ console.log("updated punchModelConfiguration", punchConfiguration);
82
+ })
83
+ .catch((err) => {
84
+ console.error("Error loading punch model:", err);
85
+ });
86
+
87
+ device.addEventListener("connected", async () => {
88
+ if (device.type != "rightGlove") {
89
+ console.error("expected right glove");
90
+ device.disconnect();
91
+ return;
92
+ }
93
+ device.sendTfliteConfiguration(punchConfiguration);
94
+ });
95
+ device.addEventListener("tfliteIsReady", () => {
96
+ if (device.tfliteIsReady) {
97
+ device.enableTfliteInferencing();
98
+ }
99
+ });
100
+
101
+ // GAME
102
+ device.addEventListener("tfliteInference", (event) => {
103
+ switch (event.message.tfliteInference.maxClass) {
104
+ case "punch":
105
+ punch();
106
+ break;
107
+ case "hook":
108
+ hook();
109
+ break;
110
+ case "uppercut":
111
+ uppercut();
112
+ break;
113
+ }
114
+ });
115
+
116
+ // PHYSICS
117
+ const punchingBagBaseEntity = document.getElementById("punchingBagBase");
118
+ const punchingBagEntities = Array.from(
119
+ document.querySelectorAll(".punchingBag")
120
+ ).sort((a, b) => a.dataset.section - b.dataset.section);
121
+
122
+ const forces = {
123
+ punch: new THREE.Vector3(0, 0, -110),
124
+ hook: new THREE.Vector3(-30, 0, -20),
125
+ uppercut: new THREE.Vector3(-10, 0, -70),
126
+ };
127
+ function punch() {
128
+ window.force = forces.punch;
129
+ punchingBagEntities[1].click();
130
+ triggerWaveformEffect("strongClick100");
131
+ }
132
+ function hook() {
133
+ window.force = forces.hook;
134
+ punchingBagEntities[2].click();
135
+ triggerWaveformEffect("strongBuzz100");
136
+ }
137
+ function uppercut() {
138
+ window.force = forces.uppercut;
139
+ punchingBagEntities[2].click();
140
+ triggerWaveformEffect("pulsingStrong100");
141
+ }
142
+
143
+ /** @param {BS.VibrationWaveformEffect} waveformEffect */
144
+ function triggerWaveformEffect(waveformEffect) {
145
+ if (!device.isConnected) {
146
+ return;
147
+ }
148
+ device.triggerVibration([
149
+ {
150
+ type: "waveformEffect",
151
+ locations: ["rear"],
152
+ segments: [{ effect: waveformEffect }],
153
+ },
154
+ ]);
155
+ }
156
+
157
+ document.addEventListener("keydown", (event) => {
158
+ switch (event.key) {
159
+ case "p":
160
+ punch();
161
+ break;
162
+ case "h":
163
+ hook();
164
+ break;
165
+ case "u":
166
+ uppercut();
167
+ break;
168
+ }
169
+ });