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,166 @@
1
+ import { createConsole } from "../utils/Console.ts";
2
+ import { parseTimestamp } from "../utils/MathUtils.ts";
3
+ import PressureSensorDataManager, { PressureDataEventMessages } from "./PressureSensorDataManager.ts";
4
+ import MotionSensorDataManager, { MotionSensorDataEventMessages } from "./MotionSensorDataManager.ts";
5
+ import BarometerSensorDataManager, { BarometerSensorDataEventMessages } from "./BarometerSensorDataManager.ts";
6
+ import { parseMessage } from "../utils/ParseUtils.ts";
7
+ import EventDispatcher from "../utils/EventDispatcher.ts";
8
+ import { MotionSensorTypes, ContinuousMotionTypes } from "./MotionSensorDataManager.ts";
9
+ import { PressureSensorTypes, ContinuousPressureSensorTypes } from "./PressureSensorDataManager.ts";
10
+ import { BarometerSensorTypes, ContinuousBarometerSensorTypes } from "./BarometerSensorDataManager.ts";
11
+ import Device from "../Device.ts";
12
+ import { AddKeysAsPropertyToInterface, ExtendInterfaceValues, ValueOf } from "../utils/TypeScriptUtils.ts";
13
+
14
+ const _console = createConsole("SensorDataManager", { log: true });
15
+
16
+ export const SensorTypes = [...PressureSensorTypes, ...MotionSensorTypes, ...BarometerSensorTypes] as const;
17
+ export type SensorType = (typeof SensorTypes)[number];
18
+
19
+ export const ContinuousSensorTypes = [
20
+ ...ContinuousPressureSensorTypes,
21
+ ...ContinuousMotionTypes,
22
+ ...ContinuousBarometerSensorTypes,
23
+ ] as const;
24
+ export type ContinuousSensorType = (typeof ContinuousSensorTypes)[number];
25
+
26
+ export const SensorDataMessageTypes = ["getPressurePositions", "getSensorScalars", "sensorData"] as const;
27
+ export type SensorDataMessageType = (typeof SensorDataMessageTypes)[number];
28
+
29
+ export const SensorDataEventTypes = [...SensorDataMessageTypes, ...SensorTypes] as const;
30
+ export type SensorDataEventType = (typeof SensorDataEventTypes)[number];
31
+
32
+ interface BaseSensorDataEventMessage {
33
+ timestamp: number;
34
+ }
35
+
36
+ type BaseSensorDataEventMessages = BarometerSensorDataEventMessages &
37
+ MotionSensorDataEventMessages &
38
+ PressureDataEventMessages;
39
+ type _SensorDataEventMessages = ExtendInterfaceValues<
40
+ AddKeysAsPropertyToInterface<BaseSensorDataEventMessages, "sensorType">,
41
+ BaseSensorDataEventMessage
42
+ >;
43
+ export type SensorDataEventMessage = ValueOf<_SensorDataEventMessages>;
44
+ interface AnySensorDataEventMessages {
45
+ sensorData: SensorDataEventMessage;
46
+ }
47
+ export type SensorDataEventMessages = _SensorDataEventMessages & AnySensorDataEventMessages;
48
+
49
+ export type SensorDataEventDispatcher = EventDispatcher<Device, SensorDataEventType, SensorDataEventMessages>;
50
+
51
+ class SensorDataManager {
52
+ pressureSensorDataManager = new PressureSensorDataManager();
53
+ motionSensorDataManager = new MotionSensorDataManager();
54
+ barometerSensorDataManager = new BarometerSensorDataManager();
55
+
56
+ #scalars: Map<SensorType, number> = new Map();
57
+
58
+ static AssertValidSensorType(sensorType: SensorType) {
59
+ _console.assertEnumWithError(sensorType, SensorTypes);
60
+ }
61
+ static AssertValidSensorTypeEnum(sensorTypeEnum: number) {
62
+ _console.assertTypeWithError(sensorTypeEnum, "number");
63
+ _console.assertWithError(sensorTypeEnum in SensorTypes, `invalid sensorTypeEnum ${sensorTypeEnum}`);
64
+ }
65
+
66
+ eventDispatcher!: SensorDataEventDispatcher;
67
+ get dispatchEvent() {
68
+ return this.eventDispatcher.dispatchEvent;
69
+ }
70
+
71
+ parseMessage(messageType: SensorDataMessageType, dataView: DataView) {
72
+ _console.log({ messageType });
73
+
74
+ switch (messageType) {
75
+ case "getSensorScalars":
76
+ this.parseScalars(dataView);
77
+ break;
78
+ case "getPressurePositions":
79
+ this.pressureSensorDataManager.parsePositions(dataView);
80
+ break;
81
+ case "sensorData":
82
+ this.parseData(dataView);
83
+ break;
84
+ default:
85
+ throw Error(`uncaught messageType ${messageType}`);
86
+ }
87
+ }
88
+
89
+ parseScalars(dataView: DataView) {
90
+ for (let byteOffset = 0; byteOffset < dataView.byteLength; byteOffset += 5) {
91
+ const sensorTypeIndex = dataView.getUint8(byteOffset);
92
+ const sensorType = SensorTypes[sensorTypeIndex];
93
+ if (!sensorType) {
94
+ _console.warn(`unknown sensorType index ${sensorTypeIndex}`);
95
+ continue;
96
+ }
97
+ const sensorScalar = dataView.getFloat32(byteOffset + 1, true);
98
+ _console.log({ sensorType, sensorScalar });
99
+ this.#scalars.set(sensorType, sensorScalar);
100
+ }
101
+ }
102
+
103
+ private parseData(dataView: DataView) {
104
+ _console.log("sensorData", Array.from(new Uint8Array(dataView.buffer)));
105
+
106
+ let byteOffset = 0;
107
+ const timestamp = parseTimestamp(dataView, byteOffset);
108
+ byteOffset += 2;
109
+
110
+ const _dataView = new DataView(dataView.buffer, byteOffset);
111
+
112
+ parseMessage(_dataView, SensorTypes, this.parseDataCallback.bind(this), { timestamp });
113
+ }
114
+
115
+ private parseDataCallback(sensorType: SensorType, dataView: DataView, { timestamp }: { timestamp: number }) {
116
+ const scalar = this.#scalars.get(sensorType) || 1;
117
+
118
+ let sensorData = null;
119
+ switch (sensorType) {
120
+ case "pressure":
121
+ sensorData = this.pressureSensorDataManager.parseData(dataView, scalar);
122
+ break;
123
+ case "acceleration":
124
+ case "gravity":
125
+ case "linearAcceleration":
126
+ case "gyroscope":
127
+ case "magnetometer":
128
+ sensorData = this.motionSensorDataManager.parseVector3(dataView, scalar);
129
+ break;
130
+ case "gameRotation":
131
+ case "rotation":
132
+ sensorData = this.motionSensorDataManager.parseQuaternion(dataView, scalar);
133
+ break;
134
+ case "orientation":
135
+ sensorData = this.motionSensorDataManager.parseEuler(dataView, scalar);
136
+ break;
137
+ case "stepCounter":
138
+ sensorData = this.motionSensorDataManager.parseStepCounter(dataView);
139
+ break;
140
+ case "stepDetector":
141
+ sensorData = {};
142
+ break;
143
+ case "activity":
144
+ sensorData = this.motionSensorDataManager.parseActivity(dataView);
145
+ break;
146
+ case "deviceOrientation":
147
+ sensorData = this.motionSensorDataManager.parseDeviceOrientation(dataView);
148
+ break;
149
+ case "barometer":
150
+ sensorData = this.barometerSensorDataManager.parseData(dataView, scalar);
151
+ break;
152
+ default:
153
+ _console.error(`uncaught sensorType "${sensorType}"`);
154
+ }
155
+
156
+ _console.assertWithError(sensorData != null, `no sensorData defined for sensorType "${sensorType}"`);
157
+
158
+ _console.log({ sensorType, sensorData });
159
+ // @ts-expect-error
160
+ this.dispatchEvent(sensorType, { sensorType, [sensorType]: sensorData, timestamp });
161
+ // @ts-expect-error
162
+ this.dispatchEvent("sensorData", { sensorType, [sensorType]: sensorData, timestamp });
163
+ }
164
+ }
165
+
166
+ export default SensorDataManager;
@@ -0,0 +1,368 @@
1
+ import { createConsole } from "../utils/Console.ts";
2
+ import {
3
+ ServerMessageTypes,
4
+ discoveredDevicesMessage,
5
+ ServerMessage,
6
+ MessageLike,
7
+ ClientDeviceMessage,
8
+ createClientDeviceMessage,
9
+ ServerMessageType,
10
+ } from "./ServerUtils.ts";
11
+ import { parseMessage, parseStringFromDataView } from "../utils/ParseUtils.ts";
12
+ import EventDispatcher, { BoundEventListeners, Event } from "../utils/EventDispatcher.ts";
13
+ import Device from "../Device.ts";
14
+ import { sliceDataView } from "../utils/ArrayBufferUtils.ts";
15
+ import { DiscoveredDevice, DiscoveredDevicesMap, ScannerEventMessages } from "../scanner/BaseScanner.ts";
16
+ import ClientConnectionManager from "../connection/ClientConnectionManager.ts";
17
+
18
+ const _console = createConsole("BaseClient", { log: true });
19
+
20
+ export const ClientConnectionStatuses = ["notConnected", "connecting", "connected", "disconnecting"] as const;
21
+ export type ClientConnectionStatus = (typeof ClientConnectionStatuses)[number];
22
+
23
+ export const ClientEventTypes = [
24
+ ...ClientConnectionStatuses,
25
+ "connectionStatus",
26
+ "isConnected",
27
+ "isScanningAvailable",
28
+ "isScanning",
29
+ "discoveredDevice",
30
+ "expiredDiscoveredDevice",
31
+ ] as const;
32
+ export type ClientEventType = (typeof ClientEventTypes)[number];
33
+
34
+ interface ClientConnectionEventMessages {
35
+ connectionStatus: { connectionStatus: ClientConnectionStatus };
36
+ isConnected: { isConnected: boolean };
37
+ }
38
+
39
+ export type ClientEventMessages = ClientConnectionEventMessages & ScannerEventMessages;
40
+
41
+ export type ClientEventDispatcher = EventDispatcher<BaseClient, ClientEventType, ClientEventMessages>;
42
+ export type ClientEvent = Event<BaseClient, ClientEventType, ClientEventMessages>;
43
+ export type BoundClientEventListeners = BoundEventListeners<BaseClient, ClientEventType, ClientEventMessages>;
44
+
45
+ export type ServerURL = string | URL;
46
+
47
+ type DevicesMap = { [deviceId: string]: Device };
48
+
49
+ abstract class BaseClient {
50
+ protected get baseConstructor() {
51
+ return this.constructor as typeof BaseClient;
52
+ }
53
+
54
+ // DEVICES
55
+ #devices: DevicesMap = {};
56
+ get devices(): Readonly<DevicesMap> {
57
+ return this.#devices;
58
+ }
59
+
60
+ #eventDispatcher: ClientEventDispatcher = new EventDispatcher(this as BaseClient, ClientEventTypes);
61
+ get addEventListener() {
62
+ return this.#eventDispatcher.addEventListener;
63
+ }
64
+ protected get dispatchEvent() {
65
+ return this.#eventDispatcher.dispatchEvent;
66
+ }
67
+ get removeEventListener() {
68
+ return this.#eventDispatcher.removeEventListener;
69
+ }
70
+ get waitForEvent() {
71
+ return this.#eventDispatcher.waitForEvent;
72
+ }
73
+
74
+ abstract isConnected: boolean;
75
+ protected assertConnection() {
76
+ _console.assertWithError(this.isConnected, "notConnected");
77
+ }
78
+
79
+ abstract isDisconnected: boolean;
80
+ protected assertDisconnection() {
81
+ _console.assertWithError(this.isDisconnected, "not disconnected");
82
+ }
83
+
84
+ abstract connect(): void;
85
+ abstract disconnect(): void;
86
+ abstract reconnect(): void;
87
+ abstract toggleConnection(url?: ServerURL): void;
88
+
89
+ static _reconnectOnDisconnection = true;
90
+ static get ReconnectOnDisconnection() {
91
+ return this._reconnectOnDisconnection;
92
+ }
93
+ static set ReconnectOnDisconnection(newReconnectOnDisconnection) {
94
+ _console.assertTypeWithError(newReconnectOnDisconnection, "boolean");
95
+ this._reconnectOnDisconnection = newReconnectOnDisconnection;
96
+ }
97
+
98
+ protected _reconnectOnDisconnection = this.baseConstructor.ReconnectOnDisconnection;
99
+ get reconnectOnDisconnection() {
100
+ return this._reconnectOnDisconnection;
101
+ }
102
+ set reconnectOnDisconnection(newReconnectOnDisconnection) {
103
+ _console.assertTypeWithError(newReconnectOnDisconnection, "boolean");
104
+ this._reconnectOnDisconnection = newReconnectOnDisconnection;
105
+ }
106
+
107
+ abstract sendServerMessage(...messages: ServerMessage[]): void;
108
+
109
+ // CONNECTION STATUS
110
+ #_connectionStatus: ClientConnectionStatus = "notConnected";
111
+ protected get _connectionStatus() {
112
+ return this.#_connectionStatus;
113
+ }
114
+ protected set _connectionStatus(newConnectionStatus) {
115
+ _console.assertTypeWithError(newConnectionStatus, "string");
116
+ _console.log({ newConnectionStatus });
117
+ this.#_connectionStatus = newConnectionStatus;
118
+
119
+ this.dispatchEvent("connectionStatus", { connectionStatus: this.connectionStatus });
120
+ this.dispatchEvent(this.connectionStatus, {});
121
+
122
+ switch (newConnectionStatus) {
123
+ case "connected":
124
+ case "notConnected":
125
+ this.dispatchEvent("isConnected", { isConnected: this.isConnected });
126
+ if (this.isConnected) {
127
+ this.sendServerMessage("isScanningAvailable", "discoveredDevices", "connectedDevices");
128
+ } else {
129
+ this.#isScanningAvailable = false;
130
+ this.#isScanning = false;
131
+ }
132
+ break;
133
+ }
134
+ }
135
+ get connectionStatus() {
136
+ return this._connectionStatus;
137
+ }
138
+
139
+ protected parseMessage(dataView: DataView) {
140
+ _console.log("parseMessage", { dataView });
141
+ parseMessage(dataView, ServerMessageTypes, this.#parseMessageCallback.bind(this), null, true);
142
+ }
143
+
144
+ #parseMessageCallback(messageType: ServerMessageType, dataView: DataView) {
145
+ let byteOffset = 0;
146
+
147
+ _console.log({ messageType }, dataView);
148
+
149
+ switch (messageType) {
150
+ case "isScanningAvailable":
151
+ {
152
+ const isScanningAvailable = Boolean(dataView.getUint8(byteOffset++));
153
+ _console.log({ isScanningAvailable });
154
+ this.#isScanningAvailable = isScanningAvailable;
155
+ }
156
+ break;
157
+ case "isScanning":
158
+ {
159
+ const isScanning = Boolean(dataView.getUint8(byteOffset++));
160
+ _console.log({ isScanning });
161
+ this.#isScanning = isScanning;
162
+ }
163
+ break;
164
+ case "discoveredDevice":
165
+ {
166
+ const { string: discoveredDeviceString } = parseStringFromDataView(dataView, byteOffset);
167
+ _console.log({ discoveredDeviceString });
168
+
169
+ const discoveredDevice: DiscoveredDevice = JSON.parse(discoveredDeviceString);
170
+ _console.log({ discoveredDevice });
171
+
172
+ this.onDiscoveredDevice(discoveredDevice);
173
+ }
174
+ break;
175
+ case "expiredDiscoveredDevice":
176
+ {
177
+ const { string: bluetoothId } = parseStringFromDataView(dataView, byteOffset);
178
+ this.#onExpiredDiscoveredDevice(bluetoothId);
179
+ }
180
+ break;
181
+ case "connectedDevices":
182
+ {
183
+ if (dataView.byteLength == 0) {
184
+ break;
185
+ }
186
+ const { string: connectedBluetoothDeviceIdStrings } = parseStringFromDataView(dataView, byteOffset);
187
+ _console.log({ connectedBluetoothDeviceIdStrings });
188
+ const connectedBluetoothDeviceIds = JSON.parse(connectedBluetoothDeviceIdStrings);
189
+ _console.log({ connectedBluetoothDeviceIds });
190
+ this.onConnectedBluetoothDeviceIds(connectedBluetoothDeviceIds);
191
+ }
192
+ break;
193
+ case "deviceMessage":
194
+ {
195
+ const { string: bluetoothId, byteOffset: _byteOffset } = parseStringFromDataView(dataView, byteOffset);
196
+ byteOffset = _byteOffset;
197
+ const device = this.#devices[bluetoothId];
198
+ _console.assertWithError(device, `no device found for id ${bluetoothId}`);
199
+ const connectionManager = device.connectionManager! as ClientConnectionManager;
200
+ const _dataView = sliceDataView(dataView, byteOffset);
201
+ connectionManager.onClientMessage(_dataView);
202
+ }
203
+ break;
204
+ default:
205
+ _console.error(`uncaught messageType "${messageType}"`);
206
+ break;
207
+ }
208
+ }
209
+
210
+ // SCANNING
211
+ #_isScanningAvailable = false;
212
+ get #isScanningAvailable() {
213
+ return this.#_isScanningAvailable;
214
+ }
215
+ set #isScanningAvailable(newIsAvailable) {
216
+ _console.assertTypeWithError(newIsAvailable, "boolean");
217
+ this.#_isScanningAvailable = newIsAvailable;
218
+ this.dispatchEvent("isScanningAvailable", { isScanningAvailable: this.isScanningAvailable });
219
+ if (this.isScanningAvailable) {
220
+ this.#requestIsScanning();
221
+ }
222
+ }
223
+ get isScanningAvailable() {
224
+ return this.#isScanningAvailable;
225
+ }
226
+ #assertIsScanningAvailable() {
227
+ this.assertConnection();
228
+ _console.assertWithError(this.isScanningAvailable, "scanning is not available");
229
+ }
230
+ protected requestIsScanningAvailable() {
231
+ this.sendServerMessage("isScanningAvailable");
232
+ }
233
+
234
+ #_isScanning = false;
235
+ get #isScanning() {
236
+ return this.#_isScanning;
237
+ }
238
+ set #isScanning(newIsScanning) {
239
+ _console.assertTypeWithError(newIsScanning, "boolean");
240
+ this.#_isScanning = newIsScanning;
241
+ this.dispatchEvent("isScanning", { isScanning: this.isScanning });
242
+ }
243
+ get isScanning() {
244
+ return this.#isScanning;
245
+ }
246
+ #requestIsScanning() {
247
+ this.sendServerMessage("isScanning");
248
+ }
249
+
250
+ #assertIsScanning() {
251
+ _console.assertWithError(this.isScanning, "is not scanning");
252
+ }
253
+ #assertIsNotScanning() {
254
+ _console.assertWithError(!this.isScanning, "is already scanning");
255
+ }
256
+
257
+ startScan() {
258
+ this.#assertIsNotScanning();
259
+ this.sendServerMessage("startScan");
260
+ }
261
+ stopScan() {
262
+ this.#assertIsScanning();
263
+ this.sendServerMessage("stopScan");
264
+ }
265
+ toggleScan() {
266
+ this.#assertIsScanningAvailable();
267
+
268
+ if (this.isScanning) {
269
+ this.stopScan();
270
+ } else {
271
+ this.startScan();
272
+ }
273
+ }
274
+
275
+ // PERIPHERALS
276
+ #discoveredDevices: DiscoveredDevicesMap = {};
277
+ get discoveredDevices(): Readonly<DiscoveredDevicesMap> {
278
+ return this.#discoveredDevices;
279
+ }
280
+
281
+ protected onDiscoveredDevice(discoveredDevice: DiscoveredDevice) {
282
+ _console.log({ discoveredDevice });
283
+ this.#discoveredDevices[discoveredDevice.bluetoothId] = discoveredDevice;
284
+ this.dispatchEvent("discoveredDevice", { discoveredDevice });
285
+ }
286
+ requestDiscoveredDevices() {
287
+ this.sendServerMessage({ type: "discoveredDevices" });
288
+ }
289
+ #onExpiredDiscoveredDevice(bluetoothId: string) {
290
+ _console.log({ expiredBluetoothDeviceId: bluetoothId });
291
+ const discoveredDevice = this.#discoveredDevices[bluetoothId];
292
+ if (!discoveredDevice) {
293
+ _console.warn(`no discoveredDevice found with id "${bluetoothId}"`);
294
+ return;
295
+ }
296
+ _console.log({ expiredDiscoveredDevice: discoveredDevice });
297
+ delete this.#discoveredDevices[bluetoothId];
298
+ this.dispatchEvent("expiredDiscoveredDevice", { discoveredDevice });
299
+ }
300
+
301
+ // DEVICE CONNECTION
302
+ connectToDevice(bluetoothId: string) {
303
+ return this.requestConnectionToDevice(bluetoothId);
304
+ }
305
+ protected requestConnectionToDevice(bluetoothId: string) {
306
+ this.assertConnection();
307
+ _console.assertTypeWithError(bluetoothId, "string");
308
+ const device = this.#getOrCreateDevice(bluetoothId);
309
+ device.connect();
310
+ return device;
311
+ }
312
+ protected sendConnectToDeviceMessage(bluetoothId: string) {
313
+ this.sendServerMessage({ type: "connectToDevice", data: bluetoothId });
314
+ }
315
+
316
+ // DEVICE CONNECTION
317
+ createDevice(bluetoothId: string) {
318
+ const device = new Device();
319
+ const clientConnectionManager = new ClientConnectionManager();
320
+ clientConnectionManager.bluetoothId = bluetoothId;
321
+ clientConnectionManager.sendClientMessage = this.sendDeviceMessage.bind(this, bluetoothId);
322
+ clientConnectionManager.sendClientConnectMessage = this.sendConnectToDeviceMessage.bind(this, bluetoothId);
323
+ clientConnectionManager.sendClientDisconnectMessage = this.sendDisconnectFromDeviceMessage.bind(this, bluetoothId);
324
+ device.connectionManager = clientConnectionManager;
325
+ return device;
326
+ }
327
+
328
+ #getOrCreateDevice(bluetoothId: string) {
329
+ let device = this.#devices[bluetoothId];
330
+ if (!device) {
331
+ device = this.createDevice(bluetoothId);
332
+ this.#devices[bluetoothId] = device;
333
+ }
334
+ return device;
335
+ }
336
+ protected onConnectedBluetoothDeviceIds(bluetoothIds: string[]) {
337
+ _console.log({ bluetoothIds });
338
+ bluetoothIds.forEach((bluetoothId) => {
339
+ const device = this.#getOrCreateDevice(bluetoothId);
340
+ const connectionManager = device.connectionManager! as ClientConnectionManager;
341
+ connectionManager.isConnected = true;
342
+ });
343
+ }
344
+
345
+ disconnectFromDevice(bluetoothId: string) {
346
+ this.requestDisconnectionFromDevice(bluetoothId);
347
+ }
348
+ protected requestDisconnectionFromDevice(bluetoothId: string) {
349
+ this.assertConnection();
350
+ _console.assertTypeWithError(bluetoothId, "string");
351
+ const device = this.devices[bluetoothId];
352
+ _console.assertWithError(device, `no device found with id ${bluetoothId}`);
353
+ device.disconnect();
354
+ return device;
355
+ }
356
+ protected sendDisconnectFromDeviceMessage(bluetoothId: string) {
357
+ this.sendServerMessage({ type: "disconnectFromDevice", data: bluetoothId });
358
+ }
359
+
360
+ protected sendDeviceMessage(bluetoothId: string, ...messages: ClientDeviceMessage[]) {
361
+ this.sendServerMessage({
362
+ type: "deviceMessage",
363
+ data: [bluetoothId, createClientDeviceMessage(...messages)],
364
+ });
365
+ }
366
+ }
367
+
368
+ export default BaseClient;