22 using BluetoothLEAdvertisementWatcher = winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementWatcher;
23 using BluetoothLEAdvertisementReceivedEventArgs = winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementReceivedEventArgs;
24 using BluetoothLEAdvertisementWatcherStoppedEventArgs = winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementWatcherStoppedEventArgs;
27 BluetoothLEAdvertisementWatcher _watcher{
nullptr };
28 winrt::event_token _receivedToken{};
29 winrt::event_token _stoppedToken{};
32 std::vector<winrt::guid> _requestedServices{};
35 std::mutex _peripheralsMtx{};
36 std::map<bluetooth_address_t, std::shared_ptr<const ScannedPeripheral>> _peripherals{};
39 std::function<void(std::shared_ptr<const ScannedPeripheral>)> _onPeripheralDiscovered{};
53 std::function<
void(std::shared_ptr<const ScannedPeripheral>)> peripheralDiscovered,
54 std::vector<winrt::guid> services = std::vector<winrt::guid>{})
57 _requestedServices{ services },
58 _onPeripheralDiscovered{ peripheralDiscovered }
60 using namespace winrt::Windows::Devices::Bluetooth::Advertisement;
63 _watcher.AllowExtendedAdvertisements(
true);
66 _watcher.ScanningMode(BluetoothLEScanningMode::Active);
69 _receivedToken = _watcher.Received({
this, &Scanner::onReceived });
70 _stoppedToken = _watcher.Stopped({
this, &Scanner::onStopped });
85 std::lock_guard lock{ _peripheralsMtx };
86 outDiscoveredPeripherals.reserve(outDiscoveredPeripherals.size() + _peripherals.size());
87 for (
auto& [_, p] : _peripherals)
89 outDiscoveredPeripherals.emplace_back(p);
100 _watcher.Received(_receivedToken);
101 _watcher.Stopped(_stoppedToken);
110 BluetoothLEAdvertisementWatcher
const& ,
111 BluetoothLEAdvertisementReceivedEventArgs
const& args)
113 using namespace winrt::Windows::Devices::Bluetooth::Advertisement;
116 std::vector<winrt::guid> services{};
117 std::vector<ManufacturerData> manufacturersData{};
118 std::vector<ServiceData> servicesData{};
119 std::vector<AdvertisementData> advertisingData{};
121 auto advertisement = args.Advertisement();
125 name = advertisement.LocalName();
128 auto serv = advertisement.ServiceUuids();
131 services.reserve(serv.Size());
132 for (
const auto& uuid : serv)
134 services.push_back(uuid);
139 auto manufDataList = advertisement.ManufacturerData();
142 manufacturersData.reserve(manufDataList.Size());
143 for (
const auto& manuf : manufDataList)
145 manufacturersData.emplace_back(ManufacturerData{ manuf.CompanyId(), manuf.Data() });
150 auto advDataList = advertisement.DataSections();
153 advertisingData.reserve(advDataList.Size());
154 for (
const auto& adv : advDataList)
156 advertisingData.emplace_back(AdvertisementData{ adv.DataType(), adv.Data() });
159 if (adv.DataType() == 0x16)
161 servicesData.emplace_back(ServiceData{ adv.Data() });
169 if (args.TransmitPowerLevelInDBm())
171 txPower = args.TransmitPowerLevelInDBm().Value();
174 switch (args.AdvertisementType())
176 case BluetoothLEAdvertisementType::ConnectableUndirected:
177 case BluetoothLEAdvertisementType::ConnectableDirected:
178 case BluetoothLEAdvertisementType::ScannableUndirected:
179 case BluetoothLEAdvertisementType::NonConnectableUndirected:
182 std::shared_ptr<const ScannedPeripheral> peripheral{
183 new ScannedPeripheral(
185 args.BluetoothAddress(),
187 args.IsConnectable(),
188 args.RawSignalStrengthInDBm(),
196 std::lock_guard lock{ _peripheralsMtx };
197 _peripherals[peripheral->address()] = peripheral;
203 case BluetoothLEAdvertisementType::ScanResponse:
205 std::shared_ptr<const ScannedPeripheral> updatedPeripheral{};
207 std::lock_guard lock{ _peripheralsMtx };
208 auto it = _peripherals.find(args.BluetoothAddress());
209 if (it != _peripherals.end())
213 updatedPeripheral.reset(
214 new ScannedPeripheral(
218 args.RawSignalStrengthInDBm(),
225 _peripherals[updatedPeripheral->address()] = updatedPeripheral;
228 if (updatedPeripheral)
230 notify(updatedPeripheral);
238 void notify(
const std::shared_ptr<const ScannedPeripheral>& peripheral)
240 if (_onPeripheralDiscovered &&
241 (_requestedServices.empty() || Internal::isSubset(_requestedServices, peripheral->services())))
243 _onPeripheralDiscovered(peripheral);
249 BluetoothLEAdvertisementWatcher
const& ,
250 BluetoothLEAdvertisementWatcherStoppedEventArgs
const& )
Common types used across the Systemic::BluetoothLE namespace.
Definition of the ManufacturerData, AdvertisementData and DiscoveredPeripheral classes.
Implements scanning of Bluetooth Low Energy (BLE) peripherals. It stores and notifies of discovered p...
Definition: Scanner.h:21
~Scanner()
Stops the scan and destroys the Scanner instance.
Definition: Scanner.h:96
Scanner(std::function< void(std::shared_ptr< const ScannedPeripheral >)> peripheralDiscovered, std::vector< winrt::guid > services=std::vector< winrt::guid >{})
Initializes a new instance of Scanner and immediately starts scanning for BLE peripherals.
Definition: Scanner.h:52
void copyDiscoveredPeripherals(std::vector< std::shared_ptr< const ScannedPeripheral > > &outDiscoveredPeripherals)
Copy the discovered peripherals to the given std::vector.
Definition: Scanner.h:83
A collection of C++ classes that provides a simplified access to Bluetooth Low Energy peripherals.
Definition: BleTypes.h:38