@stoprocent/noble 1.9.2-16
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/.editorconfig +11 -0
- package/.eslintrc.js +25 -0
- package/.github/FUNDING.yml +2 -0
- package/.github/workflows/fediverse-action.yml +16 -0
- package/.github/workflows/nodepackage.yml +77 -0
- package/.github/workflows/npm-publish.yml +26 -0
- package/.github/workflows/prebuild.yml +65 -0
- package/.nycrc.json +4 -0
- package/CHANGELOG.md +119 -0
- package/LICENSE +20 -0
- package/MAINTAINERS.md +1 -0
- package/README.md +833 -0
- package/assets/noble-logo.png +0 -0
- package/assets/noble-logo.svg +13 -0
- package/binding.gyp +19 -0
- package/codecov.yml +5 -0
- package/examples/advertisement-discovery.js +65 -0
- package/examples/cache-gatt-discovery.js +198 -0
- package/examples/cache-gatt-reconnect.js +164 -0
- package/examples/echo.js +104 -0
- package/examples/enter-exit.js +78 -0
- package/examples/peripheral-explorer-async.js +133 -0
- package/examples/peripheral-explorer.js +225 -0
- package/examples/pizza/README.md +15 -0
- package/examples/pizza/central.js +194 -0
- package/examples/pizza/pizza.js +60 -0
- package/index.d.ts +203 -0
- package/index.js +6 -0
- package/lib/characteristic.js +161 -0
- package/lib/characteristics.json +449 -0
- package/lib/descriptor.js +72 -0
- package/lib/descriptors.json +47 -0
- package/lib/distributed/bindings.js +326 -0
- package/lib/hci-socket/acl-stream.js +60 -0
- package/lib/hci-socket/bindings.js +788 -0
- package/lib/hci-socket/crypto.js +74 -0
- package/lib/hci-socket/gap.js +432 -0
- package/lib/hci-socket/gatt.js +809 -0
- package/lib/hci-socket/hci-status.json +71 -0
- package/lib/hci-socket/hci.js +1264 -0
- package/lib/hci-socket/signaling.js +76 -0
- package/lib/hci-socket/smp.js +140 -0
- package/lib/hci-uart/bindings.js +569 -0
- package/lib/hci-uart/hci-serial-parser.js +70 -0
- package/lib/hci-uart/hci.js +1336 -0
- package/lib/mac/binding.gyp +26 -0
- package/lib/mac/bindings.js +11 -0
- package/lib/mac/src/ble_manager.h +41 -0
- package/lib/mac/src/ble_manager.mm +435 -0
- package/lib/mac/src/callbacks.cc +222 -0
- package/lib/mac/src/callbacks.h +84 -0
- package/lib/mac/src/napi_objc.h +12 -0
- package/lib/mac/src/napi_objc.mm +50 -0
- package/lib/mac/src/noble_mac.h +34 -0
- package/lib/mac/src/noble_mac.mm +264 -0
- package/lib/mac/src/objc_cpp.h +26 -0
- package/lib/mac/src/objc_cpp.mm +126 -0
- package/lib/mac/src/peripheral.h +23 -0
- package/lib/manufacture.js +48 -0
- package/lib/noble.js +593 -0
- package/lib/peripheral.js +219 -0
- package/lib/resolve-bindings-web.js +9 -0
- package/lib/resolve-bindings.js +44 -0
- package/lib/service.js +72 -0
- package/lib/services.json +92 -0
- package/lib/webbluetooth/bindings.js +368 -0
- package/lib/websocket/bindings.js +321 -0
- package/lib/win/binding.gyp +23 -0
- package/lib/win/bindings.js +11 -0
- package/lib/win/src/ble_manager.cc +802 -0
- package/lib/win/src/ble_manager.h +77 -0
- package/lib/win/src/callbacks.cc +274 -0
- package/lib/win/src/callbacks.h +33 -0
- package/lib/win/src/napi_winrt.cc +76 -0
- package/lib/win/src/napi_winrt.h +12 -0
- package/lib/win/src/noble_winrt.cc +308 -0
- package/lib/win/src/noble_winrt.h +34 -0
- package/lib/win/src/notify_map.cc +62 -0
- package/lib/win/src/notify_map.h +50 -0
- package/lib/win/src/peripheral.h +23 -0
- package/lib/win/src/peripheral_winrt.cc +296 -0
- package/lib/win/src/peripheral_winrt.h +82 -0
- package/lib/win/src/radio_watcher.cc +125 -0
- package/lib/win/src/radio_watcher.h +61 -0
- package/lib/win/src/winrt_cpp.cc +82 -0
- package/lib/win/src/winrt_cpp.h +11 -0
- package/lib/win/src/winrt_guid.cc +12 -0
- package/lib/win/src/winrt_guid.h +13 -0
- package/misc/nrf52840dk.hex +6921 -0
- package/misc/prj.conf +43 -0
- package/package.json +96 -0
- package/test/lib/characteristic.test.js +791 -0
- package/test/lib/descriptor.test.js +249 -0
- package/test/lib/distributed/bindings.test.js +918 -0
- package/test/lib/hci-socket/acl-stream.test.js +188 -0
- package/test/lib/hci-socket/bindings.test.js +1756 -0
- package/test/lib/hci-socket/crypto.test.js +55 -0
- package/test/lib/hci-socket/gap.test.js +1089 -0
- package/test/lib/hci-socket/gatt.test.js +2392 -0
- package/test/lib/hci-socket/hci.test.js +1891 -0
- package/test/lib/hci-socket/signaling.test.js +94 -0
- package/test/lib/hci-socket/smp.test.js +268 -0
- package/test/lib/manufacture.test.js +77 -0
- package/test/lib/peripheral.test.js +623 -0
- package/test/lib/resolve-bindings.test.js +102 -0
- package/test/lib/service.test.js +195 -0
- package/test/lib/webbluetooth/bindings.test.js +190 -0
- package/test/lib/websocket/bindings.test.js +456 -0
- package/test/noble.test.js +1565 -0
- package/test.js +131 -0
- package/with-bindings.js +5 -0
- package/ws-slave.js +404 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
#include "peripheral_winrt.h"
|
|
2
|
+
#include "winrt_cpp.h"
|
|
3
|
+
|
|
4
|
+
#include <winrt/Windows.Storage.Streams.h>
|
|
5
|
+
using namespace winrt::Windows::Storage::Streams;
|
|
6
|
+
|
|
7
|
+
using winrt::Windows::Devices::Bluetooth::BluetoothCacheMode;
|
|
8
|
+
using winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattCharacteristicsResult;
|
|
9
|
+
using winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDescriptorsResult;
|
|
10
|
+
using winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDeviceServicesResult;
|
|
11
|
+
using winrt::Windows::Foundation::AsyncStatus;
|
|
12
|
+
using winrt::Windows::Foundation::IAsyncOperation;
|
|
13
|
+
|
|
14
|
+
PeripheralWinrt::PeripheralWinrt(uint64_t bluetoothAddress,
|
|
15
|
+
BluetoothLEAdvertisementType advertismentType, const int rssiValue,
|
|
16
|
+
const BluetoothLEAdvertisement& advertisment)
|
|
17
|
+
{
|
|
18
|
+
this->bluetoothAddress = bluetoothAddress;
|
|
19
|
+
address = formatBluetoothAddress(bluetoothAddress);
|
|
20
|
+
// Random addresses have the two most-significant bits set of the 48-bit address.
|
|
21
|
+
addressType = (bluetoothAddress >= 211106232532992) ? RANDOM : PUBLIC;
|
|
22
|
+
Update(rssiValue, advertisment, advertismentType);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
PeripheralWinrt::~PeripheralWinrt()
|
|
26
|
+
{
|
|
27
|
+
if (device.has_value() && connectionToken)
|
|
28
|
+
{
|
|
29
|
+
device->ConnectionStatusChanged(connectionToken);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
void PeripheralWinrt::Update(const int rssiValue, const BluetoothLEAdvertisement& advertisment,
|
|
34
|
+
const BluetoothLEAdvertisementType& advertismentType)
|
|
35
|
+
{
|
|
36
|
+
std::string localName = ws2s(advertisment.LocalName().c_str());
|
|
37
|
+
if (!localName.empty())
|
|
38
|
+
{
|
|
39
|
+
name = localName;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
connectable = advertismentType == BluetoothLEAdvertisementType::ConnectableUndirected ||
|
|
43
|
+
advertismentType == BluetoothLEAdvertisementType::ConnectableDirected;
|
|
44
|
+
|
|
45
|
+
manufacturerData.clear();
|
|
46
|
+
for (auto ds : advertisment.DataSections())
|
|
47
|
+
{
|
|
48
|
+
if (ds.DataType() == BluetoothLEAdvertisementDataTypes::TxPowerLevel())
|
|
49
|
+
{
|
|
50
|
+
auto d = ds.Data();
|
|
51
|
+
auto dr = DataReader::FromBuffer(d);
|
|
52
|
+
txPowerLevel = dr.ReadByte();
|
|
53
|
+
if (txPowerLevel >= 128)
|
|
54
|
+
txPowerLevel -= 256;
|
|
55
|
+
dr.Close();
|
|
56
|
+
}
|
|
57
|
+
if (ds.DataType() == BluetoothLEAdvertisementDataTypes::ManufacturerSpecificData())
|
|
58
|
+
{
|
|
59
|
+
auto d = ds.Data();
|
|
60
|
+
auto dr = DataReader::FromBuffer(d);
|
|
61
|
+
manufacturerData.resize(d.Length());
|
|
62
|
+
dr.ReadBytes(manufacturerData);
|
|
63
|
+
dr.Close();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
serviceUuids.clear();
|
|
68
|
+
for (auto uuid : advertisment.ServiceUuids())
|
|
69
|
+
{
|
|
70
|
+
serviceUuids.push_back(toStr(uuid));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
rssi = rssiValue;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
void PeripheralWinrt::Disconnect()
|
|
77
|
+
{
|
|
78
|
+
cachedServices.clear();
|
|
79
|
+
if (device.has_value() && connectionToken)
|
|
80
|
+
{
|
|
81
|
+
device->ConnectionStatusChanged(connectionToken);
|
|
82
|
+
}
|
|
83
|
+
device = std::nullopt;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
void PeripheralWinrt::GetServiceFromDevice(
|
|
87
|
+
winrt::guid serviceUuid, std::function<void(std::optional<GattDeviceService>)> callback)
|
|
88
|
+
{
|
|
89
|
+
if (device.has_value())
|
|
90
|
+
{
|
|
91
|
+
device->GetGattServicesForUuidAsync(serviceUuid, BluetoothCacheMode::Cached)
|
|
92
|
+
.Completed([=](IAsyncOperation<GattDeviceServicesResult> result, auto& status) {
|
|
93
|
+
if (status == AsyncStatus::Completed)
|
|
94
|
+
{
|
|
95
|
+
auto services = result.GetResults();
|
|
96
|
+
auto service = services.Services().First();
|
|
97
|
+
if (service.HasCurrent())
|
|
98
|
+
{
|
|
99
|
+
GattDeviceService s = service.Current();
|
|
100
|
+
cachedServices.insert(std::make_pair(serviceUuid, CachedService(s)));
|
|
101
|
+
callback(s);
|
|
102
|
+
}
|
|
103
|
+
else
|
|
104
|
+
{
|
|
105
|
+
printf("GetGattServicesForUuidAsync: no service with given id\n");
|
|
106
|
+
callback(std::nullopt);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else
|
|
110
|
+
{
|
|
111
|
+
printf("GetGattServicesForUuidAsync: failed with status: %d\n", status);
|
|
112
|
+
callback(std::nullopt);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
else
|
|
117
|
+
{
|
|
118
|
+
printf("GetGattServicesForUuidAsync: no device currently connected\n");
|
|
119
|
+
callback(std::nullopt);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
void PeripheralWinrt::GetService(winrt::guid serviceUuid,
|
|
124
|
+
std::function<void(std::optional<GattDeviceService>)> callback)
|
|
125
|
+
{
|
|
126
|
+
auto it = cachedServices.find(serviceUuid);
|
|
127
|
+
if (it != cachedServices.end())
|
|
128
|
+
{
|
|
129
|
+
callback(it->second.service);
|
|
130
|
+
}
|
|
131
|
+
else
|
|
132
|
+
{
|
|
133
|
+
GetServiceFromDevice(serviceUuid, callback);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
void PeripheralWinrt::GetCharacteristicFromService(
|
|
138
|
+
GattDeviceService service, winrt::guid characteristicUuid,
|
|
139
|
+
std::function<void(std::optional<GattCharacteristic>)> callback)
|
|
140
|
+
{
|
|
141
|
+
service.GetCharacteristicsForUuidAsync(characteristicUuid, BluetoothCacheMode::Cached)
|
|
142
|
+
.Completed([=](IAsyncOperation<GattCharacteristicsResult> result, auto& status) {
|
|
143
|
+
if (status == AsyncStatus::Completed)
|
|
144
|
+
{
|
|
145
|
+
auto characteristics = result.GetResults();
|
|
146
|
+
auto characteristic = characteristics.Characteristics().First();
|
|
147
|
+
if (characteristic.HasCurrent())
|
|
148
|
+
{
|
|
149
|
+
winrt::guid serviceUuid = service.Uuid();
|
|
150
|
+
CachedService& cachedService = cachedServices[serviceUuid];
|
|
151
|
+
GattCharacteristic c = characteristic.Current();
|
|
152
|
+
cachedService.characterisitics.insert(
|
|
153
|
+
std::make_pair(c.Uuid(), CachedCharacteristic(c)));
|
|
154
|
+
callback(c);
|
|
155
|
+
}
|
|
156
|
+
else
|
|
157
|
+
{
|
|
158
|
+
printf("GetCharacteristicsForUuidAsync: no characteristic with given id\n");
|
|
159
|
+
callback(std::nullopt);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else
|
|
163
|
+
{
|
|
164
|
+
printf("GetCharacteristicsForUuidAsync: failed with status: %d\n", status);
|
|
165
|
+
callback(std::nullopt);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
void PeripheralWinrt::GetCharacteristic(
|
|
171
|
+
winrt::guid serviceUuid, winrt::guid characteristicUuid,
|
|
172
|
+
std::function<void(std::optional<GattCharacteristic>)> callback)
|
|
173
|
+
{
|
|
174
|
+
auto it = cachedServices.find(serviceUuid);
|
|
175
|
+
if (it != cachedServices.end())
|
|
176
|
+
{
|
|
177
|
+
auto& cachedService = it->second;
|
|
178
|
+
auto cit = cachedService.characterisitics.find(characteristicUuid);
|
|
179
|
+
if (cit != cachedService.characterisitics.end())
|
|
180
|
+
{
|
|
181
|
+
callback(cit->second.characteristic);
|
|
182
|
+
}
|
|
183
|
+
else
|
|
184
|
+
{
|
|
185
|
+
GetCharacteristicFromService(cachedService.service, characteristicUuid, callback);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else
|
|
189
|
+
{
|
|
190
|
+
GetServiceFromDevice(serviceUuid, [=](std::optional<GattDeviceService> service) {
|
|
191
|
+
if (service)
|
|
192
|
+
{
|
|
193
|
+
GetCharacteristicFromService(*service, characteristicUuid, callback);
|
|
194
|
+
}
|
|
195
|
+
else
|
|
196
|
+
{
|
|
197
|
+
printf("GetCharacteristic: get service failed\n");
|
|
198
|
+
callback(nullptr);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
void PeripheralWinrt::GetDescriptorFromCharacteristic(
|
|
205
|
+
GattCharacteristic characteristic, winrt::guid descriptorUuid,
|
|
206
|
+
std::function<void(std::optional<GattDescriptor>)> callback)
|
|
207
|
+
{
|
|
208
|
+
characteristic.GetDescriptorsForUuidAsync(descriptorUuid, BluetoothCacheMode::Cached)
|
|
209
|
+
.Completed([=](IAsyncOperation<GattDescriptorsResult> result, auto& status) {
|
|
210
|
+
if (status == AsyncStatus::Completed)
|
|
211
|
+
{
|
|
212
|
+
auto descriptors = result.GetResults();
|
|
213
|
+
auto descriptor = descriptors.Descriptors().First();
|
|
214
|
+
if (descriptor.HasCurrent())
|
|
215
|
+
{
|
|
216
|
+
GattDescriptor d = descriptor.Current();
|
|
217
|
+
winrt::guid characteristicUuid = characteristic.Uuid();
|
|
218
|
+
winrt::guid descriptorUuid = d.Uuid();
|
|
219
|
+
winrt::guid serviceUuid = characteristic.Service().Uuid();
|
|
220
|
+
CachedService& cachedService = cachedServices[serviceUuid];
|
|
221
|
+
CachedCharacteristic& c = cachedService.characterisitics[characteristicUuid];
|
|
222
|
+
c.descriptors.insert(std::make_pair(descriptorUuid, d));
|
|
223
|
+
callback(d);
|
|
224
|
+
}
|
|
225
|
+
else
|
|
226
|
+
{
|
|
227
|
+
printf("GetDescriptorsForUuidAsync: no characteristic with given id\n");
|
|
228
|
+
callback(std::nullopt);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
else
|
|
232
|
+
{
|
|
233
|
+
printf("GetDescriptorsForUuidAsync: failed with status: %d\n", status);
|
|
234
|
+
callback(std::nullopt);
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
void PeripheralWinrt::GetDescriptor(winrt::guid serviceUuid, winrt::guid characteristicUuid,
|
|
240
|
+
winrt::guid descriptorUuid,
|
|
241
|
+
std::function<void(std::optional<GattDescriptor>)> callback)
|
|
242
|
+
{
|
|
243
|
+
auto it = cachedServices.find(serviceUuid);
|
|
244
|
+
if (it != cachedServices.end())
|
|
245
|
+
{
|
|
246
|
+
auto& cachedService = it->second;
|
|
247
|
+
auto cit = cachedService.characterisitics.find(characteristicUuid);
|
|
248
|
+
if (cit != cachedService.characterisitics.end())
|
|
249
|
+
{
|
|
250
|
+
GetDescriptorFromCharacteristic(cit->second.characteristic, descriptorUuid, callback);
|
|
251
|
+
}
|
|
252
|
+
else
|
|
253
|
+
{
|
|
254
|
+
GetCharacteristicFromService(
|
|
255
|
+
cachedService.service, characteristicUuid,
|
|
256
|
+
[=](std::optional<GattCharacteristic> characteristic) {
|
|
257
|
+
if (characteristic)
|
|
258
|
+
{
|
|
259
|
+
GetDescriptorFromCharacteristic(*characteristic, descriptorUuid, callback);
|
|
260
|
+
}
|
|
261
|
+
else
|
|
262
|
+
{
|
|
263
|
+
printf("GetDescriptor: get characteristic failed 1\n");
|
|
264
|
+
callback(nullptr);
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else
|
|
270
|
+
{
|
|
271
|
+
GetServiceFromDevice(serviceUuid, [=](std::optional<GattDeviceService> service) {
|
|
272
|
+
if (service)
|
|
273
|
+
{
|
|
274
|
+
GetCharacteristicFromService(
|
|
275
|
+
*service, characteristicUuid,
|
|
276
|
+
[=](std::optional<GattCharacteristic> characteristic) {
|
|
277
|
+
if (characteristic)
|
|
278
|
+
{
|
|
279
|
+
GetDescriptorFromCharacteristic(*characteristic, descriptorUuid,
|
|
280
|
+
callback);
|
|
281
|
+
}
|
|
282
|
+
else
|
|
283
|
+
{
|
|
284
|
+
printf("GetDescriptor: get characteristic failed 2\n");
|
|
285
|
+
callback(nullptr);
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
else
|
|
290
|
+
{
|
|
291
|
+
printf("GetDescriptor: get service failed\n");
|
|
292
|
+
callback(nullptr);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <napi.h>
|
|
4
|
+
#define WIN32_LEAN_AND_MEAN
|
|
5
|
+
#include <Windows.h>
|
|
6
|
+
#include <winrt/Windows.Devices.Bluetooth.Advertisement.h>
|
|
7
|
+
|
|
8
|
+
using namespace winrt::Windows::Devices::Bluetooth::Advertisement;
|
|
9
|
+
using winrt::Windows::Devices::Bluetooth::BluetoothLEDevice;
|
|
10
|
+
using winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattCharacteristic;
|
|
11
|
+
using winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDescriptor;
|
|
12
|
+
using winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDeviceService;
|
|
13
|
+
|
|
14
|
+
#include "winrt/Windows.Devices.Bluetooth.h"
|
|
15
|
+
|
|
16
|
+
#include <string>
|
|
17
|
+
#include <optional>
|
|
18
|
+
|
|
19
|
+
#include "peripheral.h"
|
|
20
|
+
#include "winrt_guid.h"
|
|
21
|
+
|
|
22
|
+
class CachedCharacteristic
|
|
23
|
+
{
|
|
24
|
+
public:
|
|
25
|
+
CachedCharacteristic() = default;
|
|
26
|
+
CachedCharacteristic(GattCharacteristic& c) : characteristic(c)
|
|
27
|
+
{
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
GattCharacteristic characteristic = nullptr;
|
|
31
|
+
std::unordered_map<winrt::guid, GattDescriptor> descriptors;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
class CachedService
|
|
35
|
+
{
|
|
36
|
+
public:
|
|
37
|
+
CachedService() = default;
|
|
38
|
+
CachedService(GattDeviceService& s) : service(s)
|
|
39
|
+
{
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
GattDeviceService service = nullptr;
|
|
43
|
+
std::unordered_map<winrt::guid, CachedCharacteristic> characterisitics;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
class PeripheralWinrt : public Peripheral
|
|
47
|
+
{
|
|
48
|
+
public:
|
|
49
|
+
PeripheralWinrt() = default;
|
|
50
|
+
PeripheralWinrt(uint64_t bluetoothAddress, BluetoothLEAdvertisementType advertismentType,
|
|
51
|
+
int rssiValue, const BluetoothLEAdvertisement& advertisment);
|
|
52
|
+
~PeripheralWinrt();
|
|
53
|
+
|
|
54
|
+
void Update(int rssiValue, const BluetoothLEAdvertisement& advertisment,
|
|
55
|
+
const BluetoothLEAdvertisementType& advertismentType);
|
|
56
|
+
|
|
57
|
+
void Disconnect();
|
|
58
|
+
|
|
59
|
+
void GetService(winrt::guid serviceUuid,
|
|
60
|
+
std::function<void(std::optional<GattDeviceService>)> callback);
|
|
61
|
+
void GetCharacteristic(winrt::guid serviceUuid, winrt::guid characteristicUuid,
|
|
62
|
+
std::function<void(std::optional<GattCharacteristic>)> callback);
|
|
63
|
+
void GetDescriptor(winrt::guid serviceUuid, winrt::guid characteristicUuid,
|
|
64
|
+
winrt::guid descriptorUuid,
|
|
65
|
+
std::function<void(std::optional<GattDescriptor>)> callback);
|
|
66
|
+
|
|
67
|
+
int rssi;
|
|
68
|
+
uint64_t bluetoothAddress;
|
|
69
|
+
std::optional<BluetoothLEDevice> device;
|
|
70
|
+
winrt::event_token connectionToken;
|
|
71
|
+
|
|
72
|
+
private:
|
|
73
|
+
void GetServiceFromDevice(winrt::guid serviceUuid,
|
|
74
|
+
std::function<void(std::optional<GattDeviceService>)> callback);
|
|
75
|
+
void
|
|
76
|
+
GetCharacteristicFromService(GattDeviceService service, winrt::guid characteristicUuid,
|
|
77
|
+
std::function<void(std::optional<GattCharacteristic>)> callback);
|
|
78
|
+
void
|
|
79
|
+
GetDescriptorFromCharacteristic(GattCharacteristic characteristic, winrt::guid descriptorUuid,
|
|
80
|
+
std::function<void(std::optional<GattDescriptor>)> callback);
|
|
81
|
+
std::unordered_map<winrt::guid, CachedService> cachedServices;
|
|
82
|
+
};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
//
|
|
2
|
+
// radio_watcher.cc
|
|
3
|
+
// noble-winrt-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Georg Vienna on 07.09.18.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include "radio_watcher.h"
|
|
11
|
+
#include "winrt_cpp.h"
|
|
12
|
+
|
|
13
|
+
using winrt::Windows::Devices::Radios::RadioKind;
|
|
14
|
+
using winrt::Windows::Foundation::AsyncStatus;
|
|
15
|
+
|
|
16
|
+
template <typename O, typename M, class... Types> auto bind2(O* object, M method, Types&... args)
|
|
17
|
+
{
|
|
18
|
+
return std::bind(method, object, std::placeholders::_1, std::placeholders::_2, args...);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#define RADIO_INTERFACE_CLASS_GUID \
|
|
22
|
+
L"System.Devices.InterfaceClassGuid:=\"{A8804298-2D5F-42E3-9531-9C8C39EB29CE}\""
|
|
23
|
+
|
|
24
|
+
RadioWatcher::RadioWatcher()
|
|
25
|
+
: mRadio(nullptr), watcher(DeviceInformation::CreateWatcher(RADIO_INTERFACE_CLASS_GUID))
|
|
26
|
+
{
|
|
27
|
+
mAddedRevoker = watcher.Added(winrt::auto_revoke, bind2(this, &RadioWatcher::OnAdded));
|
|
28
|
+
mUpdatedRevoker = watcher.Updated(winrt::auto_revoke, bind2(this, &RadioWatcher::OnUpdated));
|
|
29
|
+
mRemovedRevoker = watcher.Removed(winrt::auto_revoke, bind2(this, &RadioWatcher::OnRemoved));
|
|
30
|
+
auto completed = bind2(this, &RadioWatcher::OnCompleted);
|
|
31
|
+
mCompletedRevoker = watcher.EnumerationCompleted(winrt::auto_revoke, completed);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
void RadioWatcher::Start(std::function<void(Radio& radio)> on)
|
|
35
|
+
{
|
|
36
|
+
radioStateChanged = on;
|
|
37
|
+
inEnumeration = true;
|
|
38
|
+
initialDone = false;
|
|
39
|
+
initialCount = 0;
|
|
40
|
+
watcher.Start();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
IAsyncOperation<Radio> RadioWatcher::GetRadios(std::set<winrt::hstring> ids)
|
|
44
|
+
{
|
|
45
|
+
Radio bluetooth = nullptr;
|
|
46
|
+
for (auto id : ids)
|
|
47
|
+
{
|
|
48
|
+
try
|
|
49
|
+
{
|
|
50
|
+
auto radio = co_await Radio::FromIdAsync(id);
|
|
51
|
+
if (radio && radio.Kind() == RadioKind::Bluetooth)
|
|
52
|
+
{
|
|
53
|
+
auto state = radio.State();
|
|
54
|
+
// we only get state changes for turned on/off adapter but not for disabled adapter
|
|
55
|
+
if (state == RadioState::On || state == RadioState::Off)
|
|
56
|
+
{
|
|
57
|
+
bluetooth = radio;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (...)
|
|
62
|
+
{
|
|
63
|
+
// Radio::RadioFromAsync throws if the device is not available (unplugged)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
co_return bluetooth;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
void RadioWatcher::OnRadioChanged()
|
|
70
|
+
{
|
|
71
|
+
GetRadios(radioIds).Completed([=](auto&& asyncOp, auto&& status) {
|
|
72
|
+
if (status == AsyncStatus::Completed)
|
|
73
|
+
{
|
|
74
|
+
Radio radio = asyncOp.GetResults();
|
|
75
|
+
// !radio: to handle if there is no radio
|
|
76
|
+
if (!radio || radio != mRadio)
|
|
77
|
+
{
|
|
78
|
+
if (radio)
|
|
79
|
+
{
|
|
80
|
+
mRadioStateChangedRevoker.revoke();
|
|
81
|
+
mRadioStateChangedRevoker = radio.StateChanged(
|
|
82
|
+
winrt::auto_revoke, [=](Radio radio, auto&&) { radioStateChanged(radio); });
|
|
83
|
+
}
|
|
84
|
+
else
|
|
85
|
+
{
|
|
86
|
+
mRadioStateChangedRevoker.revoke();
|
|
87
|
+
}
|
|
88
|
+
radioStateChanged(radio);
|
|
89
|
+
mRadio = radio;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else
|
|
93
|
+
{
|
|
94
|
+
mRadio = nullptr;
|
|
95
|
+
mRadioStateChangedRevoker.revoke();
|
|
96
|
+
radioStateChanged(mRadio);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
void RadioWatcher::OnAdded(DeviceWatcher watcher, DeviceInformation info)
|
|
102
|
+
{
|
|
103
|
+
radioIds.insert(info.Id());
|
|
104
|
+
if (!inEnumeration)
|
|
105
|
+
{
|
|
106
|
+
OnRadioChanged();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
void RadioWatcher::OnUpdated(DeviceWatcher watcher, DeviceInformationUpdate info)
|
|
111
|
+
{
|
|
112
|
+
OnRadioChanged();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
void RadioWatcher::OnRemoved(DeviceWatcher watcher, DeviceInformationUpdate info)
|
|
116
|
+
{
|
|
117
|
+
radioIds.erase(info.Id());
|
|
118
|
+
OnRadioChanged();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
void RadioWatcher::OnCompleted(DeviceWatcher watcher, IInspectable info)
|
|
122
|
+
{
|
|
123
|
+
inEnumeration = false;
|
|
124
|
+
OnRadioChanged();
|
|
125
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
//
|
|
2
|
+
// radio_watcher.h
|
|
3
|
+
// noble-winrt-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Georg Vienna on 07.09.18.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include <functional>
|
|
11
|
+
#include <set>
|
|
12
|
+
#include <winrt/Windows.Devices.Enumeration.h>
|
|
13
|
+
#include <winrt/Windows.Devices.Radios.h>
|
|
14
|
+
|
|
15
|
+
using namespace winrt::Windows::Devices::Enumeration;
|
|
16
|
+
|
|
17
|
+
using winrt::Windows::Devices::Radios::IRadio;
|
|
18
|
+
using winrt::Windows::Devices::Radios::Radio;
|
|
19
|
+
using winrt::Windows::Devices::Radios::RadioState;
|
|
20
|
+
using winrt::Windows::Foundation::IAsyncOperation;
|
|
21
|
+
using winrt::Windows::Foundation::IInspectable;
|
|
22
|
+
|
|
23
|
+
enum class AdapterState : int32_t
|
|
24
|
+
{
|
|
25
|
+
Initial = -2,
|
|
26
|
+
Unsupported = -1,
|
|
27
|
+
Unknown = (int32_t)RadioState::Unknown,
|
|
28
|
+
On = (int32_t)RadioState::On,
|
|
29
|
+
Off = (int32_t)RadioState::Off,
|
|
30
|
+
Disabled = (int32_t)RadioState::Disabled,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
class RadioWatcher
|
|
34
|
+
{
|
|
35
|
+
public:
|
|
36
|
+
RadioWatcher();
|
|
37
|
+
|
|
38
|
+
void Start(std::function<void(Radio& radio)> on);
|
|
39
|
+
|
|
40
|
+
private:
|
|
41
|
+
IAsyncOperation<Radio> GetRadios(std::set<winrt::hstring> ids);
|
|
42
|
+
|
|
43
|
+
void OnRadioChanged();
|
|
44
|
+
void OnAdded(DeviceWatcher watcher, DeviceInformation info);
|
|
45
|
+
void OnUpdated(DeviceWatcher watcher, DeviceInformationUpdate info);
|
|
46
|
+
void OnRemoved(DeviceWatcher watcher, DeviceInformationUpdate info);
|
|
47
|
+
void OnCompleted(DeviceWatcher watcher, IInspectable info);
|
|
48
|
+
|
|
49
|
+
DeviceWatcher watcher;
|
|
50
|
+
winrt::event_revoker<IDeviceWatcher> mAddedRevoker;
|
|
51
|
+
winrt::event_revoker<IDeviceWatcher> mUpdatedRevoker;
|
|
52
|
+
winrt::event_revoker<IDeviceWatcher> mRemovedRevoker;
|
|
53
|
+
winrt::event_revoker<IDeviceWatcher> mCompletedRevoker;
|
|
54
|
+
bool inEnumeration;
|
|
55
|
+
bool initialDone;
|
|
56
|
+
int initialCount;
|
|
57
|
+
std::set<winrt::hstring> radioIds;
|
|
58
|
+
Radio mRadio;
|
|
59
|
+
winrt::event_revoker<IRadio> mRadioStateChangedRevoker;
|
|
60
|
+
std::function<void(Radio& radio)> radioStateChanged;
|
|
61
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#include "winrt_cpp.h"
|
|
2
|
+
|
|
3
|
+
#include <sstream>
|
|
4
|
+
#include <iomanip>
|
|
5
|
+
|
|
6
|
+
#include <winrt\Windows.Devices.Bluetooth.h>
|
|
7
|
+
|
|
8
|
+
std::string ws2s(const wchar_t* wstr)
|
|
9
|
+
{
|
|
10
|
+
return winrt::to_string(wstr);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
std::string formatBluetoothAddress(unsigned long long BluetoothAddress)
|
|
14
|
+
{
|
|
15
|
+
std::ostringstream ret;
|
|
16
|
+
ret << std::hex << std::setfill('0') << std::setw(2) << ((BluetoothAddress >> (5 * 8)) & 0xff)
|
|
17
|
+
<< ":" << std::setw(2) << ((BluetoothAddress >> (4 * 8)) & 0xff) << ":" << std::setw(2)
|
|
18
|
+
<< ((BluetoothAddress >> (3 * 8)) & 0xff) << ":" << std::setw(2)
|
|
19
|
+
<< ((BluetoothAddress >> (2 * 8)) & 0xff) << ":" << std::setw(2)
|
|
20
|
+
<< ((BluetoothAddress >> (1 * 8)) & 0xff) << ":" << std::setw(2)
|
|
21
|
+
<< ((BluetoothAddress >> (0 * 8)) & 0xff);
|
|
22
|
+
return ret.str();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
std::string formatBluetoothUuid(unsigned long long BluetoothAddress)
|
|
26
|
+
{
|
|
27
|
+
std::ostringstream ret;
|
|
28
|
+
ret << std::hex << std::setfill('0') << std::setw(2) << ((BluetoothAddress >> (5 * 8)) & 0xff)
|
|
29
|
+
<< std::setw(2) << ((BluetoothAddress >> (4 * 8)) & 0xff) << std::setw(2)
|
|
30
|
+
<< ((BluetoothAddress >> (3 * 8)) & 0xff) << std::setw(2)
|
|
31
|
+
<< ((BluetoothAddress >> (2 * 8)) & 0xff) << std::setw(2)
|
|
32
|
+
<< ((BluetoothAddress >> (1 * 8)) & 0xff) << std::setw(2)
|
|
33
|
+
<< ((BluetoothAddress >> (0 * 8)) & 0xff);
|
|
34
|
+
return ret.str();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
std::string toStr(winrt::guid uuid)
|
|
38
|
+
{
|
|
39
|
+
try
|
|
40
|
+
{
|
|
41
|
+
auto ref = winrt::Windows::Devices::Bluetooth::BluetoothUuidHelper::TryGetShortId(uuid);
|
|
42
|
+
if (ref)
|
|
43
|
+
{
|
|
44
|
+
auto i = ref.Value();
|
|
45
|
+
std::ostringstream ret;
|
|
46
|
+
ret << std::hex << i;
|
|
47
|
+
return ret.str();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (...)
|
|
51
|
+
{
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// taken from winrt/base.h
|
|
55
|
+
char buffer[38];
|
|
56
|
+
// 00000000-0000-0000-0000-000000000000
|
|
57
|
+
sprintf_s(buffer, "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
|
|
58
|
+
uuid.Data1, uuid.Data2, uuid.Data3, uuid.Data4[0], uuid.Data4[1], uuid.Data4[2],
|
|
59
|
+
uuid.Data4[3], uuid.Data4[4], uuid.Data4[5], uuid.Data4[6], uuid.Data4[7]);
|
|
60
|
+
return std::string(buffer);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#define SET_VAL(prop, val, str) \
|
|
64
|
+
if ((prop & val) == val) \
|
|
65
|
+
{ \
|
|
66
|
+
arr.push_back(str); \
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
std::vector<std::string> toPropertyArray(GattCharacteristicProperties& properties)
|
|
70
|
+
{
|
|
71
|
+
std::vector<std::string> arr;
|
|
72
|
+
SET_VAL(properties, GattCharacteristicProperties::Broadcast, "broadcast")
|
|
73
|
+
SET_VAL(properties, GattCharacteristicProperties::Read, "read")
|
|
74
|
+
SET_VAL(properties, GattCharacteristicProperties::WriteWithoutResponse, "writeWithoutResponse")
|
|
75
|
+
SET_VAL(properties, GattCharacteristicProperties::Write, "write")
|
|
76
|
+
SET_VAL(properties, GattCharacteristicProperties::Notify, "notify")
|
|
77
|
+
SET_VAL(properties, GattCharacteristicProperties::Indicate, "indicate")
|
|
78
|
+
SET_VAL(properties, GattCharacteristicProperties::AuthenticatedSignedWrites,
|
|
79
|
+
"authenticatedSignedWrites")
|
|
80
|
+
SET_VAL(properties, GattCharacteristicProperties::ExtendedProperties, "extendedProperties")
|
|
81
|
+
return arr;
|
|
82
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
|
|
4
|
+
|
|
5
|
+
using winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattCharacteristicProperties;
|
|
6
|
+
|
|
7
|
+
std::string ws2s(const wchar_t* wstr);
|
|
8
|
+
std::string formatBluetoothAddress(unsigned long long BluetoothAddress);
|
|
9
|
+
std::string formatBluetoothUuid(unsigned long long BluetoothAddress);
|
|
10
|
+
std::string toStr(winrt::guid uuid);
|
|
11
|
+
std::vector<std::string> toPropertyArray(GattCharacteristicProperties& properties);
|