@hangtime/grip-connect 0.10.9 → 0.13.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 (125) hide show
  1. package/README.md +14 -3
  2. package/dist/cjs/index.d.ts +2 -2
  3. package/dist/cjs/index.d.ts.map +1 -1
  4. package/dist/cjs/index.js +2 -1
  5. package/dist/cjs/index.js.map +1 -1
  6. package/dist/cjs/interfaces/command.interface.d.ts +120 -20
  7. package/dist/cjs/interfaces/command.interface.d.ts.map +1 -1
  8. package/dist/cjs/interfaces/device/climbro.interface.d.ts +25 -0
  9. package/dist/cjs/interfaces/device/climbro.interface.d.ts.map +1 -1
  10. package/dist/cjs/interfaces/device/cts500.interface.d.ts +96 -0
  11. package/dist/cjs/interfaces/device/cts500.interface.d.ts.map +1 -0
  12. package/dist/cjs/interfaces/device/cts500.interface.js +3 -0
  13. package/dist/cjs/interfaces/device/cts500.interface.js.map +1 -0
  14. package/dist/cjs/interfaces/device/forceboard.interface.d.ts +2 -2
  15. package/dist/cjs/interfaces/device/forceboard.interface.d.ts.map +1 -1
  16. package/dist/cjs/interfaces/device/progressor.interface.d.ts +17 -7
  17. package/dist/cjs/interfaces/device/progressor.interface.d.ts.map +1 -1
  18. package/dist/cjs/interfaces/index.d.ts +2 -0
  19. package/dist/cjs/interfaces/index.d.ts.map +1 -1
  20. package/dist/cjs/interfaces/nordic.interface.d.ts +47 -0
  21. package/dist/cjs/interfaces/nordic.interface.d.ts.map +1 -0
  22. package/dist/cjs/interfaces/nordic.interface.js +3 -0
  23. package/dist/cjs/interfaces/nordic.interface.js.map +1 -0
  24. package/dist/cjs/models/device/climbro.model.d.ts +25 -0
  25. package/dist/cjs/models/device/climbro.model.d.ts.map +1 -1
  26. package/dist/cjs/models/device/climbro.model.js +93 -1
  27. package/dist/cjs/models/device/climbro.model.js.map +1 -1
  28. package/dist/cjs/models/device/cts500.model.d.ts +173 -0
  29. package/dist/cjs/models/device/cts500.model.d.ts.map +1 -0
  30. package/dist/cjs/models/device/cts500.model.js +588 -0
  31. package/dist/cjs/models/device/cts500.model.js.map +1 -0
  32. package/dist/cjs/models/device/entralpi.model.d.ts.map +1 -1
  33. package/dist/cjs/models/device/entralpi.model.js +3 -5
  34. package/dist/cjs/models/device/entralpi.model.js.map +1 -1
  35. package/dist/cjs/models/device/forceboard.model.d.ts +2 -2
  36. package/dist/cjs/models/device/forceboard.model.d.ts.map +1 -1
  37. package/dist/cjs/models/device/forceboard.model.js +3 -14
  38. package/dist/cjs/models/device/forceboard.model.js.map +1 -1
  39. package/dist/cjs/models/device/progressor.model.d.ts +25 -12
  40. package/dist/cjs/models/device/progressor.model.d.ts.map +1 -1
  41. package/dist/cjs/models/device/progressor.model.js +82 -31
  42. package/dist/cjs/models/device/progressor.model.js.map +1 -1
  43. package/dist/cjs/models/device.model.d.ts +7 -0
  44. package/dist/cjs/models/device.model.d.ts.map +1 -1
  45. package/dist/cjs/models/device.model.js +52 -32
  46. package/dist/cjs/models/device.model.js.map +1 -1
  47. package/dist/cjs/models/index.d.ts +2 -0
  48. package/dist/cjs/models/index.d.ts.map +1 -1
  49. package/dist/cjs/models/index.js +6 -1
  50. package/dist/cjs/models/index.js.map +1 -1
  51. package/dist/cjs/models/nordic.model.d.ts +128 -0
  52. package/dist/cjs/models/nordic.model.d.ts.map +1 -0
  53. package/dist/cjs/models/nordic.model.js +405 -0
  54. package/dist/cjs/models/nordic.model.js.map +1 -0
  55. package/dist/index.d.ts +2 -2
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +1 -1
  58. package/dist/index.js.map +1 -1
  59. package/dist/interfaces/command.interface.d.ts +120 -20
  60. package/dist/interfaces/command.interface.d.ts.map +1 -1
  61. package/dist/interfaces/device/climbro.interface.d.ts +25 -0
  62. package/dist/interfaces/device/climbro.interface.d.ts.map +1 -1
  63. package/dist/interfaces/device/cts500.interface.d.ts +96 -0
  64. package/dist/interfaces/device/cts500.interface.d.ts.map +1 -0
  65. package/dist/interfaces/device/cts500.interface.js +2 -0
  66. package/dist/interfaces/device/cts500.interface.js.map +1 -0
  67. package/dist/interfaces/device/forceboard.interface.d.ts +2 -2
  68. package/dist/interfaces/device/forceboard.interface.d.ts.map +1 -1
  69. package/dist/interfaces/device/progressor.interface.d.ts +17 -7
  70. package/dist/interfaces/device/progressor.interface.d.ts.map +1 -1
  71. package/dist/interfaces/index.d.ts +2 -0
  72. package/dist/interfaces/index.d.ts.map +1 -1
  73. package/dist/interfaces/nordic.interface.d.ts +47 -0
  74. package/dist/interfaces/nordic.interface.d.ts.map +1 -0
  75. package/dist/interfaces/nordic.interface.js +2 -0
  76. package/dist/interfaces/nordic.interface.js.map +1 -0
  77. package/dist/models/device/climbro.model.d.ts +25 -0
  78. package/dist/models/device/climbro.model.d.ts.map +1 -1
  79. package/dist/models/device/climbro.model.js +93 -1
  80. package/dist/models/device/climbro.model.js.map +1 -1
  81. package/dist/models/device/cts500.model.d.ts +173 -0
  82. package/dist/models/device/cts500.model.d.ts.map +1 -0
  83. package/dist/models/device/cts500.model.js +584 -0
  84. package/dist/models/device/cts500.model.js.map +1 -0
  85. package/dist/models/device/entralpi.model.d.ts.map +1 -1
  86. package/dist/models/device/entralpi.model.js +3 -5
  87. package/dist/models/device/entralpi.model.js.map +1 -1
  88. package/dist/models/device/forceboard.model.d.ts +2 -2
  89. package/dist/models/device/forceboard.model.d.ts.map +1 -1
  90. package/dist/models/device/forceboard.model.js +3 -14
  91. package/dist/models/device/forceboard.model.js.map +1 -1
  92. package/dist/models/device/progressor.model.d.ts +25 -12
  93. package/dist/models/device/progressor.model.d.ts.map +1 -1
  94. package/dist/models/device/progressor.model.js +82 -31
  95. package/dist/models/device/progressor.model.js.map +1 -1
  96. package/dist/models/device.model.d.ts +7 -0
  97. package/dist/models/device.model.d.ts.map +1 -1
  98. package/dist/models/device.model.js +51 -32
  99. package/dist/models/device.model.js.map +1 -1
  100. package/dist/models/index.d.ts +2 -0
  101. package/dist/models/index.d.ts.map +1 -1
  102. package/dist/models/index.js +2 -0
  103. package/dist/models/index.js.map +1 -1
  104. package/dist/models/nordic.model.d.ts +128 -0
  105. package/dist/models/nordic.model.d.ts.map +1 -0
  106. package/dist/models/nordic.model.js +393 -0
  107. package/dist/models/nordic.model.js.map +1 -0
  108. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  109. package/package.json +4 -3
  110. package/src/index.ts +2 -0
  111. package/src/interfaces/command.interface.ts +143 -20
  112. package/src/interfaces/device/climbro.interface.ts +30 -0
  113. package/src/interfaces/device/cts500.interface.ts +113 -0
  114. package/src/interfaces/device/forceboard.interface.ts +2 -2
  115. package/src/interfaces/device/progressor.interface.ts +19 -7
  116. package/src/interfaces/index.ts +4 -0
  117. package/src/interfaces/nordic.interface.ts +47 -0
  118. package/src/models/device/climbro.model.ts +98 -1
  119. package/src/models/device/cts500.model.ts +702 -0
  120. package/src/models/device/entralpi.model.ts +3 -5
  121. package/src/models/device/forceboard.model.ts +3 -14
  122. package/src/models/device/progressor.model.ts +86 -31
  123. package/src/models/device.model.ts +60 -32
  124. package/src/models/index.ts +4 -0
  125. package/src/models/nordic.model.ts +468 -0
