@hangtime/grip-connect 0.4.2 → 0.5.0

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 (167) hide show
  1. package/README.md +49 -40
  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 -13
  8. package/dist/index.js +3 -23
  9. package/dist/interfaces/base.interface.d.ts +5 -0
  10. package/dist/interfaces/device/climbro.interface.d.ts +3 -0
  11. package/dist/interfaces/device/climbro.interface.js +1 -0
  12. package/dist/interfaces/device/entralpi.interface.d.ts +3 -0
  13. package/dist/interfaces/device/entralpi.interface.js +1 -0
  14. package/dist/interfaces/device/forceboard.interface.d.ts +3 -0
  15. package/dist/interfaces/device/forceboard.interface.js +1 -0
  16. package/dist/interfaces/device/kilterboard.interface.d.ts +3 -0
  17. package/dist/interfaces/device/kilterboard.interface.js +1 -0
  18. package/dist/interfaces/device/motherboard.interface.d.ts +10 -0
  19. package/dist/interfaces/device/motherboard.interface.js +1 -0
  20. package/dist/interfaces/device/mysmartboard.interface.d.ts +3 -0
  21. package/dist/interfaces/device/mysmartboard.interface.js +1 -0
  22. package/dist/interfaces/device/progressor.interface.d.ts +3 -0
  23. package/dist/interfaces/device/progressor.interface.js +1 -0
  24. package/dist/interfaces/device/wh-c06.interface.d.ts +3 -0
  25. package/dist/interfaces/device/wh-c06.interface.js +1 -0
  26. package/dist/interfaces/device.interface.d.ts +76 -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 +43 -0
  35. package/dist/models/device/entralpi.model.js +246 -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 +76 -0
  41. package/dist/models/device/motherboard.model.js +391 -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 +32 -0
  45. package/dist/models/device/progressor.model.js +177 -0
  46. package/dist/models/device/wh-c06.model.d.ts +15 -0
  47. package/dist/models/device/wh-c06.model.js +97 -0
  48. package/dist/models/device.model.d.ts +45 -0
  49. package/dist/models/device.model.js +140 -0
  50. package/dist/models/index.d.ts +8 -0
  51. package/dist/models/index.js +8 -0
  52. package/dist/notify.js +1 -1
  53. package/dist/read.d.ts +1 -1
  54. package/dist/read.js +1 -2
  55. package/dist/stop.d.ts +1 -1
  56. package/dist/stop.js +1 -2
  57. package/dist/write.d.ts +1 -1
  58. package/dist/write.js +1 -2
  59. package/package.json +4 -2
  60. package/src/characteristic.ts +1 -1
  61. package/src/commands/forceboard.ts +6 -0
  62. package/src/commands/index.ts +4 -2
  63. package/src/index.ts +14 -27
  64. package/src/interfaces/base.interface.ts +5 -0
  65. package/src/interfaces/device/climbro.interface.ts +4 -0
  66. package/src/interfaces/device/entralpi.interface.ts +4 -0
  67. package/src/interfaces/device/forceboard.interface.ts +4 -0
  68. package/src/interfaces/device/kilterboard.interface.ts +4 -0
  69. package/src/interfaces/device/motherboard.interface.ts +11 -0
  70. package/src/interfaces/device/mysmartboard.interface.ts +4 -0
  71. package/src/interfaces/device/progressor.interface.ts +4 -0
  72. package/src/interfaces/device/wh-c06.interface.ts +4 -0
  73. package/src/interfaces/device.interface.ts +85 -0
  74. package/src/is-device.ts +23 -16
  75. package/src/models/base.model.ts +16 -0
  76. package/src/models/device/climbro.model.ts +15 -0
  77. package/src/models/device/entralpi.model.ts +264 -0
  78. package/src/models/device/forceboard.model.ts +206 -0
  79. package/src/models/device/kilterboard.model.ts +229 -0
  80. package/src/models/device/motherboard.model.ts +430 -0
  81. package/src/models/device/mysmartboard.model.ts +15 -0
  82. package/src/models/device/progressor.model.ts +184 -0
  83. package/src/models/device/wh-c06.model.ts +118 -0
  84. package/src/models/device.model.ts +159 -0
  85. package/src/models/index.ts +15 -0
  86. package/src/notify.ts +1 -1
  87. package/src/read.ts +2 -3
  88. package/src/stop.ts +2 -3
  89. package/src/write.ts +2 -3
  90. package/dist/battery.d.ts +0 -10
  91. package/dist/battery.js +0 -34
  92. package/dist/calibration.d.ts +0 -7
  93. package/dist/calibration.js +0 -21
  94. package/dist/connect.d.ts +0 -8
  95. package/dist/connect.js +0 -163
  96. package/dist/data/entralpi.d.ts +0 -5
  97. package/dist/data/entralpi.js +0 -33
  98. package/dist/data/index.d.ts +0 -4
  99. package/dist/data/index.js +0 -4
  100. package/dist/data/motherboard.d.ts +0 -10
  101. package/dist/data/motherboard.js +0 -141
  102. package/dist/data/progressor.d.ts +0 -9
  103. package/dist/data/progressor.js +0 -78
  104. package/dist/data/wh-c06.d.ts +0 -5
  105. package/dist/data/wh-c06.js +0 -38
  106. package/dist/devices/climbro.d.ts +0 -6
  107. package/dist/devices/climbro.js +0 -8
  108. package/dist/devices/entralpi.d.ts +0 -5
  109. package/dist/devices/entralpi.js +0 -59
  110. package/dist/devices/index.d.ts +0 -7
  111. package/dist/devices/index.js +0 -7
  112. package/dist/devices/kilterboard.d.ts +0 -10
  113. package/dist/devices/kilterboard.js +0 -34
  114. package/dist/devices/motherboard.d.ts +0 -5
  115. package/dist/devices/motherboard.js +0 -81
  116. package/dist/devices/mysmartboard.d.ts +0 -6
  117. package/dist/devices/mysmartboard.js +0 -8
  118. package/dist/devices/progressor.d.ts +0 -5
  119. package/dist/devices/progressor.js +0 -37
  120. package/dist/devices/wh-c06.d.ts +0 -6
  121. package/dist/devices/wh-c06.js +0 -17
  122. package/dist/disconnect.d.ts +0 -8
  123. package/dist/disconnect.js +0 -14
  124. package/dist/firmware.d.ts +0 -10
  125. package/dist/firmware.js +0 -34
  126. package/dist/hardware.d.ts +0 -9
  127. package/dist/hardware.js +0 -22
  128. package/dist/is-connected.d.ts +0 -7
  129. package/dist/is-connected.js +0 -13
  130. package/dist/led.d.ts +0 -24
  131. package/dist/led.js +0 -195
  132. package/dist/manufacturer.d.ts +0 -9
  133. package/dist/manufacturer.js +0 -22
  134. package/dist/serial.d.ts +0 -9
  135. package/dist/serial.js +0 -27
  136. package/dist/stream.d.ts +0 -8
  137. package/dist/stream.js +0 -41
  138. package/dist/text.d.ts +0 -12
  139. package/dist/text.js +0 -30
  140. package/dist/types/devices.d.ts +0 -38
  141. package/src/battery.ts +0 -36
  142. package/src/calibration.ts +0 -23
  143. package/src/connect.ts +0 -187
  144. package/src/data/entralpi.ts +0 -41
  145. package/src/data/index.ts +0 -7
  146. package/src/data/motherboard.ts +0 -163
  147. package/src/data/progressor.ts +0 -79
  148. package/src/data/wh-c06.ts +0 -47
  149. package/src/devices/climbro.ts +0 -10
  150. package/src/devices/entralpi.ts +0 -61
  151. package/src/devices/index.ts +0 -13
  152. package/src/devices/kilterboard.ts +0 -37
  153. package/src/devices/motherboard.ts +0 -83
  154. package/src/devices/mysmartboard.ts +0 -10
  155. package/src/devices/progressor.ts +0 -38
  156. package/src/devices/wh-c06.ts +0 -19
  157. package/src/disconnect.ts +0 -16
  158. package/src/firmware.ts +0 -36
  159. package/src/hardware.ts +0 -24
  160. package/src/is-connected.ts +0 -15
  161. package/src/led.ts +0 -210
  162. package/src/manufacturer.ts +0 -24
  163. package/src/serial.ts +0 -29
  164. package/src/stream.ts +0 -43
  165. package/src/text.ts +0 -32
  166. package/src/types/devices.ts +0 -39
  167. /package/dist/{types/devices.js → interfaces/base.interface.js} +0 -0
