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.
- package/LICENSE +21 -0
- package/README.md +21 -0
- package/build/brilliantsole.cjs +5957 -0
- package/build/brilliantsole.cjs.map +1 -0
- package/build/brilliantsole.js +5448 -0
- package/build/brilliantsole.js.map +1 -0
- package/build/brilliantsole.ls.js +4872 -0
- package/build/brilliantsole.ls.js.map +1 -0
- package/build/brilliantsole.min.js +6 -0
- package/build/brilliantsole.min.js.map +1 -0
- package/build/brilliantsole.module.d.ts +908 -0
- package/build/brilliantsole.module.js +5412 -0
- package/build/brilliantsole.module.js.map +1 -0
- package/build/brilliantsole.module.min.d.ts +908 -0
- package/build/brilliantsole.module.min.js +6 -0
- package/build/brilliantsole.module.min.js.map +1 -0
- package/build/brilliantsole.node.module.d.ts +908 -0
- package/build/brilliantsole.node.module.js +5906 -0
- package/build/brilliantsole.node.module.js.map +1 -0
- package/build/dts/BS.d.ts +25 -0
- package/build/dts/Device.d.ts +136 -0
- package/build/dts/DeviceInformationManager.d.ts +56 -0
- package/build/dts/DeviceManager.d.ts +67 -0
- package/build/dts/FileTransferManager.d.ts +84 -0
- package/build/dts/FirmwareManager.d.ts +71 -0
- package/build/dts/InformationManager.d.ts +66 -0
- package/build/dts/TfliteManager.d.ts +92 -0
- package/build/dts/connection/BaseConnectionManager.d.ts +59 -0
- package/build/dts/connection/ClientConnectionManager.d.ts +23 -0
- package/build/dts/connection/WebSocketClientConnectionManager.d.ts +23 -0
- package/build/dts/connection/bluetooth/BluetoothConnectionManager.d.ts +10 -0
- package/build/dts/connection/bluetooth/NobleConnectionManager.d.ts +42 -0
- package/build/dts/connection/bluetooth/WebBluetoothConnectionManager.d.ts +20 -0
- package/build/dts/connection/bluetooth/bluetoothUUIDs.d.ts +14 -0
- package/build/dts/connection/webSocket/ClientConnectionManager.d.ts +23 -0
- package/build/dts/connection/webSocket/WebSocketClientConnectionManager.d.ts +23 -0
- package/build/dts/devicePair/DevicePair.d.ts +60 -0
- package/build/dts/devicePair/DevicePairPressureSensorDataManager.d.ts +25 -0
- package/build/dts/devicePair/DevicePairSensorDataManager.d.ts +33 -0
- package/build/dts/scanner/BaseScanner.d.ts +66 -0
- package/build/dts/scanner/NobleScanner.d.ts +17 -0
- package/build/dts/scanner/Scanner.d.ts +3 -0
- package/build/dts/sensor/BarometerSensorDataManager.d.ts +16 -0
- package/build/dts/sensor/MotionSensorDataManager.d.ts +69 -0
- package/build/dts/sensor/PressureSensorDataManager.d.ts +36 -0
- package/build/dts/sensor/SensorConfigurationManager.d.ts +44 -0
- package/build/dts/sensor/SensorDataManager.d.ts +40 -0
- package/build/dts/server/BaseClient.d.ts +85 -0
- package/build/dts/server/BaseServer.d.ts +48 -0
- package/build/dts/server/ServerUtils.d.ts +23 -0
- package/build/dts/server/udp/UDPServer.d.ts +11 -0
- package/build/dts/server/udp/UDPUtils.d.ts +9 -0
- package/build/dts/server/websocket/WebSocketClient.d.ts +17 -0
- package/build/dts/server/websocket/WebSocketServer.d.ts +13 -0
- package/build/dts/server/websocket/WebSocketUtils.d.ts +9 -0
- package/build/dts/utils/ArrayBufferUtils.d.ts +7 -0
- package/build/dts/utils/ArrayUtils.d.ts +2 -0
- package/build/dts/utils/CenterOfPressureHelper.d.ts +15 -0
- package/build/dts/utils/Console.d.ts +34 -0
- package/build/dts/utils/EventDispatcher.d.ts +50 -0
- package/build/dts/utils/EventUtils.d.ts +6 -0
- package/build/dts/utils/MathUtils.d.ts +21 -0
- package/build/dts/utils/ParseUtils.d.ts +5 -0
- package/build/dts/utils/RangeHelper.d.ts +8 -0
- package/build/dts/utils/Text.d.ts +6 -0
- package/build/dts/utils/Timer.d.ts +14 -0
- package/build/dts/utils/TypeScriptUtils.d.ts +19 -0
- package/build/dts/utils/cbor.d.ts +6 -0
- package/build/dts/utils/checksum.d.ts +3 -0
- package/build/dts/utils/environment.d.ts +13 -0
- package/build/dts/utils/mcumgr.d.ts +88 -0
- package/build/dts/utils/stringUtils.d.ts +2 -0
- package/build/dts/vibration/VibrationManager.d.ts +45 -0
- package/build/dts/vibration/VibrationWaveformEffects.d.ts +2 -0
- package/build/index.d.ts +908 -0
- package/build/index.node.d.ts +908 -0
- package/examples/3d/index.html +109 -0
- package/examples/3d/scene.html +57 -0
- package/examples/3d/script.js +419 -0
- package/examples/balance/index.html +138 -0
- package/examples/balance/script.js +243 -0
- package/examples/basic/index.html +327 -0
- package/examples/basic/script.js +1093 -0
- package/examples/center-of-pressure/index.html +132 -0
- package/examples/center-of-pressure/script.js +207 -0
- package/examples/device-pair/index.html +72 -0
- package/examples/device-pair/script.js +187 -0
- package/examples/edge-impulse/index.html +94 -0
- package/examples/edge-impulse/script.js +1033 -0
- package/examples/graph/index.html +83 -0
- package/examples/graph/script.js +469 -0
- package/examples/machine-learning/index.html +366 -0
- package/examples/machine-learning/script.js +1774 -0
- package/examples/pressure/index.html +145 -0
- package/examples/pressure/script.js +201 -0
- package/examples/recording/index.html +187 -0
- package/examples/recording/script.js +736 -0
- package/examples/server/index.html +266 -0
- package/examples/server/script.js +925 -0
- package/examples/utils/aframe/fingertip-button-component.js +201 -0
- package/examples/utils/aframe/fingertip-collider-target-component.js +102 -0
- package/examples/utils/aframe/fingertip-colliders-component.js +147 -0
- package/examples/utils/three/three.module.min.js +24846 -0
- package/examples/webxr/index.html +221 -0
- package/examples/webxr/script.js +1127 -0
- package/package.json +83 -0
- package/src/BS.ts +68 -0
- package/src/Device.ts +734 -0
- package/src/DeviceInformationManager.ts +146 -0
- package/src/DeviceManager.ts +354 -0
- package/src/FileTransferManager.ts +452 -0
- package/src/FirmwareManager.ts +357 -0
- package/src/InformationManager.ts +283 -0
- package/src/TfliteManager.ts +450 -0
- package/src/connection/BaseConnectionManager.ts +255 -0
- package/src/connection/ClientConnectionManager.ts +120 -0
- package/src/connection/bluetooth/BluetoothConnectionManager.ts +34 -0
- package/src/connection/bluetooth/NobleConnectionManager.ts +302 -0
- package/src/connection/bluetooth/WebBluetoothConnectionManager.ts +269 -0
- package/src/connection/bluetooth/bluetoothUUIDs.ts +218 -0
- package/src/devicePair/DevicePair.ts +253 -0
- package/src/devicePair/DevicePairPressureSensorDataManager.ts +82 -0
- package/src/devicePair/DevicePairSensorDataManager.ts +90 -0
- package/src/scanner/BaseScanner.ts +189 -0
- package/src/scanner/NobleScanner.ts +195 -0
- package/src/scanner/Scanner.ts +16 -0
- package/src/sensor/BarometerSensorDataManager.ts +41 -0
- package/src/sensor/MotionSensorDataManager.ts +151 -0
- package/src/sensor/PressureSensorDataManager.ts +112 -0
- package/src/sensor/SensorConfigurationManager.ts +177 -0
- package/src/sensor/SensorDataManager.ts +166 -0
- package/src/server/BaseClient.ts +368 -0
- package/src/server/BaseServer.ts +344 -0
- package/src/server/ServerUtils.ts +93 -0
- package/src/server/udp/UDPServer.ts +229 -0
- package/src/server/udp/UDPUtils.ts +20 -0
- package/src/server/websocket/WebSocketClient.ts +179 -0
- package/src/server/websocket/WebSocketServer.ts +184 -0
- package/src/server/websocket/WebSocketUtils.ts +20 -0
- package/src/utils/ArrayBufferUtils.ts +88 -0
- package/src/utils/ArrayUtils.ts +15 -0
- package/src/utils/CenterOfPressureHelper.ts +39 -0
- package/src/utils/Console.ts +156 -0
- package/src/utils/EventDispatcher.ts +153 -0
- package/src/utils/EventUtils.ts +41 -0
- package/src/utils/MathUtils.ts +53 -0
- package/src/utils/ParseUtils.ts +46 -0
- package/src/utils/RangeHelper.ts +38 -0
- package/src/utils/Text.ts +30 -0
- package/src/utils/Timer.ts +72 -0
- package/src/utils/TypeScriptUtils.ts +22 -0
- package/src/utils/cbor.js +429 -0
- package/src/utils/checksum.ts +41 -0
- package/src/utils/environment.ts +46 -0
- package/src/utils/mcumgr.js +444 -0
- package/src/utils/stringUtils.ts +11 -0
- package/src/vibration/VibrationManager.ts +308 -0
- package/src/vibration/VibrationWaveformEffects.ts +128 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { createConsole } from "../utils/Console.ts";
|
|
2
|
+
import EventDispatcher, { BoundEventListeners, Event, EventListenerMap, EventMap } from "../utils/EventDispatcher.ts";
|
|
3
|
+
import { addEventListeners, removeEventListeners } from "../utils/EventUtils.ts";
|
|
4
|
+
import Device, {
|
|
5
|
+
DeviceEvent,
|
|
6
|
+
DeviceEventType,
|
|
7
|
+
DeviceEventMessages,
|
|
8
|
+
DeviceEventTypes,
|
|
9
|
+
BoundDeviceEventListeners,
|
|
10
|
+
DeviceEventMap,
|
|
11
|
+
} from "../Device.ts";
|
|
12
|
+
import DevicePairSensorDataManager, { DevicePairSensorDataEventDispatcher } from "./DevicePairSensorDataManager.ts";
|
|
13
|
+
import { capitalizeFirstCharacter } from "../utils/stringUtils.ts";
|
|
14
|
+
import { InsoleSide, InsoleSides } from "../InformationManager.ts";
|
|
15
|
+
import { VibrationConfiguration } from "../vibration/VibrationManager.ts";
|
|
16
|
+
import { SensorConfiguration } from "../sensor/SensorConfigurationManager.ts";
|
|
17
|
+
import { DevicePairSensorDataEventMessages, DevicePairSensorDataEventTypes } from "./DevicePairSensorDataManager.ts";
|
|
18
|
+
import { AddPrefixToInterfaceKeys, ExtendInterfaceValues, KeyOf } from "../utils/TypeScriptUtils.ts";
|
|
19
|
+
import DeviceManager from "../DeviceManager.ts";
|
|
20
|
+
|
|
21
|
+
const _console = createConsole("DevicePair", { log: true });
|
|
22
|
+
|
|
23
|
+
interface BaseDevicePairDeviceEventMessage {
|
|
24
|
+
device: Device;
|
|
25
|
+
side: InsoleSide;
|
|
26
|
+
}
|
|
27
|
+
type DevicePairDeviceEventMessages = ExtendInterfaceValues<
|
|
28
|
+
AddPrefixToInterfaceKeys<DeviceEventMessages, "device">,
|
|
29
|
+
BaseDevicePairDeviceEventMessage
|
|
30
|
+
>;
|
|
31
|
+
type DevicePairDeviceEventType = KeyOf<DevicePairDeviceEventMessages>;
|
|
32
|
+
function getDevicePairDeviceEventType(deviceEventType: DeviceEventType) {
|
|
33
|
+
return `device${capitalizeFirstCharacter(deviceEventType)}` as DevicePairDeviceEventType;
|
|
34
|
+
}
|
|
35
|
+
const DevicePairDeviceEventTypes = DeviceEventTypes.map((eventType) =>
|
|
36
|
+
getDevicePairDeviceEventType(eventType)
|
|
37
|
+
) as DevicePairDeviceEventType[];
|
|
38
|
+
|
|
39
|
+
export const DevicePairConnectionEventTypes = ["isConnected"] as const;
|
|
40
|
+
export type DevicePairConnectionEventType = (typeof DevicePairConnectionEventTypes)[number];
|
|
41
|
+
|
|
42
|
+
export interface DevicePairConnectionEventMessages {
|
|
43
|
+
isConnected: { isConnected: boolean };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const DevicePairEventTypes = [
|
|
47
|
+
...DevicePairConnectionEventTypes,
|
|
48
|
+
...DevicePairSensorDataEventTypes,
|
|
49
|
+
...DevicePairDeviceEventTypes,
|
|
50
|
+
] as const;
|
|
51
|
+
export type DevicePairEventType = (typeof DevicePairEventTypes)[number];
|
|
52
|
+
|
|
53
|
+
export type DevicePairEventMessages = DevicePairConnectionEventMessages &
|
|
54
|
+
DevicePairSensorDataEventMessages &
|
|
55
|
+
DevicePairDeviceEventMessages;
|
|
56
|
+
|
|
57
|
+
export type DevicePairEventDispatcher = EventDispatcher<DevicePair, DevicePairEventType, DevicePairEventMessages>;
|
|
58
|
+
export type DevicePairEventMap = EventMap<DevicePair, DeviceEventType, DevicePairEventMessages>;
|
|
59
|
+
export type DevicePairEventListenerMap = EventListenerMap<DevicePair, DeviceEventType, DevicePairEventMessages>;
|
|
60
|
+
export type DevicePairEvent = Event<DevicePair, DeviceEventType, DevicePairEventMessages>;
|
|
61
|
+
export type BoundDevicePairEventListeners = BoundEventListeners<DevicePair, DeviceEventType, DevicePairEventMessages>;
|
|
62
|
+
|
|
63
|
+
class DevicePair {
|
|
64
|
+
constructor() {
|
|
65
|
+
this.#sensorDataManager.eventDispatcher = this.#eventDispatcher as DevicePairSensorDataEventDispatcher;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get sides() {
|
|
69
|
+
return InsoleSides;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
#eventDispatcher: DevicePairEventDispatcher = new EventDispatcher(this as DevicePair, DevicePairEventTypes);
|
|
73
|
+
get addEventListener() {
|
|
74
|
+
return this.#eventDispatcher.addEventListener;
|
|
75
|
+
}
|
|
76
|
+
get #dispatchEvent() {
|
|
77
|
+
return this.#eventDispatcher.dispatchEvent;
|
|
78
|
+
}
|
|
79
|
+
get removeEventListener() {
|
|
80
|
+
return this.#eventDispatcher.removeEventListener;
|
|
81
|
+
}
|
|
82
|
+
get waitForEvent() {
|
|
83
|
+
return this.#eventDispatcher.waitForEvent;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// SIDES
|
|
87
|
+
#left?: Device;
|
|
88
|
+
get left() {
|
|
89
|
+
return this.#left;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
#right?: Device;
|
|
93
|
+
get right() {
|
|
94
|
+
return this.#right;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
get isConnected() {
|
|
98
|
+
return InsoleSides.every((side) => this[side]?.isConnected);
|
|
99
|
+
}
|
|
100
|
+
get isPartiallyConnected() {
|
|
101
|
+
return InsoleSides.some((side) => this[side]?.isConnected);
|
|
102
|
+
}
|
|
103
|
+
get isHalfConnected() {
|
|
104
|
+
return this.isPartiallyConnected && !this.isConnected;
|
|
105
|
+
}
|
|
106
|
+
#assertIsConnected() {
|
|
107
|
+
_console.assertWithError(this.isConnected, "devicePair must be connected");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
assignInsole(device: Device) {
|
|
111
|
+
if (!device.isInsole) {
|
|
112
|
+
_console.warn("device is not an insole");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const side = device.insoleSide;
|
|
116
|
+
|
|
117
|
+
const currentDevice = this[side];
|
|
118
|
+
|
|
119
|
+
if (device == currentDevice) {
|
|
120
|
+
_console.log("device already assigned");
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (currentDevice) {
|
|
125
|
+
this.#removeDeviceEventListeners(currentDevice);
|
|
126
|
+
}
|
|
127
|
+
this.#addDeviceEventListeners(device);
|
|
128
|
+
|
|
129
|
+
switch (side) {
|
|
130
|
+
case "left":
|
|
131
|
+
this.#left = device;
|
|
132
|
+
break;
|
|
133
|
+
case "right":
|
|
134
|
+
this.#right = device;
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
_console.log(`assigned ${side} insole`, device);
|
|
139
|
+
|
|
140
|
+
this.resetPressureRange();
|
|
141
|
+
|
|
142
|
+
this.#dispatchEvent("isConnected", { isConnected: this.isConnected });
|
|
143
|
+
this.#dispatchEvent("deviceIsConnected", { device, isConnected: device.isConnected, side });
|
|
144
|
+
|
|
145
|
+
return currentDevice;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
#addDeviceEventListeners(device: Device) {
|
|
149
|
+
addEventListeners(device, this.#boundDeviceEventListeners);
|
|
150
|
+
DeviceEventTypes.forEach((deviceEventType) => {
|
|
151
|
+
// @ts-expect-error
|
|
152
|
+
device.addEventListener(deviceEventType, this.#redispatchDeviceEvent.bind(this));
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
#removeDeviceEventListeners(device: Device) {
|
|
156
|
+
removeEventListeners(device, this.#boundDeviceEventListeners);
|
|
157
|
+
DeviceEventTypes.forEach((deviceEventType) => {
|
|
158
|
+
// @ts-expect-error
|
|
159
|
+
device.removeEventListener(deviceEventType, this.#redispatchDeviceEvent.bind(this));
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
#removeInsole(device: Device) {
|
|
164
|
+
const foundDevice = InsoleSides.some((side) => {
|
|
165
|
+
if (this[side] != device) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
_console.log(`removing ${side} insole`, device);
|
|
170
|
+
removeEventListeners(device, this.#boundDeviceEventListeners);
|
|
171
|
+
delete this[side];
|
|
172
|
+
|
|
173
|
+
return true;
|
|
174
|
+
});
|
|
175
|
+
if (foundDevice) {
|
|
176
|
+
this.#dispatchEvent("isConnected", { isConnected: this.isConnected });
|
|
177
|
+
}
|
|
178
|
+
return foundDevice;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
#boundDeviceEventListeners: BoundDeviceEventListeners = {
|
|
182
|
+
isConnected: this.#onDeviceIsConnected.bind(this),
|
|
183
|
+
sensorData: this.#onDeviceSensorData.bind(this),
|
|
184
|
+
getType: this.#onDeviceType.bind(this),
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
#redispatchDeviceEvent(deviceEvent: DeviceEvent) {
|
|
188
|
+
const { type, target: device, message } = deviceEvent;
|
|
189
|
+
this.#dispatchEvent(getDevicePairDeviceEventType(type), {
|
|
190
|
+
...message,
|
|
191
|
+
device,
|
|
192
|
+
side: device.insoleSide,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
#onDeviceIsConnected(deviceEvent: DeviceEventMap["isConnected"]) {
|
|
197
|
+
this.#dispatchEvent("isConnected", { isConnected: this.isConnected });
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
#onDeviceType(deviceEvent: DeviceEventMap["getType"]) {
|
|
201
|
+
const { target: device } = deviceEvent;
|
|
202
|
+
if (this[device.insoleSide] == device) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const foundDevice = this.#removeInsole(device);
|
|
206
|
+
if (!foundDevice) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
this.assignInsole(device);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// SENSOR CONFIGURATION
|
|
213
|
+
setSensorConfiguration(sensorConfiguration: SensorConfiguration) {
|
|
214
|
+
InsoleSides.forEach((side) => {
|
|
215
|
+
this[side]?.setSensorConfiguration(sensorConfiguration);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// SENSOR DATA
|
|
220
|
+
#sensorDataManager = new DevicePairSensorDataManager();
|
|
221
|
+
#onDeviceSensorData(deviceEvent: DeviceEventMap["sensorData"]) {
|
|
222
|
+
if (this.isConnected) {
|
|
223
|
+
this.#sensorDataManager.onDeviceSensorData(deviceEvent);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
resetPressureRange() {
|
|
227
|
+
this.#sensorDataManager.resetPressureRange();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// VIBRATION
|
|
231
|
+
async triggerVibration(vibrationConfigurations: VibrationConfiguration[], sendImmediately?: boolean) {
|
|
232
|
+
const promises = InsoleSides.map((side) => {
|
|
233
|
+
return this[side]?.triggerVibration(vibrationConfigurations, sendImmediately);
|
|
234
|
+
}).filter(Boolean);
|
|
235
|
+
return Promise.allSettled(promises);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// SHARED INSTANCE
|
|
239
|
+
static #shared = new DevicePair();
|
|
240
|
+
static get shared() {
|
|
241
|
+
return this.#shared;
|
|
242
|
+
}
|
|
243
|
+
static {
|
|
244
|
+
DeviceManager.AddEventListener("deviceConnected", (event) => {
|
|
245
|
+
const { device } = event.message;
|
|
246
|
+
if (device.isInsole) {
|
|
247
|
+
this.#shared.assignInsole(device);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export default DevicePair;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { createConsole } from "../utils/Console.ts";
|
|
2
|
+
import CenterOfPressureHelper from "../utils/CenterOfPressureHelper.ts";
|
|
3
|
+
import { PressureData } from "../sensor/PressureSensorDataManager.ts";
|
|
4
|
+
import { CenterOfPressure } from "../utils/CenterOfPressureHelper.ts";
|
|
5
|
+
import { InsoleSide, InsoleSides } from "../InformationManager.ts";
|
|
6
|
+
import { DeviceEventMap } from "../Device.ts";
|
|
7
|
+
|
|
8
|
+
const _console = createConsole("DevicePairPressureSensorDataManager", { log: true });
|
|
9
|
+
|
|
10
|
+
export type DevicePairRawPressureData = { [insoleSide in InsoleSide]: PressureData };
|
|
11
|
+
|
|
12
|
+
export interface DevicePairPressureData {
|
|
13
|
+
rawSum: number;
|
|
14
|
+
normalizedSum: number;
|
|
15
|
+
center?: CenterOfPressure;
|
|
16
|
+
normalizedCenter?: CenterOfPressure;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface DevicePairPressureDataEventMessage {
|
|
20
|
+
pressure: DevicePairPressureData;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface DevicePairPressureDataEventMessages {
|
|
24
|
+
pressure: DevicePairPressureDataEventMessage;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
class DevicePairPressureSensorDataManager {
|
|
28
|
+
#rawPressure: Partial<DevicePairRawPressureData> = {};
|
|
29
|
+
|
|
30
|
+
#centerOfPressureHelper = new CenterOfPressureHelper();
|
|
31
|
+
|
|
32
|
+
resetPressureRange() {
|
|
33
|
+
this.#centerOfPressureHelper.reset();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
onDevicePressureData(event: DeviceEventMap["pressure"]) {
|
|
37
|
+
const { pressure } = event.message;
|
|
38
|
+
const insoleSide = event.target.insoleSide;
|
|
39
|
+
_console.log({ pressure, insoleSide });
|
|
40
|
+
this.#rawPressure[insoleSide] = pressure;
|
|
41
|
+
if (this.#hasAllPressureData) {
|
|
42
|
+
return this.#updatePressureData();
|
|
43
|
+
} else {
|
|
44
|
+
_console.log("doesn't have all pressure data yet...");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get #hasAllPressureData() {
|
|
49
|
+
return InsoleSides.every((side) => side in this.#rawPressure);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
#updatePressureData() {
|
|
53
|
+
const pressure: DevicePairPressureData = { rawSum: 0, normalizedSum: 0 };
|
|
54
|
+
|
|
55
|
+
InsoleSides.forEach((side) => {
|
|
56
|
+
pressure.rawSum += this.#rawPressure[side]!.scaledSum;
|
|
57
|
+
pressure.normalizedSum += this.#rawPressure[side]!.normalizedSum;
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (pressure.normalizedSum > 0) {
|
|
61
|
+
pressure.center = { x: 0, y: 0 };
|
|
62
|
+
InsoleSides.forEach((side) => {
|
|
63
|
+
const sidePressure = this.#rawPressure[side]!;
|
|
64
|
+
const normalizedPressureSumWeight = sidePressure.normalizedSum / pressure.normalizedSum;
|
|
65
|
+
if (normalizedPressureSumWeight > 0) {
|
|
66
|
+
pressure.center!.y += sidePressure.normalizedCenter!.y * normalizedPressureSumWeight;
|
|
67
|
+
if (side == "right") {
|
|
68
|
+
pressure.center!.x = normalizedPressureSumWeight;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
pressure.normalizedCenter = this.#centerOfPressureHelper.updateAndGetNormalization(pressure.center);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
_console.log({ devicePairPressure: pressure });
|
|
77
|
+
|
|
78
|
+
return pressure;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export default DevicePairPressureSensorDataManager;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import DevicePairPressureSensorDataManager, {
|
|
2
|
+
DevicePairPressureDataEventMessages,
|
|
3
|
+
} from "./DevicePairPressureSensorDataManager.ts";
|
|
4
|
+
import { createConsole } from "../utils/Console.ts";
|
|
5
|
+
import { InsoleSide } from "../InformationManager.ts";
|
|
6
|
+
import { SensorType } from "../sensor/SensorDataManager.ts";
|
|
7
|
+
import { DeviceEventMap, SpecificDeviceEvent } from "../Device.ts";
|
|
8
|
+
import EventDispatcher from "../utils/EventDispatcher.ts";
|
|
9
|
+
import DevicePair from "./DevicePair.ts";
|
|
10
|
+
import { AddKeysAsPropertyToInterface, ExtendInterfaceValues, ValueOf } from "../utils/TypeScriptUtils.ts";
|
|
11
|
+
|
|
12
|
+
const _console = createConsole("DevicePairSensorDataManager", { log: true });
|
|
13
|
+
|
|
14
|
+
export const DevicePairSensorTypes = ["pressure", "sensorData"] as const;
|
|
15
|
+
export type DevicePairSensorType = (typeof DevicePairSensorTypes)[number];
|
|
16
|
+
|
|
17
|
+
export const DevicePairSensorDataEventTypes = DevicePairSensorTypes;
|
|
18
|
+
export type DevicePairSensorDataEventType = (typeof DevicePairSensorDataEventTypes)[number];
|
|
19
|
+
|
|
20
|
+
export type DevicePairSensorDataTimestamps = { [insoleSide in InsoleSide]: number };
|
|
21
|
+
|
|
22
|
+
interface BaseDevicePairSensorDataEventMessage {
|
|
23
|
+
timestamps: DevicePairSensorDataTimestamps;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type BaseDevicePairSensorDataEventMessages = DevicePairPressureDataEventMessages;
|
|
27
|
+
type _DevicePairSensorDataEventMessages = ExtendInterfaceValues<
|
|
28
|
+
AddKeysAsPropertyToInterface<BaseDevicePairSensorDataEventMessages, "sensorType">,
|
|
29
|
+
BaseDevicePairSensorDataEventMessage
|
|
30
|
+
>;
|
|
31
|
+
|
|
32
|
+
export type DevicePairSensorDataEventMessage = ValueOf<_DevicePairSensorDataEventMessages>;
|
|
33
|
+
interface AnyDevicePairSensorDataEventMessages {
|
|
34
|
+
sensorData: DevicePairSensorDataEventMessage;
|
|
35
|
+
}
|
|
36
|
+
export type DevicePairSensorDataEventMessages = _DevicePairSensorDataEventMessages &
|
|
37
|
+
AnyDevicePairSensorDataEventMessages;
|
|
38
|
+
|
|
39
|
+
export type DevicePairSensorDataEventDispatcher = EventDispatcher<
|
|
40
|
+
DevicePair,
|
|
41
|
+
DevicePairSensorDataEventType,
|
|
42
|
+
DevicePairSensorDataEventMessages
|
|
43
|
+
>;
|
|
44
|
+
|
|
45
|
+
class DevicePairSensorDataManager {
|
|
46
|
+
eventDispatcher!: DevicePairSensorDataEventDispatcher;
|
|
47
|
+
get dispatchEvent() {
|
|
48
|
+
return this.eventDispatcher.dispatchEvent;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
#timestamps: { [sensorType in SensorType]?: Partial<DevicePairSensorDataTimestamps> } = {};
|
|
52
|
+
|
|
53
|
+
pressureSensorDataManager = new DevicePairPressureSensorDataManager();
|
|
54
|
+
resetPressureRange() {
|
|
55
|
+
this.pressureSensorDataManager.resetPressureRange();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
onDeviceSensorData(event: DeviceEventMap["sensorData"]) {
|
|
59
|
+
const { timestamp, sensorType } = event.message;
|
|
60
|
+
|
|
61
|
+
_console.log({ sensorType, timestamp, event });
|
|
62
|
+
|
|
63
|
+
if (!this.#timestamps[sensorType]) {
|
|
64
|
+
this.#timestamps[sensorType] = {};
|
|
65
|
+
}
|
|
66
|
+
this.#timestamps[sensorType]![event.target.insoleSide] = timestamp;
|
|
67
|
+
|
|
68
|
+
let value;
|
|
69
|
+
switch (sensorType) {
|
|
70
|
+
case "pressure":
|
|
71
|
+
value = this.pressureSensorDataManager.onDevicePressureData(event as unknown as DeviceEventMap["pressure"]);
|
|
72
|
+
break;
|
|
73
|
+
default:
|
|
74
|
+
_console.log(`uncaught sensorType "${sensorType}"`);
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (value) {
|
|
79
|
+
const timestamps = Object.assign({}, this.#timestamps[sensorType]) as DevicePairSensorDataTimestamps;
|
|
80
|
+
// @ts-expect-error
|
|
81
|
+
this.dispatchEvent(sensorType as DevicePairSensorDataEventType, { sensorType, timestamps, [sensorType]: value });
|
|
82
|
+
// @ts-expect-error
|
|
83
|
+
this.dispatchEvent("sensorData", { sensorType, timestamps, [sensorType]: value });
|
|
84
|
+
} else {
|
|
85
|
+
_console.log("no value received");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export default DevicePairSensorDataManager;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import EventDispatcher, { BoundEventListeners, Event, EventMap } from "../utils/EventDispatcher.ts";
|
|
2
|
+
import { addEventListeners } from "../utils/EventUtils.ts";
|
|
3
|
+
import { createConsole } from "../utils/Console.ts";
|
|
4
|
+
import Timer from "../utils/Timer.ts";
|
|
5
|
+
import { DeviceType } from "../InformationManager.ts";
|
|
6
|
+
|
|
7
|
+
const _console = createConsole("BaseScanner");
|
|
8
|
+
|
|
9
|
+
export const ScannerEventTypes = [
|
|
10
|
+
"isScanningAvailable",
|
|
11
|
+
"isScanning",
|
|
12
|
+
"discoveredDevice",
|
|
13
|
+
"expiredDiscoveredDevice",
|
|
14
|
+
] as const;
|
|
15
|
+
export type ScannerEventType = (typeof ScannerEventTypes)[number];
|
|
16
|
+
|
|
17
|
+
export interface DiscoveredDevice {
|
|
18
|
+
bluetoothId: string;
|
|
19
|
+
name: string;
|
|
20
|
+
deviceType: DeviceType;
|
|
21
|
+
rssi: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface ScannerDiscoveredDeviceEventMessage {
|
|
25
|
+
discoveredDevice: DiscoveredDevice;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ScannerEventMessages {
|
|
29
|
+
discoveredDevice: ScannerDiscoveredDeviceEventMessage;
|
|
30
|
+
expiredDiscoveredDevice: ScannerDiscoveredDeviceEventMessage;
|
|
31
|
+
isScanningAvailable: { isScanningAvailable: boolean };
|
|
32
|
+
isScanning: { isScanning: boolean };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type ScannerEventDispatcher = EventDispatcher<BaseScanner, ScannerEventType, ScannerEventMessages>;
|
|
36
|
+
export type ScannerEventMap = EventMap<BaseScanner, ScannerEventType, ScannerEventMessages>;
|
|
37
|
+
export type ScannerEvent = Event<BaseScanner, ScannerEventType, ScannerEventMessages>;
|
|
38
|
+
export type BoundScannerEventListeners = BoundEventListeners<BaseScanner, ScannerEventType, ScannerEventMessages>;
|
|
39
|
+
|
|
40
|
+
export type DiscoveredDevicesMap = { [deviceId: string]: DiscoveredDevice };
|
|
41
|
+
|
|
42
|
+
abstract class BaseScanner {
|
|
43
|
+
// IS SUPPORTED
|
|
44
|
+
protected get baseConstructor() {
|
|
45
|
+
return this.constructor as typeof BaseScanner;
|
|
46
|
+
}
|
|
47
|
+
static get isSupported() {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
get isSupported() {
|
|
51
|
+
return this.baseConstructor.isSupported;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
#assertIsSupported() {
|
|
55
|
+
_console.assertWithError(this.isSupported, `${this.constructor.name} is not supported`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// CONSTRUCTOR
|
|
59
|
+
#assertIsSubclass() {
|
|
60
|
+
_console.assertWithError(this.constructor != BaseScanner, `${this.constructor.name} must be subclassed`);
|
|
61
|
+
}
|
|
62
|
+
constructor() {
|
|
63
|
+
this.#assertIsSubclass();
|
|
64
|
+
this.#assertIsSupported();
|
|
65
|
+
addEventListeners(this, this.#boundEventListeners);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#boundEventListeners: BoundScannerEventListeners = {
|
|
69
|
+
discoveredDevice: this.#onDiscoveredDevice.bind(this),
|
|
70
|
+
isScanning: this.#onIsScanning.bind(this),
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// EVENT DISPATCHER
|
|
74
|
+
#eventDispatcher: ScannerEventDispatcher = new EventDispatcher(this as BaseScanner, ScannerEventTypes);
|
|
75
|
+
get addEventListener() {
|
|
76
|
+
return this.#eventDispatcher.addEventListener;
|
|
77
|
+
}
|
|
78
|
+
protected get dispatchEvent() {
|
|
79
|
+
return this.#eventDispatcher.dispatchEvent;
|
|
80
|
+
}
|
|
81
|
+
get removeEventListener() {
|
|
82
|
+
return this.#eventDispatcher.removeEventListener;
|
|
83
|
+
}
|
|
84
|
+
get waitForEvent() {
|
|
85
|
+
return this.#eventDispatcher.waitForEvent;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// AVAILABILITY
|
|
89
|
+
get isScanningAvailable() {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
#assertIsAvailable() {
|
|
93
|
+
_console.assertWithError(this.isScanningAvailable, "not available");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// SCANNING
|
|
97
|
+
get isScanning() {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
#assertIsScanning() {
|
|
101
|
+
_console.assertWithError(this.isScanning, "not scanning");
|
|
102
|
+
}
|
|
103
|
+
#assertIsNotScanning() {
|
|
104
|
+
_console.assertWithError(!this.isScanning, "already scanning");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
startScan() {
|
|
108
|
+
this.#assertIsAvailable();
|
|
109
|
+
this.#assertIsNotScanning();
|
|
110
|
+
}
|
|
111
|
+
stopScan() {
|
|
112
|
+
this.#assertIsScanning();
|
|
113
|
+
}
|
|
114
|
+
#onIsScanning(event: ScannerEventMap["isScanning"]) {
|
|
115
|
+
if (this.isScanning) {
|
|
116
|
+
this.#discoveredDevices = {};
|
|
117
|
+
this.#discoveredDeviceTimestamps = {};
|
|
118
|
+
} else {
|
|
119
|
+
this.#checkDiscoveredDevicesExpirationTimer.stop();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// DISCOVERED DEVICES
|
|
124
|
+
#discoveredDevices: DiscoveredDevicesMap = {};
|
|
125
|
+
get discoveredDevices(): Readonly<DiscoveredDevicesMap> {
|
|
126
|
+
return this.#discoveredDevices;
|
|
127
|
+
}
|
|
128
|
+
get discoveredDevicesArray() {
|
|
129
|
+
return Object.values(this.#discoveredDevices).sort((a, b) => {
|
|
130
|
+
return this.#discoveredDeviceTimestamps[a.bluetoothId] - this.#discoveredDeviceTimestamps[b.bluetoothId];
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
#assertValidDiscoveredDeviceId(discoveredDeviceId: string) {
|
|
134
|
+
_console.assertWithError(
|
|
135
|
+
this.#discoveredDevices[discoveredDeviceId],
|
|
136
|
+
`no discovered device with id "${discoveredDeviceId}"`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
#onDiscoveredDevice(event: ScannerEventMap["discoveredDevice"]) {
|
|
141
|
+
const { discoveredDevice } = event.message;
|
|
142
|
+
this.#discoveredDevices[discoveredDevice.bluetoothId] = discoveredDevice;
|
|
143
|
+
this.#discoveredDeviceTimestamps[discoveredDevice.bluetoothId] = Date.now();
|
|
144
|
+
this.#checkDiscoveredDevicesExpirationTimer.start();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
#discoveredDeviceTimestamps: { [id: string]: number } = {};
|
|
148
|
+
|
|
149
|
+
static #DiscoveredDeviceExpirationTimeout = 5000;
|
|
150
|
+
static get DiscoveredDeviceExpirationTimeout() {
|
|
151
|
+
return this.#DiscoveredDeviceExpirationTimeout;
|
|
152
|
+
}
|
|
153
|
+
get #discoveredDeviceExpirationTimeout() {
|
|
154
|
+
return BaseScanner.DiscoveredDeviceExpirationTimeout;
|
|
155
|
+
}
|
|
156
|
+
#checkDiscoveredDevicesExpirationTimer = new Timer(this.#checkDiscoveredDevicesExpiration.bind(this), 1000);
|
|
157
|
+
#checkDiscoveredDevicesExpiration() {
|
|
158
|
+
const entries = Object.entries(this.#discoveredDevices);
|
|
159
|
+
if (entries.length == 0) {
|
|
160
|
+
this.#checkDiscoveredDevicesExpirationTimer.stop();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const now = Date.now();
|
|
164
|
+
entries.forEach(([id, discoveredDevice]) => {
|
|
165
|
+
const timestamp = this.#discoveredDeviceTimestamps[id];
|
|
166
|
+
if (now - timestamp > this.#discoveredDeviceExpirationTimeout) {
|
|
167
|
+
_console.log("discovered device timeout");
|
|
168
|
+
delete this.#discoveredDevices[id];
|
|
169
|
+
delete this.#discoveredDeviceTimestamps[id];
|
|
170
|
+
this.dispatchEvent("expiredDiscoveredDevice", { discoveredDevice });
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// DEVICE CONNECTION
|
|
176
|
+
async connectToDevice(deviceId: string) {
|
|
177
|
+
this.#assertIsAvailable();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// RESET
|
|
181
|
+
get canReset() {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
reset() {
|
|
185
|
+
_console.log("resetting...");
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export default BaseScanner;
|