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.
- package/README.md +16 -10
- package/assets/3d/anchor.glb +0 -0
- package/assets/3d/coin.glb +0 -0
- package/assets/3d/glasses.glb +0 -0
- package/assets/3d/rightHand.glb +0 -0
- package/assets/audio/bounceMedium.wav +0 -0
- package/assets/audio/bounceStrong.wav +0 -0
- package/assets/audio/bounceWeak.wav +0 -0
- package/assets/audio/coin.wav +0 -0
- package/assets/audio/getUp.wav +0 -0
- package/assets/audio/grab.wav +0 -0
- package/assets/audio/kick.wav +0 -0
- package/assets/audio/platterFadeIn old.wav +0 -0
- package/assets/audio/platterFadeIn.wav +0 -0
- package/assets/audio/platterFadeOut.wav +0 -0
- package/assets/audio/punch.wav +0 -0
- package/assets/audio/punchSqueak.wav +0 -0
- package/assets/audio/purr.wav +0 -0
- package/assets/audio/purrFadeOut.wav +0 -0
- package/assets/audio/release.wav +0 -0
- package/assets/audio/splat.wav +0 -0
- package/assets/audio/stomp.wav +0 -0
- package/assets/images/ukaton-pressure-0.svg +9 -0
- package/assets/images/ukaton-pressure-1.svg +9 -0
- package/assets/images/ukaton-pressure-10.svg +9 -0
- package/assets/images/ukaton-pressure-11.svg +9 -0
- package/assets/images/ukaton-pressure-12.svg +9 -0
- package/assets/images/ukaton-pressure-13.svg +9 -0
- package/assets/images/ukaton-pressure-14.svg +9 -0
- package/assets/images/ukaton-pressure-15.svg +9 -0
- package/assets/images/ukaton-pressure-2.svg +9 -0
- package/assets/images/ukaton-pressure-3.svg +9 -0
- package/assets/images/ukaton-pressure-4.svg +9 -0
- package/assets/images/ukaton-pressure-5.svg +9 -0
- package/assets/images/ukaton-pressure-6.svg +9 -0
- package/assets/images/ukaton-pressure-7.svg +9 -0
- package/assets/images/ukaton-pressure-8.svg +9 -0
- package/assets/images/ukaton-pressure-9.svg +9 -0
- package/assets/images/ukaton-right-insole.svg +798 -0
- package/build/brilliantsole.cjs +2870 -882
- package/build/brilliantsole.cjs.map +1 -1
- package/build/brilliantsole.js +2477 -782
- package/build/brilliantsole.js.map +1 -1
- package/build/brilliantsole.ls.js +2260 -592
- package/build/brilliantsole.ls.js.map +1 -1
- package/build/brilliantsole.min.js +1 -1
- package/build/brilliantsole.min.js.map +1 -1
- package/build/brilliantsole.module.d.ts +302 -116
- package/build/brilliantsole.module.js +2468 -782
- package/build/brilliantsole.module.js.map +1 -1
- package/build/brilliantsole.module.min.d.ts +302 -116
- package/build/brilliantsole.module.min.js +1 -1
- package/build/brilliantsole.module.min.js.map +1 -1
- package/build/brilliantsole.node.module.d.ts +295 -113
- package/build/brilliantsole.node.module.js +2860 -882
- package/build/brilliantsole.node.module.js.map +1 -1
- package/build/dts/BS-output.d.ts +10 -0
- package/build/dts/BS.d.ts +21 -9
- package/build/dts/CameraManager.d.ts +72 -0
- package/build/dts/Device.d.ts +53 -16
- package/build/dts/DeviceInformationManager.d.ts +4 -4
- package/build/dts/DeviceManager.d.ts +3 -0
- package/build/dts/FileTransferManager.d.ts +18 -8
- package/build/dts/InformationManager.d.ts +8 -5
- package/build/dts/TfliteManager.d.ts +22 -2
- package/build/dts/WifiManager.d.ts +61 -0
- package/build/dts/connection/BaseConnectionManager.d.ts +37 -3
- package/build/dts/connection/ClientConnectionManager.d.ts +11 -2
- package/build/dts/connection/bluetooth/BluetoothConnectionManager.d.ts +1 -0
- package/build/dts/connection/bluetooth/NobleConnectionManager.d.ts +3 -1
- package/build/dts/connection/bluetooth/WebBluetoothConnectionManager.d.ts +2 -0
- package/build/dts/connection/bluetooth/bluetoothUUIDs.d.ts +2 -2
- package/build/dts/connection/udp/UDPConnectionManager.d.ts +28 -0
- package/build/dts/connection/webSocket/WebSocketConnectionManager.d.ts +25 -0
- package/build/dts/devicePair/DevicePair.d.ts +14 -10
- package/build/dts/devicePair/DevicePairPressureSensorDataManager.d.ts +8 -4
- package/build/dts/devicePair/DevicePairSensorDataManager.d.ts +2 -2
- package/build/dts/scanner/BaseScanner.d.ts +4 -1
- package/build/dts/scanner/NobleScanner.d.ts +2 -1
- package/build/dts/sensor/MotionSensorDataManager.d.ts +5 -2
- package/build/dts/sensor/SensorDataManager.d.ts +5 -4
- package/build/dts/server/BaseClient.d.ts +6 -3
- package/build/dts/server/ServerUtils.d.ts +1 -1
- package/build/dts/server/websocket/WebSocketUtils.d.ts +1 -1
- package/build/dts/utils/CenterOfPressureHelper.d.ts +2 -2
- package/build/dts/utils/Console.d.ts +2 -0
- package/build/dts/utils/MathUtils.d.ts +2 -0
- package/build/dts/utils/ThrottleUtils.d.ts +2 -0
- package/build/dts/vibration/VibrationManager.d.ts +19 -2
- package/build/index.d.ts +299 -113
- package/build/index.node.d.ts +292 -110
- package/examples/3d/scene.html +19 -5
- package/examples/3d/script.js +90 -17
- package/examples/3d-generic/index.html +144 -0
- package/examples/3d-generic/script.js +266 -0
- package/examples/balance/script.js +2 -1
- package/examples/basic/index.html +232 -18
- package/examples/basic/script.js +746 -106
- package/examples/bottango/index.html +11 -1
- package/examples/bottango/script.js +2 -2
- package/examples/center-of-pressure/index.html +114 -114
- package/examples/center-of-pressure/script.js +1 -1
- package/examples/device-pair/index.html +58 -58
- package/examples/device-pair/script.js +12 -8
- package/examples/edge-impulse/script.js +135 -44
- package/examples/edge-impulse-test/README.md +11 -0
- package/examples/edge-impulse-test/edge-impulse-standalone.js +7228 -0
- package/examples/edge-impulse-test/edge-impulse-standalone.wasm +0 -0
- package/examples/edge-impulse-test/index.html +75 -0
- package/examples/edge-impulse-test/run-impulse.js +135 -0
- package/examples/edge-impulse-test/script.js +200 -0
- package/examples/gloves/edge-impulse-standalone.js +7228 -0
- package/examples/gloves/edge-impulse-standalone.wasm +0 -0
- package/examples/gloves/index.html +119 -0
- package/examples/gloves/run-impulse.js +135 -0
- package/examples/gloves/scene.html +124 -0
- package/examples/gloves/script.js +931 -0
- package/examples/graph/index.html +11 -1
- package/examples/graph/script.js +94 -37
- package/examples/pressure/index.html +180 -12
- package/examples/pressure/script.js +144 -7
- package/examples/punch/index.html +135 -0
- package/examples/punch/punch.tflite +0 -0
- package/examples/punch/script.js +169 -0
- package/examples/recording/index.html +191 -183
- package/examples/server/index.html +109 -23
- package/examples/server/script.js +322 -111
- package/examples/ukaton-firmware-update/index.html +20 -0
- package/examples/ukaton-firmware-update/manifest.json +11 -0
- package/examples/ukaton-firmware-update/merged-firmware.bin +0 -0
- package/examples/utils/aframe/aframe-master.min.js +2 -0
- package/examples/utils/aframe/bs-vibration.js +150 -0
- package/examples/utils/aframe/force-pushable.js +80 -0
- package/examples/utils/aframe/grabbable-anchor.js +46 -0
- package/examples/utils/aframe/grabbable-listener.js +31 -0
- package/examples/utils/aframe/grabbable-physics-body.js +190 -0
- package/examples/utils/aframe/grow-shrink.js +25 -0
- package/examples/utils/aframe/hand-punch.js +119 -0
- package/examples/utils/aframe/my-obb-collider.js +293 -0
- package/examples/utils/aframe/occlude-hand-tracking-controls.js +47 -0
- package/examples/utils/aframe/occlude-mesh.js +42 -0
- package/examples/utils/aframe/palm-up-detector.js +47 -0
- package/examples/utils/aframe/shadow-material.js +20 -0
- package/examples/utils/aframe/soft-shadow-light.js +9 -0
- package/examples/webxr/script.js +3 -3
- package/examples/webxr-2/assets/3d/soccerBall.glb +0 -0
- package/examples/webxr-2/assets/audio/shellBounce.wav +0 -0
- package/examples/webxr-2/assets/audio/shellHit.wav +0 -0
- package/examples/webxr-2/assets/audio/shellKick.wav +0 -0
- package/examples/webxr-2/assets/audio/soccerBounce.wav +0 -0
- package/examples/webxr-2/assets/audio/soccerKick.mp3 +0 -0
- package/examples/webxr-2/assets/images/shellTexture.png +0 -0
- package/examples/webxr-2/components/bs-ankle.js +337 -0
- package/examples/webxr-2/components/coin.js +84 -0
- package/examples/webxr-2/components/custom-wrap.js +17 -0
- package/examples/webxr-2/components/goomba.js +3250 -0
- package/examples/webxr-2/components/init-shell-material.js +215 -0
- package/examples/webxr-2/components/platter.js +172 -0
- package/examples/webxr-2/components/shell.js +374 -0
- package/examples/webxr-2/components/soccer-ball.js +250 -0
- package/examples/webxr-2/components/squashed-goomba.js +249 -0
- package/examples/webxr-2/edge-impulse-standalone.js +7228 -0
- package/examples/webxr-2/edge-impulse-standalone.wasm +0 -0
- package/examples/webxr-2/index.html +996 -0
- package/examples/webxr-2/kick.tflite +0 -0
- package/examples/webxr-2/kick2.tflite +0 -0
- package/examples/webxr-2/run-impulse.js +135 -0
- package/examples/webxr-2/script.js +384 -0
- package/package.json +2 -1
- package/src/.prettierrc +4 -0
- package/src/BS.ts +66 -9
- package/src/CameraManager.ts +499 -0
- package/src/Device.ts +620 -92
- package/src/DeviceInformationManager.ts +22 -11
- package/src/DeviceManager.ts +94 -25
- package/src/FileTransferManager.ts +146 -21
- package/src/FirmwareManager.ts +1 -1
- package/src/InformationManager.ts +62 -20
- package/src/TfliteManager.ts +172 -26
- package/src/WifiManager.ts +323 -0
- package/src/connection/BaseConnectionManager.ts +145 -30
- package/src/connection/ClientConnectionManager.ts +47 -11
- package/src/connection/bluetooth/BluetoothConnectionManager.ts +14 -3
- package/src/connection/bluetooth/NobleConnectionManager.ts +155 -42
- package/src/connection/bluetooth/WebBluetoothConnectionManager.ts +104 -35
- package/src/connection/bluetooth/bluetoothUUIDs.ts +40 -13
- package/src/connection/udp/UDPConnectionManager.ts +356 -0
- package/src/connection/websocket/WebSocketConnectionManager.ts +282 -0
- package/src/devicePair/DevicePair.ts +145 -49
- package/src/devicePair/DevicePairPressureSensorDataManager.ts +72 -24
- package/src/devicePair/DevicePairSensorDataManager.ts +5 -5
- package/src/scanner/BaseScanner.ts +49 -11
- package/src/scanner/NobleScanner.ts +81 -17
- package/src/sensor/BarometerSensorDataManager.ts +1 -1
- package/src/sensor/MotionSensorDataManager.ts +22 -7
- package/src/sensor/PressureSensorDataManager.ts +47 -13
- package/src/sensor/SensorConfigurationManager.ts +75 -24
- package/src/sensor/SensorDataManager.ts +107 -26
- package/src/server/BaseClient.ts +192 -37
- package/src/server/BaseServer.ts +201 -43
- package/src/server/ServerUtils.ts +39 -9
- package/src/server/udp/UDPServer.ts +74 -23
- package/src/server/udp/UDPUtils.ts +9 -2
- package/src/server/websocket/WebSocketClient.ts +30 -9
- package/src/server/websocket/WebSocketServer.ts +1 -1
- package/src/server/websocket/WebSocketUtils.ts +4 -2
- package/src/utils/CenterOfPressureHelper.ts +5 -5
- package/src/utils/Console.ts +62 -9
- package/src/utils/MathUtils.ts +31 -1
- package/src/utils/ParseUtils.ts +25 -6
- package/src/utils/ThrottleUtils.ts +62 -0
- package/src/utils/Timer.ts +1 -1
- package/src/utils/checksum.ts +1 -1
- package/src/utils/mcumgr.js +1 -1
- 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, {
|
|
3
|
-
|
|
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, {
|
|
20
|
+
import DevicePairSensorDataManager, {
|
|
21
|
+
DevicePairSensorDataEventDispatcher,
|
|
22
|
+
} from "./DevicePairSensorDataManager.ts";
|
|
13
23
|
import { capitalizeFirstCharacter } from "../utils/stringUtils.ts";
|
|
14
|
-
import {
|
|
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 {
|
|
18
|
-
|
|
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:
|
|
38
|
+
const _console = createConsole("DevicePair", { log: false });
|
|
22
39
|
|
|
23
40
|
interface BaseDevicePairDeviceEventMessage {
|
|
24
41
|
device: Device;
|
|
25
|
-
side:
|
|
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(
|
|
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 =
|
|
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<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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.#
|
|
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
|
|
114
|
+
return Sides;
|
|
70
115
|
}
|
|
71
116
|
|
|
72
|
-
#
|
|
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
|
|
157
|
+
return Sides.every((side) => this[side]?.isConnected);
|
|
105
158
|
}
|
|
106
159
|
get isPartiallyConnected() {
|
|
107
|
-
return
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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.
|
|
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}
|
|
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", {
|
|
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
|
-
|
|
158
|
-
|
|
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
|
-
|
|
165
|
-
|
|
235
|
+
device.removeEventListener(
|
|
236
|
+
// @ts-expect-error
|
|
237
|
+
deviceEventType,
|
|
238
|
+
this.#redispatchDeviceEvent.bind(this)
|
|
239
|
+
);
|
|
166
240
|
});
|
|
167
241
|
}
|
|
168
242
|
|
|
169
|
-
#
|
|
170
|
-
const foundDevice =
|
|
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}
|
|
249
|
+
_console.log(`removing ${side} ${this.type} device`, device);
|
|
176
250
|
removeEventListeners(device, this.#boundDeviceEventListeners);
|
|
177
|
-
|
|
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.
|
|
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.
|
|
290
|
+
if (this[device.side] == device) {
|
|
209
291
|
return;
|
|
210
292
|
}
|
|
211
|
-
const foundDevice = this.#
|
|
293
|
+
const foundDevice = this.#removeDevice(device);
|
|
212
294
|
if (!foundDevice) {
|
|
213
295
|
return;
|
|
214
296
|
}
|
|
215
|
-
this.
|
|
297
|
+
this.assignDevice(device);
|
|
216
298
|
}
|
|
217
299
|
|
|
218
300
|
// SENSOR CONFIGURATION
|
|
219
301
|
async setSensorConfiguration(sensorConfiguration: SensorConfiguration) {
|
|
220
|
-
for (let i = 0; i <
|
|
221
|
-
const side =
|
|
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(
|
|
241
|
-
|
|
242
|
-
|
|
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
|
|
248
|
-
static #
|
|
249
|
-
static get
|
|
250
|
-
return this.#
|
|
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.#
|
|
349
|
+
this.#insoles.assignDevice(device);
|
|
350
|
+
}
|
|
351
|
+
if (device.isGlove) {
|
|
352
|
+
this.#gloves.assignDevice(device);
|
|
257
353
|
}
|
|
258
354
|
});
|
|
259
355
|
}
|