@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.
Files changed (203) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +272 -0
  3. package/dist/cjs/bluetooth/adapters/base.js +116 -0
  4. package/dist/cjs/bluetooth/adapters/base.js.map +1 -0
  5. package/dist/cjs/bluetooth/adapters/index.js +58 -0
  6. package/dist/cjs/bluetooth/adapters/index.js.map +1 -0
  7. package/dist/cjs/bluetooth/adapters/native.js +473 -0
  8. package/dist/cjs/bluetooth/adapters/native.js.map +1 -0
  9. package/dist/cjs/bluetooth/adapters/node.js +228 -0
  10. package/dist/cjs/bluetooth/adapters/node.js.map +1 -0
  11. package/dist/cjs/bluetooth/adapters/types.js +11 -0
  12. package/dist/cjs/bluetooth/adapters/types.js.map +1 -0
  13. package/dist/cjs/bluetooth/adapters/web-bluetooth-base.js +187 -0
  14. package/dist/cjs/bluetooth/adapters/web-bluetooth-base.js.map +1 -0
  15. package/dist/cjs/bluetooth/adapters/web.js +112 -0
  16. package/dist/cjs/bluetooth/adapters/web.js.map +1 -0
  17. package/dist/cjs/bluetooth/controllers/scanner-controller.js +145 -0
  18. package/dist/cjs/bluetooth/controllers/scanner-controller.js.map +1 -0
  19. package/dist/cjs/bluetooth/index.js +27 -0
  20. package/dist/cjs/bluetooth/index.js.map +1 -0
  21. package/dist/cjs/bluetooth/models/connection.js +68 -0
  22. package/dist/cjs/bluetooth/models/connection.js.map +1 -0
  23. package/dist/cjs/bluetooth/models/device.js +26 -0
  24. package/dist/cjs/bluetooth/models/device.js.map +1 -0
  25. package/dist/cjs/bluetooth/models/environment.js +106 -0
  26. package/dist/cjs/bluetooth/models/environment.js.map +1 -0
  27. package/dist/cjs/errors.js +167 -0
  28. package/dist/cjs/errors.js.map +1 -0
  29. package/dist/cjs/index.js +116 -0
  30. package/dist/cjs/index.js.map +1 -0
  31. package/dist/cjs/react/hooks.js +262 -0
  32. package/dist/cjs/react/hooks.js.map +1 -0
  33. package/dist/cjs/react/index.js +18 -0
  34. package/dist/cjs/react/index.js.map +1 -0
  35. package/dist/cjs/sdk/index.js +14 -0
  36. package/dist/cjs/sdk/index.js.map +1 -0
  37. package/dist/cjs/sdk/types.js +8 -0
  38. package/dist/cjs/sdk/types.js.map +1 -0
  39. package/dist/cjs/sdk/voltra-client.js +632 -0
  40. package/dist/cjs/sdk/voltra-client.js.map +1 -0
  41. package/dist/cjs/sdk/voltra-manager.js +419 -0
  42. package/dist/cjs/sdk/voltra-manager.js.map +1 -0
  43. package/dist/cjs/shared/index.js +12 -0
  44. package/dist/cjs/shared/index.js.map +1 -0
  45. package/dist/cjs/shared/utils.js +51 -0
  46. package/dist/cjs/shared/utils.js.map +1 -0
  47. package/dist/cjs/voltra/index.js +56 -0
  48. package/dist/cjs/voltra/index.js.map +1 -0
  49. package/dist/cjs/voltra/models/connection.js +68 -0
  50. package/dist/cjs/voltra/models/connection.js.map +1 -0
  51. package/dist/cjs/voltra/models/device-filter.js +28 -0
  52. package/dist/cjs/voltra/models/device-filter.js.map +1 -0
  53. package/dist/cjs/voltra/models/device.js +152 -0
  54. package/dist/cjs/voltra/models/device.js.map +1 -0
  55. package/dist/cjs/voltra/models/telemetry/frame.js +46 -0
  56. package/dist/cjs/voltra/models/telemetry/frame.js.map +1 -0
  57. package/dist/cjs/voltra/models/telemetry/index.js +14 -0
  58. package/dist/cjs/voltra/models/telemetry/index.js.map +1 -0
  59. package/dist/cjs/voltra/protocol/commands.js +230 -0
  60. package/dist/cjs/voltra/protocol/commands.js.map +1 -0
  61. package/dist/cjs/voltra/protocol/constants.js +136 -0
  62. package/dist/cjs/voltra/protocol/constants.js.map +1 -0
  63. package/dist/cjs/voltra/protocol/data/chains.json +830 -0
  64. package/dist/cjs/voltra/protocol/data/eccentric.json +1598 -0
  65. package/dist/cjs/voltra/protocol/data/protocol.json +54 -0
  66. package/dist/cjs/voltra/protocol/data/weights.json +62 -0
  67. package/dist/cjs/voltra/protocol/index.js +25 -0
  68. package/dist/cjs/voltra/protocol/index.js.map +1 -0
  69. package/dist/cjs/voltra/protocol/telemetry-decoder.js +146 -0
  70. package/dist/cjs/voltra/protocol/telemetry-decoder.js.map +1 -0
  71. package/dist/esm/bluetooth/adapters/base.js +112 -0
  72. package/dist/esm/bluetooth/adapters/base.js.map +1 -0
  73. package/dist/esm/bluetooth/adapters/index.js +51 -0
  74. package/dist/esm/bluetooth/adapters/index.js.map +1 -0
  75. package/dist/esm/bluetooth/adapters/native.js +469 -0
  76. package/dist/esm/bluetooth/adapters/native.js.map +1 -0
  77. package/dist/esm/bluetooth/adapters/node.js +191 -0
  78. package/dist/esm/bluetooth/adapters/node.js.map +1 -0
  79. package/dist/esm/bluetooth/adapters/types.js +10 -0
  80. package/dist/esm/bluetooth/adapters/types.js.map +1 -0
  81. package/dist/esm/bluetooth/adapters/web-bluetooth-base.js +183 -0
  82. package/dist/esm/bluetooth/adapters/web-bluetooth-base.js.map +1 -0
  83. package/dist/esm/bluetooth/adapters/web.js +108 -0
  84. package/dist/esm/bluetooth/adapters/web.js.map +1 -0
  85. package/dist/esm/bluetooth/controllers/scanner-controller.js +141 -0
  86. package/dist/esm/bluetooth/controllers/scanner-controller.js.map +1 -0
  87. package/dist/esm/bluetooth/index.js +17 -0
  88. package/dist/esm/bluetooth/index.js.map +1 -0
  89. package/dist/esm/bluetooth/models/connection.js +63 -0
  90. package/dist/esm/bluetooth/models/connection.js.map +1 -0
  91. package/dist/esm/bluetooth/models/device.js +22 -0
  92. package/dist/esm/bluetooth/models/device.js.map +1 -0
  93. package/dist/esm/bluetooth/models/environment.js +101 -0
  94. package/dist/esm/bluetooth/models/environment.js.map +1 -0
  95. package/dist/esm/errors.js +155 -0
  96. package/dist/esm/errors.js.map +1 -0
  97. package/dist/esm/index.js +72 -0
  98. package/dist/esm/index.js.map +1 -0
  99. package/dist/esm/react/hooks.js +257 -0
  100. package/dist/esm/react/hooks.js.map +1 -0
  101. package/dist/esm/react/index.js +12 -0
  102. package/dist/esm/react/index.js.map +1 -0
  103. package/dist/esm/sdk/index.js +9 -0
  104. package/dist/esm/sdk/index.js.map +1 -0
  105. package/dist/esm/sdk/types.js +7 -0
  106. package/dist/esm/sdk/types.js.map +1 -0
  107. package/dist/esm/sdk/voltra-client.js +628 -0
  108. package/dist/esm/sdk/voltra-client.js.map +1 -0
  109. package/dist/esm/sdk/voltra-manager.js +415 -0
  110. package/dist/esm/sdk/voltra-manager.js.map +1 -0
  111. package/dist/esm/shared/index.js +5 -0
  112. package/dist/esm/shared/index.js.map +1 -0
  113. package/dist/esm/shared/utils.js +45 -0
  114. package/dist/esm/shared/utils.js.map +1 -0
  115. package/dist/esm/voltra/index.js +26 -0
  116. package/dist/esm/voltra/index.js.map +1 -0
  117. package/dist/esm/voltra/models/connection.js +63 -0
  118. package/dist/esm/voltra/models/connection.js.map +1 -0
  119. package/dist/esm/voltra/models/device-filter.js +23 -0
  120. package/dist/esm/voltra/models/device-filter.js.map +1 -0
  121. package/dist/esm/voltra/models/device.js +148 -0
  122. package/dist/esm/voltra/models/device.js.map +1 -0
  123. package/dist/esm/voltra/models/telemetry/frame.js +40 -0
  124. package/dist/esm/voltra/models/telemetry/frame.js.map +1 -0
  125. package/dist/esm/voltra/models/telemetry/index.js +7 -0
  126. package/dist/esm/voltra/models/telemetry/index.js.map +1 -0
  127. package/dist/esm/voltra/protocol/commands.js +224 -0
  128. package/dist/esm/voltra/protocol/commands.js.map +1 -0
  129. package/dist/esm/voltra/protocol/constants.js +130 -0
  130. package/dist/esm/voltra/protocol/constants.js.map +1 -0
  131. package/dist/esm/voltra/protocol/data/chains.json +830 -0
  132. package/dist/esm/voltra/protocol/data/eccentric.json +1598 -0
  133. package/dist/esm/voltra/protocol/data/protocol.json +54 -0
  134. package/dist/esm/voltra/protocol/data/weights.json +62 -0
  135. package/dist/esm/voltra/protocol/index.js +9 -0
  136. package/dist/esm/voltra/protocol/index.js.map +1 -0
  137. package/dist/esm/voltra/protocol/telemetry-decoder.js +140 -0
  138. package/dist/esm/voltra/protocol/telemetry-decoder.js.map +1 -0
  139. package/dist/types/bluetooth/adapters/base.d.ts +85 -0
  140. package/dist/types/bluetooth/adapters/base.d.ts.map +1 -0
  141. package/dist/types/bluetooth/adapters/index.d.ts +35 -0
  142. package/dist/types/bluetooth/adapters/index.d.ts.map +1 -0
  143. package/dist/types/bluetooth/adapters/native.d.ts +109 -0
  144. package/dist/types/bluetooth/adapters/native.d.ts.map +1 -0
  145. package/dist/types/bluetooth/adapters/node.d.ts +91 -0
  146. package/dist/types/bluetooth/adapters/node.d.ts.map +1 -0
  147. package/dist/types/bluetooth/adapters/types.d.ts +102 -0
  148. package/dist/types/bluetooth/adapters/types.d.ts.map +1 -0
  149. package/dist/types/bluetooth/adapters/web-bluetooth-base.d.ts +90 -0
  150. package/dist/types/bluetooth/adapters/web-bluetooth-base.d.ts.map +1 -0
  151. package/dist/types/bluetooth/adapters/web.d.ts +57 -0
  152. package/dist/types/bluetooth/adapters/web.d.ts.map +1 -0
  153. package/dist/types/bluetooth/controllers/scanner-controller.d.ts +93 -0
  154. package/dist/types/bluetooth/controllers/scanner-controller.d.ts.map +1 -0
  155. package/dist/types/bluetooth/index.d.ts +14 -0
  156. package/dist/types/bluetooth/index.d.ts.map +1 -0
  157. package/dist/types/bluetooth/models/connection.d.ts +37 -0
  158. package/dist/types/bluetooth/models/connection.d.ts.map +1 -0
  159. package/dist/types/bluetooth/models/device.d.ts +25 -0
  160. package/dist/types/bluetooth/models/device.d.ts.map +1 -0
  161. package/dist/types/bluetooth/models/environment.d.ts +45 -0
  162. package/dist/types/bluetooth/models/environment.d.ts.map +1 -0
  163. package/dist/types/errors.d.ts +113 -0
  164. package/dist/types/errors.d.ts.map +1 -0
  165. package/dist/types/index.d.ts +55 -0
  166. package/dist/types/index.d.ts.map +1 -0
  167. package/dist/types/react/hooks.d.ts +130 -0
  168. package/dist/types/react/hooks.d.ts.map +1 -0
  169. package/dist/types/react/index.d.ts +12 -0
  170. package/dist/types/react/index.d.ts.map +1 -0
  171. package/dist/types/sdk/index.d.ts +11 -0
  172. package/dist/types/sdk/index.d.ts.map +1 -0
  173. package/dist/types/sdk/types.d.ts +104 -0
  174. package/dist/types/sdk/types.d.ts.map +1 -0
  175. package/dist/types/sdk/voltra-client.d.ts +221 -0
  176. package/dist/types/sdk/voltra-client.d.ts.map +1 -0
  177. package/dist/types/sdk/voltra-manager.d.ts +226 -0
  178. package/dist/types/sdk/voltra-manager.d.ts.map +1 -0
  179. package/dist/types/shared/index.d.ts +5 -0
  180. package/dist/types/shared/index.d.ts.map +1 -0
  181. package/dist/types/shared/utils.d.ts +25 -0
  182. package/dist/types/shared/utils.d.ts.map +1 -0
  183. package/dist/types/voltra/index.d.ts +13 -0
  184. package/dist/types/voltra/index.d.ts.map +1 -0
  185. package/dist/types/voltra/models/connection.d.ts +37 -0
  186. package/dist/types/voltra/models/connection.d.ts.map +1 -0
  187. package/dist/types/voltra/models/device-filter.d.ts +19 -0
  188. package/dist/types/voltra/models/device-filter.d.ts.map +1 -0
  189. package/dist/types/voltra/models/device.d.ts +105 -0
  190. package/dist/types/voltra/models/device.d.ts.map +1 -0
  191. package/dist/types/voltra/models/telemetry/frame.d.ts +41 -0
  192. package/dist/types/voltra/models/telemetry/frame.d.ts.map +1 -0
  193. package/dist/types/voltra/models/telemetry/index.d.ts +8 -0
  194. package/dist/types/voltra/models/telemetry/index.d.ts.map +1 -0
  195. package/dist/types/voltra/protocol/commands.d.ts +99 -0
  196. package/dist/types/voltra/protocol/commands.d.ts.map +1 -0
  197. package/dist/types/voltra/protocol/constants.d.ts +103 -0
  198. package/dist/types/voltra/protocol/constants.d.ts.map +1 -0
  199. package/dist/types/voltra/protocol/index.d.ts +9 -0
  200. package/dist/types/voltra/protocol/index.d.ts.map +1 -0
  201. package/dist/types/voltra/protocol/telemetry-decoder.d.ts +45 -0
  202. package/dist/types/voltra/protocol/telemetry-decoder.d.ts.map +1 -0
  203. 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":"AAAA;;;;GAIG;AAgDH;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAyB;IACpD,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,SAAS,EAAE,CAAC;CACb,CAAC;AAEF;;;;;GAKG;AACH,MAAM,OAAO,YAAY;IAUvB,YAAY,QAAgB,EAAE,UAA0B;QACtD,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC1B,IAAI,CAAC,WAAW,GAAG,UAAU,IAAI,IAAI,CAAC;QACtC,IAAI,CAAC,SAAS,GAAG,EAAE,GAAG,gBAAgB,EAAE,CAAC;QACzC,IAAI,CAAC,gBAAgB,GAAG,cAAc,CAAC;QACvC,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC;QAC9B,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,6EAA6E;IAC7E,UAAU;IACV,6EAA6E;IAE7E,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAC/B,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;IAC/B,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;IAC/B,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;IAClC,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,gBAAgB,KAAK,WAAW,CAAC;IAC/C,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,eAAe,KAAK,QAAQ,CAAC;IAC3C,CAAC;IAED,IAAI,kBAAkB;QACpB,OAAO,IAAI,CAAC,mBAAmB,CAAC;IAClC,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,6EAA6E;IAC7E,gBAAgB;IAChB,6EAA6E;IAE7E;;OAEG;IACH,cAAc,CAAC,QAAuC;QACpD,IAAI,CAAC,SAAS,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,QAAQ,EAAE,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,kBAAkB,CAAC,KAA4B;QAC7C,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,KAAc;QAC5B,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,KAA2B;QAC3C,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;QAC7B,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvB,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACxC,CAAC;aAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YAC5B,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAClC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,KAAoB;QAC3B,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,6EAA6E;IAC7E,gBAAgB;IAChB,6EAA6E;IAE7E;;OAEG;IACH,OAAO;QACL,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,SAAS;YACxB,UAAU,EAAE,IAAI,CAAC,WAAW;YAC5B,eAAe,EAAE,IAAI,CAAC,gBAAgB;YACtC,cAAc,EAAE,IAAI,CAAC,eAAe;YACpC,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE;YAC/B,cAAc,EAAE,IAAI,CAAC,eAAe;YACpC,kBAAkB,EAAE,IAAI,CAAC,mBAAmB;YAC5C,KAAK,EAAE,IAAI,CAAC,MAAM;SACnB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,SAAS,GAAG,EAAE,GAAG,gBAAgB,EAAE,CAAC;QACzC,IAAI,CAAC,gBAAgB,GAAG,cAAc,CAAC;QACvC,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC;QAC9B,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;CACF"}
@@ -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,7 @@
1
+ /**
2
+ * Telemetry Models
3
+ *
4
+ * Data structures for workout telemetry.
5
+ */
6
+ export { createFrame, isActivePhase, isConcentricPhase, isEccentricPhase } from './frame';
7
+ //# sourceMappingURL=index.js.map
@@ -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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"}