@hangtime/grip-connect 0.3.5 → 0.3.7
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/dist/battery.d.ts +7 -0
- package/dist/battery.js +25 -0
- package/dist/calibration.d.ts +7 -0
- package/dist/calibration.js +19 -0
- package/dist/characteristic.d.ts +9 -0
- package/dist/characteristic.js +20 -0
- package/dist/commands/climbro.d.ts +6 -0
- package/dist/commands/climbro.js +5 -0
- package/dist/commands/entralpi.d.ts +6 -0
- package/dist/commands/entralpi.js +5 -0
- package/dist/commands/index.d.ts +6 -0
- package/dist/commands/index.js +6 -0
- package/dist/commands/kilterboard.d.ts +23 -0
- package/dist/commands/kilterboard.js +24 -0
- package/dist/commands/motherboard.d.ts +6 -0
- package/dist/commands/motherboard.js +13 -0
- package/dist/commands/mysmartboard.d.ts +6 -0
- package/dist/commands/mysmartboard.js +5 -0
- package/dist/commands/progressor.d.ts +17 -0
- package/dist/commands/progressor.js +30 -0
- package/dist/commands/wh-c06.d.ts +6 -0
- package/dist/commands/wh-c06.js +5 -0
- package/dist/connect.d.ts +7 -0
- package/dist/connect.js +159 -0
- package/dist/data/entralpi.d.ts +5 -0
- package/dist/data/entralpi.js +30 -0
- package/dist/data/index.d.ts +4 -0
- package/dist/data/index.js +4 -0
- package/dist/data/motherboard.d.ts +6 -0
- package/dist/data/motherboard.js +133 -0
- package/dist/data/progressor.d.ts +5 -0
- package/dist/data/progressor.js +72 -0
- package/dist/data/wh-c06.d.ts +5 -0
- package/dist/data/wh-c06.js +35 -0
- package/dist/devices/climbro.d.ts +6 -0
- package/dist/devices/climbro.js +8 -0
- package/dist/devices/entralpi.d.ts +5 -0
- package/dist/devices/entralpi.js +59 -0
- package/dist/devices/index.d.ts +7 -0
- package/dist/devices/index.js +7 -0
- package/dist/devices/kilterboard.d.ts +6 -0
- package/dist/devices/kilterboard.js +30 -0
- package/dist/devices/motherboard.d.ts +5 -0
- package/dist/devices/motherboard.js +81 -0
- package/dist/devices/mysmartboard.d.ts +6 -0
- package/dist/devices/mysmartboard.js +8 -0
- package/dist/devices/progressor.d.ts +5 -0
- package/dist/devices/progressor.js +37 -0
- package/dist/devices/wh-c06.d.ts +6 -0
- package/dist/devices/wh-c06.js +17 -0
- package/dist/disconnect.d.ts +6 -0
- package/dist/disconnect.js +12 -0
- package/dist/download.d.ts +10 -0
- package/dist/download.js +50 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +22 -0
- package/dist/info.d.ts +7 -0
- package/dist/info.js +30 -0
- package/dist/is-connected.d.ts +7 -0
- package/dist/is-connected.js +13 -0
- package/dist/led.d.ts +20 -0
- package/dist/led.js +192 -0
- package/dist/notify.d.ts +16 -0
- package/dist/notify.js +14 -0
- package/dist/read.d.ts +10 -0
- package/dist/read.js +49 -0
- package/dist/stop.d.ts +7 -0
- package/dist/stop.js +21 -0
- package/dist/stream.d.ts +8 -0
- package/dist/stream.js +41 -0
- package/dist/struct/index.d.ts +9 -0
- package/dist/struct/index.js +203 -0
- package/dist/tare.d.ts +12 -0
- package/dist/tare.js +70 -0
- package/dist/types/commands.d.ts +18 -0
- package/dist/types/commands.js +1 -0
- package/dist/types/devices.d.ts +38 -0
- package/dist/types/devices.js +1 -0
- package/dist/types/download.d.ts +15 -0
- package/dist/types/download.js +1 -0
- package/dist/types/notify.d.ts +14 -0
- package/dist/types/notify.js +1 -0
- package/dist/write.d.ts +16 -0
- package/dist/write.js +57 -0
- package/package.json +3 -2
- package/src/connect.ts +1 -4
- package/src/data/index.ts +7 -0
- package/src/devices/motherboard.ts +6 -6
- package/src/is-connected.ts +1 -1
- package/src/led.ts +29 -11
- package/tsconfig.json +3 -1
package/dist/led.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { write } from "./write";
|
|
2
|
+
import { isConnected } from "./is-connected";
|
|
3
|
+
import { KilterBoard, Motherboard } from "./devices";
|
|
4
|
+
import { KilterBoardPacket } from "./commands/kilterboard";
|
|
5
|
+
/**
|
|
6
|
+
* Maximum length of the message body for byte wrapping.
|
|
7
|
+
*/
|
|
8
|
+
const MESSAGE_BODY_MAX_LENGTH = 255;
|
|
9
|
+
/**
|
|
10
|
+
* Maximum length of the the bluetooth chunk.
|
|
11
|
+
*/
|
|
12
|
+
const MAX_BLUETOOTH_MESSAGE_SIZE = 20;
|
|
13
|
+
/**
|
|
14
|
+
* Calculates the checksum for a byte array by summing up all bytes ot hre packet in a single-byte variable.
|
|
15
|
+
* @param data - The array of bytes to calculate the checksum for.
|
|
16
|
+
* @returns The calculated checksum value.
|
|
17
|
+
*/
|
|
18
|
+
function checksum(data) {
|
|
19
|
+
let i = 0;
|
|
20
|
+
for (const value of data) {
|
|
21
|
+
i = (i + value) & 255;
|
|
22
|
+
}
|
|
23
|
+
return ~i & 255;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Wraps a byte array with header and footer bytes for transmission.
|
|
27
|
+
* @param data - The array of bytes to wrap.
|
|
28
|
+
* @returns The wrapped byte array.
|
|
29
|
+
*/
|
|
30
|
+
function wrapBytes(data) {
|
|
31
|
+
if (data.length > MESSAGE_BODY_MAX_LENGTH) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
- 0x1
|
|
36
|
+
- len(packets)
|
|
37
|
+
- checksum(packets)
|
|
38
|
+
- 0x2
|
|
39
|
+
- *packets
|
|
40
|
+
- 0x3
|
|
41
|
+
|
|
42
|
+
First byte is always 1, the second is a number of packets, then checksum, then 2, packets themselves, and finally 3.
|
|
43
|
+
*/
|
|
44
|
+
return [1, data.length, checksum(data), 2, ...data, 3];
|
|
45
|
+
}
|
|
46
|
+
class ClimbPlacement {
|
|
47
|
+
position;
|
|
48
|
+
role_id;
|
|
49
|
+
constructor(position, role_id) {
|
|
50
|
+
this.position = position;
|
|
51
|
+
this.role_id = role_id;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Encodes a position into a byte array.
|
|
56
|
+
* The lowest 8 bits of the position get put in the first byte of the group.
|
|
57
|
+
* The highest 8 bits of the position get put in the second byte of the group.
|
|
58
|
+
* @param position - The position to encode.
|
|
59
|
+
* @returns The encoded byte array representing the position.
|
|
60
|
+
*/
|
|
61
|
+
function encodePosition(position) {
|
|
62
|
+
const position1 = position & 255;
|
|
63
|
+
const position2 = (position & 65280) >> 8;
|
|
64
|
+
return [position1, position2];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Encodes a color string into a numeric representation.
|
|
68
|
+
* The rgb color, 3 bits for the R and G components, 2 bits for the B component, with the 3 R bits occupying the high end of the byte and the 2 B bits in the low end (hence 3 G bits in the middle).
|
|
69
|
+
* @param color - The color string in hexadecimal format (e.g., 'FFFFFF').
|
|
70
|
+
* @returns The encoded /compressed color value.
|
|
71
|
+
*/
|
|
72
|
+
function encodeColor(color) {
|
|
73
|
+
const substring = color.substring(0, 2);
|
|
74
|
+
const substring2 = color.substring(2, 4);
|
|
75
|
+
const parsedSubstring = parseInt(substring, 16) / 32;
|
|
76
|
+
const parsedSubstring2 = parseInt(substring2, 16) / 32;
|
|
77
|
+
const parsedResult = (parsedSubstring << 5) | (parsedSubstring2 << 2);
|
|
78
|
+
const substring3 = color.substring(4, 6);
|
|
79
|
+
const parsedSubstring3 = parseInt(substring3, 16) / 64;
|
|
80
|
+
const finalParsedResult = parsedResult | parsedSubstring3;
|
|
81
|
+
return finalParsedResult;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Encodes a placement (requires a 16-bit position and a 24-bit rgb color. ) into a byte array.
|
|
85
|
+
* @param position - The position to encode.
|
|
86
|
+
* @param ledColor - The color of the LED in hexadecimal format (e.g., 'FFFFFF').
|
|
87
|
+
* @returns The encoded byte array representing the placement.
|
|
88
|
+
*/
|
|
89
|
+
function encodePlacement(position, ledColor) {
|
|
90
|
+
return [...encodePosition(position), encodeColor(ledColor)];
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Prepares byte arrays for transmission based on a list of climb placements.
|
|
94
|
+
* @param climbPlacementList - The list of climb placements containing position and role ID.
|
|
95
|
+
* @returns The final byte array ready for transmission.
|
|
96
|
+
*/
|
|
97
|
+
export function prepBytesV3(climbPlacementList) {
|
|
98
|
+
const resultArray = [];
|
|
99
|
+
let tempArray = [KilterBoardPacket.V3_MIDDLE];
|
|
100
|
+
for (const climbPlacement of climbPlacementList) {
|
|
101
|
+
if (tempArray.length + 3 > MESSAGE_BODY_MAX_LENGTH) {
|
|
102
|
+
resultArray.push(tempArray);
|
|
103
|
+
tempArray = [KilterBoardPacket.V3_MIDDLE];
|
|
104
|
+
}
|
|
105
|
+
const ledColor = climbPlacement.role_id;
|
|
106
|
+
const encodedPlacement = encodePlacement(climbPlacement.position, ledColor);
|
|
107
|
+
tempArray.push(...encodedPlacement);
|
|
108
|
+
}
|
|
109
|
+
resultArray.push(tempArray);
|
|
110
|
+
if (resultArray.length === 1) {
|
|
111
|
+
resultArray[0][0] = KilterBoardPacket.V3_ONLY;
|
|
112
|
+
}
|
|
113
|
+
else if (resultArray.length > 1) {
|
|
114
|
+
resultArray[0][0] = KilterBoardPacket.V3_FIRST;
|
|
115
|
+
resultArray[resultArray.length - 1][0] = KilterBoardPacket.V3_LAST;
|
|
116
|
+
}
|
|
117
|
+
const finalResultArray = [];
|
|
118
|
+
for (const currentArray of resultArray) {
|
|
119
|
+
finalResultArray.push(...wrapBytes(currentArray));
|
|
120
|
+
}
|
|
121
|
+
return finalResultArray;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Splits a collection into slices of the specified length.
|
|
125
|
+
* https://github.com/ramda/ramda/blob/master/source/splitEvery.js
|
|
126
|
+
* @param {Number} n
|
|
127
|
+
* @param {Array} list
|
|
128
|
+
* @return {Array}
|
|
129
|
+
*/
|
|
130
|
+
function splitEvery(n, list) {
|
|
131
|
+
if (n <= 0) {
|
|
132
|
+
throw new Error("First argument to splitEvery must be a positive integer");
|
|
133
|
+
}
|
|
134
|
+
const result = [];
|
|
135
|
+
let idx = 0;
|
|
136
|
+
while (idx < list.length) {
|
|
137
|
+
result.push(list.slice(idx, (idx += n)));
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The kilter board only supports messages of 20 bytes
|
|
143
|
+
* at a time. This method splits a full message into parts
|
|
144
|
+
* of 20 bytes
|
|
145
|
+
*
|
|
146
|
+
* @param buffer
|
|
147
|
+
*/
|
|
148
|
+
const splitMessages = (buffer) => splitEvery(MAX_BLUETOOTH_MESSAGE_SIZE, buffer).map((arr) => new Uint8Array(arr));
|
|
149
|
+
/**
|
|
150
|
+
* Sends a series of messages to a device.
|
|
151
|
+
*/
|
|
152
|
+
async function writeMessageSeries(messages) {
|
|
153
|
+
for (const message of messages) {
|
|
154
|
+
await write(KilterBoard, "uart", "tx", message);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Sets the LEDs on the specified device.
|
|
159
|
+
* @param {Device} board - The device on which to set the LEDs.
|
|
160
|
+
* @param {ClimbPlacement[]} [placement] - An optional array of climb placements for LED positioning.
|
|
161
|
+
* @returns {Promise<number[] | undefined>} A promise that resolves with the payload array if LED settings were applied, or `undefined` if no action was taken.
|
|
162
|
+
*/
|
|
163
|
+
export const led = async (board, placement) => {
|
|
164
|
+
// Check if the filter contains the Aurora Climbing Advertising service
|
|
165
|
+
const AuroraUUID = "4488b571-7806-4df6-bcff-a2897e4953ff";
|
|
166
|
+
if (board.filters.some((filter) => filter.services?.includes(AuroraUUID))) {
|
|
167
|
+
// The Aurora Boards needs a LED / Postion Placememnet Array
|
|
168
|
+
if (placement) {
|
|
169
|
+
// Prepares byte arrays for transmission based on a list of climb placements.
|
|
170
|
+
const payload = prepBytesV3(placement);
|
|
171
|
+
// Sends the payload to the device by splitting it into messages and writing each message.
|
|
172
|
+
if (isConnected(board)) {
|
|
173
|
+
writeMessageSeries(splitMessages(payload));
|
|
174
|
+
}
|
|
175
|
+
return payload;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (board.filters.some((filter) => filter.name === "Motherboard")) {
|
|
179
|
+
console.log("Green");
|
|
180
|
+
await write(Motherboard, "led", "red", new Uint8Array([0x00]));
|
|
181
|
+
await write(Motherboard, "led", "green", new Uint8Array([0x01]), 2500);
|
|
182
|
+
console.log("Red");
|
|
183
|
+
await write(Motherboard, "led", "red", new Uint8Array([0x01]));
|
|
184
|
+
await write(Motherboard, "led", "green", new Uint8Array([0x00]), 2500);
|
|
185
|
+
console.log("Orage");
|
|
186
|
+
await write(Motherboard, "led", "red", new Uint8Array([0x01]));
|
|
187
|
+
await write(Motherboard, "led", "green", new Uint8Array([0x01]), 2500);
|
|
188
|
+
console.log("Off");
|
|
189
|
+
await write(Motherboard, "led", "red", new Uint8Array([0x00]));
|
|
190
|
+
await write(Motherboard, "led", "green", new Uint8Array([0x00]), 2500);
|
|
191
|
+
}
|
|
192
|
+
};
|
package/dist/notify.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { massObject } from "./types/notify";
|
|
2
|
+
/** Define the type for the callback function */
|
|
3
|
+
type NotifyCallback = (data: massObject) => void;
|
|
4
|
+
/**
|
|
5
|
+
* Defines the type for the callback function.
|
|
6
|
+
* @callback NotifyCallback
|
|
7
|
+
* @param {massObject} data - The data passed to the callback.
|
|
8
|
+
*/
|
|
9
|
+
export declare let notifyCallback: NotifyCallback;
|
|
10
|
+
/**
|
|
11
|
+
* Sets the callback function to be called when notifications are received.
|
|
12
|
+
* @param {NotifyCallback} callback - The callback function to be set.
|
|
13
|
+
* @returns {void}
|
|
14
|
+
*/
|
|
15
|
+
export declare const notify: (callback: NotifyCallback) => void;
|
|
16
|
+
export {};
|
package/dist/notify.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defines the type for the callback function.
|
|
3
|
+
* @callback NotifyCallback
|
|
4
|
+
* @param {massObject} data - The data passed to the callback.
|
|
5
|
+
*/
|
|
6
|
+
export let notifyCallback;
|
|
7
|
+
/**
|
|
8
|
+
* Sets the callback function to be called when notifications are received.
|
|
9
|
+
* @param {NotifyCallback} callback - The callback function to be set.
|
|
10
|
+
* @returns {void}
|
|
11
|
+
*/
|
|
12
|
+
export const notify = (callback) => {
|
|
13
|
+
notifyCallback = callback;
|
|
14
|
+
};
|
package/dist/read.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Device } from "./types/devices";
|
|
2
|
+
/**
|
|
3
|
+
* Reads the value of the specified characteristic from the device.
|
|
4
|
+
* @param {Device} board - The device to read from.
|
|
5
|
+
* @param {string} serviceId - The service ID where the characteristic belongs.
|
|
6
|
+
* @param {string} characteristicId - The characteristic ID to read from.
|
|
7
|
+
* @param {number} [duration=0] - The duration to wait before resolving the promise, in milliseconds.
|
|
8
|
+
* @returns {Promise<void>} A promise that resolves when the read operation is completed.
|
|
9
|
+
*/
|
|
10
|
+
export declare const read: (board: Device, serviceId: string, characteristicId: string, duration?: number) => Promise<void>;
|
package/dist/read.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { getCharacteristic } from "./characteristic";
|
|
2
|
+
import { isConnected } from "./is-connected";
|
|
3
|
+
/**
|
|
4
|
+
* Reads the value of the specified characteristic from the device.
|
|
5
|
+
* @param {Device} board - The device to read from.
|
|
6
|
+
* @param {string} serviceId - The service ID where the characteristic belongs.
|
|
7
|
+
* @param {string} characteristicId - The characteristic ID to read from.
|
|
8
|
+
* @param {number} [duration=0] - The duration to wait before resolving the promise, in milliseconds.
|
|
9
|
+
* @returns {Promise<void>} A promise that resolves when the read operation is completed.
|
|
10
|
+
*/
|
|
11
|
+
export const read = (board, serviceId, characteristicId, duration = 0) => {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
if (isConnected(board)) {
|
|
14
|
+
const characteristic = getCharacteristic(board, serviceId, characteristicId);
|
|
15
|
+
if (characteristic) {
|
|
16
|
+
characteristic
|
|
17
|
+
.readValue()
|
|
18
|
+
.then((value) => {
|
|
19
|
+
let decodedValue;
|
|
20
|
+
const decoder = new TextDecoder("utf-8");
|
|
21
|
+
switch (characteristicId) {
|
|
22
|
+
case "level":
|
|
23
|
+
// TODO: This is Motherboard specific.
|
|
24
|
+
decodedValue = value.getUint8(0);
|
|
25
|
+
break;
|
|
26
|
+
default:
|
|
27
|
+
decodedValue = decoder.decode(value);
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
// TODO: Create Read callback
|
|
31
|
+
console.log(decodedValue);
|
|
32
|
+
// Resolve after specified duration
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
resolve();
|
|
35
|
+
}, duration);
|
|
36
|
+
})
|
|
37
|
+
.catch((error) => {
|
|
38
|
+
reject(error);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
reject(new Error("Characteristic is undefined"));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
reject(new Error("Device is not connected"));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
};
|
package/dist/stop.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Device } from "./types/devices";
|
|
2
|
+
/**
|
|
3
|
+
* Stops the data stream on the specified device.
|
|
4
|
+
* @param {Device} board - The device to stop the stream on.
|
|
5
|
+
* @returns {Promise<void>} A promise that resolves when the stream is stopped.
|
|
6
|
+
*/
|
|
7
|
+
export declare const stop: (board: Device) => Promise<void>;
|
package/dist/stop.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { write } from "./write";
|
|
2
|
+
import { isConnected } from "./is-connected";
|
|
3
|
+
import { Motherboard, Progressor } from "./devices";
|
|
4
|
+
import { MotherboardCommands, ProgressorCommands } from "./commands";
|
|
5
|
+
/**
|
|
6
|
+
* Stops the data stream on the specified device.
|
|
7
|
+
* @param {Device} board - The device to stop the stream on.
|
|
8
|
+
* @returns {Promise<void>} A promise that resolves when the stream is stopped.
|
|
9
|
+
*/
|
|
10
|
+
export const stop = async (board) => {
|
|
11
|
+
if (isConnected(board)) {
|
|
12
|
+
if (board.filters.some((filter) => filter.name === "Motherboard")) {
|
|
13
|
+
// Stop stream on Motherboard
|
|
14
|
+
await write(Motherboard, "uart", "tx", MotherboardCommands.STOP_WEIGHT_MEAS, 0);
|
|
15
|
+
}
|
|
16
|
+
if (board.filters.some((filter) => filter.namePrefix === "Progressor")) {
|
|
17
|
+
// Stop stream on Progressor
|
|
18
|
+
await write(Progressor, "progressor", "tx", ProgressorCommands.STOP_WEIGHT_MEAS, 0);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
package/dist/stream.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Device } from "./types/devices";
|
|
2
|
+
/**
|
|
3
|
+
* Starts streaming data from the specified device.
|
|
4
|
+
* @param {Device} board - The device to stream data from.
|
|
5
|
+
* @param {number} [duration=0] - The duration of the stream in milliseconds. If set to 0, stream will continue indefinitely.
|
|
6
|
+
* @returns {Promise<void>} A promise that resolves when the streaming operation is completed.
|
|
7
|
+
*/
|
|
8
|
+
export declare const stream: (board: Device, duration?: number) => Promise<void>;
|
package/dist/stream.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { isConnected } from "./is-connected";
|
|
2
|
+
import { write } from "./write";
|
|
3
|
+
import { stop } from "./stop";
|
|
4
|
+
import { Motherboard, Progressor } from "./devices";
|
|
5
|
+
import { MotherboardCommands, ProgressorCommands } from "./commands";
|
|
6
|
+
import { emptyDownloadPackets } from "./download";
|
|
7
|
+
import { CALIBRATION } from "./data/motherboard";
|
|
8
|
+
import { calibration } from "./calibration";
|
|
9
|
+
/**
|
|
10
|
+
* Starts streaming data from the specified device.
|
|
11
|
+
* @param {Device} board - The device to stream data from.
|
|
12
|
+
* @param {number} [duration=0] - The duration of the stream in milliseconds. If set to 0, stream will continue indefinitely.
|
|
13
|
+
* @returns {Promise<void>} A promise that resolves when the streaming operation is completed.
|
|
14
|
+
*/
|
|
15
|
+
export const stream = async (board, duration = 0) => {
|
|
16
|
+
if (isConnected(board)) {
|
|
17
|
+
// Reset download packets
|
|
18
|
+
emptyDownloadPackets();
|
|
19
|
+
// Device specific logic
|
|
20
|
+
if (board.filters.some((filter) => filter.name === "Motherboard")) {
|
|
21
|
+
// Read calibration data if not already available
|
|
22
|
+
if (!CALIBRATION[0].length) {
|
|
23
|
+
await calibration(Motherboard);
|
|
24
|
+
}
|
|
25
|
+
// Start streaming data
|
|
26
|
+
await write(Motherboard, "uart", "tx", MotherboardCommands.START_WEIGHT_MEAS, duration);
|
|
27
|
+
// Stop streaming if duration is set
|
|
28
|
+
if (duration !== 0) {
|
|
29
|
+
await stop(Motherboard);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (board.filters.some((filter) => filter.namePrefix === "Progressor")) {
|
|
33
|
+
// Start streaming data
|
|
34
|
+
await write(Progressor, "progressor", "tx", ProgressorCommands.START_WEIGHT_MEAS, duration);
|
|
35
|
+
// Stop streaming if duration is set
|
|
36
|
+
if (duration !== 0) {
|
|
37
|
+
await stop(Progressor);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default function struct(format: string): Readonly<{
|
|
2
|
+
unpack: (arrb: ArrayBuffer) => unknown[];
|
|
3
|
+
pack: (...values: unknown[]) => ArrayBuffer;
|
|
4
|
+
unpack_from: (arrb: ArrayBuffer, offs: number) => unknown[];
|
|
5
|
+
pack_into: (arrb: ArrayBuffer, offs: number, ...values: unknown[]) => void;
|
|
6
|
+
iter_unpack: (arrb: ArrayBuffer) => IterableIterator<unknown[]>;
|
|
7
|
+
format: string;
|
|
8
|
+
size: number;
|
|
9
|
+
}>;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
const rechk = /^([<>])?(([1-9]\d*)?([xcbB?hHiIfdsp]))*$/;
|
|
2
|
+
const refmt = /([1-9]\d*)?([xcbB?hHiIfdsp])/g;
|
|
3
|
+
const str = (v, o, c) => String.fromCharCode(...Array.from(new Uint8Array(v.buffer, v.byteOffset + o, c)));
|
|
4
|
+
const rts = (v, o, c, s) => {
|
|
5
|
+
new Uint8Array(v.buffer, v.byteOffset + o, c).set(s.split("").map((str) => str.charCodeAt(0)));
|
|
6
|
+
};
|
|
7
|
+
const pst = (v, o, c) => str(v, o + 1, Math.min(v.getUint8(o), c - 1));
|
|
8
|
+
const tsp = (v, o, c, s) => {
|
|
9
|
+
v.setUint8(o, s.length);
|
|
10
|
+
rts(v, o + 1, c - 1, s);
|
|
11
|
+
};
|
|
12
|
+
const lut = (le) => ({
|
|
13
|
+
x: (c) => [
|
|
14
|
+
1,
|
|
15
|
+
c,
|
|
16
|
+
() => ({
|
|
17
|
+
u: () => undefined,
|
|
18
|
+
p: () => undefined,
|
|
19
|
+
}),
|
|
20
|
+
],
|
|
21
|
+
c: (c) => [
|
|
22
|
+
c,
|
|
23
|
+
1,
|
|
24
|
+
(o) => ({
|
|
25
|
+
u: (v) => str(v, o, 1),
|
|
26
|
+
p: (v, s) => {
|
|
27
|
+
rts(v, o, 1, s);
|
|
28
|
+
},
|
|
29
|
+
}),
|
|
30
|
+
],
|
|
31
|
+
"?": (c) => [
|
|
32
|
+
c,
|
|
33
|
+
1,
|
|
34
|
+
(o) => ({
|
|
35
|
+
u: (v) => Boolean(v.getUint8(o)),
|
|
36
|
+
p: (v, B) => {
|
|
37
|
+
v.setUint8(o, B ? 1 : 0);
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
],
|
|
41
|
+
b: (c) => [
|
|
42
|
+
c,
|
|
43
|
+
1,
|
|
44
|
+
(o) => ({
|
|
45
|
+
u: (v) => v.getInt8(o),
|
|
46
|
+
p: (v, b) => {
|
|
47
|
+
v.setInt8(o, b);
|
|
48
|
+
},
|
|
49
|
+
}),
|
|
50
|
+
],
|
|
51
|
+
B: (c) => [
|
|
52
|
+
c,
|
|
53
|
+
1,
|
|
54
|
+
(o) => ({
|
|
55
|
+
u: (v) => v.getUint8(o),
|
|
56
|
+
p: (v, B) => {
|
|
57
|
+
v.setUint8(o, B);
|
|
58
|
+
},
|
|
59
|
+
}),
|
|
60
|
+
],
|
|
61
|
+
h: (c) => [
|
|
62
|
+
c,
|
|
63
|
+
2,
|
|
64
|
+
(o) => ({
|
|
65
|
+
u: (v) => v.getInt16(o, le),
|
|
66
|
+
p: (v, h) => {
|
|
67
|
+
v.setInt16(o, h, le);
|
|
68
|
+
},
|
|
69
|
+
}),
|
|
70
|
+
],
|
|
71
|
+
H: (c) => [
|
|
72
|
+
c,
|
|
73
|
+
2,
|
|
74
|
+
(o) => ({
|
|
75
|
+
u: (v) => v.getUint16(o, le),
|
|
76
|
+
p: (v, H) => {
|
|
77
|
+
v.setUint16(o, H, le);
|
|
78
|
+
},
|
|
79
|
+
}),
|
|
80
|
+
],
|
|
81
|
+
i: (c) => [
|
|
82
|
+
c,
|
|
83
|
+
4,
|
|
84
|
+
(o) => ({
|
|
85
|
+
u: (v) => v.getInt32(o, le),
|
|
86
|
+
p: (v, i) => {
|
|
87
|
+
v.setInt32(o, i, le);
|
|
88
|
+
},
|
|
89
|
+
}),
|
|
90
|
+
],
|
|
91
|
+
I: (c) => [
|
|
92
|
+
c,
|
|
93
|
+
4,
|
|
94
|
+
(o) => ({
|
|
95
|
+
u: (v) => v.getUint32(o, le),
|
|
96
|
+
p: (v, I) => {
|
|
97
|
+
v.setUint32(o, I, le);
|
|
98
|
+
},
|
|
99
|
+
}),
|
|
100
|
+
],
|
|
101
|
+
f: (c) => [
|
|
102
|
+
c,
|
|
103
|
+
4,
|
|
104
|
+
(o) => ({
|
|
105
|
+
u: (v) => v.getFloat32(o, le),
|
|
106
|
+
p: (v, f) => {
|
|
107
|
+
v.setFloat32(o, f, le);
|
|
108
|
+
},
|
|
109
|
+
}),
|
|
110
|
+
],
|
|
111
|
+
d: (c) => [
|
|
112
|
+
c,
|
|
113
|
+
8,
|
|
114
|
+
(o) => ({
|
|
115
|
+
u: (v) => v.getFloat64(o, le),
|
|
116
|
+
p: (v, d) => {
|
|
117
|
+
v.setFloat64(o, d, le);
|
|
118
|
+
},
|
|
119
|
+
}),
|
|
120
|
+
],
|
|
121
|
+
s: (c) => [
|
|
122
|
+
1,
|
|
123
|
+
c,
|
|
124
|
+
(o) => ({
|
|
125
|
+
u: (v) => str(v, o, c),
|
|
126
|
+
p: (v, s) => {
|
|
127
|
+
rts(v, o, c, s.slice(0, c));
|
|
128
|
+
},
|
|
129
|
+
}),
|
|
130
|
+
],
|
|
131
|
+
p: (c) => [
|
|
132
|
+
1,
|
|
133
|
+
c,
|
|
134
|
+
(o) => ({
|
|
135
|
+
u: (v) => pst(v, o, c),
|
|
136
|
+
p: (v, s) => {
|
|
137
|
+
tsp(v, o, c, s.slice(0, c - 1));
|
|
138
|
+
},
|
|
139
|
+
}),
|
|
140
|
+
],
|
|
141
|
+
});
|
|
142
|
+
const errbuf = new RangeError("Structure larger than remaining buffer");
|
|
143
|
+
const errval = new RangeError("Not enough values for structure");
|
|
144
|
+
export default function struct(format) {
|
|
145
|
+
const fns = [];
|
|
146
|
+
let size = 0;
|
|
147
|
+
let m = rechk.exec(format);
|
|
148
|
+
if (!m) {
|
|
149
|
+
throw new RangeError("Invalid format string");
|
|
150
|
+
}
|
|
151
|
+
const t = lut("<" === m[1]);
|
|
152
|
+
const lu = (n, c) => t[c](n ? parseInt(n, 10) : 1);
|
|
153
|
+
while ((m = refmt.exec(format))) {
|
|
154
|
+
;
|
|
155
|
+
((r, s, f) => {
|
|
156
|
+
for (let i = 0; i < r; ++i, size += s) {
|
|
157
|
+
if (f) {
|
|
158
|
+
fns.push(f(size));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
})(...lu(...m.slice(1)));
|
|
162
|
+
}
|
|
163
|
+
const unpack_from = (arrb, offs) => {
|
|
164
|
+
if (arrb.byteLength < (offs | 0) + size) {
|
|
165
|
+
throw errbuf;
|
|
166
|
+
}
|
|
167
|
+
const v = new DataView(arrb, offs | 0);
|
|
168
|
+
return fns.map((f) => f.u(v));
|
|
169
|
+
};
|
|
170
|
+
const pack_into = (arrb, offs, ...values) => {
|
|
171
|
+
if (values.length < fns.length) {
|
|
172
|
+
throw errval;
|
|
173
|
+
}
|
|
174
|
+
if (arrb.byteLength < offs + size) {
|
|
175
|
+
throw errbuf;
|
|
176
|
+
}
|
|
177
|
+
const v = new DataView(arrb, offs);
|
|
178
|
+
new Uint8Array(arrb, offs, size).fill(0);
|
|
179
|
+
fns.forEach((f, i) => {
|
|
180
|
+
f.p(v, values[i]);
|
|
181
|
+
});
|
|
182
|
+
};
|
|
183
|
+
const pack = (...values) => {
|
|
184
|
+
const b = new ArrayBuffer(size);
|
|
185
|
+
pack_into(b, 0, ...values);
|
|
186
|
+
return b;
|
|
187
|
+
};
|
|
188
|
+
const unpack = (arrb) => unpack_from(arrb, 0);
|
|
189
|
+
function* iter_unpack(arrb) {
|
|
190
|
+
for (let offs = 0; offs + size <= arrb.byteLength; offs += size) {
|
|
191
|
+
yield unpack_from(arrb, offs);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return Object.freeze({
|
|
195
|
+
unpack,
|
|
196
|
+
pack,
|
|
197
|
+
unpack_from,
|
|
198
|
+
pack_into,
|
|
199
|
+
iter_unpack,
|
|
200
|
+
format,
|
|
201
|
+
size,
|
|
202
|
+
});
|
|
203
|
+
}
|
package/dist/tare.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Initiates the tare calibration process.
|
|
3
|
+
* @param {number} time - The duration time for tare calibration process.
|
|
4
|
+
* @returns {void} A Promise that resolves when tare calibration is initiated.
|
|
5
|
+
*/
|
|
6
|
+
export declare const tare: (time?: number) => void;
|
|
7
|
+
/**
|
|
8
|
+
* Apply tare calibration to the provided sample.
|
|
9
|
+
* @param {number} sample - The sample to calibrate.
|
|
10
|
+
* @returns {number} The calibrated tare value.
|
|
11
|
+
*/
|
|
12
|
+
export declare const applyTare: (sample: number) => number;
|
package/dist/tare.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents the current tare value for calibration.
|
|
3
|
+
* @type {number}
|
|
4
|
+
*/
|
|
5
|
+
let currentTare = 0;
|
|
6
|
+
/**
|
|
7
|
+
* Represents the state of tare calibration.
|
|
8
|
+
* - If `false`, tare calibration is not active.
|
|
9
|
+
* - If `true`, tare calibration process is initiated.
|
|
10
|
+
* - If `Date` object, tare calibration process is ongoing and started at this date.
|
|
11
|
+
* @type {boolean | Date}
|
|
12
|
+
*/
|
|
13
|
+
let runTare = false;
|
|
14
|
+
/**
|
|
15
|
+
* Array holding the samples collected during tare calibration.
|
|
16
|
+
* @type {number[]}
|
|
17
|
+
*/
|
|
18
|
+
let tareSamples = [];
|
|
19
|
+
/**
|
|
20
|
+
* Array holding the sum of samples collected during tare calibration.
|
|
21
|
+
* @type {number}
|
|
22
|
+
*/
|
|
23
|
+
let newTares = 0;
|
|
24
|
+
/**
|
|
25
|
+
* Duration time for tare calibration process.
|
|
26
|
+
* @type {number}
|
|
27
|
+
*/
|
|
28
|
+
let timeTare = 5000;
|
|
29
|
+
/**
|
|
30
|
+
* Initiates the tare calibration process.
|
|
31
|
+
* @param {number} time - The duration time for tare calibration process.
|
|
32
|
+
* @returns {void} A Promise that resolves when tare calibration is initiated.
|
|
33
|
+
*/
|
|
34
|
+
export const tare = (time = 5000) => {
|
|
35
|
+
runTare = true;
|
|
36
|
+
timeTare = time;
|
|
37
|
+
tareSamples = [];
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Apply tare calibration to the provided sample.
|
|
41
|
+
* @param {number} sample - The sample to calibrate.
|
|
42
|
+
* @returns {number} The calibrated tare value.
|
|
43
|
+
*/
|
|
44
|
+
export const applyTare = (sample) => {
|
|
45
|
+
if (runTare) {
|
|
46
|
+
// If taring process is initiated
|
|
47
|
+
if (typeof runTare === "boolean" && runTare) {
|
|
48
|
+
// If tare flag is true (first time), set it to the current date
|
|
49
|
+
runTare = new Date();
|
|
50
|
+
// Initialize the sum of new tare values
|
|
51
|
+
newTares = 0;
|
|
52
|
+
}
|
|
53
|
+
// Push current sample to tareSamples array
|
|
54
|
+
tareSamples.push(sample);
|
|
55
|
+
// Check if taring process duration has passed (defaults to 5 seconds)
|
|
56
|
+
if (typeof runTare !== "boolean" && new Date().getTime() - runTare.getTime() > timeTare) {
|
|
57
|
+
// Calculate the sum of tare samples
|
|
58
|
+
for (const tareSample of tareSamples) {
|
|
59
|
+
newTares += tareSample;
|
|
60
|
+
}
|
|
61
|
+
// Calculate the average by dividing the sum by the number of samples and update the tare value with the calculated average
|
|
62
|
+
currentTare = newTares / tareSamples.length;
|
|
63
|
+
// Reset tare related variables
|
|
64
|
+
runTare = false;
|
|
65
|
+
tareSamples = [];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Apply tare correction to the sample and return the calibrated value
|
|
69
|
+
return currentTare;
|
|
70
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface Commands {
|
|
2
|
+
START_WEIGHT_MEAS?: string;
|
|
3
|
+
STOP_WEIGHT_MEAS?: string;
|
|
4
|
+
SLEEP?: number | string;
|
|
5
|
+
GET_SERIAL?: string;
|
|
6
|
+
GET_TEXT?: string;
|
|
7
|
+
DEBUG_STREAM?: string;
|
|
8
|
+
GET_CALIBRATION?: string;
|
|
9
|
+
TARE_SCALE?: string;
|
|
10
|
+
START_PEAK_RFD_MEAS?: string;
|
|
11
|
+
START_PEAK_RFD_MEAS_SERIES?: string;
|
|
12
|
+
ADD_CALIB_POINT?: string;
|
|
13
|
+
SAVE_CALIB?: string;
|
|
14
|
+
GET_FW_VERSION?: string;
|
|
15
|
+
GET_ERR_INFO?: string;
|
|
16
|
+
CLR_ERR_INFO?: string;
|
|
17
|
+
GET_BATT_VLTG?: string;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|