@voltras/node-sdk 0.1.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/LICENSE +21 -0
- package/README.md +272 -0
- package/dist/cjs/bluetooth/adapters/base.js +116 -0
- package/dist/cjs/bluetooth/adapters/base.js.map +1 -0
- package/dist/cjs/bluetooth/adapters/index.js +58 -0
- package/dist/cjs/bluetooth/adapters/index.js.map +1 -0
- package/dist/cjs/bluetooth/adapters/native.js +473 -0
- package/dist/cjs/bluetooth/adapters/native.js.map +1 -0
- package/dist/cjs/bluetooth/adapters/node.js +228 -0
- package/dist/cjs/bluetooth/adapters/node.js.map +1 -0
- package/dist/cjs/bluetooth/adapters/types.js +11 -0
- package/dist/cjs/bluetooth/adapters/types.js.map +1 -0
- package/dist/cjs/bluetooth/adapters/web-bluetooth-base.js +187 -0
- package/dist/cjs/bluetooth/adapters/web-bluetooth-base.js.map +1 -0
- package/dist/cjs/bluetooth/adapters/web.js +112 -0
- package/dist/cjs/bluetooth/adapters/web.js.map +1 -0
- package/dist/cjs/bluetooth/controllers/scanner-controller.js +145 -0
- package/dist/cjs/bluetooth/controllers/scanner-controller.js.map +1 -0
- package/dist/cjs/bluetooth/index.js +27 -0
- package/dist/cjs/bluetooth/index.js.map +1 -0
- package/dist/cjs/bluetooth/models/connection.js +68 -0
- package/dist/cjs/bluetooth/models/connection.js.map +1 -0
- package/dist/cjs/bluetooth/models/device.js +26 -0
- package/dist/cjs/bluetooth/models/device.js.map +1 -0
- package/dist/cjs/bluetooth/models/environment.js +106 -0
- package/dist/cjs/bluetooth/models/environment.js.map +1 -0
- package/dist/cjs/errors.js +167 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.js +116 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/react/hooks.js +262 -0
- package/dist/cjs/react/hooks.js.map +1 -0
- package/dist/cjs/react/index.js +18 -0
- package/dist/cjs/react/index.js.map +1 -0
- package/dist/cjs/sdk/index.js +14 -0
- package/dist/cjs/sdk/index.js.map +1 -0
- package/dist/cjs/sdk/types.js +8 -0
- package/dist/cjs/sdk/types.js.map +1 -0
- package/dist/cjs/sdk/voltra-client.js +632 -0
- package/dist/cjs/sdk/voltra-client.js.map +1 -0
- package/dist/cjs/sdk/voltra-manager.js +419 -0
- package/dist/cjs/sdk/voltra-manager.js.map +1 -0
- package/dist/cjs/shared/index.js +12 -0
- package/dist/cjs/shared/index.js.map +1 -0
- package/dist/cjs/shared/utils.js +51 -0
- package/dist/cjs/shared/utils.js.map +1 -0
- package/dist/cjs/voltra/index.js +56 -0
- package/dist/cjs/voltra/index.js.map +1 -0
- package/dist/cjs/voltra/models/connection.js +68 -0
- package/dist/cjs/voltra/models/connection.js.map +1 -0
- package/dist/cjs/voltra/models/device-filter.js +28 -0
- package/dist/cjs/voltra/models/device-filter.js.map +1 -0
- package/dist/cjs/voltra/models/device.js +152 -0
- package/dist/cjs/voltra/models/device.js.map +1 -0
- package/dist/cjs/voltra/models/telemetry/frame.js +46 -0
- package/dist/cjs/voltra/models/telemetry/frame.js.map +1 -0
- package/dist/cjs/voltra/models/telemetry/index.js +14 -0
- package/dist/cjs/voltra/models/telemetry/index.js.map +1 -0
- package/dist/cjs/voltra/protocol/commands.js +230 -0
- package/dist/cjs/voltra/protocol/commands.js.map +1 -0
- package/dist/cjs/voltra/protocol/constants.js +136 -0
- package/dist/cjs/voltra/protocol/constants.js.map +1 -0
- package/dist/cjs/voltra/protocol/data/chains.json +830 -0
- package/dist/cjs/voltra/protocol/data/eccentric.json +1598 -0
- package/dist/cjs/voltra/protocol/data/protocol.json +54 -0
- package/dist/cjs/voltra/protocol/data/weights.json +62 -0
- package/dist/cjs/voltra/protocol/index.js +25 -0
- package/dist/cjs/voltra/protocol/index.js.map +1 -0
- package/dist/cjs/voltra/protocol/telemetry-decoder.js +146 -0
- package/dist/cjs/voltra/protocol/telemetry-decoder.js.map +1 -0
- package/dist/esm/bluetooth/adapters/base.js +112 -0
- package/dist/esm/bluetooth/adapters/base.js.map +1 -0
- package/dist/esm/bluetooth/adapters/index.js +51 -0
- package/dist/esm/bluetooth/adapters/index.js.map +1 -0
- package/dist/esm/bluetooth/adapters/native.js +469 -0
- package/dist/esm/bluetooth/adapters/native.js.map +1 -0
- package/dist/esm/bluetooth/adapters/node.js +191 -0
- package/dist/esm/bluetooth/adapters/node.js.map +1 -0
- package/dist/esm/bluetooth/adapters/types.js +10 -0
- package/dist/esm/bluetooth/adapters/types.js.map +1 -0
- package/dist/esm/bluetooth/adapters/web-bluetooth-base.js +183 -0
- package/dist/esm/bluetooth/adapters/web-bluetooth-base.js.map +1 -0
- package/dist/esm/bluetooth/adapters/web.js +108 -0
- package/dist/esm/bluetooth/adapters/web.js.map +1 -0
- package/dist/esm/bluetooth/controllers/scanner-controller.js +141 -0
- package/dist/esm/bluetooth/controllers/scanner-controller.js.map +1 -0
- package/dist/esm/bluetooth/index.js +17 -0
- package/dist/esm/bluetooth/index.js.map +1 -0
- package/dist/esm/bluetooth/models/connection.js +63 -0
- package/dist/esm/bluetooth/models/connection.js.map +1 -0
- package/dist/esm/bluetooth/models/device.js +22 -0
- package/dist/esm/bluetooth/models/device.js.map +1 -0
- package/dist/esm/bluetooth/models/environment.js +101 -0
- package/dist/esm/bluetooth/models/environment.js.map +1 -0
- package/dist/esm/errors.js +155 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.js +72 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/react/hooks.js +257 -0
- package/dist/esm/react/hooks.js.map +1 -0
- package/dist/esm/react/index.js +12 -0
- package/dist/esm/react/index.js.map +1 -0
- package/dist/esm/sdk/index.js +9 -0
- package/dist/esm/sdk/index.js.map +1 -0
- package/dist/esm/sdk/types.js +7 -0
- package/dist/esm/sdk/types.js.map +1 -0
- package/dist/esm/sdk/voltra-client.js +628 -0
- package/dist/esm/sdk/voltra-client.js.map +1 -0
- package/dist/esm/sdk/voltra-manager.js +415 -0
- package/dist/esm/sdk/voltra-manager.js.map +1 -0
- package/dist/esm/shared/index.js +5 -0
- package/dist/esm/shared/index.js.map +1 -0
- package/dist/esm/shared/utils.js +45 -0
- package/dist/esm/shared/utils.js.map +1 -0
- package/dist/esm/voltra/index.js +26 -0
- package/dist/esm/voltra/index.js.map +1 -0
- package/dist/esm/voltra/models/connection.js +63 -0
- package/dist/esm/voltra/models/connection.js.map +1 -0
- package/dist/esm/voltra/models/device-filter.js +23 -0
- package/dist/esm/voltra/models/device-filter.js.map +1 -0
- package/dist/esm/voltra/models/device.js +148 -0
- package/dist/esm/voltra/models/device.js.map +1 -0
- package/dist/esm/voltra/models/telemetry/frame.js +40 -0
- package/dist/esm/voltra/models/telemetry/frame.js.map +1 -0
- package/dist/esm/voltra/models/telemetry/index.js +7 -0
- package/dist/esm/voltra/models/telemetry/index.js.map +1 -0
- package/dist/esm/voltra/protocol/commands.js +224 -0
- package/dist/esm/voltra/protocol/commands.js.map +1 -0
- package/dist/esm/voltra/protocol/constants.js +130 -0
- package/dist/esm/voltra/protocol/constants.js.map +1 -0
- package/dist/esm/voltra/protocol/data/chains.json +830 -0
- package/dist/esm/voltra/protocol/data/eccentric.json +1598 -0
- package/dist/esm/voltra/protocol/data/protocol.json +54 -0
- package/dist/esm/voltra/protocol/data/weights.json +62 -0
- package/dist/esm/voltra/protocol/index.js +9 -0
- package/dist/esm/voltra/protocol/index.js.map +1 -0
- package/dist/esm/voltra/protocol/telemetry-decoder.js +140 -0
- package/dist/esm/voltra/protocol/telemetry-decoder.js.map +1 -0
- package/dist/types/bluetooth/adapters/base.d.ts +85 -0
- package/dist/types/bluetooth/adapters/base.d.ts.map +1 -0
- package/dist/types/bluetooth/adapters/index.d.ts +35 -0
- package/dist/types/bluetooth/adapters/index.d.ts.map +1 -0
- package/dist/types/bluetooth/adapters/native.d.ts +109 -0
- package/dist/types/bluetooth/adapters/native.d.ts.map +1 -0
- package/dist/types/bluetooth/adapters/node.d.ts +91 -0
- package/dist/types/bluetooth/adapters/node.d.ts.map +1 -0
- package/dist/types/bluetooth/adapters/types.d.ts +102 -0
- package/dist/types/bluetooth/adapters/types.d.ts.map +1 -0
- package/dist/types/bluetooth/adapters/web-bluetooth-base.d.ts +90 -0
- package/dist/types/bluetooth/adapters/web-bluetooth-base.d.ts.map +1 -0
- package/dist/types/bluetooth/adapters/web.d.ts +57 -0
- package/dist/types/bluetooth/adapters/web.d.ts.map +1 -0
- package/dist/types/bluetooth/controllers/scanner-controller.d.ts +93 -0
- package/dist/types/bluetooth/controllers/scanner-controller.d.ts.map +1 -0
- package/dist/types/bluetooth/index.d.ts +14 -0
- package/dist/types/bluetooth/index.d.ts.map +1 -0
- package/dist/types/bluetooth/models/connection.d.ts +37 -0
- package/dist/types/bluetooth/models/connection.d.ts.map +1 -0
- package/dist/types/bluetooth/models/device.d.ts +25 -0
- package/dist/types/bluetooth/models/device.d.ts.map +1 -0
- package/dist/types/bluetooth/models/environment.d.ts +45 -0
- package/dist/types/bluetooth/models/environment.d.ts.map +1 -0
- package/dist/types/errors.d.ts +113 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/index.d.ts +55 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/react/hooks.d.ts +130 -0
- package/dist/types/react/hooks.d.ts.map +1 -0
- package/dist/types/react/index.d.ts +12 -0
- package/dist/types/react/index.d.ts.map +1 -0
- package/dist/types/sdk/index.d.ts +11 -0
- package/dist/types/sdk/index.d.ts.map +1 -0
- package/dist/types/sdk/types.d.ts +104 -0
- package/dist/types/sdk/types.d.ts.map +1 -0
- package/dist/types/sdk/voltra-client.d.ts +221 -0
- package/dist/types/sdk/voltra-client.d.ts.map +1 -0
- package/dist/types/sdk/voltra-manager.d.ts +226 -0
- package/dist/types/sdk/voltra-manager.d.ts.map +1 -0
- package/dist/types/shared/index.d.ts +5 -0
- package/dist/types/shared/index.d.ts.map +1 -0
- package/dist/types/shared/utils.d.ts +25 -0
- package/dist/types/shared/utils.d.ts.map +1 -0
- package/dist/types/voltra/index.d.ts +13 -0
- package/dist/types/voltra/index.d.ts.map +1 -0
- package/dist/types/voltra/models/connection.d.ts +37 -0
- package/dist/types/voltra/models/connection.d.ts.map +1 -0
- package/dist/types/voltra/models/device-filter.d.ts +19 -0
- package/dist/types/voltra/models/device-filter.d.ts.map +1 -0
- package/dist/types/voltra/models/device.d.ts +105 -0
- package/dist/types/voltra/models/device.d.ts.map +1 -0
- package/dist/types/voltra/models/telemetry/frame.d.ts +41 -0
- package/dist/types/voltra/models/telemetry/frame.d.ts.map +1 -0
- package/dist/types/voltra/models/telemetry/index.d.ts +8 -0
- package/dist/types/voltra/models/telemetry/index.d.ts.map +1 -0
- package/dist/types/voltra/protocol/commands.d.ts +99 -0
- package/dist/types/voltra/protocol/commands.d.ts.map +1 -0
- package/dist/types/voltra/protocol/constants.d.ts +103 -0
- package/dist/types/voltra/protocol/constants.d.ts.map +1 -0
- package/dist/types/voltra/protocol/index.d.ts +9 -0
- package/dist/types/voltra/protocol/index.d.ts.map +1 -0
- package/dist/types/voltra/protocol/telemetry-decoder.d.ts +45 -0
- package/dist/types/voltra/protocol/telemetry-decoder.d.ts.map +1 -0
- package/package.json +111 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voltra Device Model
|
|
3
|
+
*
|
|
4
|
+
* Represents a Voltra device with its identity, settings, and connection state.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Default settings for a new device.
|
|
8
|
+
*/
|
|
9
|
+
export const DEFAULT_SETTINGS = {
|
|
10
|
+
weight: 0,
|
|
11
|
+
chains: 0,
|
|
12
|
+
eccentric: 0,
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Voltra device model.
|
|
16
|
+
*
|
|
17
|
+
* Represents a single Voltra device with its state and settings.
|
|
18
|
+
* This is a pure model with no async operations.
|
|
19
|
+
*/
|
|
20
|
+
export class VoltraDevice {
|
|
21
|
+
constructor(deviceId, deviceName) {
|
|
22
|
+
this._deviceId = deviceId;
|
|
23
|
+
this._deviceName = deviceName ?? null;
|
|
24
|
+
this._settings = { ...DEFAULT_SETTINGS };
|
|
25
|
+
this._connectionState = 'disconnected';
|
|
26
|
+
this._isReconnecting = false;
|
|
27
|
+
this._recordingState = 'idle';
|
|
28
|
+
this._recordingStartTime = null;
|
|
29
|
+
this._error = null;
|
|
30
|
+
}
|
|
31
|
+
// ==========================================================================
|
|
32
|
+
// Getters
|
|
33
|
+
// ==========================================================================
|
|
34
|
+
get deviceId() {
|
|
35
|
+
return this._deviceId;
|
|
36
|
+
}
|
|
37
|
+
get deviceName() {
|
|
38
|
+
return this._deviceName;
|
|
39
|
+
}
|
|
40
|
+
get settings() {
|
|
41
|
+
return { ...this._settings };
|
|
42
|
+
}
|
|
43
|
+
get weight() {
|
|
44
|
+
return this._settings.weight;
|
|
45
|
+
}
|
|
46
|
+
get chains() {
|
|
47
|
+
return this._settings.chains;
|
|
48
|
+
}
|
|
49
|
+
get eccentric() {
|
|
50
|
+
return this._settings.eccentric;
|
|
51
|
+
}
|
|
52
|
+
get connectionState() {
|
|
53
|
+
return this._connectionState;
|
|
54
|
+
}
|
|
55
|
+
get isConnected() {
|
|
56
|
+
return this._connectionState === 'connected';
|
|
57
|
+
}
|
|
58
|
+
get isReconnecting() {
|
|
59
|
+
return this._isReconnecting;
|
|
60
|
+
}
|
|
61
|
+
get recordingState() {
|
|
62
|
+
return this._recordingState;
|
|
63
|
+
}
|
|
64
|
+
get isRecording() {
|
|
65
|
+
return this._recordingState === 'active';
|
|
66
|
+
}
|
|
67
|
+
get recordingStartTime() {
|
|
68
|
+
return this._recordingStartTime;
|
|
69
|
+
}
|
|
70
|
+
get error() {
|
|
71
|
+
return this._error;
|
|
72
|
+
}
|
|
73
|
+
// ==========================================================================
|
|
74
|
+
// State Updates
|
|
75
|
+
// ==========================================================================
|
|
76
|
+
/**
|
|
77
|
+
* Update device settings.
|
|
78
|
+
*/
|
|
79
|
+
updateSettings(settings) {
|
|
80
|
+
this._settings = { ...this._settings, ...settings };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Set connection state.
|
|
84
|
+
*/
|
|
85
|
+
setConnectionState(state) {
|
|
86
|
+
this._connectionState = state;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Set reconnecting flag.
|
|
90
|
+
*/
|
|
91
|
+
setReconnecting(value) {
|
|
92
|
+
this._isReconnecting = value;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Set recording state.
|
|
96
|
+
*/
|
|
97
|
+
setRecordingState(state) {
|
|
98
|
+
this._recordingState = state;
|
|
99
|
+
if (state === 'active') {
|
|
100
|
+
this._recordingStartTime = Date.now();
|
|
101
|
+
}
|
|
102
|
+
else if (state === 'idle') {
|
|
103
|
+
this._recordingStartTime = null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Set error message.
|
|
108
|
+
*/
|
|
109
|
+
setError(error) {
|
|
110
|
+
this._error = error;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Clear error.
|
|
114
|
+
*/
|
|
115
|
+
clearError() {
|
|
116
|
+
this._error = null;
|
|
117
|
+
}
|
|
118
|
+
// ==========================================================================
|
|
119
|
+
// Serialization
|
|
120
|
+
// ==========================================================================
|
|
121
|
+
/**
|
|
122
|
+
* Get a snapshot of the device state.
|
|
123
|
+
*/
|
|
124
|
+
toState() {
|
|
125
|
+
return {
|
|
126
|
+
deviceId: this._deviceId,
|
|
127
|
+
deviceName: this._deviceName,
|
|
128
|
+
connectionState: this._connectionState,
|
|
129
|
+
isReconnecting: this._isReconnecting,
|
|
130
|
+
settings: { ...this._settings },
|
|
131
|
+
recordingState: this._recordingState,
|
|
132
|
+
recordingStartTime: this._recordingStartTime,
|
|
133
|
+
error: this._error,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Reset device to initial state (keeps identity).
|
|
138
|
+
*/
|
|
139
|
+
reset() {
|
|
140
|
+
this._settings = { ...DEFAULT_SETTINGS };
|
|
141
|
+
this._connectionState = 'disconnected';
|
|
142
|
+
this._isReconnecting = false;
|
|
143
|
+
this._recordingState = 'idle';
|
|
144
|
+
this._recordingStartTime = null;
|
|
145
|
+
this._error = null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=device.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device.js","sourceRoot":"","sources":["../../../../src/voltra/models/device.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telemetry Frame Model
|
|
3
|
+
*
|
|
4
|
+
* Represents a single telemetry data point from the Voltra device.
|
|
5
|
+
*/
|
|
6
|
+
import { MovementPhase } from '../../protocol/constants';
|
|
7
|
+
/**
|
|
8
|
+
* Create a telemetry frame from parsed values.
|
|
9
|
+
*/
|
|
10
|
+
export function createFrame(sequence, phase, position, force, velocity) {
|
|
11
|
+
return {
|
|
12
|
+
sequence,
|
|
13
|
+
phase,
|
|
14
|
+
position,
|
|
15
|
+
force,
|
|
16
|
+
velocity,
|
|
17
|
+
timestamp: Date.now(),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Check if a frame represents active movement.
|
|
22
|
+
*/
|
|
23
|
+
export function isActivePhase(frame) {
|
|
24
|
+
return (frame.phase === MovementPhase.CONCENTRIC ||
|
|
25
|
+
frame.phase === MovementPhase.ECCENTRIC ||
|
|
26
|
+
frame.phase === MovementPhase.HOLD);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Check if frame is concentric (pulling) phase.
|
|
30
|
+
*/
|
|
31
|
+
export function isConcentricPhase(frame) {
|
|
32
|
+
return frame.phase === MovementPhase.CONCENTRIC;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check if frame is eccentric (lowering) phase.
|
|
36
|
+
*/
|
|
37
|
+
export function isEccentricPhase(frame) {
|
|
38
|
+
return frame.phase === MovementPhase.ECCENTRIC;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.js","sourceRoot":"","sources":["../../../../../src/voltra/models/telemetry/frame.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAqBzD;;GAEG;AACH,MAAM,UAAU,WAAW,CACzB,QAAgB,EAChB,KAAoB,EACpB,QAAgB,EAChB,KAAa,EACb,QAAgB;IAEhB,OAAO;QACL,QAAQ;QACR,KAAK;QACL,QAAQ;QACR,KAAK;QACL,QAAQ;QACR,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACtB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAqB;IACjD,OAAO,CACL,KAAK,CAAC,KAAK,KAAK,aAAa,CAAC,UAAU;QACxC,KAAK,CAAC,KAAK,KAAK,aAAa,CAAC,SAAS;QACvC,KAAK,CAAC,KAAK,KAAK,aAAa,CAAC,IAAI,CACnC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAqB;IACrD,OAAO,KAAK,CAAC,KAAK,KAAK,aAAa,CAAC,UAAU,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAqB;IACpD,OAAO,KAAK,CAAC,KAAK,KAAK,aAAa,CAAC,SAAS,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/voltra/models/telemetry/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voltra Protocol Command Builders
|
|
3
|
+
*
|
|
4
|
+
* Builds commands for setting weight, chains, and eccentric resistance.
|
|
5
|
+
*/
|
|
6
|
+
import { hexToBytes } from '../../shared/utils';
|
|
7
|
+
import weightsData from './data/weights.json';
|
|
8
|
+
import chainsData from './data/chains.json';
|
|
9
|
+
import eccentricData from './data/eccentric.json';
|
|
10
|
+
// Type the JSON imports
|
|
11
|
+
const weights = weightsData;
|
|
12
|
+
const chains = chainsData;
|
|
13
|
+
const eccentric = eccentricData;
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// Weight Commands (863e register)
|
|
16
|
+
// =============================================================================
|
|
17
|
+
/**
|
|
18
|
+
* Weight command builder for 5-200 lbs in 5 lb increments.
|
|
19
|
+
*/
|
|
20
|
+
export const WeightCommands = {
|
|
21
|
+
MIN: 5,
|
|
22
|
+
MAX: 200,
|
|
23
|
+
INCREMENT: 5,
|
|
24
|
+
/** Get available weight values */
|
|
25
|
+
getAvailable() {
|
|
26
|
+
return Object.keys(weights.values)
|
|
27
|
+
.map(Number)
|
|
28
|
+
.sort((a, b) => a - b);
|
|
29
|
+
},
|
|
30
|
+
/** Check if a weight value is valid */
|
|
31
|
+
isValid(pounds) {
|
|
32
|
+
return pounds >= this.MIN && pounds <= this.MAX && pounds % this.INCREMENT === 0;
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* Get the command to set a specific weight.
|
|
36
|
+
* @param pounds Weight in pounds (5-200 in increments of 5)
|
|
37
|
+
* @returns 21-byte command, or null if weight not available
|
|
38
|
+
*/
|
|
39
|
+
get(pounds) {
|
|
40
|
+
const key = String(pounds);
|
|
41
|
+
const values = weights.values;
|
|
42
|
+
const format = weights.format;
|
|
43
|
+
if (!(key in values)) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const data = values[key];
|
|
47
|
+
return this._build(pounds, data.seq, data.checksum, format);
|
|
48
|
+
},
|
|
49
|
+
_build(pounds, seq, checksum, format) {
|
|
50
|
+
const cmd = new Uint8Array(21);
|
|
51
|
+
let offset = 0;
|
|
52
|
+
// Prefix
|
|
53
|
+
const prefix = hexToBytes(format.prefix);
|
|
54
|
+
cmd.set(prefix, offset);
|
|
55
|
+
offset += prefix.length;
|
|
56
|
+
// Sequence
|
|
57
|
+
const seqBytes = hexToBytes(seq);
|
|
58
|
+
cmd.set(seqBytes, offset);
|
|
59
|
+
offset += seqBytes.length;
|
|
60
|
+
// Mode
|
|
61
|
+
const mode = hexToBytes(format.mode);
|
|
62
|
+
cmd.set(mode, offset);
|
|
63
|
+
offset += mode.length;
|
|
64
|
+
// Register
|
|
65
|
+
const register = hexToBytes(format.register);
|
|
66
|
+
cmd.set(register, offset);
|
|
67
|
+
offset += register.length;
|
|
68
|
+
// Value (little-endian uint16)
|
|
69
|
+
cmd[offset] = pounds & 0xff;
|
|
70
|
+
cmd[offset + 1] = (pounds >> 8) & 0xff;
|
|
71
|
+
offset += 2;
|
|
72
|
+
// Checksum
|
|
73
|
+
const checksumBytes = hexToBytes(checksum);
|
|
74
|
+
cmd.set(checksumBytes, offset);
|
|
75
|
+
offset += checksumBytes.length;
|
|
76
|
+
// Padding
|
|
77
|
+
const padding = hexToBytes(format.padding);
|
|
78
|
+
cmd.set(padding, offset);
|
|
79
|
+
return cmd;
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Chains (reverse resistance) command builder for 0-100 lbs.
|
|
84
|
+
* Requires dual commands: send step1, wait 500ms, send step2.
|
|
85
|
+
*/
|
|
86
|
+
export const ChainsCommands = {
|
|
87
|
+
MIN: 0,
|
|
88
|
+
MAX: 100,
|
|
89
|
+
/** Get available chains values */
|
|
90
|
+
getAvailable() {
|
|
91
|
+
return Object.keys(chains.values)
|
|
92
|
+
.map(Number)
|
|
93
|
+
.sort((a, b) => a - b);
|
|
94
|
+
},
|
|
95
|
+
/** Check if a chains value is valid */
|
|
96
|
+
isValid(pounds) {
|
|
97
|
+
return pounds >= this.MIN && pounds <= this.MAX;
|
|
98
|
+
},
|
|
99
|
+
/**
|
|
100
|
+
* Get dual commands to set chains weight.
|
|
101
|
+
* @param pounds Chains weight (0-100)
|
|
102
|
+
* @returns Tuple of (step1, step2) commands, or null if not available
|
|
103
|
+
*/
|
|
104
|
+
get(pounds) {
|
|
105
|
+
const key = String(pounds);
|
|
106
|
+
const values = chains.values;
|
|
107
|
+
const format = chains.format;
|
|
108
|
+
if (!(key in values)) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
const data = values[key];
|
|
112
|
+
return {
|
|
113
|
+
step1: this._build(pounds, 1, data.step1_seq, data.step1_checksum, format),
|
|
114
|
+
step2: this._build(pounds, 2, data.step2_seq, data.step2_checksum, format),
|
|
115
|
+
};
|
|
116
|
+
},
|
|
117
|
+
_build(pounds, step, seq, checksum, format) {
|
|
118
|
+
const fmt = format[`step${step}`];
|
|
119
|
+
const cmd = new Uint8Array(21);
|
|
120
|
+
let offset = 0;
|
|
121
|
+
// Prefix
|
|
122
|
+
const prefix = hexToBytes(fmt.prefix);
|
|
123
|
+
cmd.set(prefix, offset);
|
|
124
|
+
offset += prefix.length;
|
|
125
|
+
// Sequence
|
|
126
|
+
const seqBytes = hexToBytes(seq);
|
|
127
|
+
cmd.set(seqBytes, offset);
|
|
128
|
+
offset += seqBytes.length;
|
|
129
|
+
// Mode
|
|
130
|
+
const mode = hexToBytes(fmt.mode);
|
|
131
|
+
cmd.set(mode, offset);
|
|
132
|
+
offset += mode.length;
|
|
133
|
+
// Register
|
|
134
|
+
const register = hexToBytes(fmt.register);
|
|
135
|
+
cmd.set(register, offset);
|
|
136
|
+
offset += register.length;
|
|
137
|
+
// Value (little-endian uint16)
|
|
138
|
+
cmd[offset] = pounds & 0xff;
|
|
139
|
+
cmd[offset + 1] = (pounds >> 8) & 0xff;
|
|
140
|
+
offset += 2;
|
|
141
|
+
// Checksum
|
|
142
|
+
const checksumBytes = hexToBytes(checksum);
|
|
143
|
+
cmd.set(checksumBytes, offset);
|
|
144
|
+
offset += checksumBytes.length;
|
|
145
|
+
// Padding
|
|
146
|
+
const padding = hexToBytes(fmt.padding);
|
|
147
|
+
cmd.set(padding, offset);
|
|
148
|
+
return cmd;
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
// =============================================================================
|
|
152
|
+
// Eccentric Commands (883e register)
|
|
153
|
+
// =============================================================================
|
|
154
|
+
/**
|
|
155
|
+
* Eccentric load adjustment command builder for -195 to +195.
|
|
156
|
+
* Requires dual commands: send step1, wait 500ms, send step2.
|
|
157
|
+
*/
|
|
158
|
+
export const EccentricCommands = {
|
|
159
|
+
MIN: -195,
|
|
160
|
+
MAX: 195,
|
|
161
|
+
/** Get available eccentric values */
|
|
162
|
+
getAvailable() {
|
|
163
|
+
return Object.keys(eccentric.step1.checksums)
|
|
164
|
+
.map(Number)
|
|
165
|
+
.sort((a, b) => a - b);
|
|
166
|
+
},
|
|
167
|
+
/** Check if an eccentric value is valid */
|
|
168
|
+
isValid(value) {
|
|
169
|
+
return value >= this.MIN && value <= this.MAX;
|
|
170
|
+
},
|
|
171
|
+
/**
|
|
172
|
+
* Get dual commands to set eccentric load.
|
|
173
|
+
* @param value Eccentric adjustment (-195 to +195)
|
|
174
|
+
* @returns Tuple of (step1, step2) commands, or null if not available
|
|
175
|
+
*/
|
|
176
|
+
get(value) {
|
|
177
|
+
const key = String(value);
|
|
178
|
+
if (!(key in eccentric.step1.checksums)) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
step1: this._build(value, 1),
|
|
183
|
+
step2: this._build(value, 2),
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
_build(value, step) {
|
|
187
|
+
const stepKey = `step${step}`;
|
|
188
|
+
const fmt = eccentric.format[stepKey];
|
|
189
|
+
const seq = eccentric[stepKey].sequences[String(value)];
|
|
190
|
+
const checksum = eccentric[stepKey].checksums[String(value)];
|
|
191
|
+
const cmd = new Uint8Array(21);
|
|
192
|
+
let offset = 0;
|
|
193
|
+
// Prefix
|
|
194
|
+
const prefix = hexToBytes(fmt.prefix);
|
|
195
|
+
cmd.set(prefix, offset);
|
|
196
|
+
offset += prefix.length;
|
|
197
|
+
// Sequence
|
|
198
|
+
const seqBytes = hexToBytes(seq);
|
|
199
|
+
cmd.set(seqBytes, offset);
|
|
200
|
+
offset += seqBytes.length;
|
|
201
|
+
// Mode
|
|
202
|
+
const mode = hexToBytes(fmt.mode);
|
|
203
|
+
cmd.set(mode, offset);
|
|
204
|
+
offset += mode.length;
|
|
205
|
+
// Register
|
|
206
|
+
const register = hexToBytes(fmt.register);
|
|
207
|
+
cmd.set(register, offset);
|
|
208
|
+
offset += register.length;
|
|
209
|
+
// Value (little-endian int16, signed)
|
|
210
|
+
const signedValue = value < 0 ? 0x10000 + value : value;
|
|
211
|
+
cmd[offset] = signedValue & 0xff;
|
|
212
|
+
cmd[offset + 1] = (signedValue >> 8) & 0xff;
|
|
213
|
+
offset += 2;
|
|
214
|
+
// Checksum
|
|
215
|
+
const checksumBytes = hexToBytes(checksum);
|
|
216
|
+
cmd.set(checksumBytes, offset);
|
|
217
|
+
offset += checksumBytes.length;
|
|
218
|
+
// Padding
|
|
219
|
+
const padding = hexToBytes(fmt.padding);
|
|
220
|
+
cmd.set(padding, offset);
|
|
221
|
+
return cmd;
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../../src/voltra/protocol/commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voltra Protocol Constants
|
|
3
|
+
*
|
|
4
|
+
* BLE configuration, authentication, and command constants for
|
|
5
|
+
* Beyond Power Voltra resistance training devices.
|
|
6
|
+
*/
|
|
7
|
+
import { hexToBytes } from '../../shared/utils';
|
|
8
|
+
import protocolData from './data/protocol.json';
|
|
9
|
+
// =============================================================================
|
|
10
|
+
// BLE Configuration
|
|
11
|
+
// =============================================================================
|
|
12
|
+
export const BLE = {
|
|
13
|
+
/** Main service UUID for Voltra devices */
|
|
14
|
+
SERVICE_UUID: protocolData.ble.service_uuid,
|
|
15
|
+
/** Characteristic for receiving notifications */
|
|
16
|
+
NOTIFY_CHAR_UUID: protocolData.ble.notify_char_uuid,
|
|
17
|
+
/** Characteristic for writing commands */
|
|
18
|
+
WRITE_CHAR_UUID: protocolData.ble.write_char_uuid,
|
|
19
|
+
/** Device name prefix for scanning (e.g., "VTR-") */
|
|
20
|
+
DEVICE_NAME_PREFIX: protocolData.ble.device_name_prefix,
|
|
21
|
+
};
|
|
22
|
+
// =============================================================================
|
|
23
|
+
// Timing Configuration
|
|
24
|
+
// =============================================================================
|
|
25
|
+
export const Timing = {
|
|
26
|
+
/** Delay between init commands (ms) */
|
|
27
|
+
INIT_COMMAND_DELAY_MS: 20,
|
|
28
|
+
/** Delay between dual commands like chains/eccentric (ms) */
|
|
29
|
+
DUAL_COMMAND_DELAY_MS: 500,
|
|
30
|
+
/** Timeout for authentication response (ms) */
|
|
31
|
+
AUTH_TIMEOUT_MS: 3000,
|
|
32
|
+
/** Minimum responses expected during auth */
|
|
33
|
+
MIN_AUTH_RESPONSES: 2,
|
|
34
|
+
/** Minimum responses expected after commands */
|
|
35
|
+
MIN_COMMAND_RESPONSES: 4,
|
|
36
|
+
};
|
|
37
|
+
// =============================================================================
|
|
38
|
+
// Authentication
|
|
39
|
+
// =============================================================================
|
|
40
|
+
/**
|
|
41
|
+
* Device authentication identifiers.
|
|
42
|
+
*
|
|
43
|
+
* 41-byte device IDs that identify the connecting app.
|
|
44
|
+
* Both iPhone and iPad IDs work - the Voltra doesn't care which.
|
|
45
|
+
*/
|
|
46
|
+
export const Auth = {
|
|
47
|
+
/** iPhone identity from Beyond+ app */
|
|
48
|
+
DEVICE_ID: hexToBytes(protocolData.auth.iphone),
|
|
49
|
+
/** iPad identity (alternative) */
|
|
50
|
+
DEVICE_ID_IPAD: hexToBytes(protocolData.auth.ipad),
|
|
51
|
+
};
|
|
52
|
+
// =============================================================================
|
|
53
|
+
// Initialization
|
|
54
|
+
// =============================================================================
|
|
55
|
+
/**
|
|
56
|
+
* Minimal 2-command init sequence (reduced from 22+ in Beyond+ app).
|
|
57
|
+
*/
|
|
58
|
+
export const Init = {
|
|
59
|
+
SEQUENCE: protocolData.init.commands.map(hexToBytes),
|
|
60
|
+
};
|
|
61
|
+
// =============================================================================
|
|
62
|
+
// Workout Commands
|
|
63
|
+
// =============================================================================
|
|
64
|
+
/**
|
|
65
|
+
* Workout control commands.
|
|
66
|
+
*
|
|
67
|
+
* To start: set weight -> PREPARE -> SETUP -> GO
|
|
68
|
+
* To stop: STOP
|
|
69
|
+
*/
|
|
70
|
+
export const Workout = {
|
|
71
|
+
/** Prepare for workout (b04f=01) */
|
|
72
|
+
PREPARE: hexToBytes(protocolData.workout.prepare),
|
|
73
|
+
/** Setup workout mode (823e setup) */
|
|
74
|
+
SETUP: hexToBytes(protocolData.workout.setup),
|
|
75
|
+
/** Start resistance (893e=05) */
|
|
76
|
+
GO: hexToBytes(protocolData.workout.go),
|
|
77
|
+
/** Stop resistance (893e=04) */
|
|
78
|
+
STOP: hexToBytes(protocolData.workout.stop),
|
|
79
|
+
};
|
|
80
|
+
// =============================================================================
|
|
81
|
+
// Telemetry Message Types (loaded from protocol.json)
|
|
82
|
+
// =============================================================================
|
|
83
|
+
/**
|
|
84
|
+
* Message type identifiers (first 4 bytes of notifications).
|
|
85
|
+
* Values loaded from protocol.json for single source of truth.
|
|
86
|
+
*/
|
|
87
|
+
export const MessageTypes = {
|
|
88
|
+
/** Real-time telemetry stream (~11 Hz) */
|
|
89
|
+
TELEMETRY_STREAM: hexToBytes(protocolData.telemetry.message_types.stream),
|
|
90
|
+
/** Rep completion summary */
|
|
91
|
+
REP_SUMMARY: hexToBytes(protocolData.telemetry.message_types.rep_summary),
|
|
92
|
+
/** Set completion summary */
|
|
93
|
+
SET_SUMMARY: hexToBytes(protocolData.telemetry.message_types.set_summary),
|
|
94
|
+
/** Status update */
|
|
95
|
+
STATUS_UPDATE: hexToBytes(protocolData.telemetry.message_types.status_update),
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Byte offsets for parsing telemetry stream messages.
|
|
99
|
+
* Values loaded from protocol.json for single source of truth.
|
|
100
|
+
*/
|
|
101
|
+
export const TelemetryOffsets = {
|
|
102
|
+
SEQUENCE: protocolData.telemetry.offsets.sequence, // 2 bytes, little-endian
|
|
103
|
+
PHASE: protocolData.telemetry.offsets.phase, // 1 byte
|
|
104
|
+
POSITION: protocolData.telemetry.offsets.position, // 2 bytes, little-endian unsigned
|
|
105
|
+
FORCE: protocolData.telemetry.offsets.force, // 2 bytes, little-endian signed
|
|
106
|
+
VELOCITY: protocolData.telemetry.offsets.velocity, // 2 bytes, little-endian unsigned
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Movement phase during workout.
|
|
110
|
+
* Values match protocol.json telemetry.phases.
|
|
111
|
+
*/
|
|
112
|
+
export var MovementPhase;
|
|
113
|
+
(function (MovementPhase) {
|
|
114
|
+
MovementPhase[MovementPhase["IDLE"] = 0] = "IDLE";
|
|
115
|
+
MovementPhase[MovementPhase["CONCENTRIC"] = 1] = "CONCENTRIC";
|
|
116
|
+
MovementPhase[MovementPhase["HOLD"] = 2] = "HOLD";
|
|
117
|
+
MovementPhase[MovementPhase["ECCENTRIC"] = 3] = "ECCENTRIC";
|
|
118
|
+
MovementPhase[MovementPhase["UNKNOWN"] = -1] = "UNKNOWN";
|
|
119
|
+
})(MovementPhase || (MovementPhase = {}));
|
|
120
|
+
/**
|
|
121
|
+
* Human-readable phase names.
|
|
122
|
+
*/
|
|
123
|
+
export const PhaseNames = {
|
|
124
|
+
[MovementPhase.IDLE]: 'Idle',
|
|
125
|
+
[MovementPhase.CONCENTRIC]: 'Pulling',
|
|
126
|
+
[MovementPhase.HOLD]: 'Hold',
|
|
127
|
+
[MovementPhase.ECCENTRIC]: 'Lowering',
|
|
128
|
+
[MovementPhase.UNKNOWN]: 'Unknown',
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../src/voltra/protocol/constants.ts"],"names":[],"mappings":"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"}
|