@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.
Files changed (168) hide show
  1. package/README.md +40 -43
  2. package/dist/characteristic.d.ts +1 -1
  3. package/dist/commands/forceboard.d.ts +6 -0
  4. package/dist/commands/forceboard.js +5 -0
  5. package/dist/commands/index.d.ts +3 -2
  6. package/dist/commands/index.js +3 -2
  7. package/dist/index.d.ts +1 -15
  8. package/dist/index.js +3 -25
  9. package/dist/interfaces/base.interface.d.ts +17 -0
  10. package/dist/interfaces/device/climbro.interface.d.ts +6 -0
  11. package/dist/interfaces/device/climbro.interface.js +1 -0
  12. package/dist/interfaces/device/entralpi.interface.d.ts +52 -0
  13. package/dist/interfaces/device/entralpi.interface.js +1 -0
  14. package/dist/interfaces/device/forceboard.interface.d.ts +21 -0
  15. package/dist/interfaces/device/forceboard.interface.js +1 -0
  16. package/dist/interfaces/device/kilterboard.interface.d.ts +76 -0
  17. package/dist/interfaces/device/kilterboard.interface.js +1 -0
  18. package/dist/interfaces/device/motherboard.interface.d.ts +60 -0
  19. package/dist/interfaces/device/motherboard.interface.js +1 -0
  20. package/dist/interfaces/device/mysmartboard.interface.d.ts +6 -0
  21. package/dist/interfaces/device/mysmartboard.interface.js +1 -0
  22. package/dist/interfaces/device/progressor.interface.d.ts +27 -0
  23. package/dist/interfaces/device/progressor.interface.js +1 -0
  24. package/dist/interfaces/device/wh-c06.interface.d.ts +6 -0
  25. package/dist/interfaces/device/wh-c06.interface.js +1 -0
  26. package/dist/interfaces/device.interface.d.ts +90 -0
  27. package/dist/interfaces/device.interface.js +1 -0
  28. package/dist/is-device.d.ts +19 -13
  29. package/dist/is-device.js +19 -13
  30. package/dist/models/base.model.d.ts +7 -0
  31. package/dist/models/base.model.js +10 -0
  32. package/dist/models/device/climbro.model.d.ts +9 -0
  33. package/dist/models/device/climbro.model.js +13 -0
  34. package/dist/models/device/entralpi.model.d.ts +59 -0
  35. package/dist/models/device/entralpi.model.js +285 -0
  36. package/dist/models/device/forceboard.model.d.ts +23 -0
  37. package/dist/models/device/forceboard.model.js +201 -0
  38. package/dist/models/device/kilterboard.model.d.ts +85 -0
  39. package/dist/models/device/kilterboard.model.js +213 -0
  40. package/dist/models/device/motherboard.model.d.ts +81 -0
  41. package/dist/models/device/motherboard.model.js +399 -0
  42. package/dist/models/device/mysmartboard.model.d.ts +9 -0
  43. package/dist/models/device/mysmartboard.model.js +13 -0
  44. package/dist/models/device/progressor.model.d.ts +37 -0
  45. package/dist/models/device/progressor.model.js +185 -0
  46. package/dist/models/device/wh-c06.model.d.ts +15 -0
  47. package/dist/models/device/wh-c06.model.js +96 -0
  48. package/dist/models/device.model.d.ts +61 -0
  49. package/dist/models/device.model.js +154 -0
  50. package/dist/models/index.d.ts +8 -0
  51. package/dist/models/index.js +8 -0
  52. package/dist/read.d.ts +1 -1
  53. package/dist/read.js +1 -2
  54. package/dist/write.d.ts +1 -1
  55. package/dist/write.js +1 -2
  56. package/package.json +4 -2
  57. package/src/characteristic.ts +1 -1
  58. package/src/commands/forceboard.ts +6 -0
  59. package/src/commands/index.ts +4 -2
  60. package/src/index.ts +13 -30
  61. package/src/interfaces/base.interface.ts +19 -0
  62. package/src/interfaces/device/climbro.interface.ts +6 -0
  63. package/src/interfaces/device/entralpi.interface.ts +61 -0
  64. package/src/interfaces/device/forceboard.interface.ts +24 -0
  65. package/src/interfaces/device/kilterboard.interface.ts +85 -0
  66. package/src/interfaces/device/motherboard.interface.ts +70 -0
  67. package/src/interfaces/device/mysmartboard.interface.ts +6 -0
  68. package/src/interfaces/device/progressor.interface.ts +31 -0
  69. package/src/interfaces/device/wh-c06.interface.ts +6 -0
  70. package/src/interfaces/device.interface.ts +101 -0
  71. package/src/is-device.ts +23 -16
  72. package/src/models/base.model.ts +16 -0
  73. package/src/models/device/climbro.model.ts +15 -0
  74. package/src/models/device/entralpi.model.ts +306 -0
  75. package/src/models/device/forceboard.model.ts +206 -0
  76. package/src/models/device/kilterboard.model.ts +229 -0
  77. package/src/models/device/motherboard.model.ts +439 -0
  78. package/src/models/device/mysmartboard.model.ts +15 -0
  79. package/src/models/device/progressor.model.ts +193 -0
  80. package/src/models/device/wh-c06.model.ts +118 -0
  81. package/src/models/device.model.ts +177 -0
  82. package/src/models/index.ts +15 -0
  83. package/src/read.ts +2 -3
  84. package/src/write.ts +2 -3
  85. package/dist/battery.d.ts +0 -10
  86. package/dist/battery.js +0 -34
  87. package/dist/calibration.d.ts +0 -7
  88. package/dist/calibration.js +0 -21
  89. package/dist/connect.d.ts +0 -8
  90. package/dist/connect.js +0 -163
  91. package/dist/data/entralpi.d.ts +0 -5
  92. package/dist/data/entralpi.js +0 -33
  93. package/dist/data/index.d.ts +0 -4
  94. package/dist/data/index.js +0 -4
  95. package/dist/data/motherboard.d.ts +0 -10
  96. package/dist/data/motherboard.js +0 -141
  97. package/dist/data/progressor.d.ts +0 -9
  98. package/dist/data/progressor.js +0 -78
  99. package/dist/data/wh-c06.d.ts +0 -5
  100. package/dist/data/wh-c06.js +0 -38
  101. package/dist/devices/climbro.d.ts +0 -6
  102. package/dist/devices/climbro.js +0 -8
  103. package/dist/devices/entralpi.d.ts +0 -5
  104. package/dist/devices/entralpi.js +0 -59
  105. package/dist/devices/index.d.ts +0 -7
  106. package/dist/devices/index.js +0 -7
  107. package/dist/devices/kilterboard.d.ts +0 -10
  108. package/dist/devices/kilterboard.js +0 -34
  109. package/dist/devices/motherboard.d.ts +0 -5
  110. package/dist/devices/motherboard.js +0 -81
  111. package/dist/devices/mysmartboard.d.ts +0 -6
  112. package/dist/devices/mysmartboard.js +0 -8
  113. package/dist/devices/progressor.d.ts +0 -5
  114. package/dist/devices/progressor.js +0 -37
  115. package/dist/devices/wh-c06.d.ts +0 -6
  116. package/dist/devices/wh-c06.js +0 -17
  117. package/dist/disconnect.d.ts +0 -8
  118. package/dist/disconnect.js +0 -14
  119. package/dist/firmware.d.ts +0 -10
  120. package/dist/firmware.js +0 -34
  121. package/dist/hardware.d.ts +0 -9
  122. package/dist/hardware.js +0 -22
  123. package/dist/is-connected.d.ts +0 -7
  124. package/dist/is-connected.js +0 -13
  125. package/dist/led.d.ts +0 -24
  126. package/dist/led.js +0 -195
  127. package/dist/manufacturer.d.ts +0 -9
  128. package/dist/manufacturer.js +0 -22
  129. package/dist/notify.d.ts +0 -16
  130. package/dist/notify.js +0 -14
  131. package/dist/serial.d.ts +0 -9
  132. package/dist/serial.js +0 -27
  133. package/dist/stop.d.ts +0 -7
  134. package/dist/stop.js +0 -21
  135. package/dist/stream.d.ts +0 -8
  136. package/dist/stream.js +0 -41
  137. package/dist/text.d.ts +0 -12
  138. package/dist/text.js +0 -30
  139. package/dist/types/devices.d.ts +0 -38
  140. package/src/battery.ts +0 -36
  141. package/src/calibration.ts +0 -23
  142. package/src/connect.ts +0 -187
  143. package/src/data/entralpi.ts +0 -41
  144. package/src/data/index.ts +0 -7
  145. package/src/data/motherboard.ts +0 -163
  146. package/src/data/progressor.ts +0 -79
  147. package/src/data/wh-c06.ts +0 -47
  148. package/src/devices/climbro.ts +0 -10
  149. package/src/devices/entralpi.ts +0 -61
  150. package/src/devices/index.ts +0 -13
  151. package/src/devices/kilterboard.ts +0 -37
  152. package/src/devices/motherboard.ts +0 -83
  153. package/src/devices/mysmartboard.ts +0 -10
  154. package/src/devices/progressor.ts +0 -38
  155. package/src/devices/wh-c06.ts +0 -19
  156. package/src/disconnect.ts +0 -16
  157. package/src/firmware.ts +0 -36
  158. package/src/hardware.ts +0 -24
  159. package/src/is-connected.ts +0 -15
  160. package/src/led.ts +0 -210
  161. package/src/manufacturer.ts +0 -24
  162. package/src/notify.ts +0 -18
  163. package/src/serial.ts +0 -29
  164. package/src/stop.ts +0 -23
  165. package/src/stream.ts +0 -43
  166. package/src/text.ts +0 -32
  167. package/src/types/devices.ts +0 -39
  168. /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
+ }