@stoprocent/noble 1.19.0 → 2.0.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 (97) hide show
  1. package/README.md +393 -650
  2. package/examples/advertisement-discovery.js +57 -48
  3. package/examples/connect-address.js +59 -34
  4. package/examples/echo.js +59 -69
  5. package/examples/enter-exit.js +55 -49
  6. package/examples/multiple-bindings.js +53 -0
  7. package/examples/peripheral-explorer-async.js +39 -21
  8. package/examples/peripheral-explorer.ts +52 -0
  9. package/index.d.ts +249 -209
  10. package/index.js +4 -1
  11. package/jest.config.js +4 -0
  12. package/lib/characteristic.js +153 -127
  13. package/lib/{win/src/callbacks.h → common/include/Emit.h} +17 -14
  14. package/lib/common/include/Peripheral.h +31 -0
  15. package/lib/common/include/ThreadSafeCallback.h +95 -0
  16. package/lib/{win/src/callbacks.cc → common/src/Emit.cc} +111 -68
  17. package/lib/descriptor.js +57 -54
  18. package/lib/hci-socket/acl-stream.js +2 -4
  19. package/lib/hci-socket/bindings.js +96 -73
  20. package/lib/hci-socket/gap.js +2 -3
  21. package/lib/hci-socket/gatt.js +2 -5
  22. package/lib/hci-socket/hci.js +19 -7
  23. package/lib/hci-socket/signaling.js +2 -3
  24. package/lib/hci-socket/smp.js +2 -3
  25. package/lib/hci-socket/vs.js +1 -0
  26. package/lib/mac/binding.gyp +5 -7
  27. package/lib/mac/bindings.js +1 -3
  28. package/lib/mac/src/ble_manager.h +1 -8
  29. package/lib/mac/src/ble_manager.mm +87 -44
  30. package/lib/mac/src/napi_objc.h +1 -0
  31. package/lib/mac/src/napi_objc.mm +0 -6
  32. package/lib/mac/src/noble_mac.h +5 -3
  33. package/lib/mac/src/noble_mac.mm +99 -57
  34. package/lib/mac/src/objc_cpp.h +3 -2
  35. package/lib/mac/src/objc_cpp.mm +0 -6
  36. package/lib/noble.js +579 -488
  37. package/lib/peripheral.js +171 -174
  38. package/lib/resolve-bindings.js +37 -30
  39. package/lib/service.js +58 -55
  40. package/lib/win/binding.gyp +4 -11
  41. package/lib/win/bindings.js +1 -3
  42. package/lib/win/src/ble_manager.cc +291 -166
  43. package/lib/win/src/ble_manager.h +11 -13
  44. package/lib/win/src/napi_winrt.cc +1 -7
  45. package/lib/win/src/napi_winrt.h +1 -1
  46. package/lib/win/src/noble_winrt.cc +88 -61
  47. package/lib/win/src/noble_winrt.h +5 -3
  48. package/lib/win/src/notify_map.cc +0 -7
  49. package/lib/win/src/notify_map.h +1 -8
  50. package/lib/win/src/peripheral_winrt.cc +29 -11
  51. package/lib/win/src/peripheral_winrt.h +1 -1
  52. package/lib/win/src/radio_watcher.cc +79 -69
  53. package/lib/win/src/radio_watcher.h +30 -11
  54. package/lib/win/src/winrt_cpp.cc +1 -1
  55. package/lib/win/src/winrt_cpp.h +3 -0
  56. package/package.json +14 -17
  57. package/prebuilds/darwin-x64+arm64/@stoprocent+noble.node +0 -0
  58. package/prebuilds/win32-ia32/@stoprocent+noble.node +0 -0
  59. package/prebuilds/win32-x64/@stoprocent+noble.node +0 -0
  60. package/test/lib/characteristic.test.js +202 -322
  61. package/test/lib/descriptor.test.js +62 -95
  62. package/test/lib/hci-socket/acl-stream.test.js +112 -108
  63. package/test/lib/hci-socket/bindings.test.js +576 -365
  64. package/test/lib/hci-socket/hci.test.js +442 -473
  65. package/test/lib/hci-socket/signaling.test.js +45 -48
  66. package/test/lib/hci-socket/smp.test.js +144 -142
  67. package/test/lib/hci-socket/vs.test.js +193 -18
  68. package/test/lib/peripheral.test.js +492 -322
  69. package/test/lib/resolve-bindings.test.js +207 -82
  70. package/test/lib/service.test.js +79 -88
  71. package/test/noble.test.js +381 -1085
  72. package/.editorconfig +0 -11
  73. package/.nycrc.json +0 -4
  74. package/codecov.yml +0 -5
  75. package/examples/cache-gatt-discovery.js +0 -198
  76. package/examples/cache-gatt-reconnect.js +0 -164
  77. package/examples/ext-advertisement-discovery.js +0 -65
  78. package/examples/peripheral-explorer.js +0 -225
  79. package/examples/pizza/central.js +0 -194
  80. package/examples/pizza/pizza.js +0 -60
  81. package/examples/test/test.custom.js +0 -131
  82. package/examples/uart-bind-params.js +0 -28
  83. package/lib/distributed/bindings.js +0 -326
  84. package/lib/mac/src/callbacks.cc +0 -222
  85. package/lib/mac/src/callbacks.h +0 -84
  86. package/lib/mac/src/peripheral.h +0 -23
  87. package/lib/resolve-bindings-web.js +0 -9
  88. package/lib/webbluetooth/bindings.js +0 -368
  89. package/lib/websocket/bindings.js +0 -321
  90. package/lib/win/src/peripheral.h +0 -23
  91. package/test/lib/distributed/bindings.test.js +0 -918
  92. package/test/lib/webbluetooth/bindings.test.js +0 -190
  93. package/test/lib/websocket/bindings.test.js +0 -456
  94. package/test/mocha.setup.js +0 -0
  95. package/with-bindings.js +0 -5
  96. package/with-custom-binding.js +0 -6
  97. package/ws-slave.js +0 -404
