@voltras/node-sdk 0.1.1 → 0.2.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.
- package/README.md +122 -31
- package/dist/cjs/bluetooth/adapters/native.js +36 -34
- package/dist/cjs/bluetooth/adapters/native.js.map +1 -1
- package/dist/cjs/bluetooth/adapters/node.js +9 -7
- package/dist/cjs/bluetooth/adapters/node.js.map +1 -1
- package/dist/cjs/bluetooth/adapters/web-bluetooth-base.js +6 -4
- package/dist/cjs/bluetooth/adapters/web-bluetooth-base.js.map +1 -1
- package/dist/cjs/bluetooth/adapters/web.js +7 -5
- package/dist/cjs/bluetooth/adapters/web.js.map +1 -1
- package/dist/cjs/bluetooth/controllers/scanner-controller.js +0 -2
- package/dist/cjs/bluetooth/controllers/scanner-controller.js.map +1 -1
- package/dist/cjs/bluetooth/index.js.map +1 -1
- package/dist/cjs/errors.js.map +1 -1
- package/dist/cjs/index.js +19 -10
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react/hooks.js +2 -6
- package/dist/cjs/react/hooks.js.map +1 -1
- package/dist/cjs/sdk/notification-dispatcher.js +47 -0
- package/dist/cjs/sdk/notification-dispatcher.js.map +1 -0
- package/dist/cjs/sdk/reconnect-handler.js +61 -0
- package/dist/cjs/sdk/reconnect-handler.js.map +1 -0
- package/dist/cjs/sdk/voltra-client.js +206 -72
- package/dist/cjs/sdk/voltra-client.js.map +1 -1
- package/dist/cjs/sdk/voltra-manager.js +13 -2
- package/dist/cjs/sdk/voltra-manager.js.map +1 -1
- package/dist/cjs/shared/index.js +5 -1
- package/dist/cjs/shared/index.js.map +1 -1
- package/dist/cjs/shared/logger.js +54 -0
- package/dist/cjs/shared/logger.js.map +1 -0
- package/dist/cjs/voltra/index.js +15 -12
- package/dist/cjs/voltra/index.js.map +1 -1
- package/dist/cjs/voltra/models/device.js +13 -0
- package/dist/cjs/voltra/models/device.js.map +1 -1
- package/dist/cjs/voltra/protocol/commands.js +127 -210
- package/dist/cjs/voltra/protocol/commands.js.map +1 -1
- package/dist/cjs/voltra/protocol/constants/ble-config.js +24 -0
- package/dist/cjs/voltra/protocol/constants/ble-config.js.map +1 -0
- package/dist/cjs/voltra/protocol/constants/connection-commands.js +55 -0
- package/dist/cjs/voltra/protocol/constants/connection-commands.js.map +1 -0
- package/dist/cjs/voltra/protocol/constants/enums.js +117 -0
- package/dist/cjs/voltra/protocol/constants/enums.js.map +1 -0
- package/dist/cjs/voltra/protocol/constants/index.js +32 -0
- package/dist/cjs/voltra/protocol/constants/index.js.map +1 -0
- package/dist/cjs/voltra/protocol/constants/message-types.js +70 -0
- package/dist/cjs/voltra/protocol/constants/message-types.js.map +1 -0
- package/dist/cjs/voltra/protocol/constants/timing.js +21 -0
- package/dist/cjs/voltra/protocol/constants/timing.js.map +1 -0
- package/dist/cjs/voltra/protocol/data/protocol-data.generated.js +7 -0
- package/dist/cjs/voltra/protocol/data/protocol-data.generated.js.map +1 -0
- package/dist/cjs/voltra/protocol/telemetry-decoder.js +122 -6
- package/dist/cjs/voltra/protocol/telemetry-decoder.js.map +1 -1
- package/dist/cjs/voltra/protocol/types.js +9 -0
- package/dist/cjs/voltra/protocol/types.js.map +1 -0
- package/dist/esm/bluetooth/adapters/native.js +36 -34
- package/dist/esm/bluetooth/adapters/native.js.map +1 -1
- package/dist/esm/bluetooth/adapters/node.js +9 -7
- package/dist/esm/bluetooth/adapters/node.js.map +1 -1
- package/dist/esm/bluetooth/adapters/web-bluetooth-base.js +6 -4
- package/dist/esm/bluetooth/adapters/web-bluetooth-base.js.map +1 -1
- package/dist/esm/bluetooth/adapters/web.js +7 -5
- package/dist/esm/bluetooth/adapters/web.js.map +1 -1
- package/dist/esm/bluetooth/controllers/scanner-controller.js +0 -2
- package/dist/esm/bluetooth/controllers/scanner-controller.js.map +1 -1
- package/dist/esm/bluetooth/index.js +1 -1
- package/dist/esm/bluetooth/index.js.map +1 -1
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.js +4 -7
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react/hooks.js +1 -5
- package/dist/esm/react/hooks.js.map +1 -1
- package/dist/esm/sdk/notification-dispatcher.js +44 -0
- package/dist/esm/sdk/notification-dispatcher.js.map +1 -0
- package/dist/esm/sdk/reconnect-handler.js +57 -0
- package/dist/esm/sdk/reconnect-handler.js.map +1 -0
- package/dist/esm/sdk/voltra-client.js +204 -70
- package/dist/esm/sdk/voltra-client.js.map +1 -1
- package/dist/esm/sdk/voltra-manager.js +13 -2
- package/dist/esm/sdk/voltra-manager.js.map +1 -1
- package/dist/esm/shared/index.js +1 -0
- package/dist/esm/shared/index.js.map +1 -1
- package/dist/esm/shared/logger.js +49 -0
- package/dist/esm/shared/logger.js.map +1 -0
- package/dist/esm/voltra/index.js +3 -8
- package/dist/esm/voltra/index.js.map +1 -1
- package/dist/esm/voltra/models/device.js +13 -0
- package/dist/esm/voltra/models/device.js.map +1 -1
- package/dist/esm/voltra/protocol/commands.js +117 -209
- package/dist/esm/voltra/protocol/commands.js.map +1 -1
- package/dist/esm/voltra/protocol/constants/ble-config.js +18 -0
- package/dist/esm/voltra/protocol/constants/ble-config.js.map +1 -0
- package/dist/esm/voltra/protocol/constants/connection-commands.js +49 -0
- package/dist/esm/voltra/protocol/constants/connection-commands.js.map +1 -0
- package/dist/esm/voltra/protocol/constants/enums.js +114 -0
- package/dist/esm/voltra/protocol/constants/enums.js.map +1 -0
- package/dist/esm/voltra/protocol/constants/index.js +12 -0
- package/dist/esm/voltra/protocol/constants/index.js.map +1 -0
- package/dist/esm/voltra/protocol/constants/message-types.js +64 -0
- package/dist/esm/voltra/protocol/constants/message-types.js.map +1 -0
- package/dist/esm/voltra/protocol/constants/timing.js +18 -0
- package/dist/esm/voltra/protocol/constants/timing.js.map +1 -0
- package/dist/esm/voltra/protocol/data/protocol-data.generated.js +5 -0
- package/dist/esm/voltra/protocol/data/protocol-data.generated.js.map +1 -0
- package/dist/esm/voltra/protocol/telemetry-decoder.js +124 -8
- package/dist/esm/voltra/protocol/telemetry-decoder.js.map +1 -1
- package/dist/esm/voltra/protocol/types.js +8 -0
- package/dist/esm/voltra/protocol/types.js.map +1 -0
- package/dist/types/bluetooth/adapters/native.d.ts.map +1 -1
- package/dist/types/bluetooth/adapters/node.d.ts.map +1 -1
- package/dist/types/bluetooth/adapters/web-bluetooth-base.d.ts.map +1 -1
- package/dist/types/bluetooth/adapters/web.d.ts.map +1 -1
- package/dist/types/bluetooth/controllers/scanner-controller.d.ts.map +1 -1
- package/dist/types/bluetooth/index.d.ts +1 -1
- package/dist/types/bluetooth/index.d.ts.map +1 -1
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/index.d.ts +5 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/react/hooks.d.ts.map +1 -1
- package/dist/types/sdk/index.d.ts +2 -1
- package/dist/types/sdk/index.d.ts.map +1 -1
- package/dist/types/sdk/notification-dispatcher.d.ts +29 -0
- package/dist/types/sdk/notification-dispatcher.d.ts.map +1 -0
- package/dist/types/sdk/reconnect-handler.d.ts +55 -0
- package/dist/types/sdk/reconnect-handler.d.ts.map +1 -0
- package/dist/types/sdk/types.d.ts +35 -0
- package/dist/types/sdk/types.d.ts.map +1 -1
- package/dist/types/sdk/voltra-client.d.ts +77 -2
- package/dist/types/sdk/voltra-client.d.ts.map +1 -1
- package/dist/types/sdk/voltra-manager.d.ts.map +1 -1
- package/dist/types/shared/index.d.ts +1 -0
- package/dist/types/shared/index.d.ts.map +1 -1
- package/dist/types/shared/logger.d.ts +39 -0
- package/dist/types/shared/logger.d.ts.map +1 -0
- package/dist/types/voltra/index.d.ts +3 -3
- package/dist/types/voltra/index.d.ts.map +1 -1
- package/dist/types/voltra/models/device.d.ts +11 -1
- package/dist/types/voltra/models/device.d.ts.map +1 -1
- package/dist/types/voltra/protocol/commands.d.ts +47 -87
- package/dist/types/voltra/protocol/commands.d.ts.map +1 -1
- package/dist/types/voltra/protocol/constants/ble-config.d.ts +16 -0
- package/dist/types/voltra/protocol/constants/ble-config.d.ts.map +1 -0
- package/dist/types/voltra/protocol/constants/connection-commands.d.ts +37 -0
- package/dist/types/voltra/protocol/constants/connection-commands.d.ts.map +1 -0
- package/dist/types/voltra/protocol/constants/enums.d.ts +72 -0
- package/dist/types/voltra/protocol/constants/enums.d.ts.map +1 -0
- package/dist/types/voltra/protocol/constants/index.d.ts +12 -0
- package/dist/types/voltra/protocol/constants/index.d.ts.map +1 -0
- package/dist/types/voltra/protocol/constants/message-types.d.ts +52 -0
- package/dist/types/voltra/protocol/constants/message-types.d.ts.map +1 -0
- package/dist/types/voltra/protocol/constants/timing.d.ts +18 -0
- package/dist/types/voltra/protocol/constants/timing.d.ts.map +1 -0
- package/dist/types/voltra/protocol/data/protocol-data.generated.d.ts +3 -0
- package/dist/types/voltra/protocol/data/protocol-data.generated.d.ts.map +1 -0
- package/dist/types/voltra/protocol/telemetry-decoder.d.ts +15 -2
- package/dist/types/voltra/protocol/telemetry-decoder.d.ts.map +1 -1
- package/dist/types/voltra/protocol/types.d.ts +247 -0
- package/dist/types/voltra/protocol/types.d.ts.map +1 -0
- package/package.json +9 -8
- package/dist/cjs/voltra/protocol/constants.js +0 -136
- package/dist/cjs/voltra/protocol/constants.js.map +0 -1
- package/dist/cjs/voltra/protocol/data/chains.json +0 -830
- package/dist/cjs/voltra/protocol/data/eccentric.json +0 -1598
- package/dist/cjs/voltra/protocol/data/protocol.json +0 -54
- package/dist/cjs/voltra/protocol/data/weights.json +0 -62
- package/dist/esm/voltra/protocol/constants.js +0 -130
- package/dist/esm/voltra/protocol/constants.js.map +0 -1
- package/dist/esm/voltra/protocol/data/chains.json +0 -830
- package/dist/esm/voltra/protocol/data/eccentric.json +0 -1598
- package/dist/esm/voltra/protocol/data/protocol.json +0 -54
- package/dist/esm/voltra/protocol/data/weights.json +0 -62
- package/dist/types/voltra/protocol/constants.d.ts +0 -103
- package/dist/types/voltra/protocol/constants.d.ts.map +0 -1
package/dist/esm/index.js
CHANGED
|
@@ -46,21 +46,17 @@ export { NativeBLEAdapter } from './bluetooth/adapters/native';
|
|
|
46
46
|
export { createBLEAdapter } from './bluetooth/adapters';
|
|
47
47
|
export { getDeviceDisplayName, sortBySignalStrength } from './bluetooth/models/device';
|
|
48
48
|
export { VOLTRA_DEVICE_PREFIX, isVoltraDevice, filterVoltraDevices, } from './voltra/models/device-filter';
|
|
49
|
-
// =============================================================================
|
|
50
|
-
// Voltra Device
|
|
51
|
-
// =============================================================================
|
|
52
|
-
export { VoltraDevice, DEFAULT_SETTINGS, } from './voltra/models/device';
|
|
53
49
|
export { createFrame } from './voltra/models/telemetry';
|
|
54
50
|
export { decodeTelemetryFrame, decodeNotification, encodeTelemetryFrame, identifyMessageType, } from './voltra/protocol/telemetry-decoder';
|
|
55
|
-
export { MovementPhase, PhaseNames, MessageTypes, TelemetryOffsets, } from './voltra/protocol/constants';
|
|
51
|
+
export { MovementPhase, PhaseNames, MessageTypes, TelemetryOffsets, ParameterId, ParameterNames, TrainingMode, TrainingModeNames, VALID_TRAINING_MODES, } from './voltra/protocol/constants';
|
|
56
52
|
// =============================================================================
|
|
57
53
|
// Commands
|
|
58
54
|
// =============================================================================
|
|
59
|
-
export {
|
|
55
|
+
export { getWeightCommand, getChainsCommand, getEccentricCommand, getInverseChainsCommand, getModeCommand, getAvailableWeights, getAvailableChains, getAvailableEccentric, getAvailableInverseChains, getAvailableModes, } from './voltra/protocol/commands';
|
|
60
56
|
// =============================================================================
|
|
61
57
|
// Protocol Constants
|
|
62
58
|
// =============================================================================
|
|
63
|
-
export { BLE, Timing, Auth, Init, Workout
|
|
59
|
+
export { BLE, Timing, Auth, Init, Workout } from './voltra/protocol/constants';
|
|
64
60
|
// =============================================================================
|
|
65
61
|
// Errors
|
|
66
62
|
// =============================================================================
|
|
@@ -69,4 +65,5 @@ export { VoltraSDKError, ConnectionError, AuthenticationError, TimeoutError, Not
|
|
|
69
65
|
// Utilities
|
|
70
66
|
// =============================================================================
|
|
71
67
|
export { delay } from './shared/utils';
|
|
68
|
+
export { setDebugEnabled } from './shared/logger';
|
|
72
69
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,gFAAgF;AAChF,iBAAiB;AACjB,gFAAgF;AAEhF,OAAO,EACL,YAAY,EACZ,aAAa,GAad,MAAM,OAAO,CAAC;AAEf,gFAAgF;AAChF,oBAAoB;AACpB,gFAAgF;AAEhF,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAsB,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAiBxD,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEvF,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,mBAAmB,GACpB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,gFAAgF;AAChF,iBAAiB;AACjB,gFAAgF;AAEhF,OAAO,EACL,YAAY,EACZ,aAAa,GAad,MAAM,OAAO,CAAC;AAEf,gFAAgF;AAChF,oBAAoB;AACpB,gFAAgF;AAEhF,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAsB,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAiBxD,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEvF,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,mBAAmB,GACpB,MAAM,+BAA+B,CAAC;AAmBvC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,GAGpB,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EACL,aAAa,EACb,UAAU,EACV,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,YAAY,EACZ,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AAErC,gFAAgF;AAChF,WAAW;AACX,gFAAgF;AAEhF,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AAEpC,gFAAgF;AAChF,qBAAqB;AACrB,gFAAgF;AAEhF,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAE/E,gFAAgF;AAChF,SAAS;AACT,gFAAgF;AAEhF,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,yBAAyB,EACzB,YAAY,EACZ,cAAc,EACd,SAAS,GAEV,MAAM,UAAU,CAAC;AAElB,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/esm/react/hooks.js
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
* ```
|
|
43
43
|
*/
|
|
44
44
|
import { useState, useEffect, useCallback } from 'react';
|
|
45
|
+
import { DEFAULT_SETTINGS } from '../voltra/models/device';
|
|
45
46
|
/**
|
|
46
47
|
* Hook for scanning for Voltra devices.
|
|
47
48
|
*
|
|
@@ -94,11 +95,6 @@ export function useVoltraScanner(manager) {
|
|
|
94
95
|
}, []);
|
|
95
96
|
return { devices, isScanning, error, scan, clear };
|
|
96
97
|
}
|
|
97
|
-
const DEFAULT_SETTINGS = {
|
|
98
|
-
weight: 0,
|
|
99
|
-
chains: 0,
|
|
100
|
-
eccentric: 0,
|
|
101
|
-
};
|
|
102
98
|
const DEFAULT_STATE = {
|
|
103
99
|
connectionState: 'disconnected',
|
|
104
100
|
isConnected: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/react/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/react/hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification Dispatcher
|
|
3
|
+
*
|
|
4
|
+
* Decodes BLE notifications and dispatches to typed callbacks.
|
|
5
|
+
* Extracted from VoltraClient for modularity.
|
|
6
|
+
*/
|
|
7
|
+
import { decodeNotification } from '../voltra/protocol/telemetry-decoder';
|
|
8
|
+
/**
|
|
9
|
+
* Create a BLE notification handler that decodes and dispatches to typed callbacks.
|
|
10
|
+
*
|
|
11
|
+
* @param callbacks Typed callbacks for each notification type
|
|
12
|
+
* @returns NotificationCallback to pass to adapter.onNotification()
|
|
13
|
+
*/
|
|
14
|
+
export function createNotificationHandler(callbacks) {
|
|
15
|
+
return (data) => {
|
|
16
|
+
const result = decodeNotification(data);
|
|
17
|
+
if (!result)
|
|
18
|
+
return;
|
|
19
|
+
switch (result.type) {
|
|
20
|
+
case 'frame':
|
|
21
|
+
callbacks.onFrame(result.frame);
|
|
22
|
+
break;
|
|
23
|
+
case 'rep_boundary':
|
|
24
|
+
callbacks.onRepBoundary();
|
|
25
|
+
break;
|
|
26
|
+
case 'set_boundary':
|
|
27
|
+
callbacks.onSetBoundary();
|
|
28
|
+
break;
|
|
29
|
+
case 'mode_confirmation':
|
|
30
|
+
callbacks.onModeConfirmed(result.mode);
|
|
31
|
+
break;
|
|
32
|
+
case 'settings_update':
|
|
33
|
+
callbacks.onSettingsUpdate(result.settings);
|
|
34
|
+
break;
|
|
35
|
+
case 'device_status':
|
|
36
|
+
callbacks.onBatteryUpdate(result.battery);
|
|
37
|
+
break;
|
|
38
|
+
case 'unknown':
|
|
39
|
+
// Silently ignore unknown notifications
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=notification-dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-dispatcher.js","sourceRoot":"","sources":["../../../src/sdk/notification-dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAc1E;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,SAAgC;IACxE,OAAO,CAAC,IAAgB,EAAE,EAAE;QAC1B,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,OAAO;gBACV,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChC,MAAM;YAER,KAAK,cAAc;gBACjB,SAAS,CAAC,aAAa,EAAE,CAAC;gBAC1B,MAAM;YAER,KAAK,cAAc;gBACjB,SAAS,CAAC,aAAa,EAAE,CAAC;gBAC1B,MAAM;YAER,KAAK,mBAAmB;gBACtB,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACvC,MAAM;YAER,KAAK,iBAAiB;gBACpB,SAAS,CAAC,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC5C,MAAM;YAER,KAAK,eAAe;gBAClB,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC1C,MAAM;YAER,KAAK,SAAS;gBACZ,wCAAwC;gBACxC,MAAM;QACV,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reconnect Handler
|
|
3
|
+
*
|
|
4
|
+
* Manages automatic reconnection on unexpected disconnects.
|
|
5
|
+
* Extracted from VoltraClient for modularity.
|
|
6
|
+
*/
|
|
7
|
+
import { delay } from '../shared/utils';
|
|
8
|
+
/**
|
|
9
|
+
* Setup a disconnect handler on the adapter that triggers auto-reconnect.
|
|
10
|
+
*
|
|
11
|
+
* @param adapter BLE adapter to monitor
|
|
12
|
+
* @param options Reconnect options
|
|
13
|
+
* @param isConnected Function that returns current connection state
|
|
14
|
+
* @param handleDisconnect Function to call on unexpected disconnect
|
|
15
|
+
* @returns Unsubscribe function, or null if auto-reconnect is disabled
|
|
16
|
+
*/
|
|
17
|
+
export function setupDisconnectMonitor(adapter, options, isConnected, handleDisconnect) {
|
|
18
|
+
if (!options.autoReconnect)
|
|
19
|
+
return null;
|
|
20
|
+
const unsubscribe = adapter.onConnectionStateChange((state) => {
|
|
21
|
+
if (state === 'disconnected' && isConnected()) {
|
|
22
|
+
handleDisconnect();
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return unsubscribe;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Attempt to reconnect with exponential backoff.
|
|
29
|
+
*
|
|
30
|
+
* @param options Reconnect options
|
|
31
|
+
* @param callbacks Reconnect callbacks
|
|
32
|
+
* @returns Final reconnect state
|
|
33
|
+
*/
|
|
34
|
+
export async function attemptReconnect(options, callbacks) {
|
|
35
|
+
const state = {
|
|
36
|
+
isReconnecting: true,
|
|
37
|
+
reconnectAttempt: 0,
|
|
38
|
+
};
|
|
39
|
+
while (state.reconnectAttempt < options.maxReconnectAttempts) {
|
|
40
|
+
state.reconnectAttempt++;
|
|
41
|
+
callbacks.onReconnecting(state.reconnectAttempt, options.maxReconnectAttempts);
|
|
42
|
+
try {
|
|
43
|
+
await delay(options.reconnectDelayMs);
|
|
44
|
+
await callbacks.reconnect();
|
|
45
|
+
state.isReconnecting = false;
|
|
46
|
+
return state;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Continue to next attempt
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// All attempts failed
|
|
53
|
+
state.isReconnecting = false;
|
|
54
|
+
callbacks.onReconnectFailed();
|
|
55
|
+
return state;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=reconnect-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconnect-handler.js","sourceRoot":"","sources":["../../../src/sdk/reconnect-handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAkCxC;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAmB,EACnB,OAAyB,EACzB,WAA0B,EAC1B,gBAA4B;IAE5B,IAAI,CAAC,OAAO,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAExC,MAAM,WAAW,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC,KAAK,EAAE,EAAE;QAC5D,IAAI,KAAK,KAAK,cAAc,IAAI,WAAW,EAAE,EAAE,CAAC;YAC9C,gBAAgB,EAAE,CAAC;QACrB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAyB,EACzB,SAA6B;IAE7B,MAAM,KAAK,GAAmB;QAC5B,cAAc,EAAE,IAAI;QACpB,gBAAgB,EAAE,CAAC;KACpB,CAAC;IAEF,OAAO,KAAK,CAAC,gBAAgB,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;QAC7D,KAAK,CAAC,gBAAgB,EAAE,CAAC;QACzB,SAAS,CAAC,cAAc,CAAC,KAAK,CAAC,gBAAgB,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAE/E,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YACtC,MAAM,SAAS,CAAC,SAAS,EAAE,CAAC;YAC5B,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC;YAC7B,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,MAAM,CAAC;YACP,2BAA2B;QAC7B,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC;IAC7B,SAAS,CAAC,iBAAiB,EAAE,CAAC;IAC9B,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
*
|
|
18
18
|
* // Configure settings
|
|
19
19
|
* await client.setWeight(50);
|
|
20
|
+
* await client.setMode(TrainingMode.WeightTraining);
|
|
20
21
|
*
|
|
21
22
|
* // Listen for telemetry
|
|
22
23
|
* client.onFrame((frame) => {
|
|
@@ -32,12 +33,14 @@
|
|
|
32
33
|
* client.dispose();
|
|
33
34
|
* ```
|
|
34
35
|
*/
|
|
36
|
+
import { DEFAULT_SETTINGS } from '../voltra/models/device';
|
|
35
37
|
import { isValidVoltraTransition } from '../voltra/models/connection';
|
|
36
38
|
import { filterVoltraDevices } from '../voltra/models/device-filter';
|
|
37
39
|
import { Auth, Init, Timing, Workout } from '../voltra/protocol/constants';
|
|
38
|
-
import {
|
|
39
|
-
import { decodeNotification } from '../voltra/protocol/telemetry-decoder';
|
|
40
|
+
import { getWeightCommand, getChainsCommand, getEccentricCommand, getInverseChainsCommand, getModeCommand, getAvailableWeights as getAvailableWeightValues, getAvailableChains as getAvailableChainValues, getAvailableEccentric as getAvailableEccentricValues, getAvailableInverseChains as getAvailableInverseChainsValues, getAvailableModes, } from '../voltra/protocol/commands';
|
|
40
41
|
import { delay } from '../shared/utils';
|
|
42
|
+
import { createNotificationHandler } from './notification-dispatcher';
|
|
43
|
+
import { setupDisconnectMonitor, attemptReconnect } from './reconnect-handler';
|
|
41
44
|
import { ConnectionError, AuthenticationError, NotConnectedError, InvalidSettingError, CommandError, TimeoutError, ErrorCode, } from '../errors';
|
|
42
45
|
/**
|
|
43
46
|
* Default client options.
|
|
@@ -47,14 +50,6 @@ const DEFAULT_OPTIONS = {
|
|
|
47
50
|
maxReconnectAttempts: 3,
|
|
48
51
|
reconnectDelayMs: 1000,
|
|
49
52
|
};
|
|
50
|
-
/**
|
|
51
|
-
* Default device settings.
|
|
52
|
-
*/
|
|
53
|
-
const DEFAULT_SETTINGS = {
|
|
54
|
-
weight: 0,
|
|
55
|
-
chains: 0,
|
|
56
|
-
eccentric: 0,
|
|
57
|
-
};
|
|
58
53
|
/**
|
|
59
54
|
* High-level client for connecting to and controlling a Voltra device.
|
|
60
55
|
*/
|
|
@@ -75,6 +70,11 @@ export class VoltraClient {
|
|
|
75
70
|
// Event listeners
|
|
76
71
|
this.listeners = new Set();
|
|
77
72
|
this.frameListeners = new Set();
|
|
73
|
+
this.repBoundaryListeners = new Set();
|
|
74
|
+
this.setBoundaryListeners = new Set();
|
|
75
|
+
this.modeConfirmedListeners = new Set();
|
|
76
|
+
this.settingsUpdateListeners = new Set();
|
|
77
|
+
this.batteryUpdateListeners = new Set();
|
|
78
78
|
// Disposed flag
|
|
79
79
|
this.disposed = false;
|
|
80
80
|
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
@@ -266,13 +266,13 @@ export class VoltraClient {
|
|
|
266
266
|
/**
|
|
267
267
|
* Set weight in pounds.
|
|
268
268
|
*
|
|
269
|
-
* @param lbs Weight (5-200
|
|
269
|
+
* @param lbs Weight (5-200, any integer value)
|
|
270
270
|
*/
|
|
271
271
|
async setWeight(lbs) {
|
|
272
272
|
this.ensureConnected();
|
|
273
|
-
const cmd =
|
|
273
|
+
const cmd = getWeightCommand(lbs);
|
|
274
274
|
if (!cmd) {
|
|
275
|
-
throw new InvalidSettingError('weight', lbs,
|
|
275
|
+
throw new InvalidSettingError('weight', lbs, getAvailableWeightValues());
|
|
276
276
|
}
|
|
277
277
|
try {
|
|
278
278
|
await this.adapter.write(cmd);
|
|
@@ -289,20 +289,40 @@ export class VoltraClient {
|
|
|
289
289
|
*/
|
|
290
290
|
async setChains(lbs) {
|
|
291
291
|
this.ensureConnected();
|
|
292
|
-
const
|
|
293
|
-
if (!
|
|
294
|
-
throw new InvalidSettingError('chains', lbs,
|
|
292
|
+
const cmd = getChainsCommand(lbs);
|
|
293
|
+
if (!cmd) {
|
|
294
|
+
throw new InvalidSettingError('chains', lbs, getAvailableChainValues());
|
|
295
295
|
}
|
|
296
296
|
try {
|
|
297
|
-
await this.adapter.write(
|
|
298
|
-
await delay(Timing.DUAL_COMMAND_DELAY_MS);
|
|
299
|
-
await this.adapter.write(cmds.step2);
|
|
297
|
+
await this.adapter.write(cmd);
|
|
300
298
|
this._settings.chains = lbs;
|
|
301
299
|
}
|
|
302
300
|
catch (e) {
|
|
303
301
|
throw new CommandError(`Failed to set chains: ${this.getErrorMessage(e)}`, 'setChains');
|
|
304
302
|
}
|
|
305
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* Set inverse chains weight.
|
|
306
|
+
*
|
|
307
|
+
* Inverse chains reduce resistance during the concentric (lifting) phase
|
|
308
|
+
* and add resistance during the eccentric (lowering) phase - opposite of regular chains.
|
|
309
|
+
*
|
|
310
|
+
* @param lbs Inverse chains weight in pounds (0-100)
|
|
311
|
+
*/
|
|
312
|
+
async setInverseChains(lbs) {
|
|
313
|
+
this.ensureConnected();
|
|
314
|
+
const cmd = getInverseChainsCommand(lbs);
|
|
315
|
+
if (!cmd) {
|
|
316
|
+
throw new InvalidSettingError('inverseChains', lbs, getAvailableInverseChainsValues());
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
await this.adapter.write(cmd);
|
|
320
|
+
this._settings.inverseChains = lbs;
|
|
321
|
+
}
|
|
322
|
+
catch (e) {
|
|
323
|
+
throw new CommandError(`Failed to set inverse chains: ${this.getErrorMessage(e)}`, 'setInverseChains');
|
|
324
|
+
}
|
|
325
|
+
}
|
|
306
326
|
/**
|
|
307
327
|
* Set eccentric load adjustment.
|
|
308
328
|
*
|
|
@@ -310,14 +330,12 @@ export class VoltraClient {
|
|
|
310
330
|
*/
|
|
311
331
|
async setEccentric(percent) {
|
|
312
332
|
this.ensureConnected();
|
|
313
|
-
const
|
|
314
|
-
if (!
|
|
315
|
-
throw new InvalidSettingError('eccentric', percent,
|
|
333
|
+
const cmd = getEccentricCommand(percent);
|
|
334
|
+
if (!cmd) {
|
|
335
|
+
throw new InvalidSettingError('eccentric', percent, getAvailableEccentricValues());
|
|
316
336
|
}
|
|
317
337
|
try {
|
|
318
|
-
await this.adapter.write(
|
|
319
|
-
await delay(Timing.DUAL_COMMAND_DELAY_MS);
|
|
320
|
-
await this.adapter.write(cmds.step2);
|
|
338
|
+
await this.adapter.write(cmd);
|
|
321
339
|
this._settings.eccentric = percent;
|
|
322
340
|
}
|
|
323
341
|
catch (e) {
|
|
@@ -328,19 +346,49 @@ export class VoltraClient {
|
|
|
328
346
|
* Get available weight values.
|
|
329
347
|
*/
|
|
330
348
|
getAvailableWeights() {
|
|
331
|
-
return
|
|
349
|
+
return getAvailableWeightValues();
|
|
332
350
|
}
|
|
333
351
|
/**
|
|
334
352
|
* Get available chains values.
|
|
335
353
|
*/
|
|
336
354
|
getAvailableChains() {
|
|
337
|
-
return
|
|
355
|
+
return getAvailableChainValues();
|
|
338
356
|
}
|
|
339
357
|
/**
|
|
340
358
|
* Get available eccentric values.
|
|
341
359
|
*/
|
|
342
360
|
getAvailableEccentric() {
|
|
343
|
-
return
|
|
361
|
+
return getAvailableEccentricValues();
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Get available inverse chains values.
|
|
365
|
+
*/
|
|
366
|
+
getAvailableInverseChains() {
|
|
367
|
+
return getAvailableInverseChainsValues();
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Set training mode.
|
|
371
|
+
*
|
|
372
|
+
* @param mode Training mode to set
|
|
373
|
+
*/
|
|
374
|
+
async setMode(mode) {
|
|
375
|
+
this.ensureConnected();
|
|
376
|
+
const cmd = getModeCommand(mode);
|
|
377
|
+
if (!cmd) {
|
|
378
|
+
throw new InvalidSettingError('mode', mode, getAvailableModes());
|
|
379
|
+
}
|
|
380
|
+
try {
|
|
381
|
+
await this.adapter.write(cmd);
|
|
382
|
+
}
|
|
383
|
+
catch (e) {
|
|
384
|
+
throw new CommandError(`Failed to set mode: ${this.getErrorMessage(e)}`, 'setMode');
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Get available training modes.
|
|
389
|
+
*/
|
|
390
|
+
getAvailableModes() {
|
|
391
|
+
return getAvailableModes();
|
|
344
392
|
}
|
|
345
393
|
// ===========================================================================
|
|
346
394
|
// Recording
|
|
@@ -455,6 +503,61 @@ export class VoltraClient {
|
|
|
455
503
|
this.listeners.add(wrappedListener);
|
|
456
504
|
return () => this.listeners.delete(wrappedListener);
|
|
457
505
|
}
|
|
506
|
+
/**
|
|
507
|
+
* Subscribe to rep boundary events.
|
|
508
|
+
* Called when the device signals a rep completion (end of concentric or eccentric phase).
|
|
509
|
+
*
|
|
510
|
+
* @param listener Rep boundary listener
|
|
511
|
+
* @returns Unsubscribe function
|
|
512
|
+
*/
|
|
513
|
+
onRepBoundary(listener) {
|
|
514
|
+
this.repBoundaryListeners.add(listener);
|
|
515
|
+
return () => this.repBoundaryListeners.delete(listener);
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Subscribe to set boundary events.
|
|
519
|
+
* Called when the device signals set completion.
|
|
520
|
+
*
|
|
521
|
+
* @param listener Set boundary listener
|
|
522
|
+
* @returns Unsubscribe function
|
|
523
|
+
*/
|
|
524
|
+
onSetBoundary(listener) {
|
|
525
|
+
this.setBoundaryListeners.add(listener);
|
|
526
|
+
return () => this.setBoundaryListeners.delete(listener);
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Subscribe to mode confirmation events.
|
|
530
|
+
* Called when the device confirms a training mode change.
|
|
531
|
+
*
|
|
532
|
+
* @param listener Mode confirmed listener
|
|
533
|
+
* @returns Unsubscribe function
|
|
534
|
+
*/
|
|
535
|
+
onModeConfirmed(listener) {
|
|
536
|
+
this.modeConfirmedListeners.add(listener);
|
|
537
|
+
return () => this.modeConfirmedListeners.delete(listener);
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Subscribe to settings update events.
|
|
541
|
+
* Called when the device reports its current settings.
|
|
542
|
+
*
|
|
543
|
+
* @param listener Settings update listener
|
|
544
|
+
* @returns Unsubscribe function
|
|
545
|
+
*/
|
|
546
|
+
onSettingsUpdate(listener) {
|
|
547
|
+
this.settingsUpdateListeners.add(listener);
|
|
548
|
+
return () => this.settingsUpdateListeners.delete(listener);
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Subscribe to battery update events.
|
|
552
|
+
* Called when the device reports its battery level.
|
|
553
|
+
*
|
|
554
|
+
* @param listener Battery update listener
|
|
555
|
+
* @returns Unsubscribe function
|
|
556
|
+
*/
|
|
557
|
+
onBatteryUpdate(listener) {
|
|
558
|
+
this.batteryUpdateListeners.add(listener);
|
|
559
|
+
return () => this.batteryUpdateListeners.delete(listener);
|
|
560
|
+
}
|
|
458
561
|
// ===========================================================================
|
|
459
562
|
// Lifecycle
|
|
460
563
|
// ===========================================================================
|
|
@@ -471,9 +574,14 @@ export class VoltraClient {
|
|
|
471
574
|
if (this.isConnected) {
|
|
472
575
|
this.disconnect().catch(() => { });
|
|
473
576
|
}
|
|
474
|
-
// Clear listeners
|
|
577
|
+
// Clear all listeners
|
|
475
578
|
this.listeners.clear();
|
|
476
579
|
this.frameListeners.clear();
|
|
580
|
+
this.repBoundaryListeners.clear();
|
|
581
|
+
this.setBoundaryListeners.clear();
|
|
582
|
+
this.modeConfirmedListeners.clear();
|
|
583
|
+
this.settingsUpdateListeners.clear();
|
|
584
|
+
this.batteryUpdateListeners.clear();
|
|
477
585
|
// Cleanup
|
|
478
586
|
this.cleanup();
|
|
479
587
|
}
|
|
@@ -503,32 +611,45 @@ export class VoltraClient {
|
|
|
503
611
|
setupNotificationHandler() {
|
|
504
612
|
if (!this.adapter)
|
|
505
613
|
return;
|
|
506
|
-
const handler = (
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
this.
|
|
513
|
-
|
|
514
|
-
|
|
614
|
+
const handler = createNotificationHandler({
|
|
615
|
+
onFrame: (frame) => {
|
|
616
|
+
this.emit({ type: 'frame', frame });
|
|
617
|
+
this.frameListeners.forEach((listener) => listener(frame));
|
|
618
|
+
},
|
|
619
|
+
onRepBoundary: () => {
|
|
620
|
+
this.emit({ type: 'repBoundary' });
|
|
621
|
+
this.repBoundaryListeners.forEach((listener) => listener());
|
|
622
|
+
},
|
|
623
|
+
onSetBoundary: () => {
|
|
624
|
+
this.emit({ type: 'setBoundary' });
|
|
625
|
+
this.setBoundaryListeners.forEach((listener) => listener());
|
|
626
|
+
},
|
|
627
|
+
onModeConfirmed: (mode) => {
|
|
628
|
+
this.emit({ type: 'modeConfirmed', mode });
|
|
629
|
+
this.modeConfirmedListeners.forEach((listener) => listener(mode));
|
|
630
|
+
},
|
|
631
|
+
onSettingsUpdate: (settings) => {
|
|
632
|
+
this.emit({ type: 'settingsUpdate', settings });
|
|
633
|
+
this.settingsUpdateListeners.forEach((listener) => listener(settings));
|
|
634
|
+
this.syncSettingsFromDevice(settings);
|
|
635
|
+
},
|
|
636
|
+
onBatteryUpdate: (battery) => {
|
|
637
|
+
this.emit({ type: 'batteryUpdate', battery });
|
|
638
|
+
this.batteryUpdateListeners.forEach((listener) => listener(battery));
|
|
639
|
+
},
|
|
640
|
+
});
|
|
515
641
|
this.notificationUnsubscribe = this.adapter.onNotification(handler);
|
|
516
642
|
}
|
|
517
643
|
setupDisconnectHandler() {
|
|
518
|
-
if (!this.adapter
|
|
644
|
+
if (!this.adapter)
|
|
519
645
|
return;
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
this.handleUnexpectedDisconnect();
|
|
524
|
-
}
|
|
525
|
-
});
|
|
526
|
-
// Store for cleanup if the adapter supports it
|
|
527
|
-
if (checkConnection) {
|
|
646
|
+
const disconnectUnsub = setupDisconnectMonitor(this.adapter, this.options, () => this._connectionState === 'connected', () => this.handleUnexpectedDisconnect());
|
|
647
|
+
// Chain with existing notification unsubscribe for cleanup
|
|
648
|
+
if (disconnectUnsub) {
|
|
528
649
|
const originalUnsubscribe = this.notificationUnsubscribe;
|
|
529
650
|
this.notificationUnsubscribe = () => {
|
|
530
651
|
originalUnsubscribe?.();
|
|
531
|
-
|
|
652
|
+
disconnectUnsub();
|
|
532
653
|
};
|
|
533
654
|
}
|
|
534
655
|
}
|
|
@@ -541,28 +662,20 @@ export class VoltraClient {
|
|
|
541
662
|
}
|
|
542
663
|
this._isReconnecting = true;
|
|
543
664
|
this._reconnectAttempt = 0;
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
this.
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
// Continue to next attempt
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
// Reconnect failed
|
|
562
|
-
this._isReconnecting = false;
|
|
563
|
-
this.cleanup();
|
|
564
|
-
this.setConnectionState('disconnected');
|
|
565
|
-
this.emit({ type: 'disconnected', deviceId: this._connectedDeviceId ?? 'unknown' });
|
|
665
|
+
const lastDevice = this._lastConnectedDevice;
|
|
666
|
+
const result = await attemptReconnect(this.options, {
|
|
667
|
+
onReconnecting: (attempt, maxAttempts) => {
|
|
668
|
+
this._reconnectAttempt = attempt;
|
|
669
|
+
this.emit({ type: 'reconnecting', attempt, maxAttempts });
|
|
670
|
+
},
|
|
671
|
+
reconnect: () => this.connect(lastDevice),
|
|
672
|
+
onReconnectFailed: () => {
|
|
673
|
+
this.cleanup();
|
|
674
|
+
this.setConnectionState('disconnected');
|
|
675
|
+
this.emit({ type: 'disconnected', deviceId: this._connectedDeviceId ?? 'unknown' });
|
|
676
|
+
},
|
|
677
|
+
});
|
|
678
|
+
this._isReconnecting = result.isReconnecting;
|
|
566
679
|
}
|
|
567
680
|
cleanup() {
|
|
568
681
|
this.notificationUnsubscribe?.();
|
|
@@ -624,5 +737,26 @@ export class VoltraClient {
|
|
|
624
737
|
getErrorMessage(e) {
|
|
625
738
|
return e instanceof Error ? e.message : String(e);
|
|
626
739
|
}
|
|
740
|
+
/**
|
|
741
|
+
* Sync internal settings state from device-reported settings.
|
|
742
|
+
* Called when the device sends a settings_update notification.
|
|
743
|
+
*/
|
|
744
|
+
syncSettingsFromDevice(deviceSettings) {
|
|
745
|
+
if (deviceSettings.baseWeight !== undefined) {
|
|
746
|
+
this._settings.weight = deviceSettings.baseWeight;
|
|
747
|
+
}
|
|
748
|
+
if (deviceSettings.chains !== undefined) {
|
|
749
|
+
this._settings.chains = deviceSettings.chains;
|
|
750
|
+
}
|
|
751
|
+
if (deviceSettings.inverseChains !== undefined) {
|
|
752
|
+
this._settings.inverseChains = deviceSettings.inverseChains;
|
|
753
|
+
}
|
|
754
|
+
if (deviceSettings.eccentric !== undefined) {
|
|
755
|
+
this._settings.eccentric = deviceSettings.eccentric;
|
|
756
|
+
}
|
|
757
|
+
if (deviceSettings.trainingMode !== undefined) {
|
|
758
|
+
this._settings.mode = deviceSettings.trainingMode;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
627
761
|
}
|
|
628
762
|
//# sourceMappingURL=voltra-client.js.map
|