@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,415 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VoltraManager
|
|
3
|
+
*
|
|
4
|
+
* Main entry point for the Voltra SDK. Handles device discovery and connection.
|
|
5
|
+
* Returns VoltraClient instances for controlling individual devices.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { VoltraManager } from '@voltras/node-sdk';
|
|
10
|
+
*
|
|
11
|
+
* const manager = new VoltraManager();
|
|
12
|
+
*
|
|
13
|
+
* // Scan for devices
|
|
14
|
+
* const devices = await manager.scan();
|
|
15
|
+
*
|
|
16
|
+
* // Connect to a device (returns a VoltraClient)
|
|
17
|
+
* const client = await manager.connect(devices[0]);
|
|
18
|
+
*
|
|
19
|
+
* // Or connect by name (scans + connects in one step)
|
|
20
|
+
* const client = await manager.connectByName('VTR-123456');
|
|
21
|
+
*
|
|
22
|
+
* // Use the client
|
|
23
|
+
* await client.setWeight(50);
|
|
24
|
+
* client.onFrame((frame) => console.log(frame.position));
|
|
25
|
+
*
|
|
26
|
+
* // Cleanup
|
|
27
|
+
* manager.dispose();
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
import { filterVoltraDevices } from '../voltra/models/device-filter';
|
|
31
|
+
import { BLE } from '../voltra/protocol/constants';
|
|
32
|
+
import { VoltraClient } from './voltra-client';
|
|
33
|
+
/**
|
|
34
|
+
* Main entry point for the Voltra SDK.
|
|
35
|
+
*/
|
|
36
|
+
export class VoltraManager {
|
|
37
|
+
constructor(options = {}) {
|
|
38
|
+
// Connected devices
|
|
39
|
+
this.clients = new Map();
|
|
40
|
+
this.clientUnsubscribes = new Map();
|
|
41
|
+
// Discovered devices (from last scan)
|
|
42
|
+
this.discoveredDevices = [];
|
|
43
|
+
// Scanning state
|
|
44
|
+
this._isScanning = false;
|
|
45
|
+
this.scanAdapter = null;
|
|
46
|
+
// Event listeners
|
|
47
|
+
this.listeners = new Set();
|
|
48
|
+
// Disposed flag
|
|
49
|
+
this.disposed = false;
|
|
50
|
+
this.clientOptions = options.clientOptions ?? {};
|
|
51
|
+
if (options.adapterFactory) {
|
|
52
|
+
// Use provided factory
|
|
53
|
+
this.adapterFactory = options.adapterFactory;
|
|
54
|
+
this.platform = options.platform ?? 'web';
|
|
55
|
+
}
|
|
56
|
+
else if (options.platform) {
|
|
57
|
+
// Use specified platform
|
|
58
|
+
this.platform = options.platform;
|
|
59
|
+
this.adapterFactory = this.createAdapterFactory(options.platform);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Auto-detect platform
|
|
63
|
+
this.platform = this.detectPlatform();
|
|
64
|
+
this.adapterFactory = this.createAdapterFactory(this.platform);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// ===========================================================================
|
|
68
|
+
// Static Factory Methods
|
|
69
|
+
// ===========================================================================
|
|
70
|
+
/**
|
|
71
|
+
* Create a manager for web browsers.
|
|
72
|
+
*/
|
|
73
|
+
static forWeb(options) {
|
|
74
|
+
return new VoltraManager({ ...options, platform: 'web' });
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Create a manager for Node.js.
|
|
78
|
+
*/
|
|
79
|
+
static forNode(options) {
|
|
80
|
+
return new VoltraManager({ ...options, platform: 'node' });
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Create a manager for React Native.
|
|
84
|
+
* Note: Prefer importing from '@voltras/node-sdk/native' instead.
|
|
85
|
+
*/
|
|
86
|
+
static forNative(options) {
|
|
87
|
+
return new VoltraManager({ ...options, platform: 'native' });
|
|
88
|
+
}
|
|
89
|
+
// ===========================================================================
|
|
90
|
+
// Public Getters
|
|
91
|
+
// ===========================================================================
|
|
92
|
+
/**
|
|
93
|
+
* Get all connected device IDs.
|
|
94
|
+
*/
|
|
95
|
+
get connectedDeviceIds() {
|
|
96
|
+
return Array.from(this.clients.keys());
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get number of connected devices.
|
|
100
|
+
*/
|
|
101
|
+
get connectedCount() {
|
|
102
|
+
return this.clients.size;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Check if scanning is in progress.
|
|
106
|
+
*/
|
|
107
|
+
get isScanning() {
|
|
108
|
+
return this._isScanning;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get devices discovered in last scan.
|
|
112
|
+
*/
|
|
113
|
+
get devices() {
|
|
114
|
+
return [...this.discoveredDevices];
|
|
115
|
+
}
|
|
116
|
+
// ===========================================================================
|
|
117
|
+
// Device Access
|
|
118
|
+
// ===========================================================================
|
|
119
|
+
/**
|
|
120
|
+
* Get a connected device client by ID.
|
|
121
|
+
*/
|
|
122
|
+
getClient(deviceId) {
|
|
123
|
+
return this.clients.get(deviceId);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Get all connected device clients.
|
|
127
|
+
*/
|
|
128
|
+
getAllClients() {
|
|
129
|
+
return Array.from(this.clients.values());
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Check if a device is connected.
|
|
133
|
+
*/
|
|
134
|
+
isConnected(deviceId) {
|
|
135
|
+
return this.clients.has(deviceId);
|
|
136
|
+
}
|
|
137
|
+
// ===========================================================================
|
|
138
|
+
// Discovery
|
|
139
|
+
// ===========================================================================
|
|
140
|
+
/**
|
|
141
|
+
* Scan for Voltra devices.
|
|
142
|
+
*
|
|
143
|
+
* @param options Scan options
|
|
144
|
+
* @returns Array of discovered Voltra devices
|
|
145
|
+
*/
|
|
146
|
+
async scan(options = {}) {
|
|
147
|
+
this.ensureNotDisposed();
|
|
148
|
+
const { timeout = 10000, filterVoltra = true } = options;
|
|
149
|
+
this._isScanning = true;
|
|
150
|
+
this.emit({ type: 'scanStarted' });
|
|
151
|
+
try {
|
|
152
|
+
// Create adapter for scanning if needed
|
|
153
|
+
if (!this.scanAdapter) {
|
|
154
|
+
this.scanAdapter = this.adapterFactory();
|
|
155
|
+
}
|
|
156
|
+
const devices = await this.scanAdapter.scan(timeout);
|
|
157
|
+
this.discoveredDevices = filterVoltra ? filterVoltraDevices(devices) : devices;
|
|
158
|
+
this.emit({ type: 'scanStopped', devices: this.discoveredDevices });
|
|
159
|
+
return this.discoveredDevices;
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
this._isScanning = false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// ===========================================================================
|
|
166
|
+
// Connection
|
|
167
|
+
// ===========================================================================
|
|
168
|
+
/**
|
|
169
|
+
* Connect to a Voltra device.
|
|
170
|
+
*
|
|
171
|
+
* @param device Device to connect to
|
|
172
|
+
* @returns VoltraClient for the connected device
|
|
173
|
+
*/
|
|
174
|
+
async connect(device) {
|
|
175
|
+
this.ensureNotDisposed();
|
|
176
|
+
// Check if already connected
|
|
177
|
+
if (this.clients.has(device.id)) {
|
|
178
|
+
return this.clients.get(device.id);
|
|
179
|
+
}
|
|
180
|
+
// Create new adapter and client
|
|
181
|
+
const adapter = this.adapterFactory();
|
|
182
|
+
const client = new VoltraClient({
|
|
183
|
+
...this.clientOptions,
|
|
184
|
+
adapter,
|
|
185
|
+
});
|
|
186
|
+
try {
|
|
187
|
+
await client.connect(device);
|
|
188
|
+
// Store client
|
|
189
|
+
this.clients.set(device.id, client);
|
|
190
|
+
// Subscribe to client events
|
|
191
|
+
const unsubscribe = client.subscribe((event) => {
|
|
192
|
+
this.handleClientEvent(device.id, event);
|
|
193
|
+
});
|
|
194
|
+
this.clientUnsubscribes.set(device.id, unsubscribe);
|
|
195
|
+
// Emit connected event
|
|
196
|
+
this.emit({
|
|
197
|
+
type: 'deviceConnected',
|
|
198
|
+
deviceId: device.id,
|
|
199
|
+
deviceName: device.name ?? null,
|
|
200
|
+
client,
|
|
201
|
+
});
|
|
202
|
+
return client;
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
client.dispose();
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Scan for a device by name and connect to it.
|
|
211
|
+
* This is a convenience method that combines scan() and connect().
|
|
212
|
+
*
|
|
213
|
+
* @param namePattern Name or partial name to search for
|
|
214
|
+
* @param options Connection options
|
|
215
|
+
* @returns VoltraClient for the connected device
|
|
216
|
+
* @throws Error if no matching device is found
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* // Connect to device containing "VTR-123" in its name
|
|
221
|
+
* const client = await manager.connectByName('VTR-123');
|
|
222
|
+
*
|
|
223
|
+
* // Connect to exact name match
|
|
224
|
+
* const client = await manager.connectByName('VTR-123456', { matchMode: 'exact' });
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
async connectByName(namePattern, options = {}) {
|
|
228
|
+
this.ensureNotDisposed();
|
|
229
|
+
const { matchMode = 'contains', timeout = 10000, filterVoltra = true } = options;
|
|
230
|
+
// Scan for devices
|
|
231
|
+
const devices = await this.scan({ timeout, filterVoltra });
|
|
232
|
+
// Find matching device
|
|
233
|
+
const device = devices.find((d) => {
|
|
234
|
+
if (!d.name)
|
|
235
|
+
return false;
|
|
236
|
+
switch (matchMode) {
|
|
237
|
+
case 'exact':
|
|
238
|
+
return d.name === namePattern;
|
|
239
|
+
case 'startsWith':
|
|
240
|
+
return d.name.startsWith(namePattern);
|
|
241
|
+
case 'contains':
|
|
242
|
+
default:
|
|
243
|
+
return d.name.includes(namePattern);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
if (!device) {
|
|
247
|
+
throw new Error(`No Voltra device found matching "${namePattern}". ` +
|
|
248
|
+
`Found ${devices.length} device(s): ${devices.map((d) => d.name ?? d.id).join(', ') || 'none'}`);
|
|
249
|
+
}
|
|
250
|
+
return this.connect(device);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Connect to the first available Voltra device.
|
|
254
|
+
* Convenience method for single-device scenarios.
|
|
255
|
+
*
|
|
256
|
+
* @param options Scan options
|
|
257
|
+
* @returns VoltraClient for the connected device
|
|
258
|
+
* @throws Error if no devices are found
|
|
259
|
+
*/
|
|
260
|
+
async connectFirst(options = {}) {
|
|
261
|
+
const devices = await this.scan(options);
|
|
262
|
+
if (devices.length === 0) {
|
|
263
|
+
throw new Error('No Voltra devices found. Make sure your device is powered on.');
|
|
264
|
+
}
|
|
265
|
+
return this.connect(devices[0]);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Disconnect a specific device.
|
|
269
|
+
*/
|
|
270
|
+
async disconnect(deviceId) {
|
|
271
|
+
const client = this.clients.get(deviceId);
|
|
272
|
+
if (!client)
|
|
273
|
+
return;
|
|
274
|
+
const unsubscribe = this.clientUnsubscribes.get(deviceId);
|
|
275
|
+
unsubscribe?.();
|
|
276
|
+
this.clientUnsubscribes.delete(deviceId);
|
|
277
|
+
await client.disconnect();
|
|
278
|
+
client.dispose();
|
|
279
|
+
this.clients.delete(deviceId);
|
|
280
|
+
this.emit({ type: 'deviceDisconnected', deviceId });
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Disconnect all devices.
|
|
284
|
+
*/
|
|
285
|
+
async disconnectAll() {
|
|
286
|
+
const deviceIds = Array.from(this.clients.keys());
|
|
287
|
+
await Promise.all(deviceIds.map((id) => this.disconnect(id)));
|
|
288
|
+
}
|
|
289
|
+
// ===========================================================================
|
|
290
|
+
// Event Subscriptions
|
|
291
|
+
// ===========================================================================
|
|
292
|
+
/**
|
|
293
|
+
* Subscribe to manager events.
|
|
294
|
+
*/
|
|
295
|
+
subscribe(listener) {
|
|
296
|
+
this.listeners.add(listener);
|
|
297
|
+
return () => this.listeners.delete(listener);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Subscribe to device connected events.
|
|
301
|
+
*/
|
|
302
|
+
onDeviceConnected(callback) {
|
|
303
|
+
const listener = (event) => {
|
|
304
|
+
if (event.type === 'deviceConnected') {
|
|
305
|
+
callback(event.client, event.deviceId, event.deviceName);
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
this.listeners.add(listener);
|
|
309
|
+
return () => this.listeners.delete(listener);
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Subscribe to device disconnected events.
|
|
313
|
+
*/
|
|
314
|
+
onDeviceDisconnected(callback) {
|
|
315
|
+
const listener = (event) => {
|
|
316
|
+
if (event.type === 'deviceDisconnected') {
|
|
317
|
+
callback(event.deviceId);
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
this.listeners.add(listener);
|
|
321
|
+
return () => this.listeners.delete(listener);
|
|
322
|
+
}
|
|
323
|
+
// ===========================================================================
|
|
324
|
+
// Lifecycle
|
|
325
|
+
// ===========================================================================
|
|
326
|
+
/**
|
|
327
|
+
* Dispose of the manager and all connected devices.
|
|
328
|
+
*/
|
|
329
|
+
dispose() {
|
|
330
|
+
if (this.disposed)
|
|
331
|
+
return;
|
|
332
|
+
this.disposed = true;
|
|
333
|
+
this.disconnectAll().catch(() => { });
|
|
334
|
+
this.listeners.clear();
|
|
335
|
+
this.clientUnsubscribes.clear();
|
|
336
|
+
this.scanAdapter = null;
|
|
337
|
+
}
|
|
338
|
+
// ===========================================================================
|
|
339
|
+
// Private Methods
|
|
340
|
+
// ===========================================================================
|
|
341
|
+
detectPlatform() {
|
|
342
|
+
// Check for browser environment
|
|
343
|
+
if (typeof window !== 'undefined' &&
|
|
344
|
+
typeof navigator !== 'undefined' &&
|
|
345
|
+
'bluetooth' in navigator) {
|
|
346
|
+
return 'web';
|
|
347
|
+
}
|
|
348
|
+
// Check for Node.js environment
|
|
349
|
+
if (typeof process !== 'undefined' && process.versions?.node) {
|
|
350
|
+
return 'node';
|
|
351
|
+
}
|
|
352
|
+
// Default to native (React Native)
|
|
353
|
+
// Note: This fallback may not work well - users should specify platform
|
|
354
|
+
return 'native';
|
|
355
|
+
}
|
|
356
|
+
createAdapterFactory(platform) {
|
|
357
|
+
switch (platform) {
|
|
358
|
+
case 'web':
|
|
359
|
+
return () => {
|
|
360
|
+
// Dynamic import to avoid bundling issues
|
|
361
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
362
|
+
const { WebBLEAdapter } = require('../bluetooth/adapters/web');
|
|
363
|
+
return new WebBLEAdapter({ ble: BLE });
|
|
364
|
+
};
|
|
365
|
+
case 'node':
|
|
366
|
+
return () => {
|
|
367
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
368
|
+
const { NodeBLEAdapter } = require('../bluetooth/adapters/node');
|
|
369
|
+
return new NodeBLEAdapter({ ble: BLE });
|
|
370
|
+
};
|
|
371
|
+
case 'native':
|
|
372
|
+
return () => {
|
|
373
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
374
|
+
const { NativeBLEAdapter } = require('../bluetooth/adapters/native');
|
|
375
|
+
return new NativeBLEAdapter({ ble: BLE });
|
|
376
|
+
};
|
|
377
|
+
default:
|
|
378
|
+
throw new Error(`Unknown platform: ${platform}`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
handleClientEvent(deviceId, event) {
|
|
382
|
+
switch (event.type) {
|
|
383
|
+
case 'disconnected':
|
|
384
|
+
if (this.clients.has(deviceId)) {
|
|
385
|
+
const unsubscribe = this.clientUnsubscribes.get(deviceId);
|
|
386
|
+
unsubscribe?.();
|
|
387
|
+
this.clientUnsubscribes.delete(deviceId);
|
|
388
|
+
const client = this.clients.get(deviceId);
|
|
389
|
+
client?.dispose();
|
|
390
|
+
this.clients.delete(deviceId);
|
|
391
|
+
this.emit({ type: 'deviceDisconnected', deviceId });
|
|
392
|
+
}
|
|
393
|
+
break;
|
|
394
|
+
case 'error':
|
|
395
|
+
this.emit({ type: 'deviceError', deviceId, error: event.error });
|
|
396
|
+
break;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
emit(event) {
|
|
400
|
+
this.listeners.forEach((listener) => {
|
|
401
|
+
try {
|
|
402
|
+
listener(event);
|
|
403
|
+
}
|
|
404
|
+
catch (e) {
|
|
405
|
+
console.error('[VoltraManager] Event listener error:', e);
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
ensureNotDisposed() {
|
|
410
|
+
if (this.disposed) {
|
|
411
|
+
throw new Error('Manager has been disposed');
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
//# sourceMappingURL=voltra-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voltra-manager.js","sourceRoot":"","sources":["../../../src/sdk/voltra-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shared/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Utilities
|
|
3
|
+
*
|
|
4
|
+
* Common utilities used across SDK modules.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Delay execution for a specified duration.
|
|
8
|
+
* @param ms Duration in milliseconds
|
|
9
|
+
*/
|
|
10
|
+
export function delay(ms) {
|
|
11
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Convert hex string to Uint8Array.
|
|
15
|
+
* @param hex Hex string (e.g., "48656c6c6f")
|
|
16
|
+
*/
|
|
17
|
+
export function hexToBytes(hex) {
|
|
18
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
19
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
20
|
+
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
|
|
21
|
+
}
|
|
22
|
+
return bytes;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Convert Uint8Array to hex string.
|
|
26
|
+
* @param bytes Byte array
|
|
27
|
+
*/
|
|
28
|
+
export function bytesToHex(bytes) {
|
|
29
|
+
return Array.from(bytes)
|
|
30
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
31
|
+
.join('');
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Check if two byte arrays are equal.
|
|
35
|
+
*/
|
|
36
|
+
export function bytesEqual(a, b) {
|
|
37
|
+
if (a.length !== b.length)
|
|
38
|
+
return false;
|
|
39
|
+
for (let i = 0; i < a.length; i++) {
|
|
40
|
+
if (a[i] !== b[i])
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/shared/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,KAAiB;IAC1C,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;SACrB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,CAAa,EAAE,CAAa;IACrD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voltra Domain
|
|
3
|
+
*
|
|
4
|
+
* Voltra device management, telemetry processing, and workout control.
|
|
5
|
+
*/
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// Models
|
|
8
|
+
// =============================================================================
|
|
9
|
+
// Device model
|
|
10
|
+
export { VoltraDevice, DEFAULT_SETTINGS, } from './models/device';
|
|
11
|
+
// Connection model
|
|
12
|
+
export { isValidVoltraTransition, VoltraConnectionStateModel, } from './models/connection';
|
|
13
|
+
// Device filter
|
|
14
|
+
export { VOLTRA_DEVICE_PREFIX, isVoltraDevice, filterVoltraDevices } from './models/device-filter';
|
|
15
|
+
// Telemetry models
|
|
16
|
+
export { createFrame, isActivePhase, isConcentricPhase, isEccentricPhase, } from './models/telemetry';
|
|
17
|
+
// =============================================================================
|
|
18
|
+
// Protocol
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// Command builders
|
|
21
|
+
export { WeightCommands, ChainsCommands, EccentricCommands, } from './protocol/commands';
|
|
22
|
+
// Protocol constants
|
|
23
|
+
export { MessageTypes, TelemetryOffsets, Timing, Auth, Init, Workout, BLE, MovementPhase, PhaseNames, } from './protocol/constants';
|
|
24
|
+
// Telemetry decoder (low-level)
|
|
25
|
+
export { decodeNotification, decodeTelemetryFrame, encodeTelemetryFrame, identifyMessageType, } from './protocol/telemetry-decoder';
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/voltra/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,gFAAgF;AAChF,SAAS;AACT,gFAAgF;AAEhF,eAAe;AACf,OAAO,EACL,YAAY,EACZ,gBAAgB,GAIjB,MAAM,iBAAiB,CAAC;AAEzB,mBAAmB;AACnB,OAAO,EAEL,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAE7B,gBAAgB;AAChB,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAEnG,mBAAmB;AACnB,OAAO,EAEL,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,gFAAgF;AAChF,WAAW;AACX,gFAAgF;AAEhF,mBAAmB;AACnB,OAAO,EACL,cAAc,EACd,cAAc,EACd,iBAAiB,GAElB,MAAM,qBAAqB,CAAC;AAE7B,qBAAqB;AACrB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,GAAG,EACH,aAAa,EACb,UAAU,GACX,MAAM,sBAAsB,CAAC;AAE9B,gCAAgC;AAChC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,GAGpB,MAAM,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voltra Connection Model
|
|
3
|
+
*
|
|
4
|
+
* Voltra-specific connection state that includes the authentication step.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Valid state transitions for Voltra connection.
|
|
8
|
+
*/
|
|
9
|
+
const VALID_VOLTRA_TRANSITIONS = {
|
|
10
|
+
disconnected: ['connecting'],
|
|
11
|
+
connecting: ['authenticating', 'disconnected'],
|
|
12
|
+
authenticating: ['connected', 'disconnected'],
|
|
13
|
+
connected: ['disconnected'],
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Check if a Voltra state transition is valid.
|
|
17
|
+
*/
|
|
18
|
+
export function isValidVoltraTransition(from, to) {
|
|
19
|
+
return VALID_VOLTRA_TRANSITIONS[from].includes(to);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Voltra connection state model with validation.
|
|
23
|
+
*/
|
|
24
|
+
export class VoltraConnectionStateModel {
|
|
25
|
+
constructor() {
|
|
26
|
+
this._state = 'disconnected';
|
|
27
|
+
}
|
|
28
|
+
get state() {
|
|
29
|
+
return this._state;
|
|
30
|
+
}
|
|
31
|
+
get isConnected() {
|
|
32
|
+
return this._state === 'connected';
|
|
33
|
+
}
|
|
34
|
+
get isConnecting() {
|
|
35
|
+
return this._state === 'connecting' || this._state === 'authenticating';
|
|
36
|
+
}
|
|
37
|
+
get isDisconnected() {
|
|
38
|
+
return this._state === 'disconnected';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Transition to a new state.
|
|
42
|
+
* @throws Error if transition is invalid
|
|
43
|
+
*/
|
|
44
|
+
transitionTo(newState) {
|
|
45
|
+
if (!isValidVoltraTransition(this._state, newState)) {
|
|
46
|
+
throw new Error(`Invalid connection state transition: ${this._state} -> ${newState}`);
|
|
47
|
+
}
|
|
48
|
+
this._state = newState;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Force set state (for reconnection scenarios).
|
|
52
|
+
*/
|
|
53
|
+
forceState(state) {
|
|
54
|
+
this._state = state;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Reset to disconnected state.
|
|
58
|
+
*/
|
|
59
|
+
reset() {
|
|
60
|
+
this._state = 'disconnected';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../../../src/voltra/models/connection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH;;GAEG;AACH,MAAM,wBAAwB,GAA2D;IACvF,YAAY,EAAE,CAAC,YAAY,CAAC;IAC5B,UAAU,EAAE,CAAC,gBAAgB,EAAE,cAAc,CAAC;IAC9C,cAAc,EAAE,CAAC,WAAW,EAAE,cAAc,CAAC;IAC7C,SAAS,EAAE,CAAC,cAAc,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAA2B,EAC3B,EAAyB;IAEzB,OAAO,wBAAwB,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,0BAA0B;IAAvC;QACU,WAAM,GAA0B,cAAc,CAAC;IA0CzD,CAAC;IAxCC,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC;IACrC,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,MAAM,KAAK,YAAY,IAAI,IAAI,CAAC,MAAM,KAAK,gBAAgB,CAAC;IAC1E,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,MAAM,KAAK,cAAc,CAAC;IACxC,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,QAA+B;QAC1C,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,CAAC,MAAM,OAAO,QAAQ,EAAE,CAAC,CAAC;QACxF,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,KAA4B;QACrC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,cAAc,CAAC;IAC/B,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voltra Device Filter
|
|
3
|
+
*
|
|
4
|
+
* Utility functions for filtering Voltra devices from BLE scan results.
|
|
5
|
+
*/
|
|
6
|
+
import { BLE } from '../protocol/constants';
|
|
7
|
+
/**
|
|
8
|
+
* Voltra device name prefix.
|
|
9
|
+
*/
|
|
10
|
+
export const VOLTRA_DEVICE_PREFIX = BLE.DEVICE_NAME_PREFIX;
|
|
11
|
+
/**
|
|
12
|
+
* Check if a device is a Voltra device.
|
|
13
|
+
*/
|
|
14
|
+
export function isVoltraDevice(device) {
|
|
15
|
+
return device.name?.startsWith(VOLTRA_DEVICE_PREFIX) ?? false;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Filter Voltra devices from a list.
|
|
19
|
+
*/
|
|
20
|
+
export function filterVoltraDevices(devices) {
|
|
21
|
+
return devices.filter(isVoltraDevice);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=device-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-filter.js","sourceRoot":"","sources":["../../../../src/voltra/models/device-filter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAE5C;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC,kBAAkB,CAAC;AAE3D;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAwB;IACrD,OAAO,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,oBAAoB,CAAC,IAAI,KAAK,CAAC;AAChE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAA2B;IAC7D,OAAO,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;AACxC,CAAC"}
|