@@ -1,25 +1,200 @@
1
- const should = require('should');
2
- const sinon = require('sinon');
3
- const proxyquire = require('proxyquire').noCallThru();
1
+ // Mock dependencies if needed
2
+ jest.mock('os', () => ({}));
4
3
 
5
- const fakeOs = {};
6
- const { assert } = sinon;
7
- const vendorSpecific = proxyquire('../../../lib/hci-socket/vs', { os: fakeOs });
4
+ const vs = require('../../../lib/hci-socket/vs');
8
5
 
9
- describe('hci-socket vs', () => {
10
- afterEach(() => {
11
- sinon.reset();
6
+ describe('Bluetooth Address Utility', () => {
7
+ const validAddress = '00:11:22:33:44:55';
8
+
9
+ describe('setAddressCmd', () => {
10
+ test('returns null for unsupported manufacturer', () => {
11
+ const result = vs.setAddressCmd(999, validAddress);
12
+ expect(result).toBeNull();
13
+ });
14
+
15
+ test('returns null for invalid address', () => {
16
+ // Most vendor functions call parseAddress which validates the address
17
+ // Testing with a supported manufacturer (Broadcom - 15)
18
+ expect(() => vs.setAddressCmd(15, 'invalid-address')).toThrow();
19
+ });
20
+
21
+ describe('for each supported manufacturer', () => {
22
+ // Test Ericsson (0)
23
+ test('creates correct command for Ericsson (0)', () => {
24
+ const result = vs.setAddressCmd(0, validAddress);
25
+
26
+ expect(result).toBeInstanceOf(Buffer);
27
+ expect(result.length).toBe(9);
28
+ expect(result.readUInt16LE(0)).toBe(0x000d | (0x3f << 10)); // OCF | OGF
29
+ expect(result.readUInt8(2)).toBe(0x06); // Parameter length
30
+
31
+ // Check MAC address bytes are properly placed
32
+ expect(result.slice(3, 9)).toEqual(Buffer.from([0x55, 0x44, 0x33, 0x22, 0x11, 0x00]));
33
+ });
34
+
35
+ // Test CSR (10)
36
+ test('creates correct command for CSR (10)', () => {
37
+ const result = vs.setAddressCmd(10, validAddress);
38
+
39
+ expect(result).toBeInstanceOf(Buffer);
40
+ expect(result.length).toBe(27); // 3 header + 24 base
41
+ expect(result.readUInt16LE(0)).toBe(0x0000 | (0x3f << 10)); // OCF | OGF
42
+ expect(result.readUInt8(2)).toBe(0xC2);
43
+
44
+ // Check specific positions where MAC address bytes should be
45
+ expect(result.readUInt8(16 + 3)).toBe(0x33); // macAddress[2]
46
+ expect(result.readUInt8(18 + 3)).toBe(0x55); // macAddress[0]
47
+ expect(result.readUInt8(19 + 3)).toBe(0x44); // macAddress[1]
48
+ expect(result.readUInt8(20 + 3)).toBe(0x22); // macAddress[3]
49
+ expect(result.readUInt8(22 + 3)).toBe(0x11); // macAddress[4]
50
+ expect(result.readUInt8(23 + 3)).toBe(0x00); // macAddress[5]
51
+ });
52
+
53
+ // Test TI (13)
54
+ test('creates correct command for Texas Instruments (13)', () => {
55
+ const result = vs.setAddressCmd(13, validAddress);
56
+
57
+ expect(result).toBeInstanceOf(Buffer);
58
+ expect(result.length).toBe(9);
59
+ expect(result.readUInt16LE(0)).toBe(0x0006 | (0x3f << 10)); // OCF | OGF
60
+ expect(result.readUInt8(2)).toBe(0x06); // Parameter length
61
+
62
+ // Check MAC address bytes are properly placed
63
+ expect(result.slice(3, 9)).toEqual(Buffer.from([0x55, 0x44, 0x33, 0x22, 0x11, 0x00]));
64
+ });
65
+
66
+ // Test Broadcom (15)
67
+ test('creates correct command for Broadcom (15)', () => {
68
+ const result = vs.setAddressCmd(15, validAddress);
69
+
70
+ expect(result).toBeInstanceOf(Buffer);
71
+ expect(result.length).toBe(9);
72
+ expect(result.readUInt16LE(0)).toBe(0x0001 | (0x3f << 10)); // OCF | OGF
73
+ expect(result.readUInt8(2)).toBe(0x06); // Parameter length
74
+
75
+ // Check MAC address bytes are properly placed
76
+ expect(result.slice(3, 9)).toEqual(Buffer.from([0x55, 0x44, 0x33, 0x22, 0x11, 0x00]));
77
+ });
78
+
79
+ // Test Zeevo (18)
80
+ test('creates correct command for Zeevo (18)', () => {
81
+ const result = vs.setAddressCmd(18, validAddress);
82
+
83
+ expect(result).toBeInstanceOf(Buffer);
84
+ expect(result.length).toBe(9);
85
+ expect(result.readUInt16LE(0)).toBe(0x0001 | (0x3f << 10)); // OCF | OGF
86
+ expect(result.readUInt8(2)).toBe(0x06); // Parameter length
87
+
88
+ // Check MAC address bytes are properly placed
89
+ expect(result.slice(3, 9)).toEqual(Buffer.from([0x55, 0x44, 0x33, 0x22, 0x11, 0x00]));
90
+ });
91
+
92
+ // Test ST Microelectronics (48)
93
+ test('creates correct command for ST Microelectronics (48)', () => {
94
+ const result = vs.setAddressCmd(48, validAddress);
95
+
96
+ expect(result).toBeInstanceOf(Buffer);
97
+ expect(result.length).toBe(3 + 0xFF); // Header + ERICSSON_STORE_IN_FLASH_CP_SIZE
98
+ expect(result.readUInt16LE(0)).toBe(0x0022 | (0x3f << 10)); // OCF | OGF
99
+ expect(result.readUInt8(2)).toBe(0xFF); // Parameter length
100
+ expect(result.readUInt8(3)).toBe(0xFE); // user_id
101
+ expect(result.readUInt8(4)).toBe(0x06); // flash_length
102
+
103
+ // Check MAC address bytes are properly placed
104
+ expect(result.slice(5, 11)).toEqual(Buffer.from([0x55, 0x44, 0x33, 0x22, 0x11, 0x00]));
105
+ });
106
+
107
+ // Test Ericsson mobile (57)
108
+ test('creates correct command for Ericsson Mobile (57)', () => {
109
+ const result = vs.setAddressCmd(57, validAddress);
110
+
111
+ expect(result).toBeInstanceOf(Buffer);
112
+ expect(result.length).toBe(9);
113
+ expect(result.readUInt16LE(0)).toBe(0x000d | (0x3f << 10)); // OCF | OGF
114
+ expect(result.readUInt8(2)).toBe(0x06); // Parameter length
115
+
116
+ // Check MAC address bytes are properly placed
117
+ expect(result.slice(3, 9)).toEqual(Buffer.from([0x55, 0x44, 0x33, 0x22, 0x11, 0x00]));
118
+ });
119
+
120
+ // Test Marvell (72)
121
+ test('creates correct command for Marvell (72)', () => {
122
+ const result = vs.setAddressCmd(72, validAddress);
123
+
124
+ expect(result).toBeInstanceOf(Buffer);
125
+ expect(result.length).toBe(11);
126
+ expect(result.readUInt16LE(0)).toBe(0x0022 | (0x3f << 10)); // OCF | OGF
127
+ expect(result.readUInt8(2)).toBe(0x08); // Parameter length
128
+ expect(result.readUInt8(3)).toBe(0xFE); // parameter_id
129
+ expect(result.readUInt8(4)).toBe(0x06); // bdaddr_len
130
+
131
+ // Check MAC address bytes are properly placed
132
+ expect(result.slice(5, 11)).toEqual(Buffer.from([0x55, 0x44, 0x33, 0x22, 0x11, 0x00]));
133
+ });
134
+
135
+ // Test Atheros (305)
136
+ test('creates correct command for Atheros/Qualcomm (305)', () => {
137
+ const result = vs.setAddressCmd(305, validAddress);
138
+
139
+ expect(result).toBeInstanceOf(Buffer);
140
+ expect(result.length).toBe(9);
141
+ expect(result.readUInt16LE(0)).toBe(0x0001 | (0x3f << 10)); // OCF | OGF
142
+ expect(result.readUInt8(2)).toBe(0x06); // Parameter length
143
+
144
+ // Check MAC address bytes are properly placed
145
+ expect(result.slice(3, 9)).toEqual(Buffer.from([0x55, 0x44, 0x33, 0x22, 0x11, 0x00]));
146
+ });
147
+
148
+ // Test Linux Foundation (1521)
149
+ test('creates correct command for Linux Foundation (1521)', () => {
150
+ const result = vs.setAddressCmd(1521, validAddress);
151
+
152
+ expect(result).toBeInstanceOf(Buffer);
153
+ expect(result.length).toBe(9);
154
+ expect(result.readUInt16LE(0)).toBe(0x0006 | (0x3f << 10)); // OCF | OGF
155
+ expect(result.readUInt8(2)).toBe(0x06); // Parameter length
156
+
157
+ // Check MAC address bytes are properly placed
158
+ expect(result.slice(3, 9)).toEqual(Buffer.from([0x55, 0x44, 0x33, 0x22, 0x11, 0x00]));
159
+ });
160
+ });
12
161
  });
13
-
162
+
14
163
  describe('parseAddress', () => {
15
- it('should convert to Buffer', () => {
16
- assert.match(vendorSpecific.setAddressCmd(0, '00:11:22:33:44:55').slice(3), Buffer.from([0x55, 0x44, 0x33, 0x22, 0x11, 0x00]));
164
+ test('should throw an Error for invalid address', () => {
165
+ expect(() => {
166
+ vs.setAddressCmd(0, '00:11:22:33:44');
167
+ }).toThrow();
17
168
  });
18
-
19
- it('should not convert to Buffer and throw an Error', () => {
20
- should.throws(function () {
21
- vendorSpecific.setAddressCmd(0, '00:11:22:33:44');
22
- });
169
+
170
+ test('should convert to Buffer correctly', () => {
171
+ const result = vs.setAddressCmd(0, '00:11:22:33:44:55');
172
+ expect(result.slice(3)).toEqual(Buffer.from([0x55, 0x44, 0x33, 0x22, 0x11, 0x00]));
173
+ });
174
+ });
175
+
176
+ describe('edge cases', () => {
177
+ test('handle address with different case format', () => {
178
+ // Upper case should work the same
179
+ const result = vs.setAddressCmd(15, '00:11:22:33:44:55');
180
+ const resultUpperCase = vs.setAddressCmd(15, '00:11:22:33:44:55');
181
+
182
+ expect(result).toEqual(resultUpperCase);
183
+ });
184
+
185
+ test('handle invalid address format', () => {
186
+ // These should all return null
187
+ expect(() => vs.setAddressCmd(15, '00-11-22-33-44-55')).toThrow(); // Wrong separator
188
+ expect(() => vs.setAddressCmd(15, '00:11:22:33:44')).toThrow(); // Too short
189
+ expect(() => vs.setAddressCmd(15, '00:11:22:33:44:55:66')).toThrow(); // Too long
190
+ expect(() => vs.setAddressCmd(15, 'invalid')).toThrow(); // Not an address
191
+ });
192
+
193
+ test('handle non-existent manufacturer', () => {
194
+ expect(vs.setAddressCmd(9999, validAddress)).toBeNull();
195
+ expect(vs.setAddressCmd(-1, validAddress)).toBeNull();
196
+ expect(vs.setAddressCmd(null, validAddress)).toBeNull();
197
+ expect(vs.setAddressCmd(undefined, validAddress)).toBeNull();
23
198
  });
24
199
  });
25
- });
200
+ });