brilliantsole 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -0
  3. package/build/brilliantsole.cjs +5957 -0
  4. package/build/brilliantsole.cjs.map +1 -0
  5. package/build/brilliantsole.js +5448 -0
  6. package/build/brilliantsole.js.map +1 -0
  7. package/build/brilliantsole.ls.js +4872 -0
  8. package/build/brilliantsole.ls.js.map +1 -0
  9. package/build/brilliantsole.min.js +6 -0
  10. package/build/brilliantsole.min.js.map +1 -0
  11. package/build/brilliantsole.module.d.ts +908 -0
  12. package/build/brilliantsole.module.js +5412 -0
  13. package/build/brilliantsole.module.js.map +1 -0
  14. package/build/brilliantsole.module.min.d.ts +908 -0
  15. package/build/brilliantsole.module.min.js +6 -0
  16. package/build/brilliantsole.module.min.js.map +1 -0
  17. package/build/brilliantsole.node.module.d.ts +908 -0
  18. package/build/brilliantsole.node.module.js +5906 -0
  19. package/build/brilliantsole.node.module.js.map +1 -0
  20. package/build/dts/BS.d.ts +25 -0
  21. package/build/dts/Device.d.ts +136 -0
  22. package/build/dts/DeviceInformationManager.d.ts +56 -0
  23. package/build/dts/DeviceManager.d.ts +67 -0
  24. package/build/dts/FileTransferManager.d.ts +84 -0
  25. package/build/dts/FirmwareManager.d.ts +71 -0
  26. package/build/dts/InformationManager.d.ts +66 -0
  27. package/build/dts/TfliteManager.d.ts +92 -0
  28. package/build/dts/connection/BaseConnectionManager.d.ts +59 -0
  29. package/build/dts/connection/ClientConnectionManager.d.ts +23 -0
  30. package/build/dts/connection/WebSocketClientConnectionManager.d.ts +23 -0
  31. package/build/dts/connection/bluetooth/BluetoothConnectionManager.d.ts +10 -0
  32. package/build/dts/connection/bluetooth/NobleConnectionManager.d.ts +42 -0
  33. package/build/dts/connection/bluetooth/WebBluetoothConnectionManager.d.ts +20 -0
  34. package/build/dts/connection/bluetooth/bluetoothUUIDs.d.ts +14 -0
  35. package/build/dts/connection/webSocket/ClientConnectionManager.d.ts +23 -0
  36. package/build/dts/connection/webSocket/WebSocketClientConnectionManager.d.ts +23 -0
  37. package/build/dts/devicePair/DevicePair.d.ts +60 -0
  38. package/build/dts/devicePair/DevicePairPressureSensorDataManager.d.ts +25 -0
  39. package/build/dts/devicePair/DevicePairSensorDataManager.d.ts +33 -0
  40. package/build/dts/scanner/BaseScanner.d.ts +66 -0
  41. package/build/dts/scanner/NobleScanner.d.ts +17 -0
  42. package/build/dts/scanner/Scanner.d.ts +3 -0
  43. package/build/dts/sensor/BarometerSensorDataManager.d.ts +16 -0
  44. package/build/dts/sensor/MotionSensorDataManager.d.ts +69 -0
  45. package/build/dts/sensor/PressureSensorDataManager.d.ts +36 -0
  46. package/build/dts/sensor/SensorConfigurationManager.d.ts +44 -0
  47. package/build/dts/sensor/SensorDataManager.d.ts +40 -0
  48. package/build/dts/server/BaseClient.d.ts +85 -0
  49. package/build/dts/server/BaseServer.d.ts +48 -0
  50. package/build/dts/server/ServerUtils.d.ts +23 -0
  51. package/build/dts/server/udp/UDPServer.d.ts +11 -0
  52. package/build/dts/server/udp/UDPUtils.d.ts +9 -0
  53. package/build/dts/server/websocket/WebSocketClient.d.ts +17 -0
  54. package/build/dts/server/websocket/WebSocketServer.d.ts +13 -0
  55. package/build/dts/server/websocket/WebSocketUtils.d.ts +9 -0
  56. package/build/dts/utils/ArrayBufferUtils.d.ts +7 -0
  57. package/build/dts/utils/ArrayUtils.d.ts +2 -0
  58. package/build/dts/utils/CenterOfPressureHelper.d.ts +15 -0
  59. package/build/dts/utils/Console.d.ts +34 -0
  60. package/build/dts/utils/EventDispatcher.d.ts +50 -0
  61. package/build/dts/utils/EventUtils.d.ts +6 -0
  62. package/build/dts/utils/MathUtils.d.ts +21 -0
  63. package/build/dts/utils/ParseUtils.d.ts +5 -0
  64. package/build/dts/utils/RangeHelper.d.ts +8 -0
  65. package/build/dts/utils/Text.d.ts +6 -0
  66. package/build/dts/utils/Timer.d.ts +14 -0
  67. package/build/dts/utils/TypeScriptUtils.d.ts +19 -0
  68. package/build/dts/utils/cbor.d.ts +6 -0
  69. package/build/dts/utils/checksum.d.ts +3 -0
  70. package/build/dts/utils/environment.d.ts +13 -0
  71. package/build/dts/utils/mcumgr.d.ts +88 -0
  72. package/build/dts/utils/stringUtils.d.ts +2 -0
  73. package/build/dts/vibration/VibrationManager.d.ts +45 -0
  74. package/build/dts/vibration/VibrationWaveformEffects.d.ts +2 -0
  75. package/build/index.d.ts +908 -0
  76. package/build/index.node.d.ts +908 -0
  77. package/examples/3d/index.html +109 -0
  78. package/examples/3d/scene.html +57 -0
  79. package/examples/3d/script.js +419 -0
  80. package/examples/balance/index.html +138 -0
  81. package/examples/balance/script.js +243 -0
  82. package/examples/basic/index.html +327 -0
  83. package/examples/basic/script.js +1093 -0
  84. package/examples/center-of-pressure/index.html +132 -0
  85. package/examples/center-of-pressure/script.js +207 -0
  86. package/examples/device-pair/index.html +72 -0
  87. package/examples/device-pair/script.js +187 -0
  88. package/examples/edge-impulse/index.html +94 -0
  89. package/examples/edge-impulse/script.js +1033 -0
  90. package/examples/graph/index.html +83 -0
  91. package/examples/graph/script.js +469 -0
  92. package/examples/machine-learning/index.html +366 -0
  93. package/examples/machine-learning/script.js +1774 -0
  94. package/examples/pressure/index.html +145 -0
  95. package/examples/pressure/script.js +201 -0
  96. package/examples/recording/index.html +187 -0
  97. package/examples/recording/script.js +736 -0
  98. package/examples/server/index.html +266 -0
  99. package/examples/server/script.js +925 -0
  100. package/examples/utils/aframe/fingertip-button-component.js +201 -0
  101. package/examples/utils/aframe/fingertip-collider-target-component.js +102 -0
  102. package/examples/utils/aframe/fingertip-colliders-component.js +147 -0
  103. package/examples/utils/three/three.module.min.js +24846 -0
  104. package/examples/webxr/index.html +221 -0
  105. package/examples/webxr/script.js +1127 -0
  106. package/package.json +83 -0
  107. package/src/BS.ts +68 -0
  108. package/src/Device.ts +734 -0
  109. package/src/DeviceInformationManager.ts +146 -0
  110. package/src/DeviceManager.ts +354 -0
  111. package/src/FileTransferManager.ts +452 -0
  112. package/src/FirmwareManager.ts +357 -0
  113. package/src/InformationManager.ts +283 -0
  114. package/src/TfliteManager.ts +450 -0
  115. package/src/connection/BaseConnectionManager.ts +255 -0
  116. package/src/connection/ClientConnectionManager.ts +120 -0
  117. package/src/connection/bluetooth/BluetoothConnectionManager.ts +34 -0
  118. package/src/connection/bluetooth/NobleConnectionManager.ts +302 -0
  119. package/src/connection/bluetooth/WebBluetoothConnectionManager.ts +269 -0
  120. package/src/connection/bluetooth/bluetoothUUIDs.ts +218 -0
  121. package/src/devicePair/DevicePair.ts +253 -0
  122. package/src/devicePair/DevicePairPressureSensorDataManager.ts +82 -0
  123. package/src/devicePair/DevicePairSensorDataManager.ts +90 -0
  124. package/src/scanner/BaseScanner.ts +189 -0
  125. package/src/scanner/NobleScanner.ts +195 -0
  126. package/src/scanner/Scanner.ts +16 -0
  127. package/src/sensor/BarometerSensorDataManager.ts +41 -0
  128. package/src/sensor/MotionSensorDataManager.ts +151 -0
  129. package/src/sensor/PressureSensorDataManager.ts +112 -0
  130. package/src/sensor/SensorConfigurationManager.ts +177 -0
  131. package/src/sensor/SensorDataManager.ts +166 -0
  132. package/src/server/BaseClient.ts +368 -0
  133. package/src/server/BaseServer.ts +344 -0
  134. package/src/server/ServerUtils.ts +93 -0
  135. package/src/server/udp/UDPServer.ts +229 -0
  136. package/src/server/udp/UDPUtils.ts +20 -0
  137. package/src/server/websocket/WebSocketClient.ts +179 -0
  138. package/src/server/websocket/WebSocketServer.ts +184 -0
  139. package/src/server/websocket/WebSocketUtils.ts +20 -0
  140. package/src/utils/ArrayBufferUtils.ts +88 -0
  141. package/src/utils/ArrayUtils.ts +15 -0
  142. package/src/utils/CenterOfPressureHelper.ts +39 -0
  143. package/src/utils/Console.ts +156 -0
  144. package/src/utils/EventDispatcher.ts +153 -0
  145. package/src/utils/EventUtils.ts +41 -0
  146. package/src/utils/MathUtils.ts +53 -0
  147. package/src/utils/ParseUtils.ts +46 -0
  148. package/src/utils/RangeHelper.ts +38 -0
  149. package/src/utils/Text.ts +30 -0
  150. package/src/utils/Timer.ts +72 -0
  151. package/src/utils/TypeScriptUtils.ts +22 -0
  152. package/src/utils/cbor.js +429 -0
  153. package/src/utils/checksum.ts +41 -0
  154. package/src/utils/environment.ts +46 -0
  155. package/src/utils/mcumgr.js +444 -0
  156. package/src/utils/stringUtils.ts +11 -0
  157. package/src/vibration/VibrationManager.ts +308 -0
  158. package/src/vibration/VibrationWaveformEffects.ts +128 -0