@@ -0,0 +1,584 @@
1
+ import { Device } from "../device.model.js";
2
+ const CTS500_HEADER = 0x05;
3
+ const CTS500_RESPONSE_FLAG = 0x80;
4
+ const CTS500_ACK_FRAME_LENGTH = 6;
5
+ const CTS500_DATA_FRAME_LENGTH = 7;
6
+ const CTS500_RESPONSE_TIMEOUT_MS = 2000;
7
+ const CTS500_BAUD_RATE_PARAMS = {
8
+ 9600: 0x00,
9
+ 19200: 0x01,
10
+ 38400: 0x02,
11
+ 57600: 0x03,
12
+ 115200: 0x04,
13
+ };
14
+ const CTS500_SAMPLING_RATE_PARAMS = {
15
+ 10: 0x00,
16
+ 20: 0x01,
17
+ 40: 0x02,
18
+ 80: 0x03,
19
+ 160: 0x04,
20
+ 320: 0x05,
21
+ };
22
+ function calculateChecksum(bytes) {
23
+ let checksum = 0;
24
+ // CTS frames use a simple additive checksum over every byte before the checksum slot.
25
+ for (const byte of bytes) {
26
+ checksum = (checksum + byte) & 0xff;
27
+ }
28
+ return checksum;
29
+ }
30
+ function buildCommand(opcode, payload = [0x00, 0x00, 0x00]) {
31
+ const frame = new Uint8Array(CTS500_ACK_FRAME_LENGTH);
32
+ frame[0] = CTS500_HEADER;
33
+ frame[1] = opcode;
34
+ frame[2] = payload[0];
35
+ frame[3] = payload[1];
36
+ frame[4] = payload[2];
37
+ frame[5] = calculateChecksum(frame.subarray(0, frame.length - 1));
38
+ return frame;
39
+ }
40
+ /**
41
+ * Represents the CTS500 Climbing Training Scale, marketed as "Jlyscales CTS500".
42
+ * Supplier: Hunan Jinlian Cloud Information Technology Co., Ltd.
43
+ * {@link https://www.huaying-scales.com/}
44
+ * {@link https://www.alibaba.com/product-detail/Mini-Climbing-Training-Scale-CTS500-Aluminum_1601637814595.html}
45
+ */
46
+ export class CTS500 extends Device {
47
+ bufferedFrames = new Uint8Array(0);
48
+ pendingFrame = undefined;
49
+ requestQueue = Promise.resolve();
50
+ isStreaming = false;
51
+ commandOpcodes = new Set();
52
+ constructor() {
53
+ super({
54
+ filters: [{ name: "CTS-300" }, { name: "CTS500" }],
55
+ services: [
56
+ {
57
+ name: "Device Information",
58
+ id: "device",
59
+ uuid: "0000180a-0000-1000-8000-00805f9b34fb",
60
+ characteristics: [
61
+ {
62
+ name: "Model Number String",
63
+ id: "model",
64
+ uuid: "00002a24-0000-1000-8000-00805f9b34fb", // MY-BT102 https://www.muyusmart.cn/product/my-bt102/
65
+ },
66
+ // {
67
+ // name: "Serial Number String (Blocked)",
68
+ // id: "serial",
69
+ // uuid: "00002a25-0000-1000-8000-00805f9b34fb",
70
+ // },
71
+ {
72
+ name: "Firmware Revision String",
73
+ id: "firmware",
74
+ uuid: "00002a26-0000-1000-8000-00805f9b34fb", // 109a
75
+ },
76
+ {
77
+ name: "Hardware Revision String",
78
+ id: "hardware",
79
+ uuid: "00002a27-0000-1000-8000-00805f9b34fb", //1.0
80
+ },
81
+ {
82
+ name: "Software Revision String",
83
+ id: "software",
84
+ uuid: "00002a28-0000-1000-8000-00805f9b34fb", // 2.1.3
85
+ },
86
+ {
87
+ name: "Manufacturer Name String",
88
+ id: "manufacturer",
89
+ uuid: "00002a29-0000-1000-8000-00805f9b34fb", // DX
90
+ },
91
+ ],
92
+ },
93
+ {
94
+ name: "CTS500 Service",
95
+ id: "cts500",
96
+ uuid: "0000ffe0-0000-1000-8000-00805f9b34fb",
97
+ characteristics: [
98
+ {
99
+ name: "Notify",
100
+ id: "rx",
101
+ uuid: "0000ffe1-0000-1000-8000-00805f9b34fb",
102
+ },
103
+ {
104
+ name: "Write",
105
+ id: "tx",
106
+ uuid: "0000ffe2-0000-1000-8000-00805f9b34fb",
107
+ },
108
+ ],
109
+ },
110
+ ],
111
+ commands: {
112
+ SET_RANGE: 0x81, // set capacity/range; known presets include 100kg, 200kg, 300kg, 400kg, 500kg, 1T, and 3T
113
+ SET_DIVISION: 0x82, // set division; known presets include 10g, 20g, 50g, and 0.1kg
114
+ SET_FIRST_CALIBRATION_WEIGHT: 0x83, // set first calibration reference weight; known presets include 1kg, 5kg, 10kg, 20kg, 50kg, and 100kg
115
+ SET_SECOND_CALIBRATION_WEIGHT: 0x84, // set second calibration reference weight; known presets shown include 50kg, 100kg, and 200kg
116
+ POWER_ON_RESET: 0x85, // power-on reset mode; payload 00 disables automatic reset and 01 enables it
117
+ ZERO_SCALE: buildCommand(0x86), // update the hardware zero point
118
+ RUN_FIRST_CALIBRATION: buildCommand(0xa1), // run the first calibration step after placing the configured reference weight
119
+ RUN_SECOND_CALIBRATION: buildCommand(0xa2), // run the second calibration step after placing the configured reference weight
120
+ GET_FIRMWARE_VERSION: buildCommand(0xa4), // read firmware version over the transparent UART service
121
+ TARE_SCALE: buildCommand(0xa6), // tare the current load
122
+ NO_LOAD_CALIBRATION: buildCommand(0xa7), // run the no-load calibration routine with the scale unloaded
123
+ GET_WEIGHT: buildCommand(0xa9), // read the current weight immediately
124
+ START_WEIGHT_MEAS: buildCommand(0xaa), // turn on automatic weight uploading
125
+ STOP_WEIGHT_MEAS: buildCommand(0xab), // turn off automatic weight uploading
126
+ SET_BAUD_RATE: 0xc0, // set UART baud rate; payload presets are 00=9600, 01=19200, 02=38400, 03=57600, 04=115200
127
+ SET_SAMPLING_RATE: 0xc1, // set A/D sampling frequency; payload presets are 00=10Hz, 01=20Hz, 02=40Hz, 03=80Hz, 04=160Hz, 05=320Hz
128
+ SET_SHUTDOWN_TIME: 0xc3, // set auto-shutdown timer; the shown presets use payload 1E for 30 seconds and 00 to disable
129
+ GET_BATTERY_VOLTAGE: buildCommand(0xc4), // read battery voltage
130
+ GET_TEMPERATURE: buildCommand(0xc5), // read temperature
131
+ SET_UPPER_TEMPERATURE_LIMIT: 0xc6, // set upper temperature limit; the shown example uses payload 1D
132
+ SET_LOWER_TEMPERATURE_LIMIT: 0xc7, // set lower temperature limit; the shown example uses payload 2A and FF disables the lower limit
133
+ PEAK_MODE: 0xca, // peak mode; payload 00 turns it off and 01 turns it on
134
+ SET_MAX_WEIGHT_LIMIT: 0xd1, // set the upper/max weight limit threshold
135
+ SET_MIN_WEIGHT_LIMIT: 0xd2, // set the lower/min weight limit threshold
136
+ SET_WEIGHT_ALARM_MODE: 0xd3, // set weight alarm mode; payload 00 cancels, 01 alarms inside the range, and 02 alarms outside the range
137
+ SET_ALARM_OUTPUT: 0xd4, // enable or disable alarm-frame output; payload 00 turns it off and 01 turns it on
138
+ },
139
+ });
140
+ for (const command of Object.values(this.commands)) {
141
+ // Command echoes identify themselves by opcode byte 1 whether the command is stored as a raw opcode or a full frame.
142
+ if (typeof command === "number") {
143
+ this.commandOpcodes.add(command);
144
+ }
145
+ else if (command instanceof Uint8Array && command.length >= 2) {
146
+ this.commandOpcodes.add(command[1]);
147
+ }
148
+ }
149
+ }
150
+ /**
151
+ * Retrieves battery voltage from the device.
152
+ * The returned string uses two decimal places, e.g. "3.55".
153
+ * @returns {Promise<string | undefined>} A Promise that resolves with the battery voltage.
154
+ */
155
+ battery = async () => {
156
+ const command = this.commands.GET_BATTERY_VOLTAGE;
157
+ const frame = await this.queryFrame(command, (response) => this.isCommandResponse(response, command[1]));
158
+ if (!frame) {
159
+ return undefined;
160
+ }
161
+ const rawVoltage = (frame[4] << 8) | frame[5];
162
+ return (rawVoltage / 100).toFixed(2);
163
+ };
164
+ /**
165
+ * Retrieves firmware version from the device.
166
+ * @returns {Promise<string | undefined>} A Promise that resolves with the firmware version.
167
+ */
168
+ firmware = async () => {
169
+ return await this.read("device", "firmware", 250);
170
+ };
171
+ /**
172
+ * Retrieves hardware version from the device.
173
+ * @returns {Promise<string | undefined>} A Promise that resolves with the hardware version.
174
+ */
175
+ hardware = async () => {
176
+ return await this.read("device", "hardware", 250);
177
+ };
178
+ /**
179
+ * Retrieves manufacturer information from the device.
180
+ * @returns {Promise<string | undefined>} A Promise that resolves with the manufacturer information.
181
+ */
182
+ manufacturer = async () => {
183
+ return await this.read("device", "manufacturer", 250);
184
+ };
185
+ /**
186
+ * Retrieves model number from the device.
187
+ * @returns {Promise<string | undefined>} A Promise that resolves with the model number.
188
+ */
189
+ model = async () => {
190
+ return await this.read("device", "model", 250);
191
+ };
192
+ /**
193
+ * Sets whether the device should reset to zero on power-up.
194
+ * @param {boolean} enabled - Whether power-on reset should be enabled.
195
+ * @returns {Promise<void>} A promise that resolves when the command is acknowledged.
196
+ */
197
+ powerOnReset = async (enabled) => {
198
+ await this.expectAck(this.commands.POWER_ON_RESET, [0x00, 0x00, enabled ? 0x01 : 0x00]);
199
+ };
200
+ /**
201
+ * Enables or disables the device peak mode.
202
+ * @param {boolean} [enabled=true] - Whether peak mode should be enabled.
203
+ * @returns {Promise<void>} A promise that resolves when the command is acknowledged.
204
+ */
205
+ peakMode = async (enabled = true) => {
206
+ await this.expectAck(this.commands.PEAK_MODE, [0x00, 0x00, enabled ? 0x01 : 0x00]);
207
+ };
208
+ /**
209
+ * Configures the device UART baud rate.
210
+ * @param {CTS500BaudRate} baudRate - Desired baud rate.
211
+ * @returns {Promise<void>} A promise that resolves when the command is acknowledged.
212
+ */
213
+ setBaudRate = async (baudRate) => {
214
+ await this.applyConfigCommand(this.commands.SET_BAUD_RATE, [
215
+ 0x00,
216
+ 0x00,
217
+ CTS500_BAUD_RATE_PARAMS[baudRate],
218
+ ]);
219
+ };
220
+ /**
221
+ * Configures the device A/D sampling rate.
222
+ * @param {CTS500SamplingRate} samplingRate - Desired A/D sampling rate in Hz.
223
+ * @returns {Promise<void>} A promise that resolves when the command is acknowledged.
224
+ */
225
+ setSamplingRate = async (samplingRate) => {
226
+ await this.applyConfigCommand(this.commands.SET_SAMPLING_RATE, [
227
+ 0x00,
228
+ 0x00,
229
+ CTS500_SAMPLING_RATE_PARAMS[samplingRate],
230
+ ]);
231
+ };
232
+ /**
233
+ * Retrieves serial number from the device.
234
+ * @returns {Promise<string | undefined>} A Promise that resolves with the serial number.
235
+ */
236
+ serial = async () => {
237
+ const hasSerial = this.services
238
+ .find((service) => service.id === "device")
239
+ ?.characteristics.some((characteristic) => characteristic.id === "serial");
240
+ // MY-BT102 variants can omit the serial characteristic entirely, so guard the read instead of letting it throw.
241
+ if (!hasSerial) {
242
+ return undefined;
243
+ }
244
+ return await this.read("device", "serial", 250);
245
+ };
246
+ /**
247
+ * Retrieves software version from the device.
248
+ * @returns {Promise<string | undefined>} A Promise that resolves with the software version.
249
+ */
250
+ software = async () => {
251
+ return await this.read("device", "software", 250);
252
+ };
253
+ /**
254
+ * Starts automatic weight uploads.
255
+ * @param {number} [duration=0] - Optional delay before the promise resolves.
256
+ * @returns {Promise<void>} A promise that resolves once upload mode has been enabled.
257
+ */
258
+ stream = async (duration = 0) => {
259
+ this.resetPacketTracking();
260
+ this.isStreaming = true;
261
+ const command = this.commands.START_WEIGHT_MEAS;
262
+ await this.queryFrame(command, (frame) =>
263
+ // The device can start auto-uploading before it echoes the start command, so the first weight frame also confirms success.
264
+ this.isAckFrame(frame, command[1], [command[2], command[3], command[4]]) || this.isWeightFrame(frame));
265
+ if (duration > 0) {
266
+ await new Promise((resolve) => setTimeout(resolve, duration));
267
+ }
268
+ };
269
+ /**
270
+ * Stops automatic weight uploads.
271
+ * @returns {Promise<void>} A promise that resolves once upload mode has been disabled.
272
+ */
273
+ stop = async () => {
274
+ this.isStreaming = false;
275
+ const command = this.commands.STOP_WEIGHT_MEAS;
276
+ await this.queryFrame(command, (frame) => this.isAckFrame(frame, command[1], [command[2], command[3], command[4]]));
277
+ };
278
+ /**
279
+ * Reads the current temperature from the device.
280
+ * @returns {Promise<string | undefined>} A Promise that resolves with the temperature in Celsius.
281
+ */
282
+ temperature = async () => {
283
+ const command = this.commands.GET_TEMPERATURE;
284
+ const frame = await this.queryFrame(command, (response) => this.isCommandResponse(response, command[1]));
285
+ if (!frame) {
286
+ return undefined;
287
+ }
288
+ const rawTemperature = frame[5];
289
+ // Negative temperatures are sent as 0x80 + abs(value) instead of two's complement.
290
+ const temperature = rawTemperature >= 0x80 ? -(rawTemperature - 0x80) : rawTemperature;
291
+ return temperature.toString();
292
+ };
293
+ /**
294
+ * Uses the device's hardware tare command when connected and falls back to software tare otherwise.
295
+ * @param {number} [duration=5000] - Software tare duration when the device is not connected.
296
+ * @returns {boolean} `true` when the tare operation started successfully.
297
+ */
298
+ tare = (duration = 5000) => {
299
+ if (!this.isConnected()) {
300
+ return super.tare(duration);
301
+ }
302
+ this.updateTimestamp();
303
+ this.clearTareOffset();
304
+ const command = this.commands.TARE_SCALE;
305
+ void this.queryFrame(command, (frame) => this.isAckFrame(frame, command[1], [command[2], command[3], command[4]])).catch((error) => {
306
+ console.error(error);
307
+ });
308
+ return true;
309
+ };
310
+ /**
311
+ * Reads the current weight from the device in kilograms.
312
+ * @returns {Promise<number | undefined>} A Promise that resolves with the current weight.
313
+ */
314
+ weight = async () => {
315
+ const frame = await this.queryFrame(this.commands.GET_WEIGHT, (response) => this.isWeightFrame(response));
316
+ if (!frame) {
317
+ return undefined;
318
+ }
319
+ return (frame[2] * 0x1000000 + frame[3] * 0x10000 + frame[4] * 0x100 + frame[5]) / 100;
320
+ };
321
+ /**
322
+ * Updates the device hardware zero point.
323
+ * @returns {Promise<void>} A promise that resolves when the command is acknowledged.
324
+ */
325
+ zero = async () => {
326
+ await this.expectAck(this.commands.ZERO_SCALE);
327
+ };
328
+ /**
329
+ * Parses UART frames received over the MY-BT102 notify characteristic.
330
+ * Supports fragmented BLE notifications by buffering until a complete CTS500 frame is available.
331
+ *
332
+ * @param {DataView} value - The notification payload from the device.
333
+ */
334
+ handleNotifications = (value) => {
335
+ this.updateTimestamp();
336
+ const bytes = new Uint8Array(value.byteLength);
337
+ for (let index = 0; index < value.byteLength; index++) {
338
+ bytes[index] = value.getUint8(index);
339
+ }
340
+ if (bytes.length === 0) {
341
+ return;
342
+ }
343
+ // BLE notifications can split UART frames arbitrarily, so keep buffering until a full frame validates.
344
+ const combined = new Uint8Array(this.bufferedFrames.length + bytes.length);
345
+ combined.set(this.bufferedFrames);
346
+ combined.set(bytes, this.bufferedFrames.length);
347
+ this.bufferedFrames = combined;
348
+ while (this.bufferedFrames.length >= CTS500_ACK_FRAME_LENGTH) {
349
+ const headerIndex = this.bufferedFrames.indexOf(CTS500_HEADER);
350
+ if (headerIndex === -1) {
351
+ this.bufferedFrames = new Uint8Array(0);
352
+ return;
353
+ }
354
+ if (headerIndex > 0) {
355
+ this.bufferedFrames = this.bufferedFrames.slice(headerIndex);
356
+ }
357
+ const frame = this.extractNextFrame();
358
+ if (!frame) {
359
+ return;
360
+ }
361
+ this.bufferedFrames = this.bufferedFrames.slice(frame.length);
362
+ this.handleFrame(frame);
363
+ }
364
+ };
365
+ /**
366
+ * Waits for a specific frame pattern after sending a CTS500 command.
367
+ */
368
+ queryFrame = async (message, match) => {
369
+ return await this.enqueueRequest(async () => {
370
+ const waitForFrame = this.waitForFrame(match);
371
+ try {
372
+ await this.write("cts500", "tx", message, 0);
373
+ return await waitForFrame;
374
+ }
375
+ catch (error) {
376
+ this.clearPendingFrame(error instanceof Error ? error : new Error(String(error)));
377
+ throw error;
378
+ }
379
+ });
380
+ };
381
+ /**
382
+ * Sends a command that should be acknowledged with a 6-byte echo frame.
383
+ */
384
+ expectAck = async (opcode, payload = [0x00, 0x00, 0x00]) => {
385
+ await this.queryFrame(buildCommand(opcode, payload), (frame) => this.isAckFrame(frame, opcode, payload));
386
+ };
387
+ /**
388
+ * Sends a configuration command that may reply with either a 6-byte echo, a typed response, or no reply after applying.
389
+ */
390
+ applyConfigCommand = async (opcode, payload = [0x00, 0x00, 0x00]) => {
391
+ try {
392
+ await this.queryFrame(buildCommand(opcode, payload), (frame) => this.isAckFrame(frame, opcode, payload) || this.isCommandResponse(frame, opcode));
393
+ }
394
+ catch (error) {
395
+ // Some CTS firmwares apply UART/A-D rate changes immediately and do not echo a matching confirmation frame back over BLE.
396
+ if (error instanceof Error && error.message === "Timed out waiting for CTS500 response") {
397
+ return;
398
+ }
399
+ throw error;
400
+ }
401
+ };
402
+ /**
403
+ * Resolves the currently pending frame promise if the incoming frame matches.
404
+ * @returns {boolean} Whether a pending request consumed the frame.
405
+ */
406
+ consumePendingFrame = (frame) => {
407
+ if (!this.pendingFrame || !this.pendingFrame.match(frame)) {
408
+ return false;
409
+ }
410
+ const { resolve, timeout } = this.pendingFrame;
411
+ clearTimeout(timeout);
412
+ this.pendingFrame = undefined;
413
+ resolve(frame);
414
+ return true;
415
+ };
416
+ /**
417
+ * Clears the currently pending frame wait, if any.
418
+ */
419
+ clearPendingFrame = (error) => {
420
+ if (!this.pendingFrame) {
421
+ return;
422
+ }
423
+ const { timeout, reject } = this.pendingFrame;
424
+ clearTimeout(timeout);
425
+ this.pendingFrame = undefined;
426
+ if (error) {
427
+ reject(error);
428
+ }
429
+ };
430
+ /**
431
+ * Extracts the next valid CTS500 frame from the local notification buffer.
432
+ */
433
+ extractNextFrame = () => {
434
+ const secondByte = this.bufferedFrames[1];
435
+ // 6-byte command echoes and 7-byte data frames share the same header, so prefer command echoes when byte 1 is a known opcode.
436
+ if (this.commandOpcodes.has(secondByte) && this.bufferedFrames.length >= CTS500_ACK_FRAME_LENGTH) {
437
+ const commandCandidate = this.bufferedFrames.slice(0, CTS500_ACK_FRAME_LENGTH);
438
+ if (this.isValidFrame(commandCandidate)) {
439
+ return commandCandidate;
440
+ }
441
+ }
442
+ if (this.bufferedFrames.length >= CTS500_DATA_FRAME_LENGTH) {
443
+ const dataCandidate = this.bufferedFrames.slice(0, CTS500_DATA_FRAME_LENGTH);
444
+ if (this.isValidFrame(dataCandidate)) {
445
+ return dataCandidate;
446
+ }
447
+ }
448
+ if (this.bufferedFrames.length >= CTS500_DATA_FRAME_LENGTH) {
449
+ this.bufferedFrames = this.bufferedFrames.slice(1);
450
+ }
451
+ return undefined;
452
+ };
453
+ /**
454
+ * Routes a validated CTS500 frame to pending requests, callbacks, and stream processing.
455
+ */
456
+ handleFrame = (frame) => {
457
+ const matchedPendingRequest = this.consumePendingFrame(frame);
458
+ if (this.isWeightFrame(frame)) {
459
+ // Weight uploads carry a big-endian centi-unit value across bytes 2..5.
460
+ const weight = (frame[2] * 0x1000000 + frame[3] * 0x10000 + frame[4] * 0x100 + frame[5]) / 100;
461
+ this.recordWeightMeasurement(weight);
462
+ this.writeCallback(weight.toFixed(2));
463
+ return;
464
+ }
465
+ if (this.isCommandResponse(frame, this.commands.GET_BATTERY_VOLTAGE[1])) {
466
+ const voltage = ((frame[4] << 8) | frame[5]) / 100;
467
+ this.writeCallback(voltage.toFixed(2));
468
+ return;
469
+ }
470
+ if (this.isCommandResponse(frame, this.commands.GET_TEMPERATURE[1])) {
471
+ const rawTemperature = frame[5];
472
+ // Negative temperatures are sent as 0x80 + abs(value) instead of two's complement.
473
+ const temperature = rawTemperature >= 0x80 ? -(rawTemperature - 0x80) : rawTemperature;
474
+ this.writeCallback(temperature.toString());
475
+ return;
476
+ }
477
+ if (frame.length === CTS500_ACK_FRAME_LENGTH && !matchedPendingRequest) {
478
+ this.writeCallback("OK");
479
+ return;
480
+ }
481
+ if (frame.length === CTS500_DATA_FRAME_LENGTH && !matchedPendingRequest) {
482
+ this.writeCallback(Array.from(frame)
483
+ .map((byte) => byte.toString(16).padStart(2, "0").toUpperCase())
484
+ .join(" "));
485
+ }
486
+ };
487
+ /**
488
+ * Returns whether a frame is a 6-byte command acknowledgment echo for the given opcode.
489
+ */
490
+ isAckFrame = (frame, opcode, payload) => {
491
+ return (frame.length === CTS500_ACK_FRAME_LENGTH &&
492
+ frame[0] === CTS500_HEADER &&
493
+ frame[1] === opcode &&
494
+ frame[2] === payload[0] &&
495
+ frame[3] === payload[1] &&
496
+ frame[4] === payload[2] &&
497
+ this.isValidFrame(frame));
498
+ };
499
+ /**
500
+ * Returns whether a frame is a typed command response (`05 80 <opcode> ... checksum`).
501
+ */
502
+ isCommandResponse = (frame, opcode) => {
503
+ return (frame.length === CTS500_DATA_FRAME_LENGTH &&
504
+ frame[0] === CTS500_HEADER &&
505
+ frame[1] === CTS500_RESPONSE_FLAG &&
506
+ frame[2] === opcode &&
507
+ this.isValidFrame(frame));
508
+ };
509
+ /**
510
+ * Returns whether a frame contains a weight measurement payload.
511
+ */
512
+ isWeightFrame = (frame) => {
513
+ return (frame.length === CTS500_DATA_FRAME_LENGTH &&
514
+ frame[0] === CTS500_HEADER &&
515
+ frame[1] !== CTS500_RESPONSE_FLAG &&
516
+ !this.commandOpcodes.has(frame[1]) &&
517
+ this.isValidFrame(frame));
518
+ };
519
+ /**
520
+ * Updates rolling statistics and emits a force measurement from a CTS500 weight frame.
521
+ */
522
+ recordWeightMeasurement = (receivedData) => {
523
+ const receivedTime = Date.now();
524
+ this.currentSamplesPerPacket = 1;
525
+ this.recordPacketReceived();
526
+ const numericData = receivedData - this.applyTare(receivedData);
527
+ const currentMassTotal = Math.max(-1000, numericData);
528
+ this.peak = Math.max(this.peak, numericData);
529
+ this.min = Math.min(this.min, Math.max(-1000, numericData));
530
+ this.sum += currentMassTotal;
531
+ this.dataPointCount++;
532
+ this.mean = this.sum / this.dataPointCount;
533
+ this.downloadPackets.push(this.buildDownloadPacket(currentMassTotal, [Math.round(receivedData * 100)], {
534
+ timestamp: receivedTime,
535
+ sampleIndex: this.dataPointCount,
536
+ }));
537
+ if (this.isStreaming) {
538
+ void this.activityCheck(numericData);
539
+ }
540
+ this.notifyCallback(this.buildForceMeasurement(currentMassTotal));
541
+ };
542
+ /**
543
+ * Validates a CTS500 frame checksum.
544
+ */
545
+ isValidFrame = (frame) => {
546
+ if (frame.length < CTS500_ACK_FRAME_LENGTH || frame[0] !== CTS500_HEADER) {
547
+ return false;
548
+ }
549
+ return calculateChecksum(frame.subarray(0, frame.length - 1)) === frame[frame.length - 1];
550
+ };
551
+ /**
552
+ * Registers a pending frame matcher with a timeout.
553
+ */
554
+ waitForFrame = (match, timeoutMs = CTS500_RESPONSE_TIMEOUT_MS) => {
555
+ // CTS uses one transparent UART channel for both commands and telemetry, so only one response wait can be active at a time.
556
+ if (this.pendingFrame) {
557
+ throw new Error("CTS500 already has a pending response request");
558
+ }
559
+ return new Promise((resolve, reject) => {
560
+ const timeout = setTimeout(() => {
561
+ if (!this.pendingFrame) {
562
+ return;
563
+ }
564
+ this.pendingFrame = undefined;
565
+ reject(new Error("Timed out waiting for CTS500 response"));
566
+ }, timeoutMs);
567
+ this.pendingFrame = {
568
+ match,
569
+ reject,
570
+ resolve,
571
+ timeout,
572
+ };
573
+ });
574
+ };
575
+ /**
576
+ * Serializes CTS500 command/response operations so query-style methods can be called in parallel by consumers.
577
+ */
578
+ enqueueRequest = async (request) => {
579
+ const run = this.requestQueue.then(request, request);
580
+ this.requestQueue = run.then(() => undefined, () => undefined);
581
+ return await run;
582
+ };
583
+ }
584
+ //# sourceMappingURL=cts500.model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cts500.model.js","sourceRoot":"","sources":["../../../src/models/device/cts500.model.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"entralpi.model.d.ts","sourceRoot":"","sources":["../../../src/models/device/entralpi.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAA;AAE9E;;;GAGG;AACH,qBAAa,QAAS,SAAQ,MAAO,YAAW,SAAS;;IA2HvD;;;OAGG;IACH,OAAO,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE9C;IAED;;;OAGG;IACH,aAAa,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAEpD;IAED;;;OAGG;IACH,QAAQ,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE/C;IAED;;;;;;OAMG;IACM,mBAAmB,GAAI,OAAO,QAAQ,KAAG,IAAI,CAuCrD;IAED;;;OAGG;IACH,QAAQ,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE/C;IAED;;;OAGG;IACH,YAAY,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAEnD;IAED;;;OAGG;IACH,KAAK,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE5C;IAED;;;;OAIG;IACH,GAAG,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE1C;IAED;;;OAGG;IACH,QAAQ,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE/C;IAED;;;OAGG;IACH,MAAM,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE7C;CACF"}
1
+ {"version":3,"file":"entralpi.model.d.ts","sourceRoot":"","sources":["../../../src/models/device/entralpi.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAA;AAE9E;;;GAGG;AACH,qBAAa,QAAS,SAAQ,MAAO,YAAW,SAAS;;IA2HvD;;;OAGG;IACH,OAAO,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE9C;IAED;;;OAGG;IACH,aAAa,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAEpD;IAED;;;OAGG;IACH,QAAQ,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE/C;IAED;;;;;;OAMG;IACM,mBAAmB,GAAI,OAAO,QAAQ,KAAG,IAAI,CAqCrD;IAED;;;OAGG;IACH,QAAQ,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE/C;IAED;;;OAGG;IACH,YAAY,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAEnD;IAED;;;OAGG;IACH,KAAK,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE5C;IAED;;;;OAIG;IACH,GAAG,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE1C;IAED;;;OAGG;IACH,QAAQ,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE/C;IAED;;;OAGG;IACH,MAAM,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE7C;CACF"}
@@ -162,11 +162,9 @@ export class Entralpi extends Device {
162
162
  const receivedTime = Date.now();
163
163
  const receivedData = (value.getUint16(0) / 100).toFixed(1);
164
164
  const convertedData = Number(receivedData);
165
- // Adjust weight by using the tare value
166
- // If tare is 0, use the original weight, otherwise subtract tare and invert.
167
- // This will display the removed or 'no-hanging' weight.
168
- const tare = this.applyTare(convertedData);
169
- const numericData = tare === 0 ? convertedData : (convertedData - tare) * -1;
165
+ // Adjust weight by using the tare value.
166
+ // Keep stream output consistent with other devices: positive load after tare.
167
+ const numericData = convertedData - this.applyTare(convertedData);
170
168
  const currentMassTotal = Math.max(-1000, numericData);
171
169
  // Update session stats before building packet
172
170
  this.peak = Math.max(this.peak, numericData);