@hangtime/grip-connect 0.3.1 → 0.3.3
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 +25 -7
- package/package.json +1 -1
- package/src/battery.ts +3 -3
- package/src/calibration.ts +2 -2
- package/src/characteristic.ts +1 -1
- package/src/commands/climbro.ts +1 -1
- package/src/commands/entralpi.ts +1 -1
- package/src/commands/motherboard.ts +1 -1
- package/src/commands/musclemeter.ts +1 -1
- package/src/commands/mysmartboard.ts +1 -1
- package/src/commands/progressor.ts +7 -7
- package/src/connect.ts +7 -23
- package/src/data.ts +2 -1
- package/src/devices/climbro.ts +2 -2
- package/src/devices/entralpi.ts +6 -2
- package/src/devices/index.ts +2 -0
- package/src/devices/kilterboard.ts +32 -0
- package/src/devices/motherboard.ts +2 -3
- package/src/devices/musclemeter.ts +2 -2
- package/src/devices/mysmartboard.ts +2 -2
- package/src/devices/progressor.ts +2 -2
- package/src/disconnect.ts +1 -1
- package/src/download.ts +1 -11
- package/src/index.ts +1 -1
- package/src/info.ts +3 -3
- package/src/is-connected.ts +1 -1
- package/src/notify.ts +3 -10
- package/src/read.ts +1 -1
- package/src/stop.ts +3 -3
- package/src/stream.ts +3 -3
- package/src/types/devices.ts +39 -0
- package/src/types/download.ts +15 -0
- package/src/types/notify.ts +14 -0
- package/src/write.ts +1 -4
- package/src/battery.d.ts +0 -7
- package/src/battery.js +0 -25
- package/src/calibration.d.ts +0 -7
- package/src/calibration.js +0 -19
- package/src/characteristic.d.ts +0 -10
- package/src/characteristic.js +0 -20
- package/src/commands/climbro.d.ts +0 -6
- package/src/commands/climbro.js +0 -5
- package/src/commands/entralpi.d.ts +0 -6
- package/src/commands/entralpi.js +0 -5
- package/src/commands/index.d.ts +0 -6
- package/src/commands/index.js +0 -6
- package/src/commands/motherboard.d.ts +0 -6
- package/src/commands/motherboard.js +0 -13
- package/src/commands/musclemeter.d.ts +0 -6
- package/src/commands/musclemeter.js +0 -5
- package/src/commands/mysmartboard.d.ts +0 -6
- package/src/commands/mysmartboard.js +0 -5
- package/src/commands/progressor.d.ts +0 -17
- package/src/commands/progressor.js +0 -29
- package/src/commands/types.d.ts +0 -18
- package/src/commands/types.js +0 -1
- package/src/connect.d.ts +0 -7
- package/src/connect.js +0 -152
- package/src/data.d.ts +0 -16
- package/src/data.js +0 -220
- package/src/devices/climbro.d.ts +0 -6
- package/src/devices/climbro.js +0 -8
- package/src/devices/entralpi.d.ts +0 -5
- package/src/devices/entralpi.js +0 -55
- package/src/devices/index.d.ts +0 -6
- package/src/devices/index.js +0 -6
- package/src/devices/motherboard.d.ts +0 -5
- package/src/devices/motherboard.js +0 -82
- package/src/devices/musclemeter.d.ts +0 -6
- package/src/devices/musclemeter.js +0 -8
- package/src/devices/mysmartboard.d.ts +0 -6
- package/src/devices/mysmartboard.js +0 -8
- package/src/devices/progressor.d.ts +0 -5
- package/src/devices/progressor.js +0 -37
- package/src/devices/types.d.ts +0 -29
- package/src/devices/types.js +0 -1
- package/src/devices/types.ts +0 -29
- package/src/disconnect.d.ts +0 -6
- package/src/disconnect.js +0 -12
- package/src/download.d.ts +0 -19
- package/src/download.js +0 -50
- package/src/index.d.ts +0 -12
- package/src/index.js +0 -20
- package/src/info.d.ts +0 -7
- package/src/info.js +0 -30
- package/src/is-connected.d.ts +0 -7
- package/src/is-connected.js +0 -13
- package/src/notify.d.ts +0 -22
- package/src/notify.js +0 -14
- package/src/read.d.ts +0 -10
- package/src/read.js +0 -49
- package/src/stop.d.ts +0 -7
- package/src/stop.js +0 -21
- package/src/stream.d.ts +0 -8
- package/src/stream.js +0 -41
- package/src/struct/index.d.ts +0 -9
- package/src/struct/index.js +0 -176
- package/src/tare.d.ts +0 -12
- package/src/tare.js +0 -70
- package/src/write.d.ts +0 -16
- package/src/write.js +0 -56
- /package/src/{commands/types.ts → types/commands.ts} +0 -0
package/README.md
CHANGED
|
@@ -3,18 +3,31 @@
|
|
|
3
3
|
**Force-Sensing Climbing Training**
|
|
4
4
|
|
|
5
5
|
The objective of this project is to create a Web Bluetooth API client that can establish connections with various
|
|
6
|
-
Force-Sensing Hangboards / Plates used by climbers for strength measurement. Examples of such
|
|
7
|
-
[Griptonite Motherboard](https://griptonite.io/shop/motherboard/),
|
|
8
|
-
[
|
|
9
|
-
[
|
|
6
|
+
Force-Sensing Hangboards / Plates / LED system boards used by climbers for strength measurement. Examples of such
|
|
7
|
+
hangboards include the [Griptonite Motherboard](https://griptonite.io/shop/motherboard/),
|
|
8
|
+
[Climbro](https://climbro.com/), [mySmartBoard](https://www.smartboard-climbing.com/),
|
|
9
|
+
[Entralpi](https://entralpi.com/), [Tindeq Progressor](https://tindeq.com/) or
|
|
10
|
+
[MAT Muscle Meter](https://www.matassessment.com/musclemeter)
|
|
11
|
+
|
|
12
|
+
And LED system boards from [Aurora Climbing](https://auroraclimbing.com/) like the
|
|
13
|
+
[Kilter Board](https://settercloset.com/pages/the-kilter-board),
|
|
14
|
+
[Tension Board](https://tensionclimbing.com/product/tension-board-2/),
|
|
15
|
+
[Grasshopper Board](https://grasshopperclimbing.com/products/),
|
|
16
|
+
[Decoy Board](https://decoy-holds.com/pages/decoy-board), [Touchstone Board](https://touchstoneboardapp.com/) and
|
|
17
|
+
[So iLL Board](https://apps.apple.com/us/app/so-ill-board/id1358056082).
|
|
10
18
|
|
|
11
19
|
Learn more: [Docs](https://stevie-ray.github.io/hangtime-grip-connect/) -
|
|
12
20
|
[Browser Support](https://caniuse.com/web-bluetooth)
|
|
13
21
|
|
|
22
|
+
> [!CAUTION] This project is provided "as-is" without any express or implied warranties. By using this software, you
|
|
23
|
+
> assume all risks associated with its use, including but not limited to hardware damage, data loss, or any other issues
|
|
24
|
+
> that may arise. The developers and contributors are not responsible for any harm or loss incurred. Use this software
|
|
25
|
+
> at your own discretion and responsibility.
|
|
26
|
+
|
|
14
27
|
## Try it out
|
|
15
28
|
|
|
16
29
|
[Chart](https://grip-connect.vercel.app/) - [Flappy Bird](https://grip-connect-flappy-bird.vercel.app/) -
|
|
17
|
-
[
|
|
30
|
+
[Kilter Board](https://grip-connect-kilter-board.vercel.app/)
|
|
18
31
|
|
|
19
32
|
## Install
|
|
20
33
|
|
|
@@ -77,7 +90,8 @@ available services with us.
|
|
|
77
90
|
|
|
78
91
|
- ✅ Griptonite Motherboard
|
|
79
92
|
- ✅ Tindeq Progressor
|
|
80
|
-
-
|
|
93
|
+
- ⏳ Entralpi (not verified)
|
|
94
|
+
- ⏳ Kilterboard (write only, see example)
|
|
81
95
|
- ➡️ Climbro
|
|
82
96
|
- ➡️ mySmartBoard
|
|
83
97
|
- ➡️ MAT Muscle Meter
|
|
@@ -113,9 +127,13 @@ A special thank you to:
|
|
|
113
127
|
- [@donaldharvey](https://github.com/donaldharvey) for a valuable example on connecting to the Motherboard.
|
|
114
128
|
- [@ecstrema](https://github.com/ecstrema) for providing [examples](https://github.com/ecstrema/entralpi-games) on how
|
|
115
129
|
to play games with the Entralpi.
|
|
116
|
-
- [Tindeq](https://tindeq.com/) for providing an open [Progressor API](https://tindeq.com/progressor_api/)
|
|
130
|
+
- [Tindeq](https://tindeq.com/) for providing an open [Progressor API](https://tindeq.com/progressor_api/).
|
|
117
131
|
- [@StuartLittlefair](https://github.com/StuartLittlefair) for his
|
|
118
132
|
[PyTindeq](https://github.com/StuartLittlefair/PyTindeq) implementation.
|
|
133
|
+
- [@Phil9l](https://github.com/phil9l) for his research and providing a [blog](https://bazun.me/blog/kiterboard/) on how
|
|
134
|
+
to connect with the Kilter Board.
|
|
135
|
+
- [@1-max-1](https://github.com/1-max-1/fake_kilter_board) for the docs on his Kilter Board
|
|
136
|
+
[https://github.com/1-max-1/fake_kilter_board](simulator).
|
|
119
137
|
|
|
120
138
|
## Disclaimer
|
|
121
139
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hangtime/grip-connect",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "A client that can establish connections with various Force-Sensing Hangboards/Plates used by climbers for strength measurement. Examples of such hangboards include the Griptonite Motherboard, Climbro, SmartBoard, Entralpi or Tindeq Progressor",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"scripts": {
|
package/src/battery.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Device } from "./devices
|
|
1
|
+
import type { Device } from "./types/devices"
|
|
2
2
|
import { write } from "./write"
|
|
3
3
|
import { read } from "./read"
|
|
4
4
|
import { isConnected } from "./is-connected"
|
|
@@ -14,12 +14,12 @@ export const battery = async (board: Device): Promise<void> => {
|
|
|
14
14
|
// Check if the device is connected
|
|
15
15
|
if (isConnected(board)) {
|
|
16
16
|
// If the device is connected and it is a Motherboard device
|
|
17
|
-
if (board.name === "Motherboard") {
|
|
17
|
+
if (board.filters.some((filter) => filter.name === "Motherboard")) {
|
|
18
18
|
// Read battery level information from the Motherboard
|
|
19
19
|
await read(Motherboard, "battery", "level", 250)
|
|
20
20
|
}
|
|
21
21
|
// If the device is connected and its name starts with "Progressor"
|
|
22
|
-
if (board.
|
|
22
|
+
if (board.filters.some((filter) => filter.namePrefix === "Progressor")) {
|
|
23
23
|
// Write command to get battery voltage information to the Progressor
|
|
24
24
|
await write(Progressor, "progressor", "tx", ProgressorCommands.GET_BATT_VLTG, 250)
|
|
25
25
|
}
|
package/src/calibration.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Device } from "./devices
|
|
1
|
+
import type { Device } from "./types/devices"
|
|
2
2
|
import { isConnected } from "./is-connected"
|
|
3
3
|
import { write } from "./write"
|
|
4
4
|
import { Motherboard } from "./devices"
|
|
@@ -13,7 +13,7 @@ export const calibration = async (board: Device): Promise<void> => {
|
|
|
13
13
|
// Check if the device is connected
|
|
14
14
|
if (isConnected(board)) {
|
|
15
15
|
// If the device is connected, and it is a Motherboard device
|
|
16
|
-
if (board.name === "Motherboard") {
|
|
16
|
+
if (board.filters.some((filter) => filter.name === "Motherboard")) {
|
|
17
17
|
// Write the command to get calibration data to the device
|
|
18
18
|
await write(Motherboard, "uart", "tx", MotherboardCommands.GET_CALIBRATION, 2500)
|
|
19
19
|
}
|
package/src/characteristic.ts
CHANGED
package/src/commands/climbro.ts
CHANGED
package/src/commands/entralpi.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Commands } from "../commands
|
|
1
|
+
import type { Commands } from "../types/commands"
|
|
2
2
|
/**
|
|
3
3
|
* Warning:
|
|
4
4
|
* Using other commands can seriously harm your device
|
|
@@ -22,10 +22,10 @@ export const ProgressorCommands: Commands = {
|
|
|
22
22
|
* The Progressor returns a Uint8Array.
|
|
23
23
|
* The first item [0] is the type of response it returns
|
|
24
24
|
*/
|
|
25
|
-
export
|
|
26
|
-
COMMAND_RESPONSE
|
|
27
|
-
WEIGHT_MEASURE
|
|
28
|
-
PEAK_RFD_MEAS
|
|
29
|
-
PEAK_RFD_MEAS_SERIES
|
|
30
|
-
LOW_BATTERY_WARNING
|
|
25
|
+
export enum ProgressorResponses {
|
|
26
|
+
COMMAND_RESPONSE,
|
|
27
|
+
WEIGHT_MEASURE,
|
|
28
|
+
PEAK_RFD_MEAS,
|
|
29
|
+
PEAK_RFD_MEAS_SERIES,
|
|
30
|
+
LOW_BATTERY_WARNING,
|
|
31
31
|
}
|
package/src/connect.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Device } from "./devices
|
|
1
|
+
import type { Device } from "./types/devices"
|
|
2
2
|
import { handleEntralpiData, handleMotherboardData, handleProgressorData } from "./data"
|
|
3
3
|
|
|
4
4
|
let server: BluetoothRemoteGATTServer
|
|
@@ -24,7 +24,8 @@ const handleNotifications = (event: Event, board: Device): void => {
|
|
|
24
24
|
const value: DataView | undefined = characteristic.value
|
|
25
25
|
|
|
26
26
|
if (value) {
|
|
27
|
-
|
|
27
|
+
// If the device is connected and it is a Motherboard device
|
|
28
|
+
if (board.filters.some((filter) => filter.name === "Motherboard")) {
|
|
28
29
|
for (let i: number = 0; i < value.byteLength; i++) {
|
|
29
30
|
receiveBuffer.push(value.getUint8(i))
|
|
30
31
|
}
|
|
@@ -37,14 +38,14 @@ const handleNotifications = (event: Event, board: Device): void => {
|
|
|
37
38
|
const receivedData: string = decoder.decode(new Uint8Array(line))
|
|
38
39
|
handleMotherboardData(receivedData)
|
|
39
40
|
}
|
|
40
|
-
} else if (board.name === "ENTRALPI") {
|
|
41
|
+
} else if (board.filters.some((filter) => filter.name === "ENTRALPI")) {
|
|
41
42
|
if (value.buffer) {
|
|
42
43
|
const buffer: ArrayBuffer = value.buffer
|
|
43
44
|
const rawData: DataView = new DataView(buffer)
|
|
44
45
|
const receivedData: string = (rawData.getUint16(0) / 100).toFixed(1)
|
|
45
46
|
handleEntralpiData(receivedData)
|
|
46
47
|
}
|
|
47
|
-
} else if (board.
|
|
48
|
+
} else if (board.filters.some((filter) => filter.namePrefix === "Progressor")) {
|
|
48
49
|
if (value.buffer) {
|
|
49
50
|
const buffer: ArrayBuffer = value.buffer
|
|
50
51
|
const rawData: DataView = new DataView(buffer)
|
|
@@ -90,7 +91,7 @@ const onConnected = async (board: Device, onSuccess: () => void): Promise<void>
|
|
|
90
91
|
// notify
|
|
91
92
|
if (element.id === "rx") {
|
|
92
93
|
matchingCharacteristic.startNotifications()
|
|
93
|
-
matchingCharacteristic.addEventListener("characteristicvaluechanged", (event) =>
|
|
94
|
+
matchingCharacteristic.addEventListener("characteristicvaluechanged", (event: Event) =>
|
|
94
95
|
handleNotifications(event, board),
|
|
95
96
|
)
|
|
96
97
|
}
|
|
@@ -126,25 +127,8 @@ export const connect = async (board: Device, onSuccess: () => void): Promise<voi
|
|
|
126
127
|
// Request device and set up connection
|
|
127
128
|
const deviceServices = getAllServiceUUIDs(board)
|
|
128
129
|
|
|
129
|
-
// setup filter list
|
|
130
|
-
const filters = []
|
|
131
|
-
|
|
132
|
-
if (board.name) {
|
|
133
|
-
const filterName = board.name === "Progressor" ? { namePrefix: board.name } : { name: board.name }
|
|
134
|
-
filters.push(filterName)
|
|
135
|
-
}
|
|
136
|
-
if (board.companyId) {
|
|
137
|
-
filters.push({
|
|
138
|
-
manufacturerData: [
|
|
139
|
-
{
|
|
140
|
-
companyIdentifier: board.companyId,
|
|
141
|
-
},
|
|
142
|
-
],
|
|
143
|
-
})
|
|
144
|
-
}
|
|
145
|
-
|
|
146
130
|
const device = await navigator.bluetooth.requestDevice({
|
|
147
|
-
filters: filters,
|
|
131
|
+
filters: board.filters,
|
|
148
132
|
optionalServices: deviceServices,
|
|
149
133
|
})
|
|
150
134
|
|
package/src/data.ts
CHANGED
|
@@ -3,8 +3,9 @@ import { applyTare } from "./tare"
|
|
|
3
3
|
import { ProgressorCommands, ProgressorResponses } from "./commands/progressor"
|
|
4
4
|
import { MotherboardCommands } from "./commands"
|
|
5
5
|
import { lastWrite } from "./write"
|
|
6
|
-
import { DownloadPacket, DownloadPackets } from "./download"
|
|
7
6
|
import struct from "./struct"
|
|
7
|
+
import { DownloadPackets } from "./download"
|
|
8
|
+
import type { DownloadPacket } from "./types/download"
|
|
8
9
|
|
|
9
10
|
// Constants
|
|
10
11
|
const PACKET_LENGTH: number = 32
|
package/src/devices/climbro.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Device } from "
|
|
1
|
+
import type { Device } from "../types/devices"
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Represents a Climbro device
|
|
5
5
|
* TODO: Add services, do you own a Climbro? Help us!
|
|
6
6
|
*/
|
|
7
7
|
export const Climbro: Device = {
|
|
8
|
-
name: "Climbro",
|
|
8
|
+
filters: [{ name: "Climbro" }],
|
|
9
9
|
services: [],
|
|
10
10
|
}
|
package/src/devices/entralpi.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { Device } from "
|
|
1
|
+
import type { Device } from "../types/devices"
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Represents a Entralpi device
|
|
5
5
|
*/
|
|
6
6
|
export const Entralpi: Device = {
|
|
7
|
-
|
|
7
|
+
filters: [
|
|
8
|
+
{
|
|
9
|
+
name: "ENTRALPI",
|
|
10
|
+
},
|
|
11
|
+
],
|
|
8
12
|
services: [
|
|
9
13
|
{
|
|
10
14
|
name: "Device Information",
|
package/src/devices/index.ts
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Device } from "../types/devices"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents a Aurora Climbing device
|
|
5
|
+
* Kilter Board, Tension Board, Decoy Board, Touchstone Board, Grasshopper Board, Aurora Board, So iLL Board
|
|
6
|
+
*/
|
|
7
|
+
export const KilterBoard: Device = {
|
|
8
|
+
filters: [
|
|
9
|
+
{
|
|
10
|
+
services: ["4488b571-7806-4df6-bcff-a2897e4953ff"], // Aurora Climbing Advertising service
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
services: [
|
|
14
|
+
{
|
|
15
|
+
name: "UART Nordic Service",
|
|
16
|
+
id: "uart",
|
|
17
|
+
uuid: "6e400001-b5a3-f393-e0a9-e50e24dcca9e",
|
|
18
|
+
characteristics: [
|
|
19
|
+
{
|
|
20
|
+
name: "TX",
|
|
21
|
+
id: "tx",
|
|
22
|
+
uuid: "6e400002-b5a3-f393-e0a9-e50e24dcca9e",
|
|
23
|
+
},
|
|
24
|
+
// {
|
|
25
|
+
// name: "RX",
|
|
26
|
+
// id: "rx",
|
|
27
|
+
// uuid: "6e400003-b5a3-f393-e0a9-e50e24dcca9e",
|
|
28
|
+
// },
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { Device } from "
|
|
1
|
+
import type { Device } from "../types/devices"
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Represents a Griptonite Motherboard device
|
|
5
5
|
*/
|
|
6
6
|
export const Motherboard: Device = {
|
|
7
|
-
name: "Motherboard",
|
|
8
|
-
companyId: 0x2a29,
|
|
7
|
+
filters: [{ name: "Motherboard" }],
|
|
9
8
|
services: [
|
|
10
9
|
{
|
|
11
10
|
name: "Device Information",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Device } from "
|
|
1
|
+
import type { Device } from "../types/devices"
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Represents a MAT Muscle Meter device
|
|
5
5
|
* TODO: Add services, do you own a MAT Muscle Meter? Help us!
|
|
6
6
|
*/
|
|
7
7
|
export const MuscleMeter: Device = {
|
|
8
|
-
name: "MAT",
|
|
8
|
+
filters: [{ name: "MAT" }],
|
|
9
9
|
services: [],
|
|
10
10
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Device } from "
|
|
1
|
+
import type { Device } from "../types/devices"
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Represents a mySmartBoard device
|
|
5
5
|
* TODO: Add services, do you own a mySmartBoard? Help us!
|
|
6
6
|
*/
|
|
7
7
|
export const mySmartBoard: Device = {
|
|
8
|
-
name: "mySmartBoard",
|
|
8
|
+
filters: [{ name: "mySmartBoard" }],
|
|
9
9
|
services: [],
|
|
10
10
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Device } from "
|
|
1
|
+
import type { Device } from "../types/devices"
|
|
2
2
|
/**
|
|
3
3
|
* Represents a Tindeq Progressor device
|
|
4
4
|
*/
|
|
5
5
|
export const Progressor: Device = {
|
|
6
|
-
|
|
6
|
+
filters: [{ namePrefix: "Progressor" }],
|
|
7
7
|
services: [
|
|
8
8
|
{
|
|
9
9
|
name: "Progressor Service",
|
package/src/disconnect.ts
CHANGED
package/src/download.ts
CHANGED
|
@@ -1,14 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Represents a single data packet.
|
|
3
|
-
*/
|
|
4
|
-
export interface DownloadPacket {
|
|
5
|
-
received: number // Timestamp of when the packet was received
|
|
6
|
-
sampleNum: number // Sample number
|
|
7
|
-
battRaw: number // Battery raw value
|
|
8
|
-
samples: number[] // Array of sample values
|
|
9
|
-
masses: number[] // Array of mass values
|
|
10
|
-
}
|
|
11
|
-
|
|
1
|
+
import type { DownloadPacket } from "./types/download"
|
|
12
2
|
/**
|
|
13
3
|
* Array of DownloadPacket entries.
|
|
14
4
|
*/
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Export device types
|
|
2
|
-
export { Climbro, Entralpi, Motherboard, mySmartBoard, MuscleMeter, Progressor } from "./devices/index"
|
|
2
|
+
export { Climbro, Entralpi, KilterBoard, Motherboard, mySmartBoard, MuscleMeter, Progressor } from "./devices/index"
|
|
3
3
|
|
|
4
4
|
// Export battery related functions
|
|
5
5
|
export { battery } from "./battery"
|
package/src/info.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Device } from "./devices
|
|
1
|
+
import type { Device } from "./types/devices"
|
|
2
2
|
import { write } from "./write"
|
|
3
3
|
import { read } from "./read"
|
|
4
4
|
import { isConnected } from "./is-connected"
|
|
@@ -12,7 +12,7 @@ import { MotherboardCommands, ProgressorCommands } from "./commands"
|
|
|
12
12
|
*/
|
|
13
13
|
export const info = async (board: Device): Promise<void> => {
|
|
14
14
|
if (isConnected(board)) {
|
|
15
|
-
if (board.name === "Motherboard") {
|
|
15
|
+
if (board.filters.some((filter) => filter.name === "Motherboard")) {
|
|
16
16
|
// Read manufacturer information
|
|
17
17
|
await read(Motherboard, "device", "manufacturer", 250)
|
|
18
18
|
// Read hardware version
|
|
@@ -24,7 +24,7 @@ export const info = async (board: Device): Promise<void> => {
|
|
|
24
24
|
// Get serial number from Motherboard
|
|
25
25
|
await write(Motherboard, "uart", "tx", MotherboardCommands.GET_SERIAL, 250)
|
|
26
26
|
}
|
|
27
|
-
if (board.
|
|
27
|
+
if (board.filters.some((filter) => filter.namePrefix === "Progressor")) {
|
|
28
28
|
// Get firmware version from Progressor
|
|
29
29
|
await write(Progressor, "progressor", "tx", ProgressorCommands.GET_FW_VERSION, 250)
|
|
30
30
|
}
|
package/src/is-connected.ts
CHANGED
package/src/notify.ts
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
massAverage: string // The total average mass.
|
|
5
|
-
massLeft?: string // The mass on the left side (optional: Motherboard).
|
|
6
|
-
massCenter?: string // The mass at the center (optional: Motherboard).
|
|
7
|
-
massRight?: string // The mass on the right side (optional: Motherboard).
|
|
8
|
-
}
|
|
9
|
-
// Define the type for the callback function
|
|
10
|
-
type NotifyCallback = (data: massObject) => void
|
|
1
|
+
import type { massObject } from "./types/notify"
|
|
2
|
+
/** Define the type for the callback function */
|
|
3
|
+
export type NotifyCallback = (data: massObject) => void
|
|
11
4
|
/**
|
|
12
5
|
* Defines the type for the callback function.
|
|
13
6
|
* @callback NotifyCallback
|
package/src/read.ts
CHANGED
package/src/stop.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Device } from "./devices
|
|
1
|
+
import type { Device } from "./types/devices"
|
|
2
2
|
import { write } from "./write"
|
|
3
3
|
import { isConnected } from "./is-connected"
|
|
4
4
|
import { Motherboard, Progressor } from "./devices"
|
|
@@ -11,11 +11,11 @@ import { MotherboardCommands, ProgressorCommands } from "./commands"
|
|
|
11
11
|
*/
|
|
12
12
|
export const stop = async (board: Device): Promise<void> => {
|
|
13
13
|
if (isConnected(board)) {
|
|
14
|
-
if (board.name === "Motherboard") {
|
|
14
|
+
if (board.filters.some((filter) => filter.name === "Motherboard")) {
|
|
15
15
|
// Stop stream on Motherboard
|
|
16
16
|
await write(Motherboard, "uart", "tx", MotherboardCommands.STOP_WEIGHT_MEAS, 0)
|
|
17
17
|
}
|
|
18
|
-
if (board.
|
|
18
|
+
if (board.filters.some((filter) => filter.namePrefix === "Progressor")) {
|
|
19
19
|
// Stop stream on Progressor
|
|
20
20
|
await write(Progressor, "progressor", "tx", ProgressorCommands.STOP_WEIGHT_MEAS, 0)
|
|
21
21
|
}
|
package/src/stream.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Device } from "./devices
|
|
1
|
+
import type { Device } from "./types/devices"
|
|
2
2
|
import { isConnected } from "./is-connected"
|
|
3
3
|
import { write } from "./write"
|
|
4
4
|
import { stop } from "./stop"
|
|
@@ -19,7 +19,7 @@ export const stream = async (board: Device, duration: number = 0): Promise<void>
|
|
|
19
19
|
// Reset download packets
|
|
20
20
|
emptyDownloadPackets()
|
|
21
21
|
// Device specific logic
|
|
22
|
-
if (board.name === "Motherboard") {
|
|
22
|
+
if (board.filters.some((filter) => filter.name === "Motherboard")) {
|
|
23
23
|
// Read calibration data if not already available
|
|
24
24
|
if (!CALIBRATION[0].length) {
|
|
25
25
|
await calibration(Motherboard)
|
|
@@ -31,7 +31,7 @@ export const stream = async (board: Device, duration: number = 0): Promise<void>
|
|
|
31
31
|
await stop(Motherboard)
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
if (board.
|
|
34
|
+
if (board.filters.some((filter) => filter.namePrefix === "Progressor")) {
|
|
35
35
|
// Start streaming data
|
|
36
36
|
await write(Progressor, "progressor", "tx", ProgressorCommands.START_WEIGHT_MEAS, duration)
|
|
37
37
|
// Stop streaming if duration is set
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a characteristic of a Bluetooth service.
|
|
3
|
+
*/
|
|
4
|
+
interface Characteristic {
|
|
5
|
+
/** Name of the characteristic */
|
|
6
|
+
name: string
|
|
7
|
+
/** Identifier of the characteristic */
|
|
8
|
+
id: string
|
|
9
|
+
/** UUID of the characteristic */
|
|
10
|
+
uuid: string
|
|
11
|
+
/** Reference to the characteristic object */
|
|
12
|
+
characteristic?: BluetoothRemoteGATTCharacteristic
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Represents a Bluetooth service.
|
|
17
|
+
*/
|
|
18
|
+
interface Service {
|
|
19
|
+
/** Name of the service */
|
|
20
|
+
name: string
|
|
21
|
+
/** Identifier of the service */
|
|
22
|
+
id: string
|
|
23
|
+
/** UUID of the service */
|
|
24
|
+
uuid: string
|
|
25
|
+
/** Array of characteristics belonging to this service */
|
|
26
|
+
characteristics: Characteristic[]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Represents a Bluetooth device.
|
|
31
|
+
*/
|
|
32
|
+
export interface Device {
|
|
33
|
+
/** Filters to indentify the device */
|
|
34
|
+
filters: BluetoothLEScanFilter[]
|
|
35
|
+
/** Array of services provided by the device */
|
|
36
|
+
services: Service[]
|
|
37
|
+
/** Reference to the BluetoothDevice object representing this device */
|
|
38
|
+
device?: BluetoothDevice
|
|
39
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a single data packet.
|
|
3
|
+
*/
|
|
4
|
+
export interface DownloadPacket {
|
|
5
|
+
/** Timestamp of when the packet was received */
|
|
6
|
+
received: number
|
|
7
|
+
/** Sample number */
|
|
8
|
+
sampleNum: number //
|
|
9
|
+
/** Battery raw value */
|
|
10
|
+
battRaw: number
|
|
11
|
+
/** Array of sample values */
|
|
12
|
+
samples: number[]
|
|
13
|
+
/** Array of mass values */
|
|
14
|
+
masses: number[]
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface massObject {
|
|
2
|
+
/** The total mass. */
|
|
3
|
+
massTotal: string
|
|
4
|
+
/** The total maximum mass. */
|
|
5
|
+
massMax: string
|
|
6
|
+
/** The total average mass. */
|
|
7
|
+
massAverage: string
|
|
8
|
+
/** The mass on the left side (optional: Motherboard). */
|
|
9
|
+
massLeft?: string
|
|
10
|
+
/** The mass at the center (optional: Motherboard). */
|
|
11
|
+
massCenter?: string
|
|
12
|
+
/** The mass on the right side (optional: Motherboard). */
|
|
13
|
+
massRight?: string
|
|
14
|
+
}
|
package/src/write.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Device } from "./devices
|
|
1
|
+
import type { Device } from "./types/devices"
|
|
2
2
|
import { isConnected } from "./is-connected"
|
|
3
3
|
import { getCharacteristic } from "./characteristic"
|
|
4
4
|
|
|
@@ -55,9 +55,6 @@ export const write = (
|
|
|
55
55
|
// Reject if characteristic is undefined
|
|
56
56
|
reject(new Error("Characteristics is undefined"))
|
|
57
57
|
}
|
|
58
|
-
} else {
|
|
59
|
-
// Reject if device is not connected
|
|
60
|
-
reject(new Error("Device is not connected"))
|
|
61
58
|
}
|
|
62
59
|
})
|
|
63
60
|
}
|
package/src/battery.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Device } from "./devices/types";
|
|
2
|
-
/**
|
|
3
|
-
* Retrieves battery or voltage information from the device.
|
|
4
|
-
* @param {Device} board - The device.
|
|
5
|
-
* @returns {Promise<void>} A Promise that resolves when the information is successfully retrieved.
|
|
6
|
-
*/
|
|
7
|
-
export declare const battery: (board: Device) => Promise<void>;
|
package/src/battery.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { write } from "./write";
|
|
2
|
-
import { read } from "./read";
|
|
3
|
-
import { isConnected } from "./is-connected";
|
|
4
|
-
import { Motherboard, Progressor } from "./devices";
|
|
5
|
-
import { ProgressorCommands } from "./commands";
|
|
6
|
-
/**
|
|
7
|
-
* Retrieves battery or voltage information from the device.
|
|
8
|
-
* @param {Device} board - The device.
|
|
9
|
-
* @returns {Promise<void>} A Promise that resolves when the information is successfully retrieved.
|
|
10
|
-
*/
|
|
11
|
-
export const battery = async (board) => {
|
|
12
|
-
// Check if the device is connected
|
|
13
|
-
if (isConnected(board)) {
|
|
14
|
-
// If the device is connected and it is a Motherboard device
|
|
15
|
-
if (board.name === "Motherboard") {
|
|
16
|
-
// Read battery level information from the Motherboard
|
|
17
|
-
await read(Motherboard, "battery", "level", 250);
|
|
18
|
-
}
|
|
19
|
-
// If the device is connected and its name starts with "Progressor"
|
|
20
|
-
if (board.name && board.name.startsWith("Progressor")) {
|
|
21
|
-
// Write command to get battery voltage information to the Progressor
|
|
22
|
-
await write(Progressor, "progressor", "tx", ProgressorCommands.GET_BATT_VLTG, 250);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
};
|