@@ -0,0 +1,179 @@
1
+ import { createConsole } from "../../utils/Console.ts";
2
+ import { createServerMessage, MessageLike, ServerMessage } from "../ServerUtils.ts";
3
+ import { addEventListeners, removeEventListeners } from "../../utils/EventUtils.ts";
4
+ import ClientConnectionManager from "../../connection/ClientConnectionManager.ts";
5
+ import BaseClient, { ServerURL } from "../BaseClient.ts";
6
+ import type * as ws from "ws";
7
+ import Timer from "../../utils/Timer.ts";
8
+ import {
9
+ createWebSocketMessage,
10
+ WebSocketMessageType,
11
+ WebSocketMessageTypes,
12
+ webSocketPingTimeout,
13
+ webSocketReconnectTimeout,
14
+ WebSocketMessage,
15
+ } from "./WebSocketUtils.ts";
16
+ import { parseMessage } from "../../utils/ParseUtils.ts";
17
+
18
+ const _console = createConsole("WebSocketClient", { log: true });
19
+
20
+ class WebSocketClient extends BaseClient {
21
+ // WEBSOCKET
22
+ #webSocket?: WebSocket;
23
+ get webSocket() {
24
+ return this.#webSocket;
25
+ }
26
+ set webSocket(newWebSocket) {
27
+ if (this.#webSocket == newWebSocket) {
28
+ _console.log("redundant webSocket assignment");
29
+ return;
30
+ }
31
+
32
+ _console.log("assigning webSocket", newWebSocket);
33
+
34
+ if (this.#webSocket) {
35
+ removeEventListeners(this.#webSocket, this.#boundWebSocketEventListeners);
36
+ }
37
+
38
+ addEventListeners(newWebSocket, this.#boundWebSocketEventListeners);
39
+ this.#webSocket = newWebSocket;
40
+
41
+ _console.log("assigned webSocket");
42
+ }
43
+ get readyState() {
44
+ return this.webSocket?.readyState;
45
+ }
46
+ get isConnected() {
47
+ return this.readyState == WebSocket.OPEN;
48
+ }
49
+ get isDisconnected() {
50
+ return this.readyState == WebSocket.CLOSED;
51
+ }
52
+
53
+ connect(url: string | URL = `wss://${location.host}`) {
54
+ if (this.webSocket) {
55
+ this.assertDisconnection();
56
+ }
57
+ this._connectionStatus = "connecting";
58
+ this.webSocket = new WebSocket(url);
59
+ }
60
+
61
+ disconnect() {
62
+ this.assertConnection();
63
+ if (this.reconnectOnDisconnection) {
64
+ this.reconnectOnDisconnection = false;
65
+ this.webSocket!.addEventListener(
66
+ "close",
67
+ () => {
68
+ this.reconnectOnDisconnection = true;
69
+ },
70
+ { once: true }
71
+ );
72
+ }
73
+ this._connectionStatus = "disconnecting";
74
+ this.webSocket!.close();
75
+ }
76
+
77
+ reconnect() {
78
+ this.assertDisconnection();
79
+ this.webSocket = new WebSocket(this.webSocket!.url);
80
+ }
81
+
82
+ toggleConnection(url?: ServerURL) {
83
+ if (this.isConnected) {
84
+ this.disconnect();
85
+ } else if (url && this.webSocket?.url == url) {
86
+ this.reconnect();
87
+ } else {
88
+ this.connect(url);
89
+ }
90
+ }
91
+
92
+ // WEBSOCKET MESSAGING
93
+ sendMessage(message: MessageLike) {
94
+ this.assertConnection();
95
+ this.#webSocket!.send(message);
96
+ }
97
+
98
+ sendServerMessage(...messages: ServerMessage[]) {
99
+ this.sendMessage(createWebSocketMessage({ type: "serverMessage", data: createServerMessage(...messages) }));
100
+ }
101
+
102
+ #sendWebSocketMessage(...messages: WebSocketMessage[]) {
103
+ this.sendMessage(createWebSocketMessage(...messages));
104
+ }
105
+
106
+ // WEBSOCKET EVENTS
107
+ #boundWebSocketEventListeners: { [eventType: string]: Function } = {
108
+ open: this.#onWebSocketOpen.bind(this),
109
+ message: this.#onWebSocketMessage.bind(this),
110
+ close: this.#onWebSocketClose.bind(this),
111
+ error: this.#onWebSocketError.bind(this),
112
+ };
113
+
114
+ #onWebSocketOpen(event: ws.Event) {
115
+ _console.log("webSocket.open", event);
116
+ this.#pingTimer.start();
117
+ this._connectionStatus = "connected";
118
+ }
119
+ async #onWebSocketMessage(event: ws.MessageEvent) {
120
+ _console.log("webSocket.message", event);
121
+ this.#pingTimer.restart();
122
+ //@ts-expect-error
123
+ const arrayBuffer = await event.data.arrayBuffer();
124
+ const dataView = new DataView(arrayBuffer);
125
+ this.#parseWebSocketMessage(dataView);
126
+ }
127
+ #onWebSocketClose(event: ws.CloseEvent) {
128
+ _console.log("webSocket.close", event);
129
+
130
+ this._connectionStatus = "notConnected";
131
+
132
+ Object.entries(this.devices).forEach(([id, device]) => {
133
+ const connectionManager = device.connectionManager! as ClientConnectionManager;
134
+ connectionManager.isConnected = false;
135
+ });
136
+
137
+ this.#pingTimer.stop();
138
+ if (this.reconnectOnDisconnection) {
139
+ setTimeout(() => {
140
+ this.reconnect();
141
+ }, webSocketReconnectTimeout);
142
+ }
143
+ }
144
+ #onWebSocketError(event: ws.ErrorEvent) {
145
+ _console.error("webSocket.error", event.message);
146
+ }
147
+
148
+ // PARSING
149
+ #parseWebSocketMessage(dataView: DataView) {
150
+ parseMessage(dataView, WebSocketMessageTypes, this.#onServerMessage.bind(this), null, true);
151
+ }
152
+
153
+ #onServerMessage(messageType: WebSocketMessageType, dataView: DataView) {
154
+ switch (messageType) {
155
+ case "ping":
156
+ this.#pong();
157
+ break;
158
+ case "pong":
159
+ break;
160
+ case "serverMessage":
161
+ this.parseMessage(dataView);
162
+ break;
163
+ default:
164
+ _console.error(`uncaught messageType "${messageType}"`);
165
+ break;
166
+ }
167
+ }
168
+
169
+ // PING
170
+ #pingTimer = new Timer(this.#ping.bind(this), webSocketPingTimeout);
171
+ #ping() {
172
+ this.#sendWebSocketMessage("ping");
173
+ }
174
+ #pong() {
175
+ this.#sendWebSocketMessage("pong");
176
+ }
177
+ }
178
+
179
+ export default WebSocketClient;
@@ -0,0 +1,184 @@
1
+ import { createConsole } from "../../utils/Console.ts";
2
+ import { addEventListeners, removeEventListeners } from "../../utils/EventUtils.ts";
3
+ import { concatenateArrayBuffers, dataToArrayBuffer } from "../../utils/ArrayBufferUtils.ts";
4
+ import Timer from "../../utils/Timer.ts";
5
+ import BaseServer from "../BaseServer.ts";
6
+ import {
7
+ webSocketPingMessage,
8
+ webSocketPongMessage,
9
+ WebSocketMessageType,
10
+ WebSocketMessageTypes,
11
+ webSocketPingTimeout,
12
+ createWebSocketMessage,
13
+ } from "./WebSocketUtils.ts";
14
+
15
+ const _console = createConsole("WebSocketServer", { log: true });
16
+
17
+ /** NODE_START */
18
+ import type * as ws from "ws";
19
+ import { parseMessage } from "../../utils/ParseUtils.ts";
20
+ /** NODE_END */
21
+
22
+ interface WebSocketClient extends ws.WebSocket {
23
+ isAlive: boolean;
24
+ pingClientTimer?: Timer;
25
+ }
26
+ interface WebSocketServer extends ws.WebSocketServer {}
27
+
28
+ class WebSocketServer extends BaseServer {
29
+ get numberOfClients() {
30
+ return this.#server?.clients.size || 0;
31
+ }
32
+
33
+ // WEBSOCKET SERVER
34
+
35
+ #server?: WebSocketServer;
36
+ get server() {
37
+ return this.#server;
38
+ }
39
+ set server(newServer) {
40
+ if (this.#server == newServer) {
41
+ _console.log("redundant WebSocket server assignment");
42
+ return;
43
+ }
44
+ _console.log("assigning WebSocket server...");
45
+
46
+ if (this.#server) {
47
+ _console.log("clearing existing WebSocket server...");
48
+ removeEventListeners(this.#server, this.#boundWebSocketServerListeners);
49
+ }
50
+
51
+ addEventListeners(newServer, this.#boundWebSocketServerListeners);
52
+ this.#server = newServer;
53
+
54
+ _console.log("assigned WebSocket server");
55
+ }
56
+
57
+ // WEBSOCKET SERVER LISTENERS
58
+
59
+ #boundWebSocketServerListeners = {
60
+ close: this.#onWebSocketServerClose.bind(this),
61
+ connection: this.#onWebSocketServerConnection.bind(this),
62
+ error: this.#onWebSocketServerError.bind(this),
63
+ headers: this.#onWebSocketServerHeaders.bind(this),
64
+ listening: this.#onWebSocketServerListening.bind(this),
65
+ };
66
+
67
+ #onWebSocketServerClose() {
68
+ _console.log("server.close");
69
+ }
70
+ #onWebSocketServerConnection(client: WebSocketClient) {
71
+ _console.log("server.connection");
72
+ client.isAlive = true;
73
+ client.pingClientTimer = new Timer(() => this.#pingClient(client), webSocketPingTimeout);
74
+ client.pingClientTimer.start();
75
+ addEventListeners(client, this.#boundWebSocketClientListeners);
76
+ this.dispatchEvent("clientConnected", { client });
77
+ }
78
+ #onWebSocketServerError(error: Error) {
79
+ _console.error(error);
80
+ }
81
+ #onWebSocketServerHeaders() {
82
+ //_console.log("server.headers");
83
+ }
84
+ #onWebSocketServerListening() {
85
+ _console.log("server.listening");
86
+ }
87
+
88
+ // WEBSOCKET CLIENT LISTENERS
89
+
90
+ #boundWebSocketClientListeners: { [eventType: string]: Function } = {
91
+ open: this.#onWebSocketClientOpen.bind(this),
92
+ message: this.#onWebSocketClientMessage.bind(this),
93
+ close: this.#onWebSocketClientClose.bind(this),
94
+ error: this.#onWebSocketClientError.bind(this),
95
+ };
96
+ #onWebSocketClientOpen(event: ws.Event) {
97
+ _console.log("client.open");
98
+ }
99
+ #onWebSocketClientMessage(event: ws.MessageEvent) {
100
+ _console.log("client.message");
101
+ const client = event.target as WebSocketClient;
102
+ client.isAlive = true;
103
+ client.pingClientTimer!.restart();
104
+ const dataView = new DataView(dataToArrayBuffer(event.data as Buffer));
105
+ _console.log(`received ${dataView.byteLength} bytes`, dataView.buffer);
106
+ this.#parseWebSocketClientMessage(client, dataView);
107
+ }
108
+ #onWebSocketClientClose(event: ws.CloseEvent) {
109
+ _console.log("client.close");
110
+ const client = event.target as WebSocketClient;
111
+ client.pingClientTimer!.stop();
112
+ removeEventListeners(client, this.#boundWebSocketClientListeners);
113
+ this.dispatchEvent("clientDisconnected", { client });
114
+ }
115
+ #onWebSocketClientError(event: ws.ErrorEvent) {
116
+ _console.error("client.error", event.message);
117
+ }
118
+
119
+ // PARSING
120
+ #parseWebSocketClientMessage(client: WebSocketClient, dataView: DataView) {
121
+ let responseMessages: ArrayBuffer[] = [];
122
+
123
+ parseMessage(dataView, WebSocketMessageTypes, this.#onClientMessage.bind(this), { responseMessages }, true);
124
+
125
+ responseMessages = responseMessages.filter(Boolean);
126
+
127
+ if (responseMessages.length == 0) {
128
+ _console.log("nothing to send back");
129
+ return;
130
+ }
131
+
132
+ const responseMessage = concatenateArrayBuffers(responseMessages);
133
+ _console.log(`sending ${responseMessage.byteLength} bytes to client...`);
134
+ try {
135
+ client.send(responseMessage);
136
+ } catch (error) {
137
+ _console.log("error sending message", error);
138
+ }
139
+ }
140
+
141
+ #onClientMessage(
142
+ messageType: WebSocketMessageType,
143
+ dataView: DataView,
144
+ context: { responseMessages: (ArrayBuffer | undefined)[] }
145
+ ) {
146
+ const { responseMessages } = context;
147
+ switch (messageType) {
148
+ case "ping":
149
+ responseMessages.push(webSocketPongMessage);
150
+ break;
151
+ case "pong":
152
+ break;
153
+ case "serverMessage":
154
+ const responseMessage = this.parseClientMessage(dataView);
155
+ if (responseMessage) {
156
+ responseMessages.push(createWebSocketMessage({ type: "serverMessage", data: responseMessage }));
157
+ }
158
+ break;
159
+ default:
160
+ _console.error(`uncaught messageType "${messageType}"`);
161
+ break;
162
+ }
163
+ }
164
+
165
+ // CLIENT MESSAGING
166
+ broadcastMessage(message: ArrayBuffer) {
167
+ super.broadcastMessage(message);
168
+ this.server!.clients.forEach((client) => {
169
+ client.send(createWebSocketMessage({ type: "serverMessage", data: message }));
170
+ });
171
+ }
172
+
173
+ // PING
174
+ #pingClient(client: WebSocketClient) {
175
+ if (!client.isAlive) {
176
+ client.terminate();
177
+ return;
178
+ }
179
+ client.isAlive = false;
180
+ client.send(webSocketPingMessage);
181
+ }
182
+ }
183
+
184
+ export default WebSocketServer;
@@ -0,0 +1,20 @@
1
+ import { createConsole } from "../../utils/Console.ts";
2
+ import { createMessage, Message } from "../ServerUtils.ts";
3
+
4
+ const _console = createConsole("WebSocketUtils", { log: false });
5
+
6
+ export const webSocketPingTimeout = 30_000_000;
7
+ export const webSocketReconnectTimeout = 3_000;
8
+
9
+ export const WebSocketMessageTypes = ["ping", "pong", "serverMessage"] as const;
10
+ export type WebSocketMessageType = (typeof WebSocketMessageTypes)[number];
11
+
12
+ export type WebSocketMessage = WebSocketMessageType | Message<WebSocketMessageType>;
13
+ export function createWebSocketMessage(...messages: WebSocketMessage[]) {
14
+ _console.log("createWebSocketMessage", ...messages);
15
+ return createMessage(WebSocketMessageTypes, ...messages);
16
+ }
17
+
18
+ // STATIC MESSAGES
19
+ export const webSocketPingMessage = createWebSocketMessage("ping");
20
+ export const webSocketPongMessage = createWebSocketMessage("pong");
@@ -0,0 +1,88 @@
1
+ import { createConsole } from "./Console.ts";
2
+ import { textEncoder } from "./Text.ts";
3
+
4
+ const _console = createConsole("ArrayBufferUtils", { log: false });
5
+
6
+ export function concatenateArrayBuffers(...arrayBuffers: any[]): ArrayBuffer {
7
+ arrayBuffers = arrayBuffers.filter((arrayBuffer) => arrayBuffer != undefined || arrayBuffer != null);
8
+ arrayBuffers = arrayBuffers.map((arrayBuffer) => {
9
+ if (typeof arrayBuffer == "number") {
10
+ const number = arrayBuffer;
11
+ return Uint8Array.from([Math.floor(number)]);
12
+ } else if (typeof arrayBuffer == "boolean") {
13
+ const boolean = arrayBuffer;
14
+ return Uint8Array.from([boolean ? 1 : 0]);
15
+ } else if (typeof arrayBuffer == "string") {
16
+ const string = arrayBuffer;
17
+ return stringToArrayBuffer(string);
18
+ } else if (arrayBuffer instanceof Array) {
19
+ const array = arrayBuffer;
20
+ return concatenateArrayBuffers(...array);
21
+ } else if (arrayBuffer instanceof ArrayBuffer) {
22
+ return arrayBuffer;
23
+ } else if ("buffer" in arrayBuffer && arrayBuffer.buffer instanceof ArrayBuffer) {
24
+ const bufferContainer = arrayBuffer;
25
+ return bufferContainer.buffer;
26
+ } else if (arrayBuffer instanceof DataView) {
27
+ const dataView = arrayBuffer;
28
+ return dataView.buffer;
29
+ } else if (typeof arrayBuffer == "object") {
30
+ const object = arrayBuffer;
31
+ return objectToArrayBuffer(object);
32
+ } else {
33
+ return arrayBuffer;
34
+ }
35
+ });
36
+ arrayBuffers = arrayBuffers.filter((arrayBuffer) => arrayBuffer && "byteLength" in arrayBuffer);
37
+ const length = arrayBuffers.reduce((length, arrayBuffer) => length + arrayBuffer.byteLength, 0);
38
+ const uint8Array = new Uint8Array(length);
39
+ let byteOffset = 0;
40
+ arrayBuffers.forEach((arrayBuffer) => {
41
+ uint8Array.set(new Uint8Array(arrayBuffer), byteOffset);
42
+ byteOffset += arrayBuffer.byteLength;
43
+ });
44
+ return uint8Array.buffer;
45
+ }
46
+
47
+ export function dataToArrayBuffer(data: Buffer) {
48
+ return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
49
+ }
50
+
51
+ export function stringToArrayBuffer(string: string) {
52
+ const encoding = textEncoder.encode(string);
53
+ return concatenateArrayBuffers(encoding.byteLength, encoding);
54
+ }
55
+
56
+ export function objectToArrayBuffer(object: object) {
57
+ return stringToArrayBuffer(JSON.stringify(object));
58
+ }
59
+
60
+ export function sliceDataView(dataView: DataView, begin: number, length?: number) {
61
+ let end;
62
+ if (length != undefined) {
63
+ end = dataView.byteOffset + begin + length;
64
+ }
65
+ _console.log({ dataView, begin, end, length });
66
+ return new DataView(dataView.buffer.slice(dataView.byteOffset + begin, end));
67
+ }
68
+
69
+ export type FileLike = number[] | ArrayBuffer | DataView | URL | string | File;
70
+
71
+ export async function getFileBuffer(file: FileLike) {
72
+ let fileBuffer;
73
+ if (file instanceof Array) {
74
+ fileBuffer = Uint8Array.from(file);
75
+ } else if (file instanceof DataView) {
76
+ fileBuffer = file.buffer;
77
+ } else if (typeof file == "string" || file instanceof URL) {
78
+ const response = await fetch(file);
79
+ fileBuffer = await response.arrayBuffer();
80
+ } else if (file instanceof File) {
81
+ fileBuffer = await file.arrayBuffer();
82
+ } else if (file instanceof ArrayBuffer) {
83
+ fileBuffer = file;
84
+ } else {
85
+ throw { error: "invalid file type", file };
86
+ }
87
+ return fileBuffer;
88
+ }
@@ -0,0 +1,15 @@
1
+ export function createArray(arrayLength: number, objectOrCallback: ((index: number) => any) | object) {
2
+ return new Array(arrayLength).fill(1).map((_, index) => {
3
+ if (typeof objectOrCallback == "function") {
4
+ const callback = objectOrCallback;
5
+ return callback(index);
6
+ } else {
7
+ const object = objectOrCallback;
8
+ return Object.assign({}, object);
9
+ }
10
+ });
11
+ }
12
+
13
+ export function arrayWithoutDuplicates(array: any[]) {
14
+ return array.filter((value, index) => array.indexOf(value) == index);
15
+ }
@@ -0,0 +1,39 @@
1
+ import RangeHelper from "./RangeHelper.ts";
2
+
3
+ import { Vector2 } from "./MathUtils.ts";
4
+
5
+ export type CenterOfPressure = Vector2;
6
+
7
+ export interface CenterOfPressureRange {
8
+ x: RangeHelper;
9
+ y: RangeHelper;
10
+ }
11
+
12
+ class CenterOfPressureHelper {
13
+ #range: CenterOfPressureRange = {
14
+ x: new RangeHelper(),
15
+ y: new RangeHelper(),
16
+ };
17
+ reset() {
18
+ this.#range.x.reset();
19
+ this.#range.y.reset();
20
+ }
21
+
22
+ update(centerOfPressure: CenterOfPressure) {
23
+ this.#range.x.update(centerOfPressure.x);
24
+ this.#range.y.update(centerOfPressure.y);
25
+ }
26
+ getNormalization(centerOfPressure: CenterOfPressure): CenterOfPressure {
27
+ return {
28
+ x: this.#range.x.getNormalization(centerOfPressure.x, false),
29
+ y: this.#range.y.getNormalization(centerOfPressure.y, false),
30
+ };
31
+ }
32
+
33
+ updateAndGetNormalization(centerOfPressure: CenterOfPressure) {
34
+ this.update(centerOfPressure);
35
+ return this.getNormalization(centerOfPressure);
36
+ }
37
+ }
38
+
39
+ export default CenterOfPressureHelper;
@@ -0,0 +1,156 @@
1
+ import { isInDev, isInLensStudio } from "./environment.ts";
2
+
3
+ declare var Studio: any | undefined;
4
+
5
+ export type LogFunction = (...data: any[]) => void;
6
+ export type AssertLogFunction = (condition: boolean, ...data: any[]) => void;
7
+
8
+ export interface ConsoleLevelFlags {
9
+ log?: boolean;
10
+ warn?: boolean;
11
+ error?: boolean;
12
+ assert?: boolean;
13
+ table?: boolean;
14
+ }
15
+
16
+ interface ConsoleLike {
17
+ log?: LogFunction;
18
+ warn?: LogFunction;
19
+ error?: LogFunction;
20
+ assert?: AssertLogFunction;
21
+ table?: LogFunction;
22
+ }
23
+
24
+ var __console: ConsoleLike;
25
+ if (isInLensStudio) {
26
+ const log = function (...args: any[]) {
27
+ Studio.log(args.map((value) => new String(value)).join(","));
28
+ };
29
+ __console = {};
30
+ __console.log = log;
31
+ __console.warn = log.bind(__console, "WARNING");
32
+ __console.error = log.bind(__console, "ERROR");
33
+ } else {
34
+ __console = console;
35
+ }
36
+
37
+ // console.assert not supported in WebBLE
38
+ if (!__console.assert) {
39
+ const assert: AssertLogFunction = (condition, ...data) => {
40
+ if (!condition) {
41
+ __console.warn!(...data);
42
+ }
43
+ };
44
+ __console.assert = assert;
45
+ }
46
+
47
+ // console.table not supported in WebBLE
48
+ if (!__console.table) {
49
+ const table: LogFunction = (...data) => {
50
+ __console.log!(...data);
51
+ };
52
+ __console.table = table;
53
+ }
54
+
55
+ function emptyFunction() {}
56
+
57
+ const log: LogFunction = __console.log!.bind(__console);
58
+ const warn: LogFunction = __console.warn!.bind(__console);
59
+ const error: LogFunction = __console.error!.bind(__console);
60
+ const table: LogFunction = __console.table!.bind(__console);
61
+ const assert: AssertLogFunction = __console.assert.bind(__console);
62
+
63
+ class Console {
64
+ static #consoles: { [type: string]: Console } = {};
65
+
66
+ constructor(type: string) {
67
+ if (Console.#consoles[type]) {
68
+ throw new Error(`"${type}" console already exists`);
69
+ }
70
+ Console.#consoles[type] = this;
71
+ }
72
+
73
+ #levelFlags: ConsoleLevelFlags = {
74
+ log: isInDev,
75
+ warn: isInDev,
76
+ assert: true,
77
+ error: true,
78
+ table: true,
79
+ };
80
+
81
+ setLevelFlags(levelFlags: ConsoleLevelFlags) {
82
+ Object.assign(this.#levelFlags, levelFlags);
83
+ }
84
+
85
+ /** @throws {Error} if no console with type "type" is found */
86
+ static setLevelFlagsForType(type: string, levelFlags: ConsoleLevelFlags) {
87
+ if (!this.#consoles[type]) {
88
+ throw new Error(`no console found with type "${type}"`);
89
+ }
90
+ this.#consoles[type].setLevelFlags(levelFlags);
91
+ }
92
+
93
+ static setAllLevelFlags(levelFlags: ConsoleLevelFlags) {
94
+ for (const type in this.#consoles) {
95
+ this.#consoles[type].setLevelFlags(levelFlags);
96
+ }
97
+ }
98
+
99
+ static create(type: string, levelFlags?: ConsoleLevelFlags): Console {
100
+ const console = this.#consoles[type] || new Console(type);
101
+ if (isInDev && levelFlags) {
102
+ console.setLevelFlags(levelFlags);
103
+ }
104
+ return console;
105
+ }
106
+
107
+ get log() {
108
+ return this.#levelFlags.log ? log : emptyFunction;
109
+ }
110
+
111
+ get warn() {
112
+ return this.#levelFlags.warn ? warn : emptyFunction;
113
+ }
114
+
115
+ get error() {
116
+ return this.#levelFlags.error ? error : emptyFunction;
117
+ }
118
+
119
+ get assert() {
120
+ return this.#levelFlags.assert ? assert : emptyFunction;
121
+ }
122
+
123
+ get table() {
124
+ return this.#levelFlags.table ? table : emptyFunction;
125
+ }
126
+
127
+ /** @throws {Error} if condition is not met */
128
+ assertWithError(condition: any, message: string) {
129
+ if (!Boolean(condition)) {
130
+ throw new Error(message);
131
+ }
132
+ }
133
+
134
+ /** @throws {Error} if value's type doesn't match */
135
+ assertTypeWithError(value: any, type: string) {
136
+ this.assertWithError(typeof value == type, `value ${value} of type "${typeof value}" not of type "${type}"`);
137
+ }
138
+
139
+ /** @throws {Error} if value's type doesn't match */
140
+ assertEnumWithError(value: string, enumeration: readonly string[]) {
141
+ this.assertWithError(enumeration.includes(value), `invalid enum "${value}"`);
142
+ }
143
+ }
144
+
145
+ export function createConsole(type: string, levelFlags?: ConsoleLevelFlags): Console {
146
+ return Console.create(type, levelFlags);
147
+ }
148
+
149
+ /** @throws {Error} if no console with type is found */
150
+ export function setConsoleLevelFlagsForType(type: string, levelFlags: ConsoleLevelFlags) {
151
+ Console.setLevelFlagsForType(type, levelFlags);
152
+ }
153
+
154
+ export function setAllConsoleLevelFlags(levelFlags: ConsoleLevelFlags) {
155
+ Console.setAllLevelFlags(levelFlags);
156
+ }