@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,469 @@
1
+ /**
2
+ * Native BLE Adapter
3
+ *
4
+ * Uses react-native-ble-plx for direct BLE communication on iOS/Android.
5
+ * Includes auto-reconnect functionality for seamless app resume.
6
+ *
7
+ * This adapter is generic and can be configured for any BLE device by
8
+ * providing the appropriate service/characteristic UUIDs.
9
+ *
10
+ * IMPORTANT: This adapter requires react-native-ble-plx as a peer dependency.
11
+ * Install it in your React Native project: npm install react-native-ble-plx
12
+ */
13
+ import { BleManager, State } from 'react-native-ble-plx';
14
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
15
+ // @ts-ignore - React Native imports may not be available in all environments
16
+ import { AppState, Platform, PermissionsAndroid } from 'react-native';
17
+ import { BaseBLEAdapter } from './base';
18
+ /**
19
+ * Request Android Bluetooth permissions at runtime.
20
+ * Android 12+ requires BLUETOOTH_SCAN and BLUETOOTH_CONNECT.
21
+ * Android 11 and below require ACCESS_FINE_LOCATION for BLE scanning.
22
+ */
23
+ async function requestAndroidBLEPermissions() {
24
+ if (Platform.OS !== 'android') {
25
+ return true;
26
+ }
27
+ const apiLevel = Platform.Version;
28
+ console.log('[NativeBLE] Android API level:', apiLevel);
29
+ try {
30
+ if (typeof apiLevel === 'number' && apiLevel >= 31) {
31
+ // Android 12+ (API 31+)
32
+ const results = await PermissionsAndroid.requestMultiple([
33
+ PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
34
+ PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
35
+ PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
36
+ ]);
37
+ const allGranted = Object.values(results).every((result) => result === PermissionsAndroid.RESULTS.GRANTED);
38
+ if (!allGranted) {
39
+ console.warn('[NativeBLE] Not all permissions granted:', results);
40
+ }
41
+ return allGranted;
42
+ }
43
+ else {
44
+ // Android 11 and below
45
+ const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, {
46
+ title: 'Bluetooth Permission',
47
+ message: 'This app needs access to your location to scan for Bluetooth devices.',
48
+ buttonPositive: 'OK',
49
+ });
50
+ return granted === PermissionsAndroid.RESULTS.GRANTED;
51
+ }
52
+ }
53
+ catch (error) {
54
+ console.error('[NativeBLE] Permission request error:', error);
55
+ return false;
56
+ }
57
+ }
58
+ // Base64 encoding/decoding for BLE data
59
+ function base64ToBytes(base64) {
60
+ const binary = atob(base64);
61
+ const bytes = new Uint8Array(binary.length);
62
+ for (let i = 0; i < binary.length; i++) {
63
+ bytes[i] = binary.charCodeAt(i);
64
+ }
65
+ return bytes;
66
+ }
67
+ function bytesToBase64(bytes) {
68
+ let binary = '';
69
+ for (let i = 0; i < bytes.length; i++) {
70
+ binary += String.fromCharCode(bytes[i]);
71
+ }
72
+ return btoa(binary);
73
+ }
74
+ const DEFAULT_RECONNECT_CONFIG = {
75
+ autoReconnect: true,
76
+ maxReconnectAttempts: 3,
77
+ reconnectDelayMs: 1000,
78
+ };
79
+ /**
80
+ * BLE adapter using react-native-ble-plx for native device communication.
81
+ * Supports auto-reconnect when app resumes from background.
82
+ */
83
+ export class NativeBLEAdapter extends BaseBLEAdapter {
84
+ constructor(config) {
85
+ super();
86
+ this.device = null;
87
+ this.notifySubscription = null;
88
+ this.writeSubscription = null;
89
+ // Auto-reconnect state
90
+ this.lastConnectedDeviceId = null;
91
+ this.lastConnectedDeviceName = null;
92
+ this.isReconnecting = false;
93
+ this.reconnectAttempts = 0;
94
+ this.appStateSubscription = null;
95
+ // Disconnect handling - prevents crash when subscriptions error during disconnect
96
+ this.isDisconnecting = false;
97
+ this.disconnectSubscription = null;
98
+ this.bleConfig = config.ble;
99
+ this.autoReconnect = config.autoReconnect ?? DEFAULT_RECONNECT_CONFIG.autoReconnect;
100
+ this.maxReconnectAttempts =
101
+ config.maxReconnectAttempts ?? DEFAULT_RECONNECT_CONFIG.maxReconnectAttempts;
102
+ this.reconnectDelayMs = config.reconnectDelayMs ?? DEFAULT_RECONNECT_CONFIG.reconnectDelayMs;
103
+ this.manager = new BleManager();
104
+ // Set up app state listener for auto-reconnect
105
+ if (this.autoReconnect) {
106
+ this.setupAppStateListener();
107
+ }
108
+ }
109
+ /**
110
+ * Set up listener for app state changes (background/foreground).
111
+ */
112
+ setupAppStateListener() {
113
+ this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange.bind(this));
114
+ }
115
+ /**
116
+ * Handle app state changes for auto-reconnect.
117
+ */
118
+ async handleAppStateChange(nextAppState) {
119
+ if (nextAppState === 'active') {
120
+ // App came to foreground
121
+ console.log('[NativeBLE] App became active');
122
+ // Check if we were connected and got disconnected
123
+ if (this.lastConnectedDeviceId &&
124
+ this.connectionState === 'disconnected' &&
125
+ !this.isReconnecting) {
126
+ console.log('[NativeBLE] Was connected before, attempting auto-reconnect...');
127
+ await this.attemptReconnect();
128
+ }
129
+ else if (this.device) {
130
+ // Check if device is still connected
131
+ const isConnected = await this.device.isConnected();
132
+ if (!isConnected) {
133
+ console.log('[NativeBLE] Device disconnected while in background, attempting reconnect...');
134
+ this.setConnectionState('disconnected');
135
+ await this.attemptReconnect();
136
+ }
137
+ }
138
+ }
139
+ }
140
+ /**
141
+ * Attempt to reconnect to the last known device.
142
+ */
143
+ async attemptReconnect() {
144
+ if (!this.lastConnectedDeviceId || this.isReconnecting) {
145
+ return;
146
+ }
147
+ this.isReconnecting = true;
148
+ this.reconnectAttempts = 0;
149
+ this.onReconnectStart?.();
150
+ while (this.reconnectAttempts < this.maxReconnectAttempts) {
151
+ this.reconnectAttempts++;
152
+ console.log(`[NativeBLE] Reconnect attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts}`);
153
+ try {
154
+ await this.connect(this.lastConnectedDeviceId);
155
+ console.log('[NativeBLE] Reconnect successful');
156
+ this.isReconnecting = false;
157
+ this.reconnectAttempts = 0;
158
+ this.onReconnectSuccess?.();
159
+ return;
160
+ }
161
+ catch (error) {
162
+ console.warn(`[NativeBLE] Reconnect attempt ${this.reconnectAttempts} failed:`, error);
163
+ if (this.reconnectAttempts < this.maxReconnectAttempts) {
164
+ await new Promise((resolve) => setTimeout(resolve, this.reconnectDelayMs));
165
+ }
166
+ }
167
+ }
168
+ // All attempts failed
169
+ console.error('[NativeBLE] Auto-reconnect failed after all attempts');
170
+ this.isReconnecting = false;
171
+ this.onReconnectFailed?.(new Error('Auto-reconnect failed'));
172
+ }
173
+ async waitForPoweredOn() {
174
+ return new Promise((resolve, reject) => {
175
+ const subscription = this.manager.onStateChange((state) => {
176
+ console.log('[NativeBLE] Bluetooth state:', state);
177
+ if (state === State.PoweredOn) {
178
+ subscription.remove();
179
+ resolve();
180
+ }
181
+ else if (state === State.Unauthorized) {
182
+ subscription.remove();
183
+ reject(new Error('Bluetooth permission denied. Please enable in Settings.'));
184
+ }
185
+ else if (state === State.Unsupported) {
186
+ subscription.remove();
187
+ reject(new Error('Bluetooth is not supported on this device.'));
188
+ }
189
+ else if (state === State.PoweredOff) {
190
+ // Don't reject yet - user might turn it on
191
+ console.log('[NativeBLE] Bluetooth is off - waiting for user to enable');
192
+ }
193
+ }, true);
194
+ // Timeout after 10 seconds
195
+ setTimeout(() => {
196
+ subscription.remove();
197
+ reject(new Error('Timeout waiting for Bluetooth. Please ensure Bluetooth is enabled.'));
198
+ }, 10000);
199
+ });
200
+ }
201
+ async scan(timeout) {
202
+ console.log('[NativeBLE] Starting scan...');
203
+ console.log('[NativeBLE] Looking for service:', this.bleConfig.serviceUUID);
204
+ if (this.bleConfig.deviceNamePrefix) {
205
+ console.log('[NativeBLE] Device name prefix:', this.bleConfig.deviceNamePrefix);
206
+ }
207
+ // Request Android permissions first
208
+ const hasPermissions = await requestAndroidBLEPermissions();
209
+ if (!hasPermissions) {
210
+ throw new Error('Bluetooth permissions not granted. Please enable in Settings.');
211
+ }
212
+ console.log('[NativeBLE] Permissions granted');
213
+ await this.waitForPoweredOn();
214
+ console.log('[NativeBLE] Bluetooth is powered on');
215
+ const devices = [];
216
+ const seen = new Set();
217
+ const prefix = this.bleConfig.deviceNamePrefix;
218
+ return new Promise((resolve, _reject) => {
219
+ // Scan for all devices (filtering is done by name prefix if configured)
220
+ this.manager.startDeviceScan(null, // No service filter - scan for all devices
221
+ { allowDuplicates: false }, (error, device) => {
222
+ if (error) {
223
+ console.error('[NativeBLE] Scan error:', error);
224
+ return;
225
+ }
226
+ if (device) {
227
+ // Log all devices with names for debugging
228
+ if (device.name) {
229
+ console.log(`[NativeBLE] Found device: ${device.name} (${device.id})`);
230
+ }
231
+ // Check if device matches filter (if prefix is configured)
232
+ const matchesFilter = !prefix || device.name?.startsWith(prefix) || device.localName?.startsWith(prefix);
233
+ if (matchesFilter && !seen.has(device.id) && (device.name || device.localName)) {
234
+ console.log(`[NativeBLE] ✓ Found matching device: ${device.name || device.localName}`);
235
+ seen.add(device.id);
236
+ devices.push({
237
+ id: device.id,
238
+ name: device.name || device.localName || 'Unknown Device',
239
+ rssi: device.rssi,
240
+ });
241
+ }
242
+ }
243
+ });
244
+ // Stop scan after timeout
245
+ setTimeout(() => {
246
+ this.manager.stopDeviceScan();
247
+ console.log(`[NativeBLE] Scan complete. Found ${devices.length} device(s)`);
248
+ resolve(devices);
249
+ }, timeout * 1000);
250
+ });
251
+ }
252
+ async connect(deviceId, options) {
253
+ // Request Android permissions first
254
+ const hasPermissions = await requestAndroidBLEPermissions();
255
+ if (!hasPermissions) {
256
+ throw new Error('Bluetooth permissions not granted. Please enable in Settings.');
257
+ }
258
+ await this.waitForPoweredOn();
259
+ this.setConnectionState('connecting');
260
+ try {
261
+ // Connect to device - don't request MTU yet, we need to authenticate first
262
+ const device = await this.manager.connectToDevice(deviceId, {
263
+ autoConnect: false, // Use direct connection for faster connect on Android
264
+ });
265
+ this.device = device;
266
+ this.lastConnectedDeviceId = deviceId;
267
+ this.lastConnectedDeviceName = device.name;
268
+ // Discover services and characteristics FIRST (needed for immediate write)
269
+ await device.discoverAllServicesAndCharacteristics();
270
+ // If immediate write is provided, send it NOW before anything else
271
+ // This is critical for devices that require fast authentication
272
+ if (options?.immediateWrite) {
273
+ console.log('[NativeBLE] Sending immediate auth write...');
274
+ const base64 = bytesToBase64(options.immediateWrite);
275
+ await device.writeCharacteristicWithResponseForService(this.bleConfig.serviceUUID, this.bleConfig.writeCharUUID, base64);
276
+ console.log('[NativeBLE] Immediate auth write sent');
277
+ }
278
+ // Now request MTU (optional, may fail on some devices)
279
+ try {
280
+ await device.requestMTU(512);
281
+ }
282
+ catch (mtuError) {
283
+ console.log('[NativeBLE] MTU request failed (non-fatal):', mtuError);
284
+ }
285
+ // Set up disconnect listener BEFORE setting up characteristic monitors
286
+ // This ensures we can clean up subscriptions before the error propagates
287
+ this.disconnectSubscription = device.onDisconnected((error, _disconnectedDevice) => {
288
+ console.log('[NativeBLE] Device disconnected', error ? `(error: ${error.message})` : '');
289
+ // Mark as disconnecting to prevent monitor errors from crashing
290
+ this.isDisconnecting = true;
291
+ // Clean up subscriptions IMMEDIATELY to prevent RxJava crash
292
+ this.cleanupSubscriptions();
293
+ this.setConnectionState('disconnected');
294
+ this.device = null;
295
+ this.isDisconnecting = false;
296
+ // Don't clear lastConnectedDeviceId - we want to try reconnecting
297
+ });
298
+ // Subscribe to notifications on notify characteristic
299
+ // Error callback must handle disconnect gracefully to avoid Android crash
300
+ this.notifySubscription = device.monitorCharacteristicForService(this.bleConfig.serviceUUID, this.bleConfig.notifyCharUUID, (error, characteristic) => {
301
+ if (error) {
302
+ // Ignore errors if we're disconnecting - this prevents the Android crash
303
+ if (this.isDisconnecting || !this.device) {
304
+ console.log('[NativeBLE] Notification error during disconnect (ignored):', error.message);
305
+ return;
306
+ }
307
+ console.error('[NativeBLE] Notification error:', error);
308
+ return;
309
+ }
310
+ if (characteristic?.value) {
311
+ const bytes = base64ToBytes(characteristic.value);
312
+ this.emitNotification(bytes);
313
+ }
314
+ });
315
+ // Also subscribe to write characteristic (it also sends notifications)
316
+ // Error callback must handle disconnect gracefully to avoid Android crash
317
+ this.writeSubscription = device.monitorCharacteristicForService(this.bleConfig.serviceUUID, this.bleConfig.writeCharUUID, (error, characteristic) => {
318
+ if (error) {
319
+ // Ignore errors if we're disconnecting - this prevents the Android crash
320
+ if (this.isDisconnecting || !this.device) {
321
+ console.log('[NativeBLE] Write char error during disconnect (ignored):', error.message);
322
+ return;
323
+ }
324
+ console.error('[NativeBLE] Write char notification error:', error);
325
+ return;
326
+ }
327
+ if (characteristic?.value) {
328
+ const bytes = base64ToBytes(characteristic.value);
329
+ this.emitNotification(bytes);
330
+ }
331
+ });
332
+ this.setConnectionState('connected');
333
+ }
334
+ catch (error) {
335
+ console.error('[NativeBLE] Connect error:', error);
336
+ this.setConnectionState('disconnected');
337
+ throw error;
338
+ }
339
+ }
340
+ cleanupSubscriptions() {
341
+ // Clean up characteristic monitor subscriptions
342
+ // Must be done synchronously to prevent RxJava crash on Android
343
+ if (this.notifySubscription) {
344
+ try {
345
+ this.notifySubscription.remove();
346
+ }
347
+ catch (e) {
348
+ console.log('[NativeBLE] Error removing notify subscription:', e);
349
+ }
350
+ this.notifySubscription = null;
351
+ }
352
+ if (this.writeSubscription) {
353
+ try {
354
+ this.writeSubscription.remove();
355
+ }
356
+ catch (e) {
357
+ console.log('[NativeBLE] Error removing write subscription:', e);
358
+ }
359
+ this.writeSubscription = null;
360
+ }
361
+ }
362
+ cleanupAllSubscriptions() {
363
+ this.cleanupSubscriptions();
364
+ if (this.disconnectSubscription) {
365
+ try {
366
+ this.disconnectSubscription.remove();
367
+ }
368
+ catch (e) {
369
+ console.log('[NativeBLE] Error removing disconnect subscription:', e);
370
+ }
371
+ this.disconnectSubscription = null;
372
+ }
373
+ }
374
+ async disconnect() {
375
+ this.setConnectionState('disconnecting');
376
+ // Mark as disconnecting to prevent monitor errors from crashing
377
+ this.isDisconnecting = true;
378
+ // Clean up all subscriptions BEFORE canceling connection
379
+ // This prevents the RxJava crash on Android
380
+ this.cleanupAllSubscriptions();
381
+ if (this.device) {
382
+ try {
383
+ await this.device.cancelConnection();
384
+ }
385
+ catch (error) {
386
+ console.error('[NativeBLE] Disconnect error:', error);
387
+ }
388
+ this.device = null;
389
+ }
390
+ // Clear last device so we don't auto-reconnect after intentional disconnect
391
+ this.lastConnectedDeviceId = null;
392
+ this.lastConnectedDeviceName = null;
393
+ this.isDisconnecting = false;
394
+ this.setConnectionState('disconnected');
395
+ }
396
+ async write(data) {
397
+ if (!this.device) {
398
+ throw new Error('Not connected to device');
399
+ }
400
+ const base64 = bytesToBase64(data);
401
+ await this.device.writeCharacteristicWithResponseForService(this.bleConfig.serviceUUID, this.bleConfig.writeCharUUID, base64);
402
+ }
403
+ /**
404
+ * Override isConnected to also check if device exists.
405
+ */
406
+ isConnected() {
407
+ return super.isConnected() && this.device !== null;
408
+ }
409
+ /**
410
+ * Get info about the currently connected device.
411
+ */
412
+ getConnectedDevice() {
413
+ if (!this.device)
414
+ return null;
415
+ return {
416
+ id: this.device.id,
417
+ name: this.device.name,
418
+ rssi: null, // Not available after connection
419
+ };
420
+ }
421
+ /**
422
+ * Get the last connected device ID (for reconnection).
423
+ */
424
+ getLastConnectedDeviceId() {
425
+ return this.lastConnectedDeviceId;
426
+ }
427
+ /**
428
+ * Set callbacks for reconnect events.
429
+ */
430
+ setReconnectCallbacks(callbacks) {
431
+ this.onReconnectStart = callbacks.onStart;
432
+ this.onReconnectSuccess = callbacks.onSuccess;
433
+ this.onReconnectFailed = callbacks.onFailed;
434
+ }
435
+ /**
436
+ * Manually trigger a reconnect attempt.
437
+ */
438
+ async reconnect() {
439
+ if (this.lastConnectedDeviceId) {
440
+ await this.connect(this.lastConnectedDeviceId);
441
+ }
442
+ else {
443
+ throw new Error('No previous device to reconnect to');
444
+ }
445
+ }
446
+ /**
447
+ * Set the last connected device (for restoring from storage).
448
+ */
449
+ setLastConnectedDevice(deviceId, deviceName) {
450
+ this.lastConnectedDeviceId = deviceId;
451
+ this.lastConnectedDeviceName = deviceName ?? null;
452
+ }
453
+ /**
454
+ * Check if auto-reconnect is in progress.
455
+ */
456
+ isAutoReconnecting() {
457
+ return this.isReconnecting;
458
+ }
459
+ /**
460
+ * Destroy the BLE manager (call when app is closing).
461
+ */
462
+ destroy() {
463
+ this.isDisconnecting = true;
464
+ this.appStateSubscription?.remove();
465
+ this.cleanupAllSubscriptions();
466
+ this.manager.destroy();
467
+ }
468
+ }
469
+ //# sourceMappingURL=native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.js","sourceRoot":"","sources":["../../../../src/bluetooth/adapters/native.ts"],"names":[],"mappings":"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"}