@hangtime/grip-connect 0.8.5 → 0.8.7

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 (229) hide show
  1. package/dist/cjs/index.d.ts +3 -0
  2. package/dist/cjs/index.d.ts.map +1 -0
  3. package/dist/cjs/index.js +14 -0
  4. package/dist/cjs/index.js.map +1 -0
  5. package/dist/cjs/interfaces/base.interface.d.ts +18 -0
  6. package/dist/cjs/interfaces/base.interface.d.ts.map +1 -0
  7. package/dist/cjs/interfaces/base.interface.js +3 -0
  8. package/dist/cjs/interfaces/base.interface.js.map +1 -0
  9. package/dist/cjs/interfaces/callback.interface.d.ts +56 -0
  10. package/dist/cjs/interfaces/callback.interface.d.ts.map +1 -0
  11. package/dist/cjs/interfaces/callback.interface.js +3 -0
  12. package/dist/cjs/interfaces/callback.interface.js.map +1 -0
  13. package/dist/cjs/interfaces/command.interface.d.ts +92 -0
  14. package/dist/cjs/interfaces/command.interface.d.ts.map +1 -0
  15. package/dist/cjs/interfaces/command.interface.js +3 -0
  16. package/dist/cjs/interfaces/command.interface.js.map +1 -0
  17. package/dist/cjs/interfaces/device/climbro.interface.d.ts +7 -0
  18. package/dist/cjs/interfaces/device/climbro.interface.d.ts.map +1 -0
  19. package/dist/cjs/interfaces/device/climbro.interface.js +3 -0
  20. package/dist/cjs/interfaces/device/climbro.interface.js.map +1 -0
  21. package/dist/cjs/interfaces/device/entralpi.interface.d.ts +53 -0
  22. package/dist/cjs/interfaces/device/entralpi.interface.d.ts.map +1 -0
  23. package/dist/cjs/interfaces/device/entralpi.interface.js +3 -0
  24. package/dist/cjs/interfaces/device/entralpi.interface.js.map +1 -0
  25. package/dist/cjs/interfaces/device/forceboard.interface.d.ts +64 -0
  26. package/dist/cjs/interfaces/device/forceboard.interface.d.ts.map +1 -0
  27. package/dist/cjs/interfaces/device/forceboard.interface.js +3 -0
  28. package/dist/cjs/interfaces/device/forceboard.interface.js.map +1 -0
  29. package/dist/cjs/interfaces/device/kilterboard.interface.d.ts +16 -0
  30. package/dist/cjs/interfaces/device/kilterboard.interface.d.ts.map +1 -0
  31. package/dist/cjs/interfaces/device/kilterboard.interface.js +3 -0
  32. package/dist/cjs/interfaces/device/kilterboard.interface.js.map +1 -0
  33. package/dist/cjs/interfaces/device/motherboard.interface.d.ts +54 -0
  34. package/dist/cjs/interfaces/device/motherboard.interface.d.ts.map +1 -0
  35. package/dist/cjs/interfaces/device/motherboard.interface.js +3 -0
  36. package/dist/cjs/interfaces/device/motherboard.interface.js.map +1 -0
  37. package/dist/cjs/interfaces/device/mysmartboard.interface.d.ts +7 -0
  38. package/dist/cjs/interfaces/device/mysmartboard.interface.d.ts.map +1 -0
  39. package/dist/cjs/interfaces/device/mysmartboard.interface.js +3 -0
  40. package/dist/cjs/interfaces/device/mysmartboard.interface.js.map +1 -0
  41. package/dist/cjs/interfaces/device/progressor.interface.d.ts +28 -0
  42. package/dist/cjs/interfaces/device/progressor.interface.d.ts.map +1 -0
  43. package/dist/cjs/interfaces/device/progressor.interface.js +3 -0
  44. package/dist/cjs/interfaces/device/progressor.interface.js.map +1 -0
  45. package/dist/cjs/interfaces/device/smartboard-pro.interface.d.ts +7 -0
  46. package/dist/cjs/interfaces/device/smartboard-pro.interface.d.ts.map +1 -0
  47. package/dist/cjs/interfaces/device/smartboard-pro.interface.js +3 -0
  48. package/dist/cjs/interfaces/device/smartboard-pro.interface.js.map +1 -0
  49. package/dist/cjs/interfaces/device/wh-c06.interface.d.ts +7 -0
  50. package/dist/cjs/interfaces/device/wh-c06.interface.d.ts.map +1 -0
  51. package/dist/cjs/interfaces/device/wh-c06.interface.js +3 -0
  52. package/dist/cjs/interfaces/device/wh-c06.interface.js.map +1 -0
  53. package/dist/cjs/interfaces/device.interface.d.ts +203 -0
  54. package/dist/cjs/interfaces/device.interface.d.ts.map +1 -0
  55. package/dist/cjs/interfaces/device.interface.js +3 -0
  56. package/dist/cjs/interfaces/device.interface.js.map +1 -0
  57. package/dist/cjs/interfaces/download.interface.d.ts +16 -0
  58. package/dist/cjs/interfaces/download.interface.d.ts.map +1 -0
  59. package/dist/cjs/interfaces/download.interface.js +3 -0
  60. package/dist/cjs/interfaces/download.interface.js.map +1 -0
  61. package/dist/cjs/interfaces/index.d.ts +10 -0
  62. package/dist/cjs/interfaces/index.d.ts.map +1 -0
  63. package/dist/cjs/interfaces/index.js +3 -0
  64. package/dist/cjs/interfaces/index.js.map +1 -0
  65. package/dist/cjs/models/base.model.d.ts +13 -0
  66. package/dist/cjs/models/base.model.d.ts.map +1 -0
  67. package/dist/cjs/models/base.model.js +24 -0
  68. package/dist/cjs/models/base.model.js.map +1 -0
  69. package/dist/cjs/models/device/climbro.model.d.ts +11 -0
  70. package/dist/cjs/models/device/climbro.model.d.ts.map +1 -0
  71. package/dist/cjs/models/device/climbro.model.js +19 -0
  72. package/dist/cjs/models/device/climbro.model.js.map +1 -0
  73. package/dist/cjs/models/device/entralpi.model.d.ts +64 -0
  74. package/dist/cjs/models/device/entralpi.model.d.ts.map +1 -0
  75. package/dist/cjs/models/device/entralpi.model.js +244 -0
  76. package/dist/cjs/models/device/entralpi.model.js.map +1 -0
  77. package/dist/cjs/models/device/forceboard.model.d.ts +73 -0
  78. package/dist/cjs/models/device/forceboard.model.d.ts.map +1 -0
  79. package/dist/cjs/models/device/forceboard.model.js +316 -0
  80. package/dist/cjs/models/device/forceboard.model.js.map +1 -0
  81. package/dist/cjs/models/device/kilterboard.model.d.ts +144 -0
  82. package/dist/cjs/models/device/kilterboard.model.d.ts.map +1 -0
  83. package/dist/cjs/models/device/kilterboard.model.js +291 -0
  84. package/dist/cjs/models/device/kilterboard.model.js.map +1 -0
  85. package/dist/cjs/models/device/motherboard.model.d.ts +110 -0
  86. package/dist/cjs/models/device/motherboard.model.d.ts.map +1 -0
  87. package/dist/cjs/models/device/motherboard.model.js +382 -0
  88. package/dist/cjs/models/device/motherboard.model.js.map +1 -0
  89. package/dist/cjs/models/device/mysmartboard.model.d.ts +11 -0
  90. package/dist/cjs/models/device/mysmartboard.model.d.ts.map +1 -0
  91. package/dist/cjs/models/device/mysmartboard.model.js +19 -0
  92. package/dist/cjs/models/device/mysmartboard.model.js.map +1 -0
  93. package/dist/cjs/models/device/progressor.model.d.ts +39 -0
  94. package/dist/cjs/models/device/progressor.model.d.ts.map +1 -0
  95. package/dist/cjs/models/device/progressor.model.js +220 -0
  96. package/dist/cjs/models/device/progressor.model.js.map +1 -0
  97. package/dist/cjs/models/device/smartboard-pro.model.d.ts +11 -0
  98. package/dist/cjs/models/device/smartboard-pro.model.d.ts.map +1 -0
  99. package/dist/cjs/models/device/smartboard-pro.model.js +56 -0
  100. package/dist/cjs/models/device/smartboard-pro.model.js.map +1 -0
  101. package/dist/cjs/models/device/wh-c06.model.d.ts +57 -0
  102. package/dist/cjs/models/device/wh-c06.model.d.ts.map +1 -0
  103. package/dist/cjs/models/device/wh-c06.model.js +171 -0
  104. package/dist/cjs/models/device/wh-c06.model.js.map +1 -0
  105. package/dist/cjs/models/device.model.d.ts +408 -0
  106. package/dist/cjs/models/device.model.d.ts.map +1 -0
  107. package/dist/cjs/models/device.model.js +665 -0
  108. package/dist/cjs/models/device.model.js.map +1 -0
  109. package/dist/cjs/models/index.d.ts +10 -0
  110. package/dist/cjs/models/index.d.ts.map +1 -0
  111. package/dist/cjs/models/index.js +22 -0
  112. package/dist/cjs/models/index.js.map +1 -0
  113. package/dist/index.d.ts +3 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +2 -0
  116. package/dist/index.js.map +1 -0
  117. package/dist/interfaces/base.interface.d.ts +18 -0
  118. package/dist/interfaces/base.interface.d.ts.map +1 -0
  119. package/dist/interfaces/base.interface.js +2 -0
  120. package/dist/interfaces/base.interface.js.map +1 -0
  121. package/dist/interfaces/callback.interface.d.ts +56 -0
  122. package/dist/interfaces/callback.interface.d.ts.map +1 -0
  123. package/dist/interfaces/callback.interface.js +2 -0
  124. package/dist/interfaces/callback.interface.js.map +1 -0
  125. package/dist/interfaces/command.interface.d.ts +92 -0
  126. package/dist/interfaces/command.interface.d.ts.map +1 -0
  127. package/dist/interfaces/command.interface.js +2 -0
  128. package/dist/interfaces/command.interface.js.map +1 -0
  129. package/dist/interfaces/device/climbro.interface.d.ts +7 -0
  130. package/dist/interfaces/device/climbro.interface.d.ts.map +1 -0
  131. package/dist/interfaces/device/climbro.interface.js +2 -0
  132. package/dist/interfaces/device/climbro.interface.js.map +1 -0
  133. package/dist/interfaces/device/entralpi.interface.d.ts +53 -0
  134. package/dist/interfaces/device/entralpi.interface.d.ts.map +1 -0
  135. package/dist/interfaces/device/entralpi.interface.js +2 -0
  136. package/dist/interfaces/device/entralpi.interface.js.map +1 -0
  137. package/dist/interfaces/device/forceboard.interface.d.ts +64 -0
  138. package/dist/interfaces/device/forceboard.interface.d.ts.map +1 -0
  139. package/dist/interfaces/device/forceboard.interface.js +2 -0
  140. package/dist/interfaces/device/forceboard.interface.js.map +1 -0
  141. package/dist/interfaces/device/kilterboard.interface.d.ts +16 -0
  142. package/dist/interfaces/device/kilterboard.interface.d.ts.map +1 -0
  143. package/dist/interfaces/device/kilterboard.interface.js +2 -0
  144. package/dist/interfaces/device/kilterboard.interface.js.map +1 -0
  145. package/dist/interfaces/device/motherboard.interface.d.ts +54 -0
  146. package/dist/interfaces/device/motherboard.interface.d.ts.map +1 -0
  147. package/dist/interfaces/device/motherboard.interface.js +2 -0
  148. package/dist/interfaces/device/motherboard.interface.js.map +1 -0
  149. package/dist/interfaces/device/mysmartboard.interface.d.ts +7 -0
  150. package/dist/interfaces/device/mysmartboard.interface.d.ts.map +1 -0
  151. package/dist/interfaces/device/mysmartboard.interface.js +2 -0
  152. package/dist/interfaces/device/mysmartboard.interface.js.map +1 -0
  153. package/dist/interfaces/device/progressor.interface.d.ts +28 -0
  154. package/dist/interfaces/device/progressor.interface.d.ts.map +1 -0
  155. package/dist/interfaces/device/progressor.interface.js +2 -0
  156. package/dist/interfaces/device/progressor.interface.js.map +1 -0
  157. package/dist/interfaces/device/smartboard-pro.interface.d.ts +7 -0
  158. package/dist/interfaces/device/smartboard-pro.interface.d.ts.map +1 -0
  159. package/dist/interfaces/device/smartboard-pro.interface.js +2 -0
  160. package/dist/interfaces/device/smartboard-pro.interface.js.map +1 -0
  161. package/dist/interfaces/device/wh-c06.interface.d.ts +7 -0
  162. package/dist/interfaces/device/wh-c06.interface.d.ts.map +1 -0
  163. package/dist/interfaces/device/wh-c06.interface.js +2 -0
  164. package/dist/interfaces/device/wh-c06.interface.js.map +1 -0
  165. package/dist/interfaces/device.interface.d.ts +203 -0
  166. package/dist/interfaces/device.interface.d.ts.map +1 -0
  167. package/dist/interfaces/device.interface.js +2 -0
  168. package/dist/interfaces/device.interface.js.map +1 -0
  169. package/dist/interfaces/download.interface.d.ts +16 -0
  170. package/dist/interfaces/download.interface.d.ts.map +1 -0
  171. package/dist/interfaces/download.interface.js +2 -0
  172. package/dist/interfaces/download.interface.js.map +1 -0
  173. package/dist/interfaces/index.d.ts +10 -0
  174. package/dist/interfaces/index.d.ts.map +1 -0
  175. package/dist/interfaces/index.js +2 -0
  176. package/dist/interfaces/index.js.map +1 -0
  177. package/dist/models/base.model.d.ts +13 -0
  178. package/dist/models/base.model.d.ts.map +1 -0
  179. package/dist/models/base.model.js +22 -0
  180. package/dist/models/base.model.js.map +1 -0
  181. package/dist/models/device/climbro.model.d.ts +11 -0
  182. package/dist/models/device/climbro.model.d.ts.map +1 -0
  183. package/dist/models/device/climbro.model.js +15 -0
  184. package/dist/models/device/climbro.model.js.map +1 -0
  185. package/dist/models/device/entralpi.model.d.ts +64 -0
  186. package/dist/models/device/entralpi.model.d.ts.map +1 -0
  187. package/dist/models/device/entralpi.model.js +240 -0
  188. package/dist/models/device/entralpi.model.js.map +1 -0
  189. package/dist/models/device/forceboard.model.d.ts +73 -0
  190. package/dist/models/device/forceboard.model.d.ts.map +1 -0
  191. package/dist/models/device/forceboard.model.js +312 -0
  192. package/dist/models/device/forceboard.model.js.map +1 -0
  193. package/dist/models/device/kilterboard.model.d.ts +144 -0
  194. package/dist/models/device/kilterboard.model.d.ts.map +1 -0
  195. package/dist/models/device/kilterboard.model.js +287 -0
  196. package/dist/models/device/kilterboard.model.js.map +1 -0
  197. package/dist/models/device/motherboard.model.d.ts +110 -0
  198. package/dist/models/device/motherboard.model.d.ts.map +1 -0
  199. package/dist/models/device/motherboard.model.js +378 -0
  200. package/dist/models/device/motherboard.model.js.map +1 -0
  201. package/dist/models/device/mysmartboard.model.d.ts +11 -0
  202. package/dist/models/device/mysmartboard.model.d.ts.map +1 -0
  203. package/dist/models/device/mysmartboard.model.js +15 -0
  204. package/dist/models/device/mysmartboard.model.js.map +1 -0
  205. package/dist/models/device/progressor.model.d.ts +39 -0
  206. package/dist/models/device/progressor.model.d.ts.map +1 -0
  207. package/dist/models/device/progressor.model.js +216 -0
  208. package/dist/models/device/progressor.model.js.map +1 -0
  209. package/dist/models/device/smartboard-pro.model.d.ts +11 -0
  210. package/dist/models/device/smartboard-pro.model.d.ts.map +1 -0
  211. package/dist/models/device/smartboard-pro.model.js +52 -0
  212. package/dist/models/device/smartboard-pro.model.js.map +1 -0
  213. package/dist/models/device/wh-c06.model.d.ts +57 -0
  214. package/dist/models/device/wh-c06.model.d.ts.map +1 -0
  215. package/dist/models/device/wh-c06.model.js +167 -0
  216. package/dist/models/device/wh-c06.model.js.map +1 -0
  217. package/dist/models/device.model.d.ts +408 -0
  218. package/dist/models/device.model.d.ts.map +1 -0
  219. package/dist/models/device.model.js +720 -0
  220. package/dist/models/device.model.js.map +1 -0
  221. package/dist/models/index.d.ts +10 -0
  222. package/dist/models/index.d.ts.map +1 -0
  223. package/dist/models/index.js +10 -0
  224. package/dist/models/index.js.map +1 -0
  225. package/dist/tsconfig.cjs.tsbuildinfo +1 -0
  226. package/package.json +5 -1
  227. package/deno.json +0 -8
  228. package/tsconfig.cjs.json +0 -15
  229. package/tsconfig.json +0 -13