package/src/connect.ts DELETED
@@ -1,187 +0,0 @@
1
- import type { Device } from "./types/devices"
2
- import { handleEntralpiData, handleMotherboardData, handleProgressorData, handleWHC06Data } from "./data"
3
- import { isEntralpi, isMotherboard, isProgressor } from "./is-device"
4
-
5
- let server: BluetoothRemoteGATTServer
6
- const receiveBuffer: number[] = []
7
-
8
- /**
9
- * Handles the 'disconnected' event.
10
- * @param {Event} event - The 'disconnected' event.
11
- * @param {Device} board - The device that is disconnected.
12
- */
13
- const onDisconnected = (event: Event, board: Device): void => {
14
- board.device = undefined
15
- const device = event.target as BluetoothDevice
16
- throw new Error(`Device ${device.name} is disconnected.`)
17
- }
18
- /**
19
- * Handles notifications received from a characteristic.
20
- * @param {Event} event - The notification event.
21
- * @param {Device} board - The device associated with the characteristic.
22
- */
23
- const handleNotifications = (event: Event, board: Device): void => {
24
- const characteristic: BluetoothRemoteGATTCharacteristic = event.target as BluetoothRemoteGATTCharacteristic
25
- const value: DataView | undefined = characteristic.value
26
-
27
- if (value) {
28
- // If the device is connected and it is a Motherboard device
29
- if (isMotherboard(board)) {
30
- for (let i = 0; i < value.byteLength; i++) {
31
- receiveBuffer.push(value.getUint8(i))
32
- }
33
-
34
- let idx: number
35
- while ((idx = receiveBuffer.indexOf(10)) >= 0) {
36
- const line: number[] = receiveBuffer.splice(0, idx + 1).slice(0, -1) // Combine and remove LF
37
- if (line.length > 0 && line[line.length - 1] === 13) line.pop() // Remove CR
38
- const decoder: TextDecoder = new TextDecoder("utf-8")
39
- const receivedData: string = decoder.decode(new Uint8Array(line))
40
- handleMotherboardData(receivedData)
41
- }
42
- } else if (isEntralpi(board)) {
43
- if (value.buffer) {
44
- const buffer: ArrayBuffer = value.buffer
45
- const rawData: DataView = new DataView(buffer)
46
- const receivedData: string = (rawData.getUint16(0) / 100).toFixed(1)
47
- handleEntralpiData(receivedData)
48
- }
49
- } else if (isProgressor(board)) {
50
- if (value.buffer) {
51
- const buffer: ArrayBuffer = value.buffer
52
- const rawData: DataView = new DataView(buffer)
53
- handleProgressorData(rawData)
54
- }
55
- } else {
56
- console.log(value)
57
- }
58
- }
59
- }
60
- /**
61
- * Handles the 'connected' event.
62
- * @param {Device} board - The connected device.
63
- * @param {Function} onSuccess - Callback function to execute on successful connection.
64
- */
65
- const onConnected = async (board: Device, onSuccess: () => void): Promise<void> => {
66
- // Connect to GATT server and set up characteristics
67
- const services: BluetoothRemoteGATTService[] = await server.getPrimaryServices()
68
-
69
- if (!services || services.length === 0) {
70
- throw new Error("No services found")
71
- }
72
-
73
- for (const service of services) {
74
- const matchingService = board.services.find((boardService) => boardService.uuid === service.uuid)
75
-
76
- if (matchingService) {
77
- // Android bug: Introduce a delay before getting characteristics
78
- await new Promise((resolve) => setTimeout(resolve, 100))
79
-
80
- const characteristics = await service.getCharacteristics()
81
-
82
- for (const characteristic of matchingService.characteristics) {
83
- const matchingCharacteristic = characteristics.find((char) => char.uuid === characteristic.uuid)
84
-
85
- if (matchingCharacteristic) {
86
- const element = matchingService.characteristics.find((char) => char.uuid === matchingCharacteristic.uuid)
87
- if (element) {
88
- element.characteristic = matchingCharacteristic
89
-
90
- // notify
91
- if (element.id === "rx") {
92
- matchingCharacteristic.startNotifications()
93
- matchingCharacteristic.addEventListener("characteristicvaluechanged", (event: Event) => {
94
- handleNotifications(event, board)
95
- })
96
- }
97
- }
98
- } else {
99
- throw new Error(`Characteristic ${characteristic.uuid} not found in service ${service.uuid}`)
100
- }
101
- }
102
- }
103
- }
104
-
105
- // Call the onSuccess callback after successful connection and setup
106
- onSuccess()
107
- }
108
- /**
109
- * Returns UUIDs of all services associated with the device.
110
- * @param {Device} device - The device.
111
- * @returns {string[]} Array of service UUIDs.
112
- */
113
- const getAllServiceUUIDs = (device: Device) => {
114
- return device.services.map((service) => service.uuid)
115
- }
116
- /**
117
- * Connects to a Bluetooth device.
118
- * @param {Device} board - The device to connect to.
119
- * @param {Function} [onSuccess] - Optional callback function to execute on successful connection. Default logs success.
120
- * @param {Function} [onError] - Optional callback function to execute on error. Default logs the error.
121
- */
122
- export const connect = async (
123
- board: Device,
124
- onSuccess: () => void = () => console.log("Connected successfully"),
125
- onError: (error: Error) => void = (error) => console.error(error),
126
- ): Promise<void> => {
127
- try {
128
- // Request device and set up connection
129
- const deviceServices = getAllServiceUUIDs(board)
130
-
131
- // Only data matching the optionalManufacturerData parameter to requestDevice is included in the advertisement event: https://github.com/WebBluetoothCG/web-bluetooth/issues/598
132
- const optionalManufacturerData = board.filters.flatMap(
133
- (filter) => filter.manufacturerData?.map((data) => data.companyIdentifier) || [],
134
- )
135
-
136
- const device = await navigator.bluetooth.requestDevice({
137
- filters: board.filters,
138
- optionalServices: deviceServices,
139
- optionalManufacturerData,
140
- })
141
-
142
- board.device = device
143
-
144
- if (!board.device.gatt) {
145
- throw new Error("GATT is not available on this device")
146
- }
147
-
148
- board.device.addEventListener("gattserverdisconnected", (event) => {
149
- onDisconnected(event, board)
150
- })
151
-
152
- // WH-C06
153
- const MANUFACTURER_ID = 256 // 0x0100
154
-
155
- board.device.addEventListener("advertisementreceived", (event) => {
156
- const manufacturerData = event.manufacturerData.get(MANUFACTURER_ID)
157
- if (manufacturerData) {
158
- // Device has no services / characteristics
159
- onSuccess()
160
- // Handle recieved data
161
- handleWHC06Data(manufacturerData)
162
- }
163
- })
164
-
165
- // When the companyIdentifier is provided we want to get manufacturerData using watchAdvertisements.
166
- if (optionalManufacturerData.length) {
167
- // Receive events when the system receives an advertisement packet from a watched device.
168
- // To use this function in Chrome: chrome://flags/#enable-experimental-web-platform-features has to be enabled.
169
- // More info: https://chromestatus.com/feature/5180688812736512
170
- if (typeof board.device.watchAdvertisements === "function") {
171
- await board.device.watchAdvertisements()
172
- } else {
173
- throw new Error(
174
- "watchAdvertisements isn't supported. For Chrome, enable it at chrome://flags/#enable-experimental-web-platform-features.",
175
- )
176
- }
177
- }
178
-
179
- server = await board.device.gatt.connect()
180
-
181
- if (server.connected) {
182
- await onConnected(board, onSuccess)
183
- }
184
- } catch (error) {
185
- onError(error as Error)
186
- }
187
- }
@@ -1,41 +0,0 @@
1
- import { notifyCallback } from "./../notify"
2
- import { checkActivity } from "./../is-active"
3
- import { applyTare } from "./../tare"
4
-
5
- // Constants
6
- let MASS_MAX = "0"
7
- let MASS_AVERAGE = "0"
8
- let MASS_TOTAL_SUM = 0
9
- let DATAPOINT_COUNT = 0
10
-
11
- /**
12
- * Handles data received from the Entralpi device.
13
- * @param {string} receivedData - The received data string.
14
- */
15
- export const handleEntralpiData = (receivedData: string): void => {
16
- let numericData = Number(receivedData)
17
-
18
- // Tare correction
19
- numericData -= applyTare(numericData)
20
-
21
- // Update MASS_MAX
22
- MASS_MAX = Math.max(Number(MASS_MAX), numericData).toFixed(1)
23
-
24
- // Update running sum and count
25
- const currentMassTotal = Math.max(-1000, numericData)
26
- MASS_TOTAL_SUM += currentMassTotal
27
- DATAPOINT_COUNT++
28
-
29
- // Calculate the average dynamically
30
- MASS_AVERAGE = (MASS_TOTAL_SUM / DATAPOINT_COUNT).toFixed(1)
31
-
32
- // Check if device is being used
33
- checkActivity(numericData)
34
-
35
- // Notify with weight data
36
- notifyCallback({
37
- massMax: MASS_MAX,
38
- massAverage: MASS_AVERAGE,
39
- massTotal: Math.max(-1000, numericData).toFixed(1),
40
- })
41
- }
package/src/data/index.ts DELETED
@@ -1,7 +0,0 @@
1
- export { handleEntralpiData } from "./entralpi"
2
-
3
- export { handleMotherboardData } from "./motherboard"
4
-
5
- export { handleProgressorData } from "./progressor"
6
-
7
- export { handleWHC06Data } from "./wh-c06"
@@ -1,163 +0,0 @@
1
- import { notifyCallback } from "./../notify"
2
- import { writeCallback } from "./../write"
3
- import { applyTare } from "./../tare"
4
- import { MotherboardCommands } from "./../commands"
5
- import { checkActivity } from "./../is-active"
6
- import { lastWrite } from "./../write"
7
- import { DownloadPackets } from "./../download"
8
- import type { DownloadPacket } from "./../types/download"
9
-
10
- // Constants
11
- const PACKET_LENGTH = 32
12
- const NUM_SAMPLES = 3
13
- let MASS_MAX = "0"
14
- let MASS_AVERAGE = "0"
15
- let MASS_TOTAL_SUM = 0
16
- let DATAPOINT_COUNT = 0
17
- export const CALIBRATION = [[], [], [], []]
18
-
19
- /**
20
- * Applies calibration to a sample value.
21
- * @param {number} sample - The sample value to calibrate.
22
- * @param {number[][]} calibration - The calibration data.
23
- * @returns {number} The calibrated sample value.
24
- */
25
- const applyCalibration = (sample: number, calibration: number[][]): number => {
26
- // Extract the calibrated value for the zero point
27
- const zeroCalibration: number = calibration[0][2]
28
- // Initialize sign as positive
29
- let sign = 1
30
- // Initialize the final calibrated value
31
- let final = 0
32
-
33
- // If the sample value is less than the zero calibration point
34
- if (sample < zeroCalibration) {
35
- // Change the sign to negative
36
- sign = -1
37
- // Reflect the sample around the zero calibration point
38
- sample = /* 2 * zeroCalibration */ -sample
39
- }
40
-
41
- // Iterate through the calibration data
42
- for (let i = 1; i < calibration.length; i++) {
43
- // Extract the lower and upper bounds of the current calibration range
44
- const calibrationStart: number = calibration[i - 1][2]
45
- const calibrationEnd: number = calibration[i][2]
46
-
47
- // If the sample value is within the current calibration range
48
- if (sample < calibrationEnd) {
49
- // Interpolate to get the calibrated value within the range
50
- final =
51
- calibration[i - 1][1] +
52
- ((sample - calibrationStart) / (calibrationEnd - calibrationStart)) *
53
- (calibration[i][1] - calibration[i - 1][1])
54
- break
55
- }
56
- }
57
- // Return the calibrated value with the appropriate sign (positive/negative)
58
- return sign * final
59
- }
60
- /**
61
- * Handles data received from the Motherboard device. Processes hex-encoded streaming packets
62
- * to extract samples, calibrate masses, and update running averages of mass data.
63
- * If the received data is not a valid hex packet, it returns the unprocessed data.
64
- *
65
- * @param {string} receivedData - The raw data received from the Motherboard device.
66
- * @returns {void}
67
- */
68
- export const handleMotherboardData = (receivedData: string): void => {
69
- const receivedTime: number = Date.now()
70
-
71
- // Check if the line is entirely hex characters
72
- const isAllHex: boolean = /^[0-9A-Fa-f]+$/g.test(receivedData)
73
-
74
- // Handle streaming packet
75
- if (isAllHex && receivedData.length === PACKET_LENGTH) {
76
- // Base-16 decode the string: convert hex pairs to byte values
77
- const bytes: number[] = Array.from({ length: receivedData.length / 2 }, (_, i) =>
78
- Number(`0x${receivedData.substring(i * 2, i * 2 + 2)}`),
79
- )
80
-
81
- // Translate header into packet, number of samples from the packet length
82
- const packet: DownloadPacket = {
83
- received: receivedTime,
84
- sampleNum: new DataView(new Uint8Array(bytes).buffer).getUint16(0, true),
85
- battRaw: new DataView(new Uint8Array(bytes).buffer).getUint16(2, true),
86
- samples: [],
87
- masses: [],
88
- }
89
-
90
- const dataView = new DataView(new Uint8Array(bytes).buffer)
91
-
92
- for (let i = 0; i < NUM_SAMPLES; i++) {
93
- const sampleStart: number = 4 + 3 * i
94
- // Use DataView to read the 24-bit unsigned integer
95
- const rawValue =
96
- dataView.getUint8(sampleStart) |
97
- (dataView.getUint8(sampleStart + 1) << 8) |
98
- (dataView.getUint8(sampleStart + 2) << 16)
99
-
100
- // Ensure unsigned 32-bit integer
101
- packet.samples[i] = rawValue >>> 0
102
-
103
- if (packet.samples[i] >= 0x7fffff) {
104
- packet.samples[i] -= 0x1000000
105
- }
106
- packet.masses[i] = applyCalibration(packet.samples[i], CALIBRATION[i])
107
- }
108
- // invert center and right values
109
- packet.masses[1] *= -1
110
- packet.masses[2] *= -1
111
-
112
- // Add data to downloadable Array
113
- DownloadPackets.push({
114
- received: packet.received,
115
- sampleNum: packet.battRaw,
116
- battRaw: packet.received,
117
- samples: [...packet.samples],
118
- masses: [...packet.masses],
119
- })
120
-
121
- let left: number = packet.masses[0]
122
- let center: number = packet.masses[1]
123
- let right: number = packet.masses[2]
124
-
125
- // Tare correction
126
- left -= applyTare(left)
127
- center -= applyTare(center)
128
- right -= applyTare(right)
129
-
130
- MASS_MAX = Math.max(Number(MASS_MAX), Math.max(-1000, left + center + right)).toFixed(1)
131
-
132
- // Update running sum and count
133
- const currentMassTotal = Math.max(-1000, left + center + right)
134
- MASS_TOTAL_SUM += currentMassTotal
135
- DATAPOINT_COUNT++
136
-
137
- // Calculate the average dynamically
138
- MASS_AVERAGE = (MASS_TOTAL_SUM / DATAPOINT_COUNT).toFixed(1)
139
-
140
- // Check if device is being used
141
- checkActivity(center)
142
-
143
- // Notify with weight data
144
- notifyCallback({
145
- massTotal: Math.max(-1000, left + center + right).toFixed(1),
146
- massMax: MASS_MAX,
147
- massAverage: MASS_AVERAGE,
148
- massLeft: Math.max(-1000, packet.masses[0]).toFixed(1),
149
- massCenter: Math.max(-1000, packet.masses[1]).toFixed(1),
150
- massRight: Math.max(-1000, packet.masses[2]).toFixed(1),
151
- })
152
- } else if (lastWrite === MotherboardCommands.GET_CALIBRATION) {
153
- // check data integrity
154
- if ((receivedData.match(/,/g) || []).length === 3) {
155
- const parts: string[] = receivedData.split(",")
156
- const numericParts: number[] = parts.map((x) => parseFloat(x))
157
- ;(CALIBRATION[numericParts[0]] as number[][]).push(numericParts.slice(1))
158
- }
159
- } else {
160
- // unhandled data
161
- writeCallback(receivedData)
162
- }
163
- }
@@ -1,79 +0,0 @@
1
- import { notifyCallback } from "./../notify"
2
- import { applyTare } from "./../tare"
3
- import { checkActivity } from "./../is-active"
4
- import { ProgressorCommands, ProgressorResponses } from "./../commands/progressor"
5
- import { lastWrite, writeCallback } from "./../write"
6
- import struct from "./../struct"
7
- import { DownloadPackets } from "./../download"
8
-
9
- // Constants
10
- let MASS_MAX = "0"
11
- let MASS_AVERAGE = "0"
12
- let MASS_TOTAL_SUM = 0
13
- let DATAPOINT_COUNT = 0
14
-
15
- /**
16
- * Handles data received from the Progressor device, processes weight measurements,
17
- * and updates mass data including maximum and average values.
18
- * It also handles command responses for retrieving device information.
19
- *
20
- * @param {DataView} data - The raw binary data received from the Progressor device.
21
- * @returns {void}
22
- */
23
- export const handleProgressorData = (data: DataView): void => {
24
- const receivedTime: number = Date.now()
25
- const [kind] = struct("<bb").unpack(data.buffer.slice(0, 2))
26
- if (kind === ProgressorResponses.WEIGHT_MEASURE) {
27
- const iterable: IterableIterator<unknown[]> = struct("<fi").iter_unpack(data.buffer.slice(2))
28
- // eslint-disable-next-line prefer-const
29
- for (let [weight, seconds] of iterable) {
30
- if (typeof weight === "number" && !isNaN(weight) && typeof seconds === "number" && !isNaN(seconds)) {
31
- // Add data to downloadable Array: sample and mass are the same
32
- DownloadPackets.push({
33
- received: receivedTime,
34
- sampleNum: seconds,
35
- battRaw: 0,
36
- samples: [weight],
37
- masses: [weight],
38
- })
39
- // Tare correction
40
- weight -= applyTare(weight)
41
- // Check for max weight
42
- MASS_MAX = Math.max(Number(MASS_MAX), Number(weight)).toFixed(1)
43
- // Update running sum and count
44
- const currentMassTotal = Math.max(-1000, Number(weight))
45
- MASS_TOTAL_SUM += currentMassTotal
46
- DATAPOINT_COUNT++
47
-
48
- // Calculate the average dynamically
49
- MASS_AVERAGE = (MASS_TOTAL_SUM / DATAPOINT_COUNT).toFixed(1)
50
-
51
- // Check if device is being used
52
- checkActivity(weight)
53
-
54
- notifyCallback({
55
- massMax: MASS_MAX,
56
- massAverage: MASS_AVERAGE,
57
- massTotal: Math.max(-1000, weight).toFixed(1),
58
- })
59
- }
60
- }
61
- } else if (kind === ProgressorResponses.COMMAND_RESPONSE) {
62
- if (!lastWrite) return
63
-
64
- let value = ""
65
-
66
- if (lastWrite === ProgressorCommands.GET_BATT_VLTG) {
67
- value = new DataView(data.buffer, 2).getUint32(0, true).toString()
68
- } else if (lastWrite === ProgressorCommands.GET_FW_VERSION) {
69
- value = new TextDecoder().decode(data.buffer.slice(2))
70
- } else if (lastWrite === ProgressorCommands.GET_ERR_INFO) {
71
- value = new TextDecoder().decode(data.buffer.slice(2))
72
- }
73
- writeCallback(value)
74
- } else if (kind === ProgressorResponses.LOW_BATTERY_WARNING) {
75
- console.warn("⚠️ Low power detected. Please consider connecting to a power source.")
76
- } else {
77
- throw new Error(`Unknown message kind detected: ${kind}`)
78
- }
79
- }
@@ -1,47 +0,0 @@
1
- import { checkActivity } from "./../is-active"
2
- import { notifyCallback } from "./../notify"
3
- import { applyTare } from "./../tare"
4
-
5
- // Constants
6
- let MASS_MAX = "0"
7
- let MASS_AVERAGE = "0"
8
- let MASS_TOTAL_SUM = 0
9
- let DATAPOINT_COUNT = 0
10
- const WEIGHT_OFFSET = 10
11
- // const STABLE_OFFSET = 14
12
-
13
- /**
14
- * Handles data received from the WH-C06 device.
15
- * @param {DataView} data - The received data.
16
- */
17
- export const handleWHC06Data = (data: DataView): void => {
18
- const weight = (data.getUint8(WEIGHT_OFFSET) << 8) | data.getUint8(WEIGHT_OFFSET + 1)
19
- // const stable = (data.getUint8(STABLE_OFFSET) & 0xf0) >> 4
20
- // const unit = data.getUint8(STABLE_OFFSET) & 0x0f
21
-
22
- let numericData = weight / 100
23
-
24
- // Tare correction
25
- numericData -= applyTare(numericData)
26
-
27
- // Update MASS_MAX
28
- MASS_MAX = Math.max(Number(MASS_MAX), numericData).toFixed(1)
29
-
30
- // Update running sum and count
31
- const currentMassTotal = Math.max(-1000, numericData)
32
- MASS_TOTAL_SUM += currentMassTotal
33
- DATAPOINT_COUNT++
34
-
35
- // Calculate the average dynamically
36
- MASS_AVERAGE = (MASS_TOTAL_SUM / DATAPOINT_COUNT).toFixed(1)
37
-
38
- // Check if device is being used
39
- checkActivity(numericData)
40
-
41
- // Notify with weight data
42
- notifyCallback({
43
- massMax: MASS_MAX,
44
- massAverage: MASS_AVERAGE,
45
- massTotal: Math.max(-1000, numericData).toFixed(1),
46
- })
47
- }
@@ -1,10 +0,0 @@
1
- import type { Device } from "../types/devices"
2
-
3
- /**
4
- * Represents a Climbro device
5
- * TODO: Add services, do you own a Climbro? Help us!
6
- */
7
- export const Climbro: Device = {
8
- filters: [{ name: "Climbro" }],
9
- services: [],
10
- }
@@ -1,61 +0,0 @@
1
- import type { Device } from "../types/devices"
2
-
3
- /**
4
- * Represents a Entralpi device
5
- */
6
- export const Entralpi: Device = {
7
- filters: [
8
- {
9
- name: "ENTRALPI",
10
- },
11
- ],
12
- services: [
13
- {
14
- name: "Device Information",
15
- id: "device",
16
- uuid: "0000180a-0000-1000-8000-00805f9b34fb",
17
- characteristics: [],
18
- },
19
- {
20
- name: "Battery Service",
21
- id: "battery",
22
- uuid: "0000180f-0000-1000-8000-00805f9b34fb",
23
- characteristics: [],
24
- },
25
- {
26
- name: "Generic Attribute",
27
- id: "attribute",
28
- uuid: "00001801-0000-1000-8000-00805f9b34fb",
29
- characteristics: [],
30
- },
31
- {
32
- name: "UART ISSC Transparent Service",
33
- id: "uart",
34
- uuid: "0000fff0-0000-1000-8000-00805f9b34fb",
35
- characteristics: [
36
- {
37
- name: "TX",
38
- id: "tx",
39
- uuid: "0000fff5-0000-1000-8000-00805f9b34fb",
40
- },
41
- {
42
- name: "RX",
43
- id: "rx",
44
- uuid: "0000fff4-0000-1000-8000-00805f9b34fb",
45
- },
46
- ],
47
- },
48
- {
49
- name: "Weight Scale",
50
- id: "weight",
51
- uuid: "0000181d-0000-1000-8000-00805f9b34fb",
52
- characteristics: [],
53
- },
54
- {
55
- name: "Generic Access",
56
- id: "access",
57
- uuid: "00001800-0000-1000-8000-00805f9b34fb",
58
- characteristics: [],
59
- },
60
- ],
61
- }
@@ -1,13 +0,0 @@
1
- export { Climbro } from "./climbro"
2
-
3
- export { Entralpi } from "./entralpi"
4
-
5
- export { KilterBoard } from "./kilterboard"
6
-
7
- export { Motherboard } from "./motherboard"
8
-
9
- export { mySmartBoard } from "./mysmartboard"
10
-
11
- export { WHC06 } from "./wh-c06"
12
-
13
- export { Progressor } from "./progressor"
@@ -1,37 +0,0 @@
1
- import type { Device } from "../types/devices"
2
-
3
- /**
4
- * Aurora Climbing Advertising service
5
- */
6
- export const AuroraUUID = "4488b571-7806-4df6-bcff-a2897e4953ff"
7
-
8
- /**
9
- * Represents a Aurora Climbing device
10
- * Kilter Board, Tension Board, Decoy Board, Touchstone Board, Grasshopper Board, Aurora Board, So iLL Board
11
- */
12
- export const KilterBoard: Device = {
13
- filters: [
14
- {
15
- services: [AuroraUUID],
16
- },
17
- ],
18
- services: [
19
- {
20
- name: "UART Nordic Service",
21
- id: "uart",
22
- uuid: "6e400001-b5a3-f393-e0a9-e50e24dcca9e",
23
- characteristics: [
24
- {
25
- name: "TX",
26
- id: "tx",
27
- uuid: "6e400002-b5a3-f393-e0a9-e50e24dcca9e",
28
- },
29
- // {
30
- // name: "RX",
31
- // id: "rx",
32
- // uuid: "6e400003-b5a3-f393-e0a9-e50e24dcca9e",
33
- // },
34
- ],
35
- },
36
- ],
37
- }