@hangtime/grip-connect 0.4.2 → 0.5.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/README.md +40 -43
- package/dist/characteristic.d.ts +1 -1
- package/dist/commands/forceboard.d.ts +6 -0
- package/dist/commands/forceboard.js +5 -0
- package/dist/commands/index.d.ts +3 -2
- package/dist/commands/index.js +3 -2
- package/dist/index.d.ts +1 -15
- package/dist/index.js +3 -25
- package/dist/interfaces/base.interface.d.ts +17 -0
- package/dist/interfaces/device/climbro.interface.d.ts +6 -0
- package/dist/interfaces/device/climbro.interface.js +1 -0
- package/dist/interfaces/device/entralpi.interface.d.ts +52 -0
- package/dist/interfaces/device/entralpi.interface.js +1 -0
- package/dist/interfaces/device/forceboard.interface.d.ts +21 -0
- package/dist/interfaces/device/forceboard.interface.js +1 -0
- package/dist/interfaces/device/kilterboard.interface.d.ts +76 -0
- package/dist/interfaces/device/kilterboard.interface.js +1 -0
- package/dist/interfaces/device/motherboard.interface.d.ts +60 -0
- package/dist/interfaces/device/motherboard.interface.js +1 -0
- package/dist/interfaces/device/mysmartboard.interface.d.ts +6 -0
- package/dist/interfaces/device/mysmartboard.interface.js +1 -0
- package/dist/interfaces/device/progressor.interface.d.ts +27 -0
- package/dist/interfaces/device/progressor.interface.js +1 -0
- package/dist/interfaces/device/wh-c06.interface.d.ts +6 -0
- package/dist/interfaces/device/wh-c06.interface.js +1 -0
- package/dist/interfaces/device.interface.d.ts +90 -0
- package/dist/interfaces/device.interface.js +1 -0
- package/dist/is-device.d.ts +19 -13
- package/dist/is-device.js +19 -13
- package/dist/models/base.model.d.ts +7 -0
- package/dist/models/base.model.js +10 -0
- package/dist/models/device/climbro.model.d.ts +9 -0
- package/dist/models/device/climbro.model.js +13 -0
- package/dist/models/device/entralpi.model.d.ts +59 -0
- package/dist/models/device/entralpi.model.js +285 -0
- package/dist/models/device/forceboard.model.d.ts +23 -0
- package/dist/models/device/forceboard.model.js +201 -0
- package/dist/models/device/kilterboard.model.d.ts +85 -0
- package/dist/models/device/kilterboard.model.js +213 -0
- package/dist/models/device/motherboard.model.d.ts +81 -0
- package/dist/models/device/motherboard.model.js +399 -0
- package/dist/models/device/mysmartboard.model.d.ts +9 -0
- package/dist/models/device/mysmartboard.model.js +13 -0
- package/dist/models/device/progressor.model.d.ts +37 -0
- package/dist/models/device/progressor.model.js +185 -0
- package/dist/models/device/wh-c06.model.d.ts +15 -0
- package/dist/models/device/wh-c06.model.js +96 -0
- package/dist/models/device.model.d.ts +61 -0
- package/dist/models/device.model.js +154 -0
- package/dist/models/index.d.ts +8 -0
- package/dist/models/index.js +8 -0
- package/dist/read.d.ts +1 -1
- package/dist/read.js +1 -2
- package/dist/write.d.ts +1 -1
- package/dist/write.js +1 -2
- package/package.json +4 -2
- package/src/characteristic.ts +1 -1
- package/src/commands/forceboard.ts +6 -0
- package/src/commands/index.ts +4 -2
- package/src/index.ts +13 -30
- package/src/interfaces/base.interface.ts +19 -0
- package/src/interfaces/device/climbro.interface.ts +6 -0
- package/src/interfaces/device/entralpi.interface.ts +61 -0
- package/src/interfaces/device/forceboard.interface.ts +24 -0
- package/src/interfaces/device/kilterboard.interface.ts +85 -0
- package/src/interfaces/device/motherboard.interface.ts +70 -0
- package/src/interfaces/device/mysmartboard.interface.ts +6 -0
- package/src/interfaces/device/progressor.interface.ts +31 -0
- package/src/interfaces/device/wh-c06.interface.ts +6 -0
- package/src/interfaces/device.interface.ts +101 -0
- package/src/is-device.ts +23 -16
- package/src/models/base.model.ts +16 -0
- package/src/models/device/climbro.model.ts +15 -0
- package/src/models/device/entralpi.model.ts +306 -0
- package/src/models/device/forceboard.model.ts +206 -0
- package/src/models/device/kilterboard.model.ts +229 -0
- package/src/models/device/motherboard.model.ts +439 -0
- package/src/models/device/mysmartboard.model.ts +15 -0
- package/src/models/device/progressor.model.ts +193 -0
- package/src/models/device/wh-c06.model.ts +118 -0
- package/src/models/device.model.ts +177 -0
- package/src/models/index.ts +15 -0
- package/src/read.ts +2 -3
- package/src/write.ts +2 -3
- package/dist/battery.d.ts +0 -10
- package/dist/battery.js +0 -34
- package/dist/calibration.d.ts +0 -7
- package/dist/calibration.js +0 -21
- package/dist/connect.d.ts +0 -8
- package/dist/connect.js +0 -163
- package/dist/data/entralpi.d.ts +0 -5
- package/dist/data/entralpi.js +0 -33
- package/dist/data/index.d.ts +0 -4
- package/dist/data/index.js +0 -4
- package/dist/data/motherboard.d.ts +0 -10
- package/dist/data/motherboard.js +0 -141
- package/dist/data/progressor.d.ts +0 -9
- package/dist/data/progressor.js +0 -78
- package/dist/data/wh-c06.d.ts +0 -5
- package/dist/data/wh-c06.js +0 -38
- package/dist/devices/climbro.d.ts +0 -6
- package/dist/devices/climbro.js +0 -8
- package/dist/devices/entralpi.d.ts +0 -5
- package/dist/devices/entralpi.js +0 -59
- package/dist/devices/index.d.ts +0 -7
- package/dist/devices/index.js +0 -7
- package/dist/devices/kilterboard.d.ts +0 -10
- package/dist/devices/kilterboard.js +0 -34
- package/dist/devices/motherboard.d.ts +0 -5
- package/dist/devices/motherboard.js +0 -81
- package/dist/devices/mysmartboard.d.ts +0 -6
- package/dist/devices/mysmartboard.js +0 -8
- package/dist/devices/progressor.d.ts +0 -5
- package/dist/devices/progressor.js +0 -37
- package/dist/devices/wh-c06.d.ts +0 -6
- package/dist/devices/wh-c06.js +0 -17
- package/dist/disconnect.d.ts +0 -8
- package/dist/disconnect.js +0 -14
- package/dist/firmware.d.ts +0 -10
- package/dist/firmware.js +0 -34
- package/dist/hardware.d.ts +0 -9
- package/dist/hardware.js +0 -22
- package/dist/is-connected.d.ts +0 -7
- package/dist/is-connected.js +0 -13
- package/dist/led.d.ts +0 -24
- package/dist/led.js +0 -195
- package/dist/manufacturer.d.ts +0 -9
- package/dist/manufacturer.js +0 -22
- package/dist/notify.d.ts +0 -16
- package/dist/notify.js +0 -14
- package/dist/serial.d.ts +0 -9
- package/dist/serial.js +0 -27
- package/dist/stop.d.ts +0 -7
- package/dist/stop.js +0 -21
- package/dist/stream.d.ts +0 -8
- package/dist/stream.js +0 -41
- package/dist/text.d.ts +0 -12
- package/dist/text.js +0 -30
- package/dist/types/devices.d.ts +0 -38
- package/src/battery.ts +0 -36
- package/src/calibration.ts +0 -23
- package/src/connect.ts +0 -187
- package/src/data/entralpi.ts +0 -41
- package/src/data/index.ts +0 -7
- package/src/data/motherboard.ts +0 -163
- package/src/data/progressor.ts +0 -79
- package/src/data/wh-c06.ts +0 -47
- package/src/devices/climbro.ts +0 -10
- package/src/devices/entralpi.ts +0 -61
- package/src/devices/index.ts +0 -13
- package/src/devices/kilterboard.ts +0 -37
- package/src/devices/motherboard.ts +0 -83
- package/src/devices/mysmartboard.ts +0 -10
- package/src/devices/progressor.ts +0 -38
- package/src/devices/wh-c06.ts +0 -19
- package/src/disconnect.ts +0 -16
- package/src/firmware.ts +0 -36
- package/src/hardware.ts +0 -24
- package/src/is-connected.ts +0 -15
- package/src/led.ts +0 -210
- package/src/manufacturer.ts +0 -24
- package/src/notify.ts +0 -18
- package/src/serial.ts +0 -29
- package/src/stop.ts +0 -23
- package/src/stream.ts +0 -43
- package/src/text.ts +0 -32
- package/src/types/devices.ts +0 -39
- /package/dist/{types/devices.js → interfaces/base.interface.js} +0 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { Device } from "../device.model";
|
|
2
|
+
import { read } from "../../read";
|
|
3
|
+
/**
|
|
4
|
+
* Represents a PitchSix Force Board device
|
|
5
|
+
*/
|
|
6
|
+
export class ForceBoard extends Device {
|
|
7
|
+
constructor() {
|
|
8
|
+
super({
|
|
9
|
+
filters: [{ name: "Force Board" }],
|
|
10
|
+
services: [
|
|
11
|
+
{
|
|
12
|
+
name: "Device Information",
|
|
13
|
+
id: "device",
|
|
14
|
+
uuid: "0000180a-0000-1000-8000-00805f9b34fb",
|
|
15
|
+
characteristics: [
|
|
16
|
+
// {
|
|
17
|
+
// name: "Serial Number String (Blocked)",
|
|
18
|
+
// id: "serial",
|
|
19
|
+
// uuid: "00002a25-0000-1000-8000-00805f9b34fb",
|
|
20
|
+
// },
|
|
21
|
+
// {
|
|
22
|
+
// name: "Firmware Revision String (Blocked)",
|
|
23
|
+
// id: "firmware",
|
|
24
|
+
// uuid: "00002a26-0000-1000-8000-00805f9b34f",
|
|
25
|
+
// },
|
|
26
|
+
{
|
|
27
|
+
name: "Manufacturer Name String",
|
|
28
|
+
id: "manufacturer",
|
|
29
|
+
uuid: "00002a29-0000-1000-8000-00805f9b34fb",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "Battery Service",
|
|
35
|
+
id: "battery",
|
|
36
|
+
uuid: "0000180f-0000-1000-8000-00805f9b34fb",
|
|
37
|
+
characteristics: [
|
|
38
|
+
{
|
|
39
|
+
name: "Battery Level",
|
|
40
|
+
id: "level",
|
|
41
|
+
uuid: "00002a19-0000-1000-8000-00805f9b34fb",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "Nordic Device Firmware Update (DFU) Service",
|
|
47
|
+
id: "dfu",
|
|
48
|
+
uuid: "0000fe59-0000-1000-8000-00805f9b34fb",
|
|
49
|
+
characteristics: [
|
|
50
|
+
{
|
|
51
|
+
name: "Buttonless DFU",
|
|
52
|
+
id: "dfu",
|
|
53
|
+
uuid: "8ec90003-f315-4f60-9fb8-838830daea50",
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "",
|
|
59
|
+
id: "",
|
|
60
|
+
uuid: "f3641400-00b0-4240-ba50-05ca45bf8abc",
|
|
61
|
+
characteristics: [
|
|
62
|
+
{
|
|
63
|
+
name: "Read + Indicate",
|
|
64
|
+
id: "",
|
|
65
|
+
uuid: "f3641401-00b0-4240-ba50-05ca45bf8abc",
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: "Humidity Service",
|
|
71
|
+
id: "humidity",
|
|
72
|
+
uuid: "cf194c6f-d0c1-47b2-aeff-dc610f09bd18",
|
|
73
|
+
characteristics: [
|
|
74
|
+
{
|
|
75
|
+
name: "Humidity Level",
|
|
76
|
+
id: "level",
|
|
77
|
+
uuid: "cf194c70-d0c1-47b2-aeff-dc610f09bd18",
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: "",
|
|
83
|
+
id: "",
|
|
84
|
+
uuid: "3a90328c-c266-4c76-b05a-6af6104a0b13",
|
|
85
|
+
characteristics: [
|
|
86
|
+
{
|
|
87
|
+
name: "Read",
|
|
88
|
+
id: "",
|
|
89
|
+
uuid: "3a90328d-c266-4c76-b05a-6af6104a0b13",
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: "",
|
|
95
|
+
id: "forceboard",
|
|
96
|
+
uuid: "9a88d67f-8df2-4afe-9e0d-c2bbbe773dd0",
|
|
97
|
+
characteristics: [
|
|
98
|
+
{
|
|
99
|
+
name: "Write",
|
|
100
|
+
id: "",
|
|
101
|
+
uuid: "9a88d680-8df2-4afe-9e0d-c2bbbe773dd0",
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "Read + Indicate",
|
|
105
|
+
id: "",
|
|
106
|
+
uuid: "9a88d681-8df2-4afe-9e0d-c2bbbe773dd0",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "Read + Notify",
|
|
110
|
+
id: "rx",
|
|
111
|
+
uuid: "9a88d682-8df2-4afe-9e0d-c2bbbe773dd0",
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: "Write",
|
|
115
|
+
id: "",
|
|
116
|
+
uuid: "9a88d683-8df2-4afe-9e0d-c2bbbe773dd0",
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: "Read",
|
|
120
|
+
id: "",
|
|
121
|
+
uuid: "9a88d685-8df2-4afe-9e0d-c2bbbe773dd0",
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: "Write",
|
|
125
|
+
id: "",
|
|
126
|
+
uuid: "9a88d686-8df2-4afe-9e0d-c2bbbe773dd0",
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: "Read + Write",
|
|
130
|
+
id: "",
|
|
131
|
+
uuid: "9a88d687-8df2-4afe-9e0d-c2bbbe773dd0",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: "Serial / Read + Write",
|
|
135
|
+
id: "",
|
|
136
|
+
uuid: "9a88d688-8df2-4afe-9e0d-c2bbbe773dd0",
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: "Read + Write",
|
|
140
|
+
id: "",
|
|
141
|
+
uuid: "9a88d689-8df2-4afe-9e0d-c2bbbe773dd0",
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: "",
|
|
147
|
+
id: "",
|
|
148
|
+
uuid: "467a8516-6e39-11eb-9439-0242ac130002",
|
|
149
|
+
characteristics: [
|
|
150
|
+
{
|
|
151
|
+
name: "Read + Write",
|
|
152
|
+
id: "",
|
|
153
|
+
uuid: "467a8517-6e39-11eb-9439-0242ac130002",
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
name: "Read + Write",
|
|
157
|
+
id: "",
|
|
158
|
+
uuid: "467a8518-6e39-11eb-9439-0242ac130002",
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Retrieves battery or voltage information from the device.
|
|
167
|
+
* @returns {Promise<string | undefined>} A Promise that resolves with the battery or voltage information,
|
|
168
|
+
*/
|
|
169
|
+
battery = async () => {
|
|
170
|
+
if (this.isConnected()) {
|
|
171
|
+
return await read(this, "battery", "level", 250);
|
|
172
|
+
}
|
|
173
|
+
// If device is not found, return undefined
|
|
174
|
+
return undefined;
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* Retrieves humidity level from the device.
|
|
178
|
+
* @returns {Promise<string>} A Promise that resolves with the humidity level,
|
|
179
|
+
*/
|
|
180
|
+
humidity = async () => {
|
|
181
|
+
// Check if the device is connected
|
|
182
|
+
if (this.isConnected()) {
|
|
183
|
+
return await read(this, "humidity", "level", 250);
|
|
184
|
+
}
|
|
185
|
+
// If device is not found, return undefined
|
|
186
|
+
return undefined;
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Retrieves manufacturer information from the device.
|
|
190
|
+
* @returns {Promise<string>} A Promise that resolves with the manufacturer information,
|
|
191
|
+
*/
|
|
192
|
+
manufacturer = async () => {
|
|
193
|
+
// Check if the device is connected
|
|
194
|
+
if (this.isConnected()) {
|
|
195
|
+
// Read manufacturer information from the device
|
|
196
|
+
return await read(this, "device", "manufacturer", 250);
|
|
197
|
+
}
|
|
198
|
+
// If device is not found, return undefined
|
|
199
|
+
return undefined;
|
|
200
|
+
};
|
|
201
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Device } from "../device.model";
|
|
2
|
+
import type { IKilterBoard } from "../../interfaces/device/kilterboard.interface";
|
|
3
|
+
/**
|
|
4
|
+
* Aurora Climbing Advertising service
|
|
5
|
+
*/
|
|
6
|
+
export declare const AuroraUUID = "4488b571-7806-4df6-bcff-a2897e4953ff";
|
|
7
|
+
declare class ClimbPlacement {
|
|
8
|
+
position: number;
|
|
9
|
+
role_id: number;
|
|
10
|
+
constructor(position: number, role_id: number);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Represents a Aurora Climbing device
|
|
14
|
+
* Kilter Board, Tension Board, Decoy Board, Touchstone Board, Grasshopper Board, Aurora Board, So iLL Board
|
|
15
|
+
*/
|
|
16
|
+
export declare class KilterBoard extends Device implements IKilterBoard {
|
|
17
|
+
constructor();
|
|
18
|
+
/**
|
|
19
|
+
* Calculates the checksum for a byte array by summing up all bytes ot hre packet in a single-byte variable.
|
|
20
|
+
* @param data - The array of bytes to calculate the checksum for.
|
|
21
|
+
* @returns The calculated checksum value.
|
|
22
|
+
*/
|
|
23
|
+
checksum(data: number[]): number;
|
|
24
|
+
/**
|
|
25
|
+
* Wraps a byte array with header and footer bytes for transmission.
|
|
26
|
+
* @param data - The array of bytes to wrap.
|
|
27
|
+
* @returns The wrapped byte array.
|
|
28
|
+
*/
|
|
29
|
+
wrapBytes(data: number[]): number[];
|
|
30
|
+
/**
|
|
31
|
+
* Encodes a position into a byte array.
|
|
32
|
+
* The lowest 8 bits of the position get put in the first byte of the group.
|
|
33
|
+
* The highest 8 bits of the position get put in the second byte of the group.
|
|
34
|
+
* @param position - The position to encode.
|
|
35
|
+
* @returns The encoded byte array representing the position.
|
|
36
|
+
*/
|
|
37
|
+
encodePosition(position: number): number[];
|
|
38
|
+
/**
|
|
39
|
+
* Encodes a color string into a numeric representation.
|
|
40
|
+
* 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).
|
|
41
|
+
* @param color - The color string in hexadecimal format (e.g., 'FFFFFF').
|
|
42
|
+
* @returns The encoded /compressed color value.
|
|
43
|
+
*/
|
|
44
|
+
encodeColor(color: string): number;
|
|
45
|
+
/**
|
|
46
|
+
* Encodes a placement (requires a 16-bit position and a 24-bit rgb color. ) into a byte array.
|
|
47
|
+
* @param position - The position to encode.
|
|
48
|
+
* @param ledColor - The color of the LED in hexadecimal format (e.g., 'FFFFFF').
|
|
49
|
+
* @returns The encoded byte array representing the placement.
|
|
50
|
+
*/
|
|
51
|
+
encodePlacement(position: number, ledColor: string): number[];
|
|
52
|
+
/**
|
|
53
|
+
* Prepares byte arrays for transmission based on a list of climb placements.
|
|
54
|
+
* @param climbPlacementList - The list of climb placements containing position and role ID.
|
|
55
|
+
* @returns The final byte array ready for transmission.
|
|
56
|
+
*/
|
|
57
|
+
prepBytesV3(climbPlacementList: ClimbPlacement[]): number[];
|
|
58
|
+
/**
|
|
59
|
+
* Splits a collection into slices of the specified length.
|
|
60
|
+
* https://github.com/ramda/ramda/blob/master/source/splitEvery.js
|
|
61
|
+
* @param {Number} n
|
|
62
|
+
* @param {Array} list
|
|
63
|
+
* @return {Array}
|
|
64
|
+
*/
|
|
65
|
+
splitEvery(n: number, list: number[]): number[][];
|
|
66
|
+
/**
|
|
67
|
+
* The kilter board only supports messages of 20 bytes
|
|
68
|
+
* at a time. This method splits a full message into parts
|
|
69
|
+
* of 20 bytes
|
|
70
|
+
*
|
|
71
|
+
* @param buffer
|
|
72
|
+
*/
|
|
73
|
+
splitMessages: (buffer: number[]) => Uint8Array[];
|
|
74
|
+
/**
|
|
75
|
+
* Sends a series of messages to a device.
|
|
76
|
+
*/
|
|
77
|
+
writeMessageSeries(messages: Uint8Array[]): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Configures the LEDs based on an array of climb placements. If a configuration is provided, it prepares and sends a payload to the device.
|
|
80
|
+
* @param {ClimbPlacement[]} [config] - Optional color or array of climb placements for the LEDs. Ignored if placements are provided.
|
|
81
|
+
* @returns {Promise<number[] | undefined>} A promise that resolves with the payload array for the Kilter Board if LED settings were applied, or `undefined` if no action was taken or for the Motherboard.
|
|
82
|
+
*/
|
|
83
|
+
led: (config?: ClimbPlacement[]) => Promise<number[] | undefined>;
|
|
84
|
+
}
|
|
85
|
+
export {};
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { Device } from "../device.model";
|
|
2
|
+
import { KilterBoardPacket, KilterBoardPlacementRoles } from "../../commands/kilterboard";
|
|
3
|
+
import { write } from "../../write";
|
|
4
|
+
/**
|
|
5
|
+
* Aurora Climbing Advertising service
|
|
6
|
+
*/
|
|
7
|
+
export const AuroraUUID = "4488b571-7806-4df6-bcff-a2897e4953ff";
|
|
8
|
+
/**
|
|
9
|
+
* Maximum length of the message body for byte wrapping.
|
|
10
|
+
*/
|
|
11
|
+
const MESSAGE_BODY_MAX_LENGTH = 255;
|
|
12
|
+
/**
|
|
13
|
+
* Maximum length of the the bluetooth chunk.
|
|
14
|
+
*/
|
|
15
|
+
const MAX_BLUETOOTH_MESSAGE_SIZE = 20;
|
|
16
|
+
class ClimbPlacement {
|
|
17
|
+
position;
|
|
18
|
+
role_id;
|
|
19
|
+
constructor(position, role_id) {
|
|
20
|
+
this.position = position;
|
|
21
|
+
this.role_id = role_id;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Represents a Aurora Climbing device
|
|
26
|
+
* Kilter Board, Tension Board, Decoy Board, Touchstone Board, Grasshopper Board, Aurora Board, So iLL Board
|
|
27
|
+
*/
|
|
28
|
+
export class KilterBoard extends Device {
|
|
29
|
+
constructor() {
|
|
30
|
+
super({
|
|
31
|
+
filters: [
|
|
32
|
+
{
|
|
33
|
+
services: [AuroraUUID],
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
services: [
|
|
37
|
+
{
|
|
38
|
+
name: "UART Nordic Service",
|
|
39
|
+
id: "uart",
|
|
40
|
+
uuid: "6e400001-b5a3-f393-e0a9-e50e24dcca9e",
|
|
41
|
+
characteristics: [
|
|
42
|
+
{
|
|
43
|
+
name: "TX",
|
|
44
|
+
id: "tx",
|
|
45
|
+
uuid: "6e400002-b5a3-f393-e0a9-e50e24dcca9e",
|
|
46
|
+
},
|
|
47
|
+
// {
|
|
48
|
+
// name: "RX",
|
|
49
|
+
// id: "rx",
|
|
50
|
+
// uuid: "6e400003-b5a3-f393-e0a9-e50e24dcca9e",
|
|
51
|
+
// },
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Calculates the checksum for a byte array by summing up all bytes ot hre packet in a single-byte variable.
|
|
59
|
+
* @param data - The array of bytes to calculate the checksum for.
|
|
60
|
+
* @returns The calculated checksum value.
|
|
61
|
+
*/
|
|
62
|
+
checksum(data) {
|
|
63
|
+
let i = 0;
|
|
64
|
+
for (const value of data) {
|
|
65
|
+
i = (i + value) & 255;
|
|
66
|
+
}
|
|
67
|
+
return ~i & 255;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Wraps a byte array with header and footer bytes for transmission.
|
|
71
|
+
* @param data - The array of bytes to wrap.
|
|
72
|
+
* @returns The wrapped byte array.
|
|
73
|
+
*/
|
|
74
|
+
wrapBytes(data) {
|
|
75
|
+
if (data.length > MESSAGE_BODY_MAX_LENGTH) {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
- 0x1
|
|
80
|
+
- len(packets)
|
|
81
|
+
- checksum(packets)
|
|
82
|
+
- 0x2
|
|
83
|
+
- *packets
|
|
84
|
+
- 0x3
|
|
85
|
+
|
|
86
|
+
First byte is always 1, the second is a number of packets, then checksum, then 2, packets themselves, and finally 3.
|
|
87
|
+
*/
|
|
88
|
+
return [1, data.length, this.checksum(data), 2, ...data, 3];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Encodes a position into a byte array.
|
|
92
|
+
* The lowest 8 bits of the position get put in the first byte of the group.
|
|
93
|
+
* The highest 8 bits of the position get put in the second byte of the group.
|
|
94
|
+
* @param position - The position to encode.
|
|
95
|
+
* @returns The encoded byte array representing the position.
|
|
96
|
+
*/
|
|
97
|
+
encodePosition(position) {
|
|
98
|
+
const position1 = position & 255;
|
|
99
|
+
const position2 = (position & 65280) >> 8;
|
|
100
|
+
return [position1, position2];
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Encodes a color string into a numeric representation.
|
|
104
|
+
* 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).
|
|
105
|
+
* @param color - The color string in hexadecimal format (e.g., 'FFFFFF').
|
|
106
|
+
* @returns The encoded /compressed color value.
|
|
107
|
+
*/
|
|
108
|
+
encodeColor(color) {
|
|
109
|
+
const substring = color.substring(0, 2);
|
|
110
|
+
const substring2 = color.substring(2, 4);
|
|
111
|
+
const parsedSubstring = parseInt(substring, 16) / 32;
|
|
112
|
+
const parsedSubstring2 = parseInt(substring2, 16) / 32;
|
|
113
|
+
const parsedResult = (parsedSubstring << 5) | (parsedSubstring2 << 2);
|
|
114
|
+
const substring3 = color.substring(4, 6);
|
|
115
|
+
const parsedSubstring3 = parseInt(substring3, 16) / 64;
|
|
116
|
+
const finalParsedResult = parsedResult | parsedSubstring3;
|
|
117
|
+
return finalParsedResult;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Encodes a placement (requires a 16-bit position and a 24-bit rgb color. ) into a byte array.
|
|
121
|
+
* @param position - The position to encode.
|
|
122
|
+
* @param ledColor - The color of the LED in hexadecimal format (e.g., 'FFFFFF').
|
|
123
|
+
* @returns The encoded byte array representing the placement.
|
|
124
|
+
*/
|
|
125
|
+
encodePlacement(position, ledColor) {
|
|
126
|
+
return [...this.encodePosition(position), this.encodeColor(ledColor)];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Prepares byte arrays for transmission based on a list of climb placements.
|
|
130
|
+
* @param climbPlacementList - The list of climb placements containing position and role ID.
|
|
131
|
+
* @returns The final byte array ready for transmission.
|
|
132
|
+
*/
|
|
133
|
+
prepBytesV3(climbPlacementList) {
|
|
134
|
+
const resultArray = [];
|
|
135
|
+
let tempArray = [KilterBoardPacket.V3_MIDDLE];
|
|
136
|
+
for (const climbPlacement of climbPlacementList) {
|
|
137
|
+
if (tempArray.length + 3 > MESSAGE_BODY_MAX_LENGTH) {
|
|
138
|
+
resultArray.push(tempArray);
|
|
139
|
+
tempArray = [KilterBoardPacket.V3_MIDDLE];
|
|
140
|
+
}
|
|
141
|
+
const role = KilterBoardPlacementRoles.find((placement) => placement.id === climbPlacement.role_id);
|
|
142
|
+
if (!role) {
|
|
143
|
+
throw new Error(`Role with id ${climbPlacement.role_id} not found in placement_roles`);
|
|
144
|
+
}
|
|
145
|
+
const encodedPlacement = this.encodePlacement(climbPlacement.position, role.led_color);
|
|
146
|
+
tempArray.push(...encodedPlacement);
|
|
147
|
+
}
|
|
148
|
+
resultArray.push(tempArray);
|
|
149
|
+
if (resultArray.length === 1) {
|
|
150
|
+
resultArray[0][0] = KilterBoardPacket.V3_ONLY;
|
|
151
|
+
}
|
|
152
|
+
else if (resultArray.length > 1) {
|
|
153
|
+
resultArray[0][0] = KilterBoardPacket.V3_FIRST;
|
|
154
|
+
resultArray[resultArray.length - 1][0] = KilterBoardPacket.V3_LAST;
|
|
155
|
+
}
|
|
156
|
+
const finalResultArray = [];
|
|
157
|
+
for (const currentArray of resultArray) {
|
|
158
|
+
finalResultArray.push(...this.wrapBytes(currentArray));
|
|
159
|
+
}
|
|
160
|
+
return finalResultArray;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Splits a collection into slices of the specified length.
|
|
164
|
+
* https://github.com/ramda/ramda/blob/master/source/splitEvery.js
|
|
165
|
+
* @param {Number} n
|
|
166
|
+
* @param {Array} list
|
|
167
|
+
* @return {Array}
|
|
168
|
+
*/
|
|
169
|
+
splitEvery(n, list) {
|
|
170
|
+
if (n <= 0) {
|
|
171
|
+
throw new Error("First argument to splitEvery must be a positive integer");
|
|
172
|
+
}
|
|
173
|
+
const result = [];
|
|
174
|
+
let idx = 0;
|
|
175
|
+
while (idx < list.length) {
|
|
176
|
+
result.push(list.slice(idx, (idx += n)));
|
|
177
|
+
}
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The kilter board only supports messages of 20 bytes
|
|
182
|
+
* at a time. This method splits a full message into parts
|
|
183
|
+
* of 20 bytes
|
|
184
|
+
*
|
|
185
|
+
* @param buffer
|
|
186
|
+
*/
|
|
187
|
+
splitMessages = (buffer) => this.splitEvery(MAX_BLUETOOTH_MESSAGE_SIZE, buffer).map((arr) => new Uint8Array(arr));
|
|
188
|
+
/**
|
|
189
|
+
* Sends a series of messages to a device.
|
|
190
|
+
*/
|
|
191
|
+
async writeMessageSeries(messages) {
|
|
192
|
+
for (const message of messages) {
|
|
193
|
+
await write(this, "uart", "tx", message);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Configures the LEDs based on an array of climb placements. If a configuration is provided, it prepares and sends a payload to the device.
|
|
198
|
+
* @param {ClimbPlacement[]} [config] - Optional color or array of climb placements for the LEDs. Ignored if placements are provided.
|
|
199
|
+
* @returns {Promise<number[] | undefined>} A promise that resolves with the payload array for the Kilter Board if LED settings were applied, or `undefined` if no action was taken or for the Motherboard.
|
|
200
|
+
*/
|
|
201
|
+
led = async (config) => {
|
|
202
|
+
// Handle Kilterboard logic: process placements and send payload if connected
|
|
203
|
+
if (Array.isArray(config)) {
|
|
204
|
+
// Prepares byte arrays for transmission based on a list of climb placements.
|
|
205
|
+
const payload = this.prepBytesV3(config);
|
|
206
|
+
if (this.isConnected()) {
|
|
207
|
+
await this.writeMessageSeries(this.splitMessages(payload));
|
|
208
|
+
}
|
|
209
|
+
return payload;
|
|
210
|
+
}
|
|
211
|
+
return undefined;
|
|
212
|
+
};
|
|
213
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Device } from "../device.model";
|
|
2
|
+
import type { IMotherboard } from "../../interfaces/device/motherboard.interface";
|
|
3
|
+
export declare const CALIBRATION: never[][];
|
|
4
|
+
/**
|
|
5
|
+
* Represents a Griptonite Motherboard device
|
|
6
|
+
*/
|
|
7
|
+
export declare class Motherboard extends Device implements IMotherboard {
|
|
8
|
+
constructor();
|
|
9
|
+
/**
|
|
10
|
+
* Applies calibration to a sample value.
|
|
11
|
+
* @param {number} sample - The sample value to calibrate.
|
|
12
|
+
* @param {number[][]} calibration - The calibration data.
|
|
13
|
+
* @returns {number} The calibrated sample value.
|
|
14
|
+
*/
|
|
15
|
+
applyCalibration: (sample: number, calibration: number[][]) => number;
|
|
16
|
+
/**
|
|
17
|
+
* Retrieves battery or voltage information from the device.
|
|
18
|
+
* @returns {Promise<string | undefined>} A Promise that resolves with the battery or voltage information,
|
|
19
|
+
*/
|
|
20
|
+
battery: () => Promise<string | undefined>;
|
|
21
|
+
/**
|
|
22
|
+
* Writes a command to get calibration data from the device.
|
|
23
|
+
* @returns {Promise<void>} A Promise that resolves when the command is successfully sent.
|
|
24
|
+
*/
|
|
25
|
+
calibration: () => Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Retrieves firmware version from the device.
|
|
28
|
+
* @returns {Promise<string>} A Promise that resolves with the firmware version,
|
|
29
|
+
*/
|
|
30
|
+
firmware: () => Promise<string | undefined>;
|
|
31
|
+
/**
|
|
32
|
+
* Handles data received from the Motherboard device. Processes hex-encoded streaming packets
|
|
33
|
+
* to extract samples, calibrate masses, and update running averages of mass data.
|
|
34
|
+
* If the received data is not a valid hex packet, it returns the unprocessed data.
|
|
35
|
+
*
|
|
36
|
+
* @param {Event} event - The notification event.
|
|
37
|
+
*/
|
|
38
|
+
handleNotifications: (event: Event) => void;
|
|
39
|
+
/**
|
|
40
|
+
* Retrieves hardware version from the device.
|
|
41
|
+
* @returns {Promise<string>} A Promise that resolves with the hardware version,
|
|
42
|
+
*/
|
|
43
|
+
hardware: () => Promise<string | undefined>;
|
|
44
|
+
/**
|
|
45
|
+
* Sets the LED color based on a single color option. Defaults to turning the LEDs off if no configuration is provided.
|
|
46
|
+
* @param {"green" | "red" | "orange"} [config] - Optional color or array of climb placements for the LEDs. Ignored if placements are provided.
|
|
47
|
+
* @returns {Promise<number[] | undefined>} A promise that resolves with the payload array for the Kilter Board if LED settings were applied, or `undefined` if no action was taken or for the Motherboard.
|
|
48
|
+
*/
|
|
49
|
+
led: (config?: "green" | "red" | "orange") => Promise<number[] | undefined>;
|
|
50
|
+
/**
|
|
51
|
+
* Retrieves manufacturer information from the device.
|
|
52
|
+
* @returns {Promise<string>} A Promise that resolves with the manufacturer information,
|
|
53
|
+
*/
|
|
54
|
+
manufacturer: () => Promise<string | undefined>;
|
|
55
|
+
/**
|
|
56
|
+
* Retrieves serial number from the device.
|
|
57
|
+
* @returns {Promise<string>} A Promise that resolves with the serial number,
|
|
58
|
+
*/
|
|
59
|
+
serial: () => Promise<string | undefined>;
|
|
60
|
+
/**
|
|
61
|
+
* Stops the data stream on the specified device.
|
|
62
|
+
* @returns {Promise<void>} A promise that resolves when the stream is stopped.
|
|
63
|
+
*/
|
|
64
|
+
stop: () => Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Starts streaming data from the specified device.
|
|
67
|
+
* @param {number} [duration=0] - The duration of the stream in milliseconds. If set to 0, stream will continue indefinitely.
|
|
68
|
+
* @returns {Promise<void>} A promise that resolves when the streaming operation is completed.
|
|
69
|
+
*/
|
|
70
|
+
stream: (duration?: number) => Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Retrieves the entire 320 bytes of non-volatile memory from the device.
|
|
73
|
+
*
|
|
74
|
+
* The memory consists of 10 segments, each 32 bytes long. If any segment was previously written,
|
|
75
|
+
* the corresponding data will appear in the response. Unused portions of the memory are
|
|
76
|
+
* padded with whitespace.
|
|
77
|
+
*
|
|
78
|
+
* @returns {Promise<string>} A Promise that resolves with the 320-byte memory content as a string,
|
|
79
|
+
*/
|
|
80
|
+
text: () => Promise<string | undefined>;
|
|
81
|
+
}
|