@@ -0,0 +1,665 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Device = void 0;
4
+ const base_model_js_1 = require("./../models/base.model.js");
5
+ class Device extends base_model_js_1.BaseModel {
6
+ constructor(device) {
7
+ super(device);
8
+ /**
9
+ * The last message written to the device.
10
+ * @type {string | Uint8Array | null}
11
+ * @protected
12
+ */
13
+ this.writeLast = null;
14
+ /**
15
+ * Indicates whether the device is currently active.
16
+ * @type {boolean}
17
+ */
18
+ this.isActive = false;
19
+ /**
20
+ * Configuration for threshold and duration.
21
+ */
22
+ this.activeConfig = {
23
+ threshold: 2.5,
24
+ duration: 1000,
25
+ };
26
+ /**
27
+ * Array of DownloadPacket entries.
28
+ * This array holds packets that contain data downloaded from the device.
29
+ * @type {DownloadPacket[]}
30
+ * @protected
31
+ */
32
+ this.downloadPackets = []; // Initialize an empty array of DownloadPacket entries
33
+ /**
34
+ * Represents the current tare value for calibration.
35
+ * @type {number}
36
+ */
37
+ this.tareCurrent = 0;
38
+ /**
39
+ * Indicates whether the tare calibration process is active.
40
+ * @type {boolean}
41
+ */
42
+ this.tareActive = false;
43
+ /**
44
+ * Timestamp when the tare calibration process started.
45
+ * @type {number | null}
46
+ */
47
+ this.tareStartTime = null;
48
+ /**
49
+ * Array holding the samples collected during tare calibration.
50
+ * @type {number[]}
51
+ */
52
+ this.tareSamples = [];
53
+ /**
54
+ * Duration time for the tare calibration process.
55
+ * @type {number}
56
+ */
57
+ this.tareDuration = 5000;
58
+ /**
59
+ * Optional callback for handling write operations.
60
+ * @callback NotifyCallback
61
+ * @param {massObject} data - The data passed to the callback.
62
+ * @type {NotifyCallback | undefined}
63
+ * @protected
64
+ */
65
+ this.notifyCallback = (data) => console.log(data);
66
+ /**
67
+ * Optional callback for handling write operations.
68
+ * @callback WriteCallback
69
+ * @param {string} data - The data passed to the callback.
70
+ * @type {WriteCallback | undefined}
71
+ * @protected
72
+ */
73
+ this.writeCallback = (data) => console.log(data);
74
+ /**
75
+ * Optional callback for handling write operations.
76
+ * @callback ActiveCallback
77
+ * @param {string} data - The data passed to the callback.
78
+ * @type {ActiveCallback | undefined}
79
+ * @protected
80
+ */
81
+ this.activeCallback = (data) => console.log(data);
82
+ /**
83
+ * Event listener for handling the 'gattserverdisconnected' event.
84
+ * This listener delegates the event to the `onDisconnected` method.
85
+ *
86
+ * @private
87
+ * @type {(event: Event) => void}
88
+ */
89
+ this.onDisconnectedListener = (event) => this.onDisconnected(event);
90
+ /**
91
+ * A map that stores notification event listeners keyed by characteristic UUIDs.
92
+ * This allows for proper addition and removal of event listeners associated with each characteristic.
93
+ *
94
+ * @private
95
+ * @type {Map<string, EventListener>}
96
+ */
97
+ this.notificationListeners = new Map();
98
+ /**
99
+ * Sets the callback function to be called when the activity status changes,
100
+ * and optionally sets the configuration for threshold and duration.
101
+ *
102
+ * This function allows you to specify a callback that will be invoked whenever
103
+ * the activity status changes, indicating whether the device is currently active.
104
+ * It also allows optionally configuring the threshold and duration used to determine activity.
105
+ *
106
+ * @param {ActiveCallback} callback - The callback function to be set. This function
107
+ * receives a boolean value indicating the new activity status.
108
+ * @param {object} [options] - Optional configuration object containing the threshold and duration.
109
+ * @param {number} [options.threshold=2.5] - The threshold value for determining activity.
110
+ * @param {number} [options.duration=1000] - The duration (in milliseconds) to monitor the input for activity.
111
+ * @returns {void}
112
+ * @public
113
+ *
114
+ * @example
115
+ * device.active((isActive) => {
116
+ * console.log(`Device is ${isActive ? 'active' : 'inactive'}`);
117
+ * }, { threshold: 3.0, duration: 1500 });
118
+ */
119
+ this.active = (callback, options) => {
120
+ var _a, _b;
121
+ this.activeCallback = callback;
122
+ // Update the config values only if provided, otherwise use defaults
123
+ this.activeConfig = {
124
+ threshold: (_a = options === null || options === void 0 ? void 0 : options.threshold) !== null && _a !== void 0 ? _a : this.activeConfig.threshold, // Use new threshold if provided, else use default
125
+ duration: (_b = options === null || options === void 0 ? void 0 : options.duration) !== null && _b !== void 0 ? _b : this.activeConfig.duration, // Use new duration if provided, else use default
126
+ };
127
+ };
128
+ /**
129
+ * Checks if a dynamic value is active based on a threshold and duration.
130
+ *
131
+ * This function assesses whether a given dynamic value surpasses a specified threshold
132
+ * and remains active for a specified duration. If the activity status changes from
133
+ * the previous state, the callback function is called with the updated activity status.
134
+ *
135
+ * @param {number} input - The dynamic value to check for activity status.
136
+ * @returns {Promise<void>} A promise that resolves once the activity check is complete.
137
+ *
138
+ * @example
139
+ * await device.activityCheck(5.0);
140
+ */
141
+ this.activityCheck = async (input) => {
142
+ var _a;
143
+ const startValue = input;
144
+ const { threshold, duration } = this.activeConfig;
145
+ // After waiting for `duration`, check if still active.
146
+ await new Promise((resolve) => setTimeout(resolve, duration));
147
+ const activeNow = startValue > threshold;
148
+ if (this.isActive !== activeNow) {
149
+ this.isActive = activeNow;
150
+ (_a = this.activeCallback) === null || _a === void 0 ? void 0 : _a.call(this, activeNow);
151
+ }
152
+ };
153
+ /**
154
+ * Connects to a Bluetooth device.
155
+ * @param {Function} [onSuccess] - Optional callback function to execute on successful connection. Default logs success.
156
+ * @param {Function} [onError] - Optional callback function to execute on error. Default logs the error.
157
+ * @public
158
+ *
159
+ * @example
160
+ * device.connect(
161
+ * () => console.log("Connected successfully"),
162
+ * (error) => console.error("Connection failed:", error)
163
+ * );
164
+ */
165
+ this.connect = async (onSuccess = () => console.log("Connected successfully"), onError = (error) => console.error(error)) => {
166
+ try {
167
+ // Request device and set up connection
168
+ const deviceServices = this.getAllServiceUUIDs();
169
+ const bluetooth = await this.getBluetooth();
170
+ this.bluetooth = await bluetooth.requestDevice({
171
+ filters: this.filters,
172
+ optionalServices: deviceServices,
173
+ });
174
+ if (!this.bluetooth.gatt) {
175
+ throw new Error("GATT is not available on this device");
176
+ }
177
+ this.bluetooth.addEventListener("gattserverdisconnected", this.onDisconnectedListener);
178
+ this.server = await this.bluetooth.gatt.connect();
179
+ if (this.server.connected) {
180
+ await this.onConnected(onSuccess);
181
+ }
182
+ }
183
+ catch (error) {
184
+ onError(error);
185
+ }
186
+ };
187
+ /**
188
+ * Disconnects the device if it is currently connected.
189
+ * - Removes all notification listeners from the device's characteristics.
190
+ * - Removes the 'gattserverdisconnected' event listener.
191
+ * - Attempts to gracefully disconnect the device's GATT server.
192
+ * - Resets relevant properties to their initial states.
193
+ * @returns {void}
194
+ * @public
195
+ *
196
+ * @example
197
+ * device.disconnect();
198
+ */
199
+ this.disconnect = () => {
200
+ var _a, _b, _c;
201
+ if (this.isConnected()) {
202
+ this.updateTimestamp();
203
+ // Remove all notification listeners
204
+ this.services.forEach((service) => {
205
+ service.characteristics.forEach((char) => {
206
+ // Look for the "rx" characteristic that accepts notifications
207
+ if (char.characteristic && char.id === "rx") {
208
+ char.characteristic.stopNotifications();
209
+ const listener = this.notificationListeners.get(char.uuid);
210
+ if (listener) {
211
+ char.characteristic.removeEventListener("characteristicvaluechanged", listener);
212
+ this.notificationListeners.delete(char.uuid);
213
+ }
214
+ }
215
+ });
216
+ });
217
+ // Remove disconnect listener
218
+ (_a = this.bluetooth) === null || _a === void 0 ? void 0 : _a.removeEventListener("gattserverdisconnected", this.onDisconnectedListener);
219
+ // Safely attempt to disconnect the device's GATT server, if available
220
+ (_c = (_b = this.bluetooth) === null || _b === void 0 ? void 0 : _b.gatt) === null || _c === void 0 ? void 0 : _c.disconnect();
221
+ // Reset properties
222
+ this.server = undefined;
223
+ this.writeLast = null;
224
+ this.isActive = false;
225
+ }
226
+ };
227
+ /**
228
+ * Converts the `downloadPackets` array into a CSV formatted string.
229
+ * @returns {string} A CSV string representation of the `downloadPackets` data, with each packet on a new line.
230
+ * @private
231
+ *
232
+ * @example
233
+ * const csvData = device.downloadToCSV();
234
+ * console.log(csvData);
235
+ */
236
+ this.downloadToCSV = () => {
237
+ const packets = [...this.downloadPackets];
238
+ if (packets.length === 0) {
239
+ return "";
240
+ }
241
+ return packets
242
+ .map((packet) => [
243
+ packet.received.toString(),
244
+ packet.sampleNum.toString(),
245
+ packet.battRaw.toString(),
246
+ ...packet.samples.map(String),
247
+ ...packet.masses.map(String),
248
+ ]
249
+ .map((v) => v.replace(/"/g, '""'))
250
+ .map((v) => `"${v}"`)
251
+ .join(","))
252
+ .join("\r\n");
253
+ };
254
+ /**
255
+ * Converts an array of DownloadPacket objects to a JSON string.
256
+ * @returns {string} JSON string representation of the data.
257
+ * @private
258
+ *
259
+ * @example
260
+ * const jsonData = device.downloadToJSON();
261
+ * console.log(jsonData);
262
+ */
263
+ this.downloadToJSON = () => {
264
+ // Pretty print JSON with 2-space indentation
265
+ return JSON.stringify(this.downloadPackets, null, 2);
266
+ };
267
+ /**
268
+ * Converts an array of DownloadPacket objects to an XML string.
269
+ * @returns {string} XML string representation of the data.
270
+ * @private
271
+ *
272
+ * @example
273
+ * const xmlData = device.downloadToXML();
274
+ * console.log(xmlData);
275
+ */
276
+ this.downloadToXML = () => {
277
+ const xmlPackets = this.downloadPackets
278
+ .map((packet) => {
279
+ const samples = packet.samples.map((sample) => `<sample>${sample}</sample>`).join("");
280
+ const masses = packet.masses.map((mass) => `<mass>${mass}</mass>`).join("");
281
+ return `
282
+ <packet>
283
+ <received>${packet.received}</received>
284
+ <sampleNum>${packet.sampleNum}</sampleNum>
285
+ <battRaw>${packet.battRaw}</battRaw>
286
+ <samples>${samples}</samples>
287
+ <masses>${masses}</masses>
288
+ </packet>
289
+ `;
290
+ })
291
+ .join("");
292
+ return `<DownloadPackets>${xmlPackets}</DownloadPackets>`;
293
+ };
294
+ /**
295
+ * Exports the data in the specified format (CSV, JSON, XML) with a filename format:
296
+ * 'data-export-YYYY-MM-DD-HH-MM-SS.{format}'.
297
+ *
298
+ * @param {('csv' | 'json' | 'xml')} [format='csv'] - The format in which to download the data.
299
+ * Defaults to 'csv'. Accepted values are 'csv', 'json', and 'xml'.
300
+ *
301
+ * @returns {Promise<void>} Resolves when the data has been downloaded/written
302
+ * @public
303
+ *
304
+ * @example
305
+ * await device.download('json');
306
+ */
307
+ this.download = async (format = "csv") => {
308
+ let content = "";
309
+ if (format === "csv") {
310
+ content = this.downloadToCSV();
311
+ }
312
+ else if (format === "json") {
313
+ content = this.downloadToJSON();
314
+ }
315
+ else if (format === "xml") {
316
+ content = this.downloadToXML();
317
+ }
318
+ const now = new Date();
319
+ // YYYY-MM-DD
320
+ const date = now.toISOString().split("T")[0];
321
+ // HH-MM-SS
322
+ const time = now.toTimeString().split(" ")[0].replace(/:/g, "-");
323
+ const fileName = `data-export-${date}-${time}.${format}`;
324
+ const mimeTypes = {
325
+ csv: "text/csv",
326
+ json: "application/json",
327
+ xml: "application/xml",
328
+ };
329
+ // Create a Blob object containing the data
330
+ const blob = new Blob([content], { type: mimeTypes[format] });
331
+ // Create a URL for the Blob
332
+ const url = globalThis.URL.createObjectURL(blob);
333
+ // Create a link element
334
+ const link = document.createElement("a");
335
+ // Set link attributes
336
+ link.href = url;
337
+ link.setAttribute("download", fileName);
338
+ // Append link to document body
339
+ document.body.appendChild(link);
340
+ // Programmatically click the link to trigger the download
341
+ link.click();
342
+ // Clean up: remove the link and revoke the URL
343
+ document.body.removeChild(link);
344
+ globalThis.URL.revokeObjectURL(url);
345
+ };
346
+ /**
347
+ * Returns UUIDs of all services associated with the device.
348
+ * @returns {string[]} Array of service UUIDs.
349
+ * @protected
350
+ *
351
+ * @example
352
+ * const serviceUUIDs = device.getAllServiceUUIDs();
353
+ * console.log(serviceUUIDs);
354
+ */
355
+ this.getAllServiceUUIDs = () => {
356
+ return this.services.filter((service) => service === null || service === void 0 ? void 0 : service.uuid).map((service) => service.uuid);
357
+ };
358
+ /**
359
+ * Handles notifications received from a characteristic.
360
+ * @param {DataView} value - The notification event.
361
+ *
362
+ * @example
363
+ * device.handleNotifications(someCharacteristic);
364
+ */
365
+ this.handleNotifications = (value) => {
366
+ if (!value)
367
+ return;
368
+ this.updateTimestamp();
369
+ // Received notification data
370
+ console.log(value);
371
+ };
372
+ /**
373
+ * Checks if a Bluetooth device is connected.
374
+ * @returns {boolean} A boolean indicating whether the device is connected.
375
+ * @public
376
+ *
377
+ * @example
378
+ * if (device.isConnected()) {
379
+ * console.log('Device is connected');
380
+ * } else {
381
+ * console.log('Device is not connected');
382
+ * }
383
+ */
384
+ this.isConnected = () => {
385
+ var _a;
386
+ // Check if the device is defined and available
387
+ if (!this.bluetooth) {
388
+ return false;
389
+ }
390
+ // Check if the device is connected
391
+ return !!((_a = this.bluetooth.gatt) === null || _a === void 0 ? void 0 : _a.connected);
392
+ };
393
+ /**
394
+ * Sets the callback function to be called when notifications are received.
395
+ * @param {NotifyCallback} callback - The callback function to be set.
396
+ * @returns {void}
397
+ * @public
398
+ *
399
+ * @example
400
+ * device.notify((data) => {
401
+ * console.log('Received notification:', data);
402
+ * });
403
+ */
404
+ this.notify = (callback) => {
405
+ this.notifyCallback = callback;
406
+ };
407
+ /**
408
+ * Handles the 'connected' event.
409
+ * @param {Function} onSuccess - Callback function to execute on successful connection.
410
+ * @public
411
+ *
412
+ * @example
413
+ * device.onConnected(() => {
414
+ * console.log('Device connected successfully');
415
+ * });
416
+ */
417
+ this.onConnected = async (onSuccess) => {
418
+ this.updateTimestamp();
419
+ if (!this.server) {
420
+ throw new Error("GATT server is not available");
421
+ }
422
+ // Connect to GATT server and set up characteristics
423
+ const services = await this.server.getPrimaryServices();
424
+ if (!services || services.length === 0) {
425
+ throw new Error("No services found");
426
+ }
427
+ for (const service of services) {
428
+ const matchingService = this.services.find((boardService) => boardService.uuid === service.uuid);
429
+ if (matchingService) {
430
+ // Android bug: Add a small delay before getting characteristics
431
+ await new Promise((resolve) => setTimeout(resolve, 100));
432
+ const characteristics = await service.getCharacteristics();
433
+ for (const characteristic of matchingService.characteristics) {
434
+ const matchingCharacteristic = characteristics.find((char) => char.uuid === characteristic.uuid);
435
+ if (matchingCharacteristic) {
436
+ // Find the corresponding characteristic descriptor in the service's characteristics array
437
+ const descriptor = matchingService.characteristics.find((char) => char.uuid === matchingCharacteristic.uuid);
438
+ if (descriptor) {
439
+ // Assign the actual Bluetooth characteristic object to the descriptor so it can be used later
440
+ descriptor.characteristic = matchingCharacteristic;
441
+ // Look for the "rx" characteristic id that accepts notifications
442
+ if (descriptor.id === "rx") {
443
+ // Start receiving notifications for changes on this characteristic
444
+ matchingCharacteristic.startNotifications();
445
+ // Triggered when the characteristic's value changes
446
+ const listener = (event) => {
447
+ // Cast the event's target to a BluetoothRemoteGATTCharacteristic to access its properties
448
+ const target = event.target;
449
+ if (target && target.value) {
450
+ // Delegate the data to handleNotifications method
451
+ this.handleNotifications(target.value);
452
+ }
453
+ };
454
+ // Attach the event listener to listen for changes in the characteristic's value
455
+ matchingCharacteristic.addEventListener("characteristicvaluechanged", listener);
456
+ // Store the listener so it can be referenced (for later removal)
457
+ this.notificationListeners.set(descriptor.uuid, listener);
458
+ }
459
+ }
460
+ }
461
+ else {
462
+ throw new Error(`Characteristic ${characteristic.uuid} not found in service ${service.uuid}`);
463
+ }
464
+ }
465
+ }
466
+ }
467
+ // Call the onSuccess callback after successful connection and setup
468
+ onSuccess();
469
+ };
470
+ /**
471
+ * Handles the 'disconnected' event.
472
+ * @param {Event} event - The 'disconnected' event.
473
+ * @public
474
+ *
475
+ * @example
476
+ * device.onDisconnected(event);
477
+ */
478
+ this.onDisconnected = (event) => {
479
+ console.warn(`Device ${event.target.name} is disconnected.`);
480
+ this.disconnect();
481
+ };
482
+ /**
483
+ * Reads the value of the specified characteristic from the device.
484
+ * @param {string} serviceId - The service ID where the characteristic belongs.
485
+ * @param {string} characteristicId - The characteristic ID to read from.
486
+ * @param {number} [duration=0] - The duration to wait before resolving the promise, in milliseconds.
487
+ * @returns {Promise<string | undefined>} A promise that resolves when the read operation is completed.
488
+ * @public
489
+ *
490
+ * @example
491
+ * const value = await device.read('battery', 'level', 1000);
492
+ * console.log('Battery level:', value);
493
+ */
494
+ this.read = async (serviceId, characteristicId, duration = 0) => {
495
+ var _a, _b;
496
+ if (!this.isConnected()) {
497
+ return undefined;
498
+ }
499
+ // Get the characteristic from the service
500
+ const characteristic = (_b = (_a = this.services
501
+ .find((service) => service.id === serviceId)) === null || _a === void 0 ? void 0 : _a.characteristics.find((char) => char.id === characteristicId)) === null || _b === void 0 ? void 0 : _b.characteristic;
502
+ if (!characteristic) {
503
+ throw new Error(`Characteristic "${characteristicId}" not found in service "${serviceId}"`);
504
+ }
505
+ this.updateTimestamp();
506
+ // Decode the value based on characteristicId and serviceId
507
+ let decodedValue;
508
+ const decoder = new TextDecoder("utf-8");
509
+ // Read the value from the characteristic
510
+ const value = await characteristic.readValue();
511
+ if ((serviceId === "battery" || serviceId === "humidity" || serviceId === "temperature") &&
512
+ characteristicId === "level") {
513
+ // This is battery-specific; return the first byte as the level
514
+ decodedValue = value.getUint8(0).toString();
515
+ }
516
+ else {
517
+ // Otherwise use a UTF-8 decoder
518
+ decodedValue = decoder.decode(value);
519
+ }
520
+ // Wait for the specified duration before returning the result
521
+ if (duration > 0) {
522
+ await new Promise((resolve) => setTimeout(resolve, duration));
523
+ }
524
+ return decodedValue;
525
+ };
526
+ /**
527
+ * Updates the timestamp of the last device interaction.
528
+ * This method sets the updatedAt property to the current date and time.
529
+ * @protected
530
+ *
531
+ * @example
532
+ * device.updateTimestamp();
533
+ * console.log('Last updated:', device.updatedAt);
534
+ */
535
+ this.updateTimestamp = () => {
536
+ this.updatedAt = new Date();
537
+ };
538
+ /**
539
+ * Writes a message to the specified characteristic of a Bluetooth device and optionally provides a callback to handle responses.
540
+ * @param {string} serviceId - The service UUID of the Bluetooth device containing the target characteristic.
541
+ * @param {string} characteristicId - The characteristic UUID where the message will be written.
542
+ * @param {string | Uint8Array | undefined} message - The message to be written to the characteristic. It can be a string or a Uint8Array.
543
+ * @param {number} [duration=0] - Optional. The time in milliseconds to wait before resolving the promise. Defaults to 0 for immediate resolution.
544
+ * @param {WriteCallback} [callback=writeCallback] - Optional. A custom callback to handle the response after the write operation is successful.
545
+ * @returns {Promise<void>} A promise that resolves once the write operation is complete.
546
+ * @public
547
+ * @throws {Error} Throws an error if the characteristic is undefined.
548
+ *
549
+ * @example
550
+ * // Example usage of the write function with a custom callback
551
+ * await Progressor.write("progressor", "tx", ProgressorCommands.GET_BATT_VLTG, 250, (data) => {
552
+ * console.log(`Battery voltage: ${data}`);
553
+ * });
554
+ */
555
+ this.write = async (serviceId, characteristicId, message, duration = 0, callback = this.writeCallback) => {
556
+ var _a, _b;
557
+ // Check if not connected or no message is provided
558
+ if (!this.isConnected() || message === undefined) {
559
+ return Promise.resolve();
560
+ }
561
+ // Get the characteristic from the service
562
+ const characteristic = (_b = (_a = this.services
563
+ .find((service) => service.id === serviceId)) === null || _a === void 0 ? void 0 : _a.characteristics.find((char) => char.id === characteristicId)) === null || _b === void 0 ? void 0 : _b.characteristic;
564
+ if (!characteristic) {
565
+ throw new Error(`Characteristic "${characteristicId}" not found in service "${serviceId}"`);
566
+ }
567
+ this.updateTimestamp();
568
+ // Convert the message to Uint8Array if it's a string
569
+ const valueToWrite = typeof message === "string" ? new Uint8Array(new TextEncoder().encode(message)) : new Uint8Array(message);
570
+ // Write the value to the characteristic
571
+ await characteristic.writeValue(valueToWrite);
572
+ // Update the last written message
573
+ this.writeLast = message;
574
+ // Assign the provided callback to `writeCallback`
575
+ this.writeCallback = callback;
576
+ // If a duration is specified, resolve the promise after the duration
577
+ if (duration > 0) {
578
+ await new Promise((resolve) => setTimeout(resolve, duration));
579
+ }
580
+ };
581
+ this.filters = device.filters || [];
582
+ this.services = device.services || [];
583
+ this.commands = device.commands || {};
584
+ if (device.bluetooth !== undefined) {
585
+ this.bluetooth = device.bluetooth;
586
+ }
587
+ this.massMax = "0";
588
+ this.massAverage = "0";
589
+ this.massTotalSum = 0;
590
+ this.dataPointCount = 0;
591
+ this.createdAt = new Date();
592
+ this.updatedAt = new Date();
593
+ }
594
+ /**
595
+ * Returns the Bluetooth instance available for the current environment.
596
+ * In browsers, it returns the native Web Bluetooth API (i.e. `navigator.bluetooth`).
597
+ * In a Node, Bun, or Deno environment, it dynamically imports the `webbluetooth` package.
598
+ * {@link https://github.com/thegecko/webbluetooth}
599
+ *
600
+ * @returns {Promise<Bluetooth>} A promise that resolves to the Bluetooth instance.
601
+ * @throws {Error} If Web Bluetooth is not available in the current environment.
602
+ */
603
+ async getBluetooth() {
604
+ // If running in a browser with native Web Bluetooth support:
605
+ if (typeof navigator !== "undefined" && navigator.bluetooth) {
606
+ return navigator.bluetooth;
607
+ }
608
+ // If none of the above conditions are met, throw an error.
609
+ throw new Error("Bluetooth not available.");
610
+ }
611
+ /**
612
+ * Initiates the tare calibration process.
613
+ * @param {number} duration - The duration time for tare calibration.
614
+ * @returns {boolean} A boolean indicating whether the tare calibration was successful.
615
+ * @public
616
+ *
617
+ * @example
618
+ * const success = device.tare(5000);
619
+ * if (success) {
620
+ * console.log('Tare calibration started');
621
+ * } else {
622
+ * console.log('Tare calibration failed to start');
623
+ * }
624
+ */
625
+ tare(duration = 5000) {
626
+ if (this.tareActive)
627
+ return false;
628
+ this.updateTimestamp();
629
+ this.tareActive = true;
630
+ this.tareDuration = duration;
631
+ this.tareSamples = [];
632
+ this.tareStartTime = Date.now();
633
+ return true;
634
+ }
635
+ /**
636
+ * Apply tare calibration to the provided sample.
637
+ * @param {number} sample - The sample to calibrate.
638
+ * @returns {number} The calibrated tare value.
639
+ * @protected
640
+ *
641
+ * @example
642
+ * const calibratedSample = device.applyTare(rawSample);
643
+ * console.log('Calibrated sample:', calibratedSample);
644
+ */
645
+ applyTare(sample) {
646
+ if (this.tareActive && this.tareStartTime) {
647
+ // Add current sample to the tare samples array
648
+ this.tareSamples.push(sample);
649
+ // Check if the tare calibration duration has passed
650
+ if (Date.now() - this.tareStartTime >= this.tareDuration) {
651
+ // Calculate the average of the tare samples
652
+ const total = this.tareSamples.reduce((acc, sample) => acc + sample, 0);
653
+ this.tareCurrent = total / this.tareSamples.length;
654
+ // Reset the tare calibration process
655
+ this.tareActive = false;
656
+ this.tareStartTime = null;
657
+ this.tareSamples = [];
658
+ }
659
+ }
660
+ // Return the current tare-adjusted value
661
+ return this.tareCurrent;
662
+ }
663
+ }
664
+ exports.Device = Device;
665
+ //# sourceMappingURL=device.model.js.map