@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,54 @@
1
+ {
2
+ "_comment": "Voltra BLE Protocol - Authentication, Initialization, and Telemetry",
3
+ "_version": "1.1.0",
4
+ "ble": {
5
+ "service_uuid": "E4DADA34-0867-8783-9F70-2CA29216C7E4",
6
+ "notify_char_uuid": "55CA1E52-7354-25DE-6AFC-B7DF1E8816AC",
7
+ "write_char_uuid": "A010891D-F50F-44F0-901F-9A2421A9E050",
8
+ "device_name_prefix": "VTR-"
9
+ },
10
+ "auth": {
11
+ "_comment": "41-byte device IDs with proprietary checksums",
12
+ "iphone": "552904c90110000020004f6950686f6e6500000000000000000000000000000084ab1a5f29200172d8",
13
+ "ipad": "552904c90110000020004f69506164000000000000000000000000000000000084ab1a5f292001ea4f"
14
+ },
15
+ "init": {
16
+ "_comment": "Minimal 2-command init sequence (reduced from 22+ in Beyond+ app)",
17
+ "commands": [
18
+ "550f0801aad200002000ff00aa04194000",
19
+ "551f044eaa100000200027811065f8c6b9179047b797d3351c04bffb925cd64100"
20
+ ]
21
+ },
22
+ "workout": {
23
+ "_comment": "Workout control commands",
24
+ "prepare": "551204c7aa1014002000110100b04f01db10",
25
+ "setup": "55130403aa10150020000f02006a50823e8f2f",
26
+ "go": "55130403aa1016002000110100893e05008173",
27
+ "stop": "55130403aa101b002000110100893e040037dd"
28
+ },
29
+ "telemetry": {
30
+ "_comment": "Telemetry parsing configuration - message types, byte offsets, movement phases",
31
+ "message_types": {
32
+ "_comment": "First 4 bytes of notifications identify message type",
33
+ "stream": "553a0470",
34
+ "rep_summary": "554a04c6",
35
+ "set_summary": "554f0439",
36
+ "status_update": "553404ac"
37
+ },
38
+ "offsets": {
39
+ "_comment": "Byte offsets for parsing telemetry stream messages",
40
+ "sequence": 6,
41
+ "phase": 13,
42
+ "position": 24,
43
+ "force": 26,
44
+ "velocity": 28
45
+ },
46
+ "phases": {
47
+ "_comment": "Movement phase values (byte at offset 13)",
48
+ "idle": 0,
49
+ "concentric": 1,
50
+ "hold": 2,
51
+ "eccentric": 3
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "_comment": "Weight commands (863e register) - 5 to 200 lbs in 5 lb increments",
3
+ "format": {
4
+ "description": "21-byte command structure",
5
+ "length": 21,
6
+ "structure": [
7
+ { "name": "prefix", "bytes": "0-5", "value": "55130403aa10", "constant": true },
8
+ { "name": "sequence", "bytes": "6-7", "value": "varies", "encoding": "uint16_le" },
9
+ { "name": "mode", "bytes": "8-12", "value": "2000110100", "constant": true },
10
+ { "name": "register", "bytes": "13-14", "value": "863e", "constant": true },
11
+ { "name": "value", "bytes": "15-16", "value": "weight_in_lbs", "encoding": "uint16_le" },
12
+ { "name": "checksum", "bytes": "17-19", "value": "varies", "encoding": "3_bytes_hex" },
13
+ { "name": "padding", "bytes": "20", "value": "00", "constant": true }
14
+ ],
15
+ "prefix": "55130403aa10",
16
+ "mode": "2000110100",
17
+ "register": "863e",
18
+ "padding": "00"
19
+ },
20
+ "values": {
21
+ "5": { "seq": "1500", "checksum": "cb3f37", "_full": "55130403aa1015002000110100863e0500cb3f3700" },
22
+ "10": { "seq": "1400", "checksum": "92e941", "_full": "55130403aa1014002000110100863e0a0092e94100" },
23
+ "15": { "seq": "1500", "checksum": "bbc234", "_full": "55130403aa1015002000110100863e0f00bbc23400" },
24
+ "20": { "seq": "1600", "checksum": "314d40", "_full": "55130403aa1016002000110100863e1400314d4000" },
25
+ "25": { "seq": "1700", "checksum": "d8a836", "_full": "55130403aa1017002000110100863e1900d8a83600" },
26
+ "30": { "seq": "1800", "checksum": "9cf934", "_full": "55130403aa1018002000110100863e1e009cf93400" },
27
+ "35": { "seq": "1900", "checksum": "d7aa37", "_full": "55130403aa1019002000110100863e2300d7aa3700" },
28
+ "40": { "seq": "1a00", "checksum": "ccb037", "_full": "55130403aa101a002000110100863e2800ccb03700" },
29
+ "45": { "seq": "1b00", "checksum": "e59b40", "_full": "55130403aa101b002000110100863e2d00e59b4000" },
30
+ "50": { "seq": "1c00", "checksum": "5a2d37", "_full": "55130403aa101c002000110100863e32005a2d3700" },
31
+ "55": { "seq": "1700", "checksum": "fb1112", "_full": "55130403aa1017002000110100863e3700fb111200" },
32
+ "60": { "seq": "1800", "checksum": "1fe937", "_full": "55130403aa1018002000110100863e3c001fe93700" },
33
+ "65": { "seq": "1900", "checksum": "32fc40", "_full": "55130403aa1019002000110100863e410032fc4000" },
34
+ "70": { "seq": "1a00", "checksum": "894f37", "_full": "55130403aa101a002000110100863e4600894f3700" },
35
+ "75": { "seq": "1b00", "checksum": "60aa12", "_full": "55130403aa101b002000110100863e4b0060aa1200" },
36
+ "80": { "seq": "1c00", "checksum": "bf7b43", "_full": "55130403aa101c002000110100863e5000bf7b4300" },
37
+ "85": { "seq": "1d00", "checksum": "965037", "_full": "55130403aa101d002000110100863e550096503700" },
38
+ "90": { "seq": "1e00", "checksum": "ed2d37", "_full": "55130403aa101e002000110100863e5a00ed2d3700" },
39
+ "95": { "seq": "1f00", "checksum": "c40634", "_full": "55130403aa101f002000110100863e5f00c4063400" },
40
+ "100": { "seq": "2000", "checksum": "4ddb12", "_full": "55130403aa1020002000110100863e64004ddb1200" },
41
+ "105": { "seq": "2100", "checksum": "a43e37", "_full": "55130403aa1021002000110100863e6900a43e3700" },
42
+ "110": { "seq": "3000", "checksum": "785740", "_full": "55130403aa1030002000110100863e6e0078574000" },
43
+ "115": { "seq": "3100", "checksum": "00272d", "_full": "55130403aa1031002000110100863e730000272d00" },
44
+ "120": { "seq": "3200", "checksum": "1b3d40", "_full": "55130403aa1032002000110100863e78001b3d4000" },
45
+ "125": { "seq": "3900", "checksum": "ba013f", "_full": "55130403aa1039002000110100863e7d00ba013f00" },
46
+ "130": { "seq": "3a00", "checksum": "c90037", "_full": "55130403aa103a002000110100863e8200c9003700" },
47
+ "135": { "seq": "3b00", "checksum": "e02b34", "_full": "55130403aa103b002000110100863e8700e02b3400" },
48
+ "140": { "seq": "3c00", "checksum": "ae6f12", "_full": "55130403aa103c002000110100863e8c00ae6f1200" },
49
+ "145": { "seq": "3d00", "checksum": "d61f37", "_full": "55130403aa103d002000110100863e9100d61f3700" },
50
+ "150": { "seq": "3e00", "checksum": "6dac2d", "_full": "55130403aa103e002000110100863e96006dac2d00" },
51
+ "155": { "seq": "3f00", "checksum": "844937", "_full": "55130403aa103f002000110100863e9b0084493700" },
52
+ "160": { "seq": "4000", "checksum": "085941", "_full": "55130403aa1040002000110100863ea00008594100" },
53
+ "165": { "seq": "4100", "checksum": "217237", "_full": "55130403aa1041002000110100863ea50021723700" },
54
+ "170": { "seq": "4200", "checksum": "5a0f43", "_full": "55130403aa1042002000110100863eaa005a0f4300" },
55
+ "175": { "seq": "4300", "checksum": "732434", "_full": "55130403aa1043002000110100863eaf0073243400" },
56
+ "180": { "seq": "4400", "checksum": "acf537", "_full": "55130403aa1044002000110100863eb400acf53700" },
57
+ "185": { "seq": "4500", "checksum": "451037", "_full": "55130403aa1045002000110100863eb90045103700" },
58
+ "190": { "seq": "4600", "checksum": "fea312", "_full": "55130403aa1046002000110100863ebe00fea31200" },
59
+ "195": { "seq": "4700", "checksum": "d3b637", "_full": "55130403aa1047002000110100863ec300d3b63700" },
60
+ "200": { "seq": "4800", "checksum": "374e41", "_full": "55130403aa1048002000110100863ec800374e4100" }
61
+ }
62
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Voltra Protocol Module
3
+ *
4
+ * Complete TypeScript implementation of the Voltra BLE protocol.
5
+ */
6
+ export * from './constants';
7
+ export * from './commands';
8
+ export * from './telemetry-decoder';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/voltra/protocol/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Telemetry Decoder
3
+ *
4
+ * Low-level protocol decoder for Voltra BLE telemetry notifications.
5
+ * Only handles parsing bytes into typed data - no business logic.
6
+ */
7
+ import { MessageTypes, TelemetryOffsets, MovementPhase } from './constants';
8
+ import { createFrame } from '../models/telemetry/frame';
9
+ import { bytesEqual } from '../../shared/utils';
10
+ // =============================================================================
11
+ // Byte Parsing Helpers
12
+ // =============================================================================
13
+ /**
14
+ * Read a little-endian uint16 from a Uint8Array.
15
+ */
16
+ function readUint16LE(data, offset) {
17
+ return data[offset] | (data[offset + 1] << 8);
18
+ }
19
+ /**
20
+ * Read a little-endian int16 from a Uint8Array.
21
+ */
22
+ function readInt16LE(data, offset) {
23
+ const value = readUint16LE(data, offset);
24
+ return value > 0x7fff ? value - 0x10000 : value;
25
+ }
26
+ /**
27
+ * Write a little-endian uint16 to a Uint8Array.
28
+ */
29
+ function writeUint16LE(data, offset, value) {
30
+ data[offset] = value & 0xff;
31
+ data[offset + 1] = (value >> 8) & 0xff;
32
+ }
33
+ /**
34
+ * Write a little-endian int16 to a Uint8Array.
35
+ */
36
+ function writeInt16LE(data, offset, value) {
37
+ if (value < 0) {
38
+ value = value + 0x10000;
39
+ }
40
+ writeUint16LE(data, offset, value);
41
+ }
42
+ /**
43
+ * Identify the message type from raw bytes.
44
+ */
45
+ export function identifyMessageType(data) {
46
+ if (data.length < 4)
47
+ return 'unknown';
48
+ const msgType = data.slice(0, 4);
49
+ if (bytesEqual(msgType, MessageTypes.TELEMETRY_STREAM)) {
50
+ return 'telemetry_stream';
51
+ }
52
+ else if (bytesEqual(msgType, MessageTypes.REP_SUMMARY)) {
53
+ return 'rep_summary';
54
+ }
55
+ else if (bytesEqual(msgType, MessageTypes.SET_SUMMARY)) {
56
+ return 'set_summary';
57
+ }
58
+ else if (bytesEqual(msgType, MessageTypes.STATUS_UPDATE)) {
59
+ return 'status_update';
60
+ }
61
+ return 'unknown';
62
+ }
63
+ // =============================================================================
64
+ // Decoder
65
+ // =============================================================================
66
+ /**
67
+ * Decode a telemetry stream message into a TelemetryFrame.
68
+ */
69
+ export function decodeTelemetryFrame(data) {
70
+ if (data.length < 30) {
71
+ return null;
72
+ }
73
+ // Sequence number
74
+ const sequence = readUint16LE(data, TelemetryOffsets.SEQUENCE);
75
+ // Phase
76
+ const phaseByte = data[TelemetryOffsets.PHASE];
77
+ let phase;
78
+ if (phaseByte >= 0 && phaseByte <= 3) {
79
+ phase = phaseByte;
80
+ }
81
+ else {
82
+ phase = MovementPhase.UNKNOWN;
83
+ }
84
+ // Sensor data
85
+ const position = readUint16LE(data, TelemetryOffsets.POSITION);
86
+ const force = readInt16LE(data, TelemetryOffsets.FORCE);
87
+ const velocity = readUint16LE(data, TelemetryOffsets.VELOCITY);
88
+ return createFrame(sequence, phase, position, force, velocity);
89
+ }
90
+ /**
91
+ * Decode a BLE notification.
92
+ * Returns structured data based on message type.
93
+ */
94
+ export function decodeNotification(data) {
95
+ const msgType = identifyMessageType(data);
96
+ switch (msgType) {
97
+ case 'telemetry_stream': {
98
+ const frame = decodeTelemetryFrame(data);
99
+ return frame ? { type: 'frame', frame } : null;
100
+ }
101
+ case 'rep_summary':
102
+ // Device is signaling a rep boundary (end of concentric or eccentric)
103
+ return { type: 'rep_boundary' };
104
+ case 'set_summary':
105
+ // Device is signaling set completion
106
+ return { type: 'set_boundary' };
107
+ case 'status_update':
108
+ return { type: 'status', data };
109
+ default:
110
+ return null;
111
+ }
112
+ }
113
+ // =============================================================================
114
+ // Encoder (for replay)
115
+ // =============================================================================
116
+ /**
117
+ * Encode a TelemetryFrame into a BLE notification payload.
118
+ * Creates a minimal 30-byte message that can be decoded by decodeTelemetryFrame.
119
+ * Used for replay functionality.
120
+ */
121
+ export function encodeTelemetryFrame(frame) {
122
+ const data = new Uint8Array(30);
123
+ // Message type header (telemetry stream)
124
+ data[0] = 0x55;
125
+ data[1] = 0x3a;
126
+ data[2] = 0x04;
127
+ data[3] = 0x70;
128
+ // Sequence (bytes 6-7)
129
+ writeUint16LE(data, TelemetryOffsets.SEQUENCE, frame.sequence);
130
+ // Phase (byte 13)
131
+ data[TelemetryOffsets.PHASE] = frame.phase;
132
+ // Position (bytes 24-25)
133
+ writeUint16LE(data, TelemetryOffsets.POSITION, frame.position);
134
+ // Force (bytes 26-27, signed)
135
+ writeInt16LE(data, TelemetryOffsets.FORCE, frame.force);
136
+ // Velocity (bytes 28-29)
137
+ writeUint16LE(data, TelemetryOffsets.VELOCITY, frame.velocity);
138
+ return data;
139
+ }
140
+ //# sourceMappingURL=telemetry-decoder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry-decoder.js","sourceRoot":"","sources":["../../../../src/voltra/protocol/telemetry-decoder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * BaseBLEAdapter
3
+ *
4
+ * Abstract base class for all BLE adapters. Provides shared implementation
5
+ * for connection state management and callback registration/notification.
6
+ *
7
+ * Subclasses implement the platform-specific BLE operations:
8
+ * - NativeBLEAdapter: react-native-ble-plx for iOS/Android
9
+ * - WebBLEAdapter: Web Bluetooth API for browsers
10
+ * - NodeBLEAdapter: webbluetooth npm for Node.js
11
+ * - ReplayBLEAdapter: Playback for testing/demos
12
+ */
13
+ import type { BLEAdapter, Device, ConnectionState, NotificationCallback, ConnectionStateCallback, ConnectOptions } from './types';
14
+ /**
15
+ * Abstract base class implementing shared BLE adapter functionality.
16
+ *
17
+ * Provides:
18
+ * - Connection state management with change notifications
19
+ * - Notification callback registration (supports multiple listeners)
20
+ * - State callback registration (supports multiple listeners)
21
+ * - Protected utilities for subclasses to emit events
22
+ */
23
+ export declare abstract class BaseBLEAdapter implements BLEAdapter {
24
+ /** Current connection state */
25
+ protected connectionState: ConnectionState;
26
+ /** Registered notification callbacks */
27
+ protected notificationCallbacks: NotificationCallback[];
28
+ /** Registered connection state callbacks */
29
+ protected stateCallbacks: ConnectionStateCallback[];
30
+ /**
31
+ * Get the current connection state.
32
+ */
33
+ getConnectionState(): ConnectionState;
34
+ /**
35
+ * Check if currently connected to a device.
36
+ */
37
+ isConnected(): boolean;
38
+ /**
39
+ * Register a callback for notifications from the device.
40
+ * @param callback Function called with notification data
41
+ * @returns Unsubscribe function
42
+ */
43
+ onNotification(callback: NotificationCallback): () => void;
44
+ /**
45
+ * Register a callback for connection state changes.
46
+ * @param callback Function called when state changes
47
+ * @returns Unsubscribe function
48
+ */
49
+ onConnectionStateChange(callback: ConnectionStateCallback): () => void;
50
+ /**
51
+ * Scan for devices.
52
+ * @param timeout Scan duration in seconds
53
+ * @returns List of discovered devices
54
+ */
55
+ abstract scan(timeout: number): Promise<Device[]>;
56
+ /**
57
+ * Connect to a device.
58
+ * @param deviceId Device identifier from scan results
59
+ * @param options Optional connection options
60
+ */
61
+ abstract connect(deviceId: string, options?: ConnectOptions): Promise<void>;
62
+ /**
63
+ * Disconnect from the current device.
64
+ */
65
+ abstract disconnect(): Promise<void>;
66
+ /**
67
+ * Write data to the device's write characteristic.
68
+ * @param data Bytes to write
69
+ */
70
+ abstract write(data: Uint8Array): Promise<void>;
71
+ /**
72
+ * Set connection state and notify all registered callbacks.
73
+ * Only notifies if state actually changed.
74
+ *
75
+ * @param state New connection state
76
+ */
77
+ protected setConnectionState(state: ConnectionState): void;
78
+ /**
79
+ * Emit notification data to all registered callbacks.
80
+ *
81
+ * @param data Notification data to emit
82
+ */
83
+ protected emitNotification(data: Uint8Array): void;
84
+ }
85
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/bluetooth/adapters/base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,MAAM,EACN,eAAe,EACf,oBAAoB,EACpB,uBAAuB,EACvB,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB;;;;;;;;GAQG;AACH,8BAAsB,cAAe,YAAW,UAAU;IACxD,+BAA+B;IAC/B,SAAS,CAAC,eAAe,EAAE,eAAe,CAAkB;IAE5D,wCAAwC;IACxC,SAAS,CAAC,qBAAqB,EAAE,oBAAoB,EAAE,CAAM;IAE7D,4CAA4C;IAC5C,SAAS,CAAC,cAAc,EAAE,uBAAuB,EAAE,CAAM;IAMzD;;OAEG;IACH,kBAAkB,IAAI,eAAe;IAIrC;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;;;OAIG;IACH,cAAc,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,IAAI;IAU1D;;;;OAIG;IACH,uBAAuB,CAAC,QAAQ,EAAE,uBAAuB,GAAG,MAAM,IAAI;IActE;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAEjD;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAE3E;;OAEG;IACH,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAEpC;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/C;;;;;OAKG;IACH,SAAS,CAAC,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAa1D;;;;OAIG;IACH,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;CASnD"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * BLE Abstraction Layer
3
+ *
4
+ * Provides a unified interface for BLE communication across platforms:
5
+ * - Native (iOS/Android): react-native-ble-plx
6
+ * - Browser: Web Bluetooth API
7
+ * - Node.js: webbluetooth npm package
8
+ */
9
+ export type { BLEAdapter, Device, ConnectionState, NotificationCallback, ConnectionStateCallback, ConnectOptions, BLEServiceConfig, } from './types';
10
+ export { WebBLEAdapter } from './web';
11
+ export { NodeBLEAdapter, type NodeBLEConfig, type DeviceChooser } from './node';
12
+ export { NativeBLEAdapter, type NativeAdapterConfig } from './native';
13
+ import type { BLEAdapter, BLEServiceConfig } from './types';
14
+ /**
15
+ * Full configuration for creating a BLE adapter.
16
+ */
17
+ export interface CreateBLEAdapterConfig {
18
+ /** BLE service configuration (UUIDs, device name prefix) */
19
+ ble: BLEServiceConfig;
20
+ }
21
+ /**
22
+ * Create a BLE adapter based on the current environment.
23
+ *
24
+ * Environment detection:
25
+ * - Web browser: WebBLEAdapter (Web Bluetooth API)
26
+ * - Node.js: NodeBLEAdapter (webbluetooth package)
27
+ *
28
+ * NOTE: For React Native, import and instantiate NativeBLEAdapter directly.
29
+ * This factory is for web/Node.js environments only.
30
+ *
31
+ * @param config Adapter configuration including BLE service UUIDs
32
+ * @returns BLEAdapter instance appropriate for the current environment
33
+ */
34
+ export declare function createBLEAdapter(config: CreateBLEAdapterConfig): BLEAdapter;
35
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/bluetooth/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,YAAY,EACV,UAAU,EACV,MAAM,EACN,eAAe,EACf,oBAAoB,EACpB,uBAAuB,EACvB,cAAc,EACd,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAKtE,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAI5D;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,4DAA4D;IAC5D,GAAG,EAAE,gBAAgB,CAAC;CACvB;AAsBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,UAAU,CAY3E"}
@@ -0,0 +1,109 @@
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 { BaseBLEAdapter } from './base';
14
+ import type { Device, ConnectOptions, BLEServiceConfig } from './types';
15
+ export type { BLEServiceConfig } from './types';
16
+ /**
17
+ * Configuration for auto-reconnect behavior.
18
+ */
19
+ export interface NativeAdapterConfig {
20
+ /** BLE service configuration */
21
+ ble: BLEServiceConfig;
22
+ /** Enable auto-reconnect when app returns to foreground */
23
+ autoReconnect?: boolean;
24
+ /** Max attempts for auto-reconnect */
25
+ maxReconnectAttempts?: number;
26
+ /** Delay between reconnect attempts (ms) */
27
+ reconnectDelayMs?: number;
28
+ }
29
+ /**
30
+ * BLE adapter using react-native-ble-plx for native device communication.
31
+ * Supports auto-reconnect when app resumes from background.
32
+ */
33
+ export declare class NativeBLEAdapter extends BaseBLEAdapter {
34
+ private manager;
35
+ private device;
36
+ private notifySubscription;
37
+ private writeSubscription;
38
+ private bleConfig;
39
+ private autoReconnect;
40
+ private maxReconnectAttempts;
41
+ private reconnectDelayMs;
42
+ private lastConnectedDeviceId;
43
+ private lastConnectedDeviceName;
44
+ private isReconnecting;
45
+ private reconnectAttempts;
46
+ private appStateSubscription;
47
+ private isDisconnecting;
48
+ private disconnectSubscription;
49
+ private onReconnectStart?;
50
+ private onReconnectSuccess?;
51
+ private onReconnectFailed?;
52
+ constructor(config: NativeAdapterConfig);
53
+ /**
54
+ * Set up listener for app state changes (background/foreground).
55
+ */
56
+ private setupAppStateListener;
57
+ /**
58
+ * Handle app state changes for auto-reconnect.
59
+ */
60
+ private handleAppStateChange;
61
+ /**
62
+ * Attempt to reconnect to the last known device.
63
+ */
64
+ private attemptReconnect;
65
+ private waitForPoweredOn;
66
+ scan(timeout: number): Promise<Device[]>;
67
+ connect(deviceId: string, options?: ConnectOptions): Promise<void>;
68
+ private cleanupSubscriptions;
69
+ private cleanupAllSubscriptions;
70
+ disconnect(): Promise<void>;
71
+ write(data: Uint8Array): Promise<void>;
72
+ /**
73
+ * Override isConnected to also check if device exists.
74
+ */
75
+ isConnected(): boolean;
76
+ /**
77
+ * Get info about the currently connected device.
78
+ */
79
+ getConnectedDevice(): Device | null;
80
+ /**
81
+ * Get the last connected device ID (for reconnection).
82
+ */
83
+ getLastConnectedDeviceId(): string | null;
84
+ /**
85
+ * Set callbacks for reconnect events.
86
+ */
87
+ setReconnectCallbacks(callbacks: {
88
+ onStart?: () => void;
89
+ onSuccess?: () => void;
90
+ onFailed?: (error: Error) => void;
91
+ }): void;
92
+ /**
93
+ * Manually trigger a reconnect attempt.
94
+ */
95
+ reconnect(): Promise<void>;
96
+ /**
97
+ * Set the last connected device (for restoring from storage).
98
+ */
99
+ setLastConnectedDevice(deviceId: string, deviceName?: string): void;
100
+ /**
101
+ * Check if auto-reconnect is in progress.
102
+ */
103
+ isAutoReconnecting(): boolean;
104
+ /**
105
+ * Destroy the BLE manager (call when app is closing).
106
+ */
107
+ destroy(): void;
108
+ }
109
+ //# sourceMappingURL=native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../../../src/bluetooth/adapters/native.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGxE,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAsEhD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,gCAAgC;IAChC,GAAG,EAAE,gBAAgB,CAAC;IACtB,2DAA2D;IAC3D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sCAAsC;IACtC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAQD;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,cAAc;IAClD,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,kBAAkB,CAAuC;IACjE,OAAO,CAAC,iBAAiB,CAAuC;IAChE,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,aAAa,CAAU;IAC/B,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,gBAAgB,CAAS;IAGjC,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,uBAAuB,CAAuB;IACtD,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,iBAAiB,CAAa;IACtC,OAAO,CAAC,oBAAoB,CAAuC;IAGnE,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,sBAAsB,CAAuC;IAGrE,OAAO,CAAC,gBAAgB,CAAC,CAAa;IACtC,OAAO,CAAC,kBAAkB,CAAC,CAAa;IACxC,OAAO,CAAC,iBAAiB,CAAC,CAAyB;gBAEvC,MAAM,EAAE,mBAAmB;IAevC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAO7B;;OAEG;YACW,oBAAoB;IA2BlC;;OAEG;YACW,gBAAgB;YAqChB,gBAAgB;IA2BxB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAkExC,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAwHxE,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,uBAAuB;IAYzB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B3B,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAc5C;;OAEG;IACM,WAAW,IAAI,OAAO;IAI/B;;OAEG;IACH,kBAAkB,IAAI,MAAM,GAAG,IAAI;IASnC;;OAEG;IACH,wBAAwB,IAAI,MAAM,GAAG,IAAI;IAIzC;;OAEG;IACH,qBAAqB,CAAC,SAAS,EAAE;QAC/B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;QACvB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;KACnC,GAAG,IAAI;IAMR;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAQhC;;OAEG;IACH,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAKnE;;OAEG;IACH,kBAAkB,IAAI,OAAO;IAI7B;;OAEG;IACH,OAAO,IAAI,IAAI;CAMhB"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * NodeBLEAdapter
3
+ *
4
+ * BLE adapter for Node.js using the webbluetooth npm package.
5
+ * Implements the same W3C Web Bluetooth API for server-side BLE.
6
+ *
7
+ * Requirements:
8
+ * - Node.js environment
9
+ * - webbluetooth npm package
10
+ * - Platform-specific Bluetooth support (macOS, Linux, Windows)
11
+ */
12
+ import { WebBluetoothBase, type WebBluetoothConfig } from './web-bluetooth-base';
13
+ import type { Device, ConnectOptions } from './types';
14
+ /**
15
+ * Device chooser function type.
16
+ * Called during scan to programmatically select a device.
17
+ */
18
+ export type DeviceChooser = (devices: Device[]) => Device | null;
19
+ /**
20
+ * Configuration for Node.js BLE adapter.
21
+ */
22
+ export interface NodeBLEConfig extends WebBluetoothConfig {
23
+ /**
24
+ * Optional device chooser function.
25
+ * If not provided, the first matching device is selected.
26
+ */
27
+ deviceChooser?: DeviceChooser;
28
+ }
29
+ /**
30
+ * BLE adapter for Node.js environments using webbluetooth package.
31
+ *
32
+ * Device selection flow:
33
+ * 1. Call scan() - starts BLE scan
34
+ * 2. Devices are discovered via deviceFound callback
35
+ * 3. deviceChooser function selects a device (or first match by default)
36
+ * 4. Call connect() to establish GATT connection
37
+ */
38
+ export declare class NodeBLEAdapter extends WebBluetoothBase {
39
+ /** Device chooser function for programmatic selection */
40
+ private deviceChooser;
41
+ /** Device selected during scan, stored for connect() */
42
+ private selectedDevice;
43
+ /** List of discovered devices during current scan */
44
+ private discoveredDevices;
45
+ constructor(config: NodeBLEConfig);
46
+ /**
47
+ * Set the device chooser function.
48
+ * Called during scan to programmatically select a device.
49
+ *
50
+ * @param chooser Function that receives discovered devices and returns the chosen one
51
+ */
52
+ setDeviceChooser(chooser: DeviceChooser): void;
53
+ /**
54
+ * Ensure webbluetooth is loaded (lazy load to avoid bundler issues).
55
+ */
56
+ private ensureBluetoothLoaded;
57
+ /**
58
+ * Scan for devices programmatically.
59
+ *
60
+ * In Node.js, there's no browser picker. Devices are discovered via
61
+ * the deviceFound callback, and the deviceChooser function selects one.
62
+ *
63
+ * IMPORTANT: The webbluetooth package requires creating a new Bluetooth
64
+ * instance with deviceFound in the constructor for the callback to work
65
+ * reliably. Using the default singleton doesn't call the callback consistently.
66
+ *
67
+ * @param timeout Scan timeout in seconds
68
+ * @returns Array of discovered devices (selection happens via deviceChooser)
69
+ */
70
+ scan(timeout: number): Promise<Device[]>;
71
+ /**
72
+ * Connect to the selected device.
73
+ *
74
+ * @param deviceId Device ID (should match the selected device)
75
+ * @param options Connection options
76
+ */
77
+ connect(deviceId: string, options?: ConnectOptions): Promise<void>;
78
+ /**
79
+ * Override disconnect to also clear selected device.
80
+ */
81
+ disconnect(): Promise<void>;
82
+ /**
83
+ * Get the list of devices discovered during the last scan.
84
+ */
85
+ getDiscoveredDevices(): Device[];
86
+ /**
87
+ * Check if running in a Node.js environment.
88
+ */
89
+ static isNodeEnvironment(): boolean;
90
+ }
91
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../../src/bluetooth/adapters/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAMtD;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,MAAM,GAAG,IAAI,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,kBAAkB;IACvD;;;OAGG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED;;;;;;;;GAQG;AACH,qBAAa,cAAe,SAAQ,gBAAgB;IAClD,yDAAyD;IACzD,OAAO,CAAC,aAAa,CAAuB;IAE5C,wDAAwD;IACxD,OAAO,CAAC,cAAc,CAAgC;IAEtD,qDAAqD;IACrD,OAAO,CAAC,iBAAiB,CAAgB;gBAE7B,MAAM,EAAE,aAAa;IAKjC;;;;;OAKG;IACH,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAI9C;;OAEG;YACW,qBAAqB;IAcnC;;;;;;;;;;;;OAYG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAuF9C;;;;;OAKG;IACG,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBxE;;OAEG;IACY,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAM1C;;OAEG;IACH,oBAAoB,IAAI,MAAM,EAAE;IAIhC;;OAEG;IACH,MAAM,CAAC,iBAAiB,IAAI,OAAO;CAKpC"}