brilliantsole 0.0.26 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -10
- package/assets/3d/anchor.glb +0 -0
- package/assets/3d/coin.glb +0 -0
- package/assets/3d/glasses.glb +0 -0
- package/assets/3d/rightHand.glb +0 -0
- package/assets/audio/bounceMedium.wav +0 -0
- package/assets/audio/bounceStrong.wav +0 -0
- package/assets/audio/bounceWeak.wav +0 -0
- package/assets/audio/coin.wav +0 -0
- package/assets/audio/getUp.wav +0 -0
- package/assets/audio/grab.wav +0 -0
- package/assets/audio/kick.wav +0 -0
- package/assets/audio/platterFadeIn old.wav +0 -0
- package/assets/audio/platterFadeIn.wav +0 -0
- package/assets/audio/platterFadeOut.wav +0 -0
- package/assets/audio/punch.wav +0 -0
- package/assets/audio/punchSqueak.wav +0 -0
- package/assets/audio/purr.wav +0 -0
- package/assets/audio/purrFadeOut.wav +0 -0
- package/assets/audio/release.wav +0 -0
- package/assets/audio/splat.wav +0 -0
- package/assets/audio/stomp.wav +0 -0
- package/assets/images/ukaton-pressure-0.svg +9 -0
- package/assets/images/ukaton-pressure-1.svg +9 -0
- package/assets/images/ukaton-pressure-10.svg +9 -0
- package/assets/images/ukaton-pressure-11.svg +9 -0
- package/assets/images/ukaton-pressure-12.svg +9 -0
- package/assets/images/ukaton-pressure-13.svg +9 -0
- package/assets/images/ukaton-pressure-14.svg +9 -0
- package/assets/images/ukaton-pressure-15.svg +9 -0
- package/assets/images/ukaton-pressure-2.svg +9 -0
- package/assets/images/ukaton-pressure-3.svg +9 -0
- package/assets/images/ukaton-pressure-4.svg +9 -0
- package/assets/images/ukaton-pressure-5.svg +9 -0
- package/assets/images/ukaton-pressure-6.svg +9 -0
- package/assets/images/ukaton-pressure-7.svg +9 -0
- package/assets/images/ukaton-pressure-8.svg +9 -0
- package/assets/images/ukaton-pressure-9.svg +9 -0
- package/assets/images/ukaton-right-insole.svg +798 -0
- package/build/brilliantsole.cjs +2870 -882
- package/build/brilliantsole.cjs.map +1 -1
- package/build/brilliantsole.js +2477 -782
- package/build/brilliantsole.js.map +1 -1
- package/build/brilliantsole.ls.js +2260 -592
- package/build/brilliantsole.ls.js.map +1 -1
- package/build/brilliantsole.min.js +1 -1
- package/build/brilliantsole.min.js.map +1 -1
- package/build/brilliantsole.module.d.ts +302 -116
- package/build/brilliantsole.module.js +2468 -782
- package/build/brilliantsole.module.js.map +1 -1
- package/build/brilliantsole.module.min.d.ts +302 -116
- package/build/brilliantsole.module.min.js +1 -1
- package/build/brilliantsole.module.min.js.map +1 -1
- package/build/brilliantsole.node.module.d.ts +295 -113
- package/build/brilliantsole.node.module.js +2860 -882
- package/build/brilliantsole.node.module.js.map +1 -1
- package/build/dts/BS-output.d.ts +10 -0
- package/build/dts/BS.d.ts +21 -9
- package/build/dts/CameraManager.d.ts +72 -0
- package/build/dts/Device.d.ts +53 -16
- package/build/dts/DeviceInformationManager.d.ts +4 -4
- package/build/dts/DeviceManager.d.ts +3 -0
- package/build/dts/FileTransferManager.d.ts +18 -8
- package/build/dts/InformationManager.d.ts +8 -5
- package/build/dts/TfliteManager.d.ts +22 -2
- package/build/dts/WifiManager.d.ts +61 -0
- package/build/dts/connection/BaseConnectionManager.d.ts +37 -3
- package/build/dts/connection/ClientConnectionManager.d.ts +11 -2
- package/build/dts/connection/bluetooth/BluetoothConnectionManager.d.ts +1 -0
- package/build/dts/connection/bluetooth/NobleConnectionManager.d.ts +3 -1
- package/build/dts/connection/bluetooth/WebBluetoothConnectionManager.d.ts +2 -0
- package/build/dts/connection/bluetooth/bluetoothUUIDs.d.ts +2 -2
- package/build/dts/connection/udp/UDPConnectionManager.d.ts +28 -0
- package/build/dts/connection/webSocket/WebSocketConnectionManager.d.ts +25 -0
- package/build/dts/devicePair/DevicePair.d.ts +14 -10
- package/build/dts/devicePair/DevicePairPressureSensorDataManager.d.ts +8 -4
- package/build/dts/devicePair/DevicePairSensorDataManager.d.ts +2 -2
- package/build/dts/scanner/BaseScanner.d.ts +4 -1
- package/build/dts/scanner/NobleScanner.d.ts +2 -1
- package/build/dts/sensor/MotionSensorDataManager.d.ts +5 -2
- package/build/dts/sensor/SensorDataManager.d.ts +5 -4
- package/build/dts/server/BaseClient.d.ts +6 -3
- package/build/dts/server/ServerUtils.d.ts +1 -1
- package/build/dts/server/websocket/WebSocketUtils.d.ts +1 -1
- package/build/dts/utils/CenterOfPressureHelper.d.ts +2 -2
- package/build/dts/utils/Console.d.ts +2 -0
- package/build/dts/utils/MathUtils.d.ts +2 -0
- package/build/dts/utils/ThrottleUtils.d.ts +2 -0
- package/build/dts/vibration/VibrationManager.d.ts +19 -2
- package/build/index.d.ts +299 -113
- package/build/index.node.d.ts +292 -110
- package/examples/3d/scene.html +19 -5
- package/examples/3d/script.js +90 -17
- package/examples/3d-generic/index.html +144 -0
- package/examples/3d-generic/script.js +266 -0
- package/examples/balance/script.js +2 -1
- package/examples/basic/index.html +232 -18
- package/examples/basic/script.js +746 -106
- package/examples/bottango/index.html +11 -1
- package/examples/bottango/script.js +2 -2
- package/examples/center-of-pressure/index.html +114 -114
- package/examples/center-of-pressure/script.js +1 -1
- package/examples/device-pair/index.html +58 -58
- package/examples/device-pair/script.js +12 -8
- package/examples/edge-impulse/script.js +135 -44
- package/examples/edge-impulse-test/README.md +11 -0
- package/examples/edge-impulse-test/edge-impulse-standalone.js +7228 -0
- package/examples/edge-impulse-test/edge-impulse-standalone.wasm +0 -0
- package/examples/edge-impulse-test/index.html +75 -0
- package/examples/edge-impulse-test/run-impulse.js +135 -0
- package/examples/edge-impulse-test/script.js +200 -0
- package/examples/gloves/edge-impulse-standalone.js +7228 -0
- package/examples/gloves/edge-impulse-standalone.wasm +0 -0
- package/examples/gloves/index.html +119 -0
- package/examples/gloves/run-impulse.js +135 -0
- package/examples/gloves/scene.html +124 -0
- package/examples/gloves/script.js +931 -0
- package/examples/graph/index.html +11 -1
- package/examples/graph/script.js +94 -37
- package/examples/pressure/index.html +180 -12
- package/examples/pressure/script.js +144 -7
- package/examples/punch/index.html +135 -0
- package/examples/punch/punch.tflite +0 -0
- package/examples/punch/script.js +169 -0
- package/examples/recording/index.html +191 -183
- package/examples/server/index.html +109 -23
- package/examples/server/script.js +322 -111
- package/examples/ukaton-firmware-update/index.html +20 -0
- package/examples/ukaton-firmware-update/manifest.json +11 -0
- package/examples/ukaton-firmware-update/merged-firmware.bin +0 -0
- package/examples/utils/aframe/aframe-master.min.js +2 -0
- package/examples/utils/aframe/bs-vibration.js +150 -0
- package/examples/utils/aframe/force-pushable.js +80 -0
- package/examples/utils/aframe/grabbable-anchor.js +46 -0
- package/examples/utils/aframe/grabbable-listener.js +31 -0
- package/examples/utils/aframe/grabbable-physics-body.js +190 -0
- package/examples/utils/aframe/grow-shrink.js +25 -0
- package/examples/utils/aframe/hand-punch.js +119 -0
- package/examples/utils/aframe/my-obb-collider.js +293 -0
- package/examples/utils/aframe/occlude-hand-tracking-controls.js +47 -0
- package/examples/utils/aframe/occlude-mesh.js +42 -0
- package/examples/utils/aframe/palm-up-detector.js +47 -0
- package/examples/utils/aframe/shadow-material.js +20 -0
- package/examples/utils/aframe/soft-shadow-light.js +9 -0
- package/examples/webxr/script.js +3 -3
- package/examples/webxr-2/assets/3d/soccerBall.glb +0 -0
- package/examples/webxr-2/assets/audio/shellBounce.wav +0 -0
- package/examples/webxr-2/assets/audio/shellHit.wav +0 -0
- package/examples/webxr-2/assets/audio/shellKick.wav +0 -0
- package/examples/webxr-2/assets/audio/soccerBounce.wav +0 -0
- package/examples/webxr-2/assets/audio/soccerKick.mp3 +0 -0
- package/examples/webxr-2/assets/images/shellTexture.png +0 -0
- package/examples/webxr-2/components/bs-ankle.js +337 -0
- package/examples/webxr-2/components/coin.js +84 -0
- package/examples/webxr-2/components/custom-wrap.js +17 -0
- package/examples/webxr-2/components/goomba.js +3250 -0
- package/examples/webxr-2/components/init-shell-material.js +215 -0
- package/examples/webxr-2/components/platter.js +172 -0
- package/examples/webxr-2/components/shell.js +374 -0
- package/examples/webxr-2/components/soccer-ball.js +250 -0
- package/examples/webxr-2/components/squashed-goomba.js +249 -0
- package/examples/webxr-2/edge-impulse-standalone.js +7228 -0
- package/examples/webxr-2/edge-impulse-standalone.wasm +0 -0
- package/examples/webxr-2/index.html +996 -0
- package/examples/webxr-2/kick.tflite +0 -0
- package/examples/webxr-2/kick2.tflite +0 -0
- package/examples/webxr-2/run-impulse.js +135 -0
- package/examples/webxr-2/script.js +384 -0
- package/package.json +2 -1
- package/src/.prettierrc +4 -0
- package/src/BS.ts +66 -9
- package/src/CameraManager.ts +499 -0
- package/src/Device.ts +620 -92
- package/src/DeviceInformationManager.ts +22 -11
- package/src/DeviceManager.ts +94 -25
- package/src/FileTransferManager.ts +146 -21
- package/src/FirmwareManager.ts +1 -1
- package/src/InformationManager.ts +62 -20
- package/src/TfliteManager.ts +172 -26
- package/src/WifiManager.ts +323 -0
- package/src/connection/BaseConnectionManager.ts +145 -30
- package/src/connection/ClientConnectionManager.ts +47 -11
- package/src/connection/bluetooth/BluetoothConnectionManager.ts +14 -3
- package/src/connection/bluetooth/NobleConnectionManager.ts +155 -42
- package/src/connection/bluetooth/WebBluetoothConnectionManager.ts +104 -35
- package/src/connection/bluetooth/bluetoothUUIDs.ts +40 -13
- package/src/connection/udp/UDPConnectionManager.ts +356 -0
- package/src/connection/websocket/WebSocketConnectionManager.ts +282 -0
- package/src/devicePair/DevicePair.ts +145 -49
- package/src/devicePair/DevicePairPressureSensorDataManager.ts +72 -24
- package/src/devicePair/DevicePairSensorDataManager.ts +5 -5
- package/src/scanner/BaseScanner.ts +49 -11
- package/src/scanner/NobleScanner.ts +81 -17
- package/src/sensor/BarometerSensorDataManager.ts +1 -1
- package/src/sensor/MotionSensorDataManager.ts +22 -7
- package/src/sensor/PressureSensorDataManager.ts +47 -13
- package/src/sensor/SensorConfigurationManager.ts +75 -24
- package/src/sensor/SensorDataManager.ts +107 -26
- package/src/server/BaseClient.ts +192 -37
- package/src/server/BaseServer.ts +201 -43
- package/src/server/ServerUtils.ts +39 -9
- package/src/server/udp/UDPServer.ts +74 -23
- package/src/server/udp/UDPUtils.ts +9 -2
- package/src/server/websocket/WebSocketClient.ts +30 -9
- package/src/server/websocket/WebSocketServer.ts +1 -1
- package/src/server/websocket/WebSocketUtils.ts +4 -2
- package/src/utils/CenterOfPressureHelper.ts +5 -5
- package/src/utils/Console.ts +62 -9
- package/src/utils/MathUtils.ts +31 -1
- package/src/utils/ParseUtils.ts +25 -6
- package/src/utils/ThrottleUtils.ts +62 -0
- package/src/utils/Timer.ts +1 -1
- package/src/utils/checksum.ts +1 -1
- package/src/utils/mcumgr.js +1 -1
- package/src/vibration/VibrationManager.ts +166 -40
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import Device, { SendMessageCallback } from "./Device.ts";
|
|
2
|
+
import { createConsole } from "./utils/Console.ts";
|
|
3
|
+
import { isInNode } from "./utils/environment.ts";
|
|
4
|
+
import EventDispatcher from "./utils/EventDispatcher.ts";
|
|
5
|
+
import autoBind from "auto-bind";
|
|
6
|
+
import { parseMessage } from "./utils/ParseUtils.ts";
|
|
7
|
+
import { concatenateArrayBuffers } from "./utils/ArrayBufferUtils.ts";
|
|
8
|
+
|
|
9
|
+
const _console = createConsole("CameraManager", { log: false });
|
|
10
|
+
|
|
11
|
+
export const CameraSensorTypes = ["camera"] as const;
|
|
12
|
+
export type CameraSensorType = (typeof CameraSensorTypes)[number];
|
|
13
|
+
|
|
14
|
+
export const CameraCommands = [
|
|
15
|
+
"focus",
|
|
16
|
+
"takePicture",
|
|
17
|
+
"stop",
|
|
18
|
+
"sleep",
|
|
19
|
+
"wake",
|
|
20
|
+
] as const;
|
|
21
|
+
export type CameraCommand = (typeof CameraCommands)[number];
|
|
22
|
+
|
|
23
|
+
export const CameraStatuses = [
|
|
24
|
+
"idle",
|
|
25
|
+
"focusing",
|
|
26
|
+
"takingPicture",
|
|
27
|
+
"asleep",
|
|
28
|
+
] as const;
|
|
29
|
+
export type CameraStatus = (typeof CameraStatuses)[number];
|
|
30
|
+
|
|
31
|
+
export const CameraDataTypes = [
|
|
32
|
+
"headerSize",
|
|
33
|
+
"header",
|
|
34
|
+
"imageSize",
|
|
35
|
+
"image",
|
|
36
|
+
"footerSize",
|
|
37
|
+
"footer",
|
|
38
|
+
] as const;
|
|
39
|
+
export type CameraDataType = (typeof CameraDataTypes)[number];
|
|
40
|
+
|
|
41
|
+
export const CameraConfigurationTypes = [
|
|
42
|
+
"resolution",
|
|
43
|
+
"qualityFactor",
|
|
44
|
+
"shutter",
|
|
45
|
+
"gain",
|
|
46
|
+
"redGain",
|
|
47
|
+
"greenGain",
|
|
48
|
+
"blueGain",
|
|
49
|
+
] as const;
|
|
50
|
+
export type CameraConfigurationType = (typeof CameraConfigurationTypes)[number];
|
|
51
|
+
|
|
52
|
+
export const CameraMessageTypes = [
|
|
53
|
+
"cameraStatus",
|
|
54
|
+
"cameraCommand",
|
|
55
|
+
"getCameraConfiguration",
|
|
56
|
+
"setCameraConfiguration",
|
|
57
|
+
"cameraData",
|
|
58
|
+
] as const;
|
|
59
|
+
export type CameraMessageType = (typeof CameraMessageTypes)[number];
|
|
60
|
+
|
|
61
|
+
export type CameraConfiguration = {
|
|
62
|
+
[cameraConfigurationType in CameraConfigurationType]?: number;
|
|
63
|
+
};
|
|
64
|
+
export type CameraConfigurationRanges = {
|
|
65
|
+
[cameraConfigurationType in CameraConfigurationType]: {
|
|
66
|
+
min: number;
|
|
67
|
+
max: number;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const RequiredCameraMessageTypes: CameraMessageType[] = [
|
|
72
|
+
"getCameraConfiguration",
|
|
73
|
+
"cameraStatus",
|
|
74
|
+
] as const;
|
|
75
|
+
|
|
76
|
+
export const CameraEventTypes = [
|
|
77
|
+
...CameraMessageTypes,
|
|
78
|
+
"cameraImageProgress",
|
|
79
|
+
"cameraImage",
|
|
80
|
+
] as const;
|
|
81
|
+
export type CameraEventType = (typeof CameraEventTypes)[number];
|
|
82
|
+
|
|
83
|
+
export interface CameraEventMessages {
|
|
84
|
+
cameraStatus: {
|
|
85
|
+
cameraStatus: CameraStatus;
|
|
86
|
+
previousCameraStatus: CameraStatus;
|
|
87
|
+
};
|
|
88
|
+
getCameraConfiguration: { cameraConfiguration: CameraConfiguration };
|
|
89
|
+
cameraImageProgress: { progress: number; type: CameraDataType };
|
|
90
|
+
cameraImage: { blob: Blob; url: string };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type CameraEventDispatcher = EventDispatcher<
|
|
94
|
+
Device,
|
|
95
|
+
CameraEventType,
|
|
96
|
+
CameraEventMessages
|
|
97
|
+
>;
|
|
98
|
+
export type SendCameraMessageCallback = SendMessageCallback<CameraMessageType>;
|
|
99
|
+
|
|
100
|
+
class CameraManager {
|
|
101
|
+
constructor() {
|
|
102
|
+
autoBind(this);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
sendMessage!: SendCameraMessageCallback;
|
|
106
|
+
|
|
107
|
+
eventDispatcher!: CameraEventDispatcher;
|
|
108
|
+
get #dispatchEvent() {
|
|
109
|
+
return this.eventDispatcher.dispatchEvent;
|
|
110
|
+
}
|
|
111
|
+
get waitForEvent() {
|
|
112
|
+
return this.eventDispatcher.waitForEvent;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
requestRequiredInformation() {
|
|
116
|
+
_console.log("requesting required camera information");
|
|
117
|
+
const messages = RequiredCameraMessageTypes.map((messageType) => ({
|
|
118
|
+
type: messageType,
|
|
119
|
+
}));
|
|
120
|
+
this.sendMessage(messages, false);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// CAMERA STATUS
|
|
124
|
+
#cameraStatus!: CameraStatus;
|
|
125
|
+
get cameraStatus() {
|
|
126
|
+
return this.#cameraStatus;
|
|
127
|
+
}
|
|
128
|
+
#parseCameraStatus(dataView: DataView) {
|
|
129
|
+
const cameraStatusIndex = dataView.getUint8(0);
|
|
130
|
+
const newCameraStatus = CameraStatuses[cameraStatusIndex];
|
|
131
|
+
this.#updateCameraStatus(newCameraStatus);
|
|
132
|
+
}
|
|
133
|
+
#updateCameraStatus(newCameraStatus: CameraStatus) {
|
|
134
|
+
_console.assertEnumWithError(newCameraStatus, CameraStatuses);
|
|
135
|
+
if (newCameraStatus == this.#cameraStatus) {
|
|
136
|
+
_console.log(`redundant cameraStatus ${newCameraStatus}`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const previousCameraStatus = this.#cameraStatus;
|
|
140
|
+
this.#cameraStatus = newCameraStatus;
|
|
141
|
+
_console.log(`updated cameraStatus to "${this.cameraStatus}"`);
|
|
142
|
+
this.#dispatchEvent("cameraStatus", {
|
|
143
|
+
cameraStatus: this.cameraStatus,
|
|
144
|
+
previousCameraStatus,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
if (
|
|
148
|
+
this.#cameraStatus != "takingPicture" &&
|
|
149
|
+
this.#imageProgress > 0 &&
|
|
150
|
+
!this.#didBuildImage
|
|
151
|
+
) {
|
|
152
|
+
this.#buildImage();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// CAMERA COMMAND
|
|
157
|
+
async #sendCameraCommand(command: CameraCommand, sendImmediately?: boolean) {
|
|
158
|
+
_console.assertEnumWithError(command, CameraCommands);
|
|
159
|
+
_console.log(`sending camera command "${command}"`);
|
|
160
|
+
|
|
161
|
+
const promise = this.waitForEvent("cameraStatus");
|
|
162
|
+
_console.log(`setting command "${command}"`);
|
|
163
|
+
const commandEnum = CameraCommands.indexOf(command);
|
|
164
|
+
this.sendMessage(
|
|
165
|
+
[
|
|
166
|
+
{
|
|
167
|
+
type: "cameraCommand",
|
|
168
|
+
data: Uint8Array.from([commandEnum]).buffer,
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
sendImmediately
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
await promise;
|
|
175
|
+
}
|
|
176
|
+
#assertIsAsleep() {
|
|
177
|
+
_console.assertWithError(
|
|
178
|
+
this.#cameraStatus == "asleep",
|
|
179
|
+
`camera is not asleep - currently ${this.#cameraStatus}`
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
#assertIsAwake() {
|
|
183
|
+
_console.assertWithError(
|
|
184
|
+
this.#cameraStatus != "asleep",
|
|
185
|
+
`camera is not awake - currently ${this.#cameraStatus}`
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
async focus() {
|
|
189
|
+
this.#assertIsAwake();
|
|
190
|
+
await this.#sendCameraCommand("focus");
|
|
191
|
+
}
|
|
192
|
+
async takePicture() {
|
|
193
|
+
this.#assertIsAwake();
|
|
194
|
+
await this.#sendCameraCommand("takePicture");
|
|
195
|
+
}
|
|
196
|
+
async stop() {
|
|
197
|
+
this.#assertIsAwake();
|
|
198
|
+
await this.#sendCameraCommand("stop");
|
|
199
|
+
}
|
|
200
|
+
async sleep() {
|
|
201
|
+
this.#assertIsAwake();
|
|
202
|
+
await this.#sendCameraCommand("sleep");
|
|
203
|
+
}
|
|
204
|
+
async wake() {
|
|
205
|
+
this.#assertIsAsleep();
|
|
206
|
+
await this.#sendCameraCommand("wake");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// CAMERA DATA
|
|
210
|
+
#parseCameraData(dataView: DataView) {
|
|
211
|
+
_console.log("parsing camera data", dataView);
|
|
212
|
+
parseMessage(
|
|
213
|
+
dataView,
|
|
214
|
+
CameraDataTypes,
|
|
215
|
+
this.#onCameraData.bind(this),
|
|
216
|
+
null,
|
|
217
|
+
true
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
#onCameraData(cameraDataType: CameraDataType, dataView: DataView) {
|
|
221
|
+
_console.log({ cameraDataType, dataView });
|
|
222
|
+
switch (cameraDataType) {
|
|
223
|
+
case "headerSize":
|
|
224
|
+
this.#headerSize = dataView.getUint16(0, true);
|
|
225
|
+
_console.log({ headerSize: this.#headerSize });
|
|
226
|
+
this.#headerData = undefined;
|
|
227
|
+
this.#headerProgress == 0;
|
|
228
|
+
break;
|
|
229
|
+
case "header":
|
|
230
|
+
this.#headerData = concatenateArrayBuffers(this.#headerData, dataView);
|
|
231
|
+
_console.log({ headerData: this.#headerData });
|
|
232
|
+
this.#headerProgress = this.#headerData?.byteLength / this.#headerSize;
|
|
233
|
+
_console.log({ headerProgress: this.#headerProgress });
|
|
234
|
+
this.#dispatchEvent("cameraImageProgress", {
|
|
235
|
+
progress: this.#headerProgress,
|
|
236
|
+
type: "header",
|
|
237
|
+
});
|
|
238
|
+
if (this.#headerProgress == 1) {
|
|
239
|
+
_console.log("finished getting header data");
|
|
240
|
+
}
|
|
241
|
+
break;
|
|
242
|
+
case "imageSize":
|
|
243
|
+
this.#imageSize = dataView.getUint16(0, true);
|
|
244
|
+
_console.log({ imageSize: this.#imageSize });
|
|
245
|
+
this.#imageData = undefined;
|
|
246
|
+
this.#imageProgress == 0;
|
|
247
|
+
this.#didBuildImage = false;
|
|
248
|
+
break;
|
|
249
|
+
case "image":
|
|
250
|
+
this.#imageData = concatenateArrayBuffers(this.#imageData, dataView);
|
|
251
|
+
_console.log({ imageData: this.#imageData });
|
|
252
|
+
this.#imageProgress = this.#imageData?.byteLength / this.#imageSize;
|
|
253
|
+
_console.log({ imageProgress: this.#imageProgress });
|
|
254
|
+
if (this.#imageProgress == 1) {
|
|
255
|
+
_console.log("finished getting image data");
|
|
256
|
+
if (this.#headerProgress == 1) {
|
|
257
|
+
this.#buildImage();
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
this.#dispatchEvent("cameraImageProgress", {
|
|
261
|
+
progress: this.#imageProgress,
|
|
262
|
+
type: "image",
|
|
263
|
+
});
|
|
264
|
+
break;
|
|
265
|
+
case "footerSize":
|
|
266
|
+
this.#footerSize = dataView.getUint16(0, true);
|
|
267
|
+
_console.log({ footerSize: this.#footerSize });
|
|
268
|
+
this.#footerData = undefined;
|
|
269
|
+
this.#footerProgress == 0;
|
|
270
|
+
break;
|
|
271
|
+
case "footer":
|
|
272
|
+
this.#footerData = concatenateArrayBuffers(this.#footerData, dataView);
|
|
273
|
+
_console.log({ footerData: this.#footerData });
|
|
274
|
+
this.#footerProgress = this.#footerData?.byteLength / this.#footerSize;
|
|
275
|
+
_console.log({ footerProgress: this.#footerProgress });
|
|
276
|
+
this.#dispatchEvent("cameraImageProgress", {
|
|
277
|
+
progress: this.#footerProgress,
|
|
278
|
+
type: "footer",
|
|
279
|
+
});
|
|
280
|
+
if (this.#footerProgress == 1) {
|
|
281
|
+
_console.log("finished getting footer data");
|
|
282
|
+
if (this.#imageProgress == 1) {
|
|
283
|
+
this.#buildImage();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
#headerSize: number = 0;
|
|
291
|
+
#headerData?: ArrayBuffer;
|
|
292
|
+
#headerProgress: number = 0;
|
|
293
|
+
|
|
294
|
+
#imageSize: number = 0;
|
|
295
|
+
#imageData?: ArrayBuffer;
|
|
296
|
+
#imageProgress: number = 0;
|
|
297
|
+
|
|
298
|
+
#footerSize: number = 0;
|
|
299
|
+
#footerData?: ArrayBuffer;
|
|
300
|
+
#footerProgress: number = 0;
|
|
301
|
+
|
|
302
|
+
#didBuildImage: boolean = false;
|
|
303
|
+
#buildImage() {
|
|
304
|
+
_console.log("building image...");
|
|
305
|
+
const imageData = concatenateArrayBuffers(
|
|
306
|
+
this.#headerData,
|
|
307
|
+
this.#imageData,
|
|
308
|
+
this.#footerData
|
|
309
|
+
);
|
|
310
|
+
_console.log({ imageData });
|
|
311
|
+
|
|
312
|
+
let blob = new Blob([imageData], { type: "image/jpeg" });
|
|
313
|
+
_console.log("created blob", blob);
|
|
314
|
+
|
|
315
|
+
const url = URL.createObjectURL(blob);
|
|
316
|
+
_console.log("created url", url);
|
|
317
|
+
|
|
318
|
+
// FILL - header stuff
|
|
319
|
+
|
|
320
|
+
this.#dispatchEvent("cameraImage", { url, blob });
|
|
321
|
+
|
|
322
|
+
this.#didBuildImage = true;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// CONFIG
|
|
326
|
+
#cameraConfiguration: CameraConfiguration = {};
|
|
327
|
+
get cameraConfiguration() {
|
|
328
|
+
return this.#cameraConfiguration;
|
|
329
|
+
}
|
|
330
|
+
#availableCameraConfigurationTypes!: CameraConfigurationType[];
|
|
331
|
+
get availableCameraConfigurationTypes() {
|
|
332
|
+
return this.#availableCameraConfigurationTypes;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
#cameraConfigurationRanges: CameraConfigurationRanges = {
|
|
336
|
+
resolution: { min: 100, max: 720 },
|
|
337
|
+
qualityFactor: { min: 15, max: 60 },
|
|
338
|
+
shutter: { min: 4, max: 16383 },
|
|
339
|
+
gain: { min: 1, max: 248 },
|
|
340
|
+
redGain: { min: 0, max: 1023 },
|
|
341
|
+
greenGain: { min: 0, max: 1023 },
|
|
342
|
+
blueGain: { min: 0, max: 1023 },
|
|
343
|
+
};
|
|
344
|
+
get cameraConfigurationRanges() {
|
|
345
|
+
return this.#cameraConfigurationRanges;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
#parseCameraConfiguration(dataView: DataView) {
|
|
349
|
+
const parsedCameraConfiguration: CameraConfiguration = {};
|
|
350
|
+
|
|
351
|
+
let byteOffset = 0;
|
|
352
|
+
while (byteOffset < dataView.byteLength) {
|
|
353
|
+
const cameraConfigurationTypeIndex = dataView.getUint8(byteOffset++);
|
|
354
|
+
const cameraConfigurationType =
|
|
355
|
+
CameraConfigurationTypes[cameraConfigurationTypeIndex];
|
|
356
|
+
_console.assertWithError(
|
|
357
|
+
cameraConfigurationType,
|
|
358
|
+
`invalid cameraConfigurationTypeIndex ${cameraConfigurationTypeIndex}`
|
|
359
|
+
);
|
|
360
|
+
parsedCameraConfiguration[cameraConfigurationType] = dataView.getUint16(
|
|
361
|
+
byteOffset,
|
|
362
|
+
true
|
|
363
|
+
);
|
|
364
|
+
byteOffset += 2;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
_console.log({ parsedCameraConfiguration });
|
|
368
|
+
this.#availableCameraConfigurationTypes = Object.keys(
|
|
369
|
+
parsedCameraConfiguration
|
|
370
|
+
) as CameraConfigurationType[];
|
|
371
|
+
this.#cameraConfiguration = parsedCameraConfiguration;
|
|
372
|
+
this.#dispatchEvent("getCameraConfiguration", {
|
|
373
|
+
cameraConfiguration: this.#cameraConfiguration,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
#isCameraConfigurationRedundant(cameraConfiguration: CameraConfiguration) {
|
|
378
|
+
let cameraConfigurationTypes = Object.keys(
|
|
379
|
+
cameraConfiguration
|
|
380
|
+
) as CameraConfigurationType[];
|
|
381
|
+
return cameraConfigurationTypes.every((cameraConfigurationType) => {
|
|
382
|
+
return (
|
|
383
|
+
this.cameraConfiguration[cameraConfigurationType] ==
|
|
384
|
+
cameraConfiguration[cameraConfigurationType]
|
|
385
|
+
);
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
async setCameraConfiguration(newCameraConfiguration: CameraConfiguration) {
|
|
389
|
+
_console.log({ newCameraConfiguration });
|
|
390
|
+
if (this.#isCameraConfigurationRedundant(newCameraConfiguration)) {
|
|
391
|
+
_console.log("redundant camera configuration");
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const setCameraConfigurationData = this.#createData(newCameraConfiguration);
|
|
395
|
+
_console.log({ setCameraConfigurationData });
|
|
396
|
+
|
|
397
|
+
const promise = this.waitForEvent("getCameraConfiguration");
|
|
398
|
+
this.sendMessage([
|
|
399
|
+
{
|
|
400
|
+
type: "setCameraConfiguration",
|
|
401
|
+
data: setCameraConfigurationData.buffer,
|
|
402
|
+
},
|
|
403
|
+
]);
|
|
404
|
+
await promise;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
#assertAvailableCameraConfigurationType(
|
|
408
|
+
cameraConfigurationType: CameraConfigurationType
|
|
409
|
+
) {
|
|
410
|
+
_console.assertWithError(
|
|
411
|
+
this.#availableCameraConfigurationTypes,
|
|
412
|
+
"must get initial cameraConfiguration"
|
|
413
|
+
);
|
|
414
|
+
const isCameraConfigurationTypeAvailable =
|
|
415
|
+
this.#availableCameraConfigurationTypes?.includes(
|
|
416
|
+
cameraConfigurationType
|
|
417
|
+
);
|
|
418
|
+
_console.assertWithError(
|
|
419
|
+
isCameraConfigurationTypeAvailable,
|
|
420
|
+
`unavailable camera configuration type "${cameraConfigurationType}"`
|
|
421
|
+
);
|
|
422
|
+
return isCameraConfigurationTypeAvailable;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
static AssertValidCameraConfigurationType(
|
|
426
|
+
cameraConfigurationType: CameraConfigurationType
|
|
427
|
+
) {
|
|
428
|
+
_console.assertEnumWithError(
|
|
429
|
+
cameraConfigurationType,
|
|
430
|
+
CameraConfigurationTypes
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
static AssertValidCameraConfigurationTypeEnum(
|
|
434
|
+
cameraConfigurationTypeEnum: number
|
|
435
|
+
) {
|
|
436
|
+
_console.assertTypeWithError(cameraConfigurationTypeEnum, "number");
|
|
437
|
+
_console.assertWithError(
|
|
438
|
+
cameraConfigurationTypeEnum in CameraConfigurationTypes,
|
|
439
|
+
`invalid cameraConfigurationTypeEnum ${cameraConfigurationTypeEnum}`
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
#createData(cameraConfiguration: CameraConfiguration) {
|
|
444
|
+
let cameraConfigurationTypes = Object.keys(
|
|
445
|
+
cameraConfiguration
|
|
446
|
+
) as CameraConfigurationType[];
|
|
447
|
+
cameraConfigurationTypes = cameraConfigurationTypes.filter(
|
|
448
|
+
(cameraConfigurationType) =>
|
|
449
|
+
this.#assertAvailableCameraConfigurationType(cameraConfigurationType)
|
|
450
|
+
);
|
|
451
|
+
|
|
452
|
+
const dataView = new DataView(
|
|
453
|
+
new ArrayBuffer(cameraConfigurationTypes.length * 3)
|
|
454
|
+
);
|
|
455
|
+
cameraConfigurationTypes.forEach((cameraConfigurationType, index) => {
|
|
456
|
+
CameraManager.AssertValidCameraConfigurationType(cameraConfigurationType);
|
|
457
|
+
const cameraConfigurationTypeEnum = CameraConfigurationTypes.indexOf(
|
|
458
|
+
cameraConfigurationType
|
|
459
|
+
);
|
|
460
|
+
dataView.setUint8(index * 3, cameraConfigurationTypeEnum);
|
|
461
|
+
|
|
462
|
+
const value = cameraConfiguration[cameraConfigurationType]!;
|
|
463
|
+
//this.#assertValidCameraConfigurationValue(cameraConfigurationType, value);
|
|
464
|
+
dataView.setUint16(index * 3 + 1, value, true);
|
|
465
|
+
});
|
|
466
|
+
_console.log({ sensorConfigurationData: dataView });
|
|
467
|
+
return dataView;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// MESSAGE
|
|
471
|
+
parseMessage(messageType: CameraMessageType, dataView: DataView) {
|
|
472
|
+
_console.log({ messageType, dataView });
|
|
473
|
+
|
|
474
|
+
switch (messageType) {
|
|
475
|
+
case "cameraStatus":
|
|
476
|
+
this.#parseCameraStatus(dataView);
|
|
477
|
+
break;
|
|
478
|
+
case "getCameraConfiguration":
|
|
479
|
+
case "setCameraConfiguration":
|
|
480
|
+
this.#parseCameraConfiguration(dataView);
|
|
481
|
+
break;
|
|
482
|
+
case "cameraData":
|
|
483
|
+
this.#parseCameraData(dataView);
|
|
484
|
+
break;
|
|
485
|
+
default:
|
|
486
|
+
throw Error(`uncaught messageType ${messageType}`);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
clear() {
|
|
491
|
+
// @ts-ignore
|
|
492
|
+
this.#cameraStatus = undefined;
|
|
493
|
+
this.#headerProgress = 0;
|
|
494
|
+
this.#imageProgress = 0;
|
|
495
|
+
this.#footerProgress = 0;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
export default CameraManager;
|