24 using BluetoothLEAdvertisementWatcher = winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementWatcher;
25 using BluetoothLEAdvertisementReceivedEventArgs = winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementReceivedEventArgs;
26 using BluetoothLEAdvertisementWatcherStoppedEventArgs = winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementWatcherStoppedEventArgs;
29 BluetoothLEAdvertisementWatcher _watcher{};
30 winrt::event_token _receivedToken{};
31 winrt::event_token _stoppedToken{};
34 std::vector<winrt::guid> _requestedServices{};
37 std::mutex _peripheralsMtx{};
38 std::map<bluetooth_address_t, std::shared_ptr<ScannedPeripheral>> _peripherals{};
41 std::function<void(std::shared_ptr<ScannedPeripheral>)> _onPeripheralDiscovered{};
56 std::function<
void(std::shared_ptr<ScannedPeripheral>)> peripheralDiscovered,
57 std::vector<winrt::guid> services = std::vector<winrt::guid>{})
59 _requestedServices{ services },
60 _onPeripheralDiscovered{ peripheralDiscovered }
62 using namespace winrt::Windows::Devices::Bluetooth::Advertisement;
65 _watcher.AllowExtendedAdvertisements(
true);
68 _watcher.ScanningMode(BluetoothLEScanningMode::Active);
71 _receivedToken = _watcher.Received({
this, &Scanner::onReceived });
72 _stoppedToken = _watcher.Stopped({
this, &Scanner::onStopped });
87 std::lock_guard lock{ _peripheralsMtx };
88 outDiscoveredPeripherals.reserve(outDiscoveredPeripherals.size() + _peripherals.size());
89 for (
auto& [_, p] : _peripherals)
91 outDiscoveredPeripherals.emplace_back(p);
102 _watcher.Received(_receivedToken);
103 _watcher.Stopped(_stoppedToken);
112 BluetoothLEAdvertisementWatcher
const& _watcher,
113 BluetoothLEAdvertisementReceivedEventArgs
const& args)
115 using namespace winrt::Windows::Devices::Bluetooth::Advertisement;
118 std::vector<winrt::guid> services{};
119 std::vector<ManufacturerData> manufacturersData{};
120 std::vector<ServiceData> servicesData{};
121 std::vector<AdvertisementData> advertisingData{};
123 auto advertisement = args.Advertisement();
127 name = advertisement.LocalName();
130 auto serv = advertisement.ServiceUuids();
133 services.reserve(serv.Size());
134 for (
const auto& uuid : serv)
136 services.push_back(uuid);
141 auto manufDataList = advertisement.ManufacturerData();
144 manufacturersData.reserve(manufDataList.Size());
145 for (
const auto& manuf : manufDataList)
147 auto size = manuf.Data().Length();
148 manufacturersData.emplace_back(ManufacturerData{ manuf.CompanyId(), manuf.Data() });
153 auto advDataList = advertisement.DataSections();
156 advertisingData.reserve(advDataList.Size());
157 for (
const auto& adv : advDataList)
159 auto size = adv.Data().Length();
160 advertisingData.emplace_back(AdvertisementData{ adv.DataType(), adv.Data() });
163 if (adv.DataType() == 0x16)
165 servicesData.emplace_back(ServiceData{ adv.Data() });
173 if (args.TransmitPowerLevelInDBm())
175 txPower = args.TransmitPowerLevelInDBm().Value();
178 switch (args.AdvertisementType())
180 case BluetoothLEAdvertisementType::ConnectableUndirected:
181 case BluetoothLEAdvertisementType::ConnectableDirected:
182 case BluetoothLEAdvertisementType::ScannableUndirected:
183 case BluetoothLEAdvertisementType::NonConnectableUndirected:
186 std::shared_ptr<ScannedPeripheral> peripheral{
187 new ScannedPeripheral(
189 args.BluetoothAddress(),
191 args.IsConnectable(),
192 args.RawSignalStrengthInDBm(),
200 std::lock_guard lock{ _peripheralsMtx };
201 _peripherals[peripheral->address()] = peripheral;
207 case BluetoothLEAdvertisementType::ScanResponse:
209 std::shared_ptr<ScannedPeripheral> updatedPeripheral{};
211 std::lock_guard lock{ _peripheralsMtx };
212 auto it = _peripherals.find(args.BluetoothAddress());
213 if (it != _peripherals.end())
217 updatedPeripheral.reset(
218 new ScannedPeripheral(
222 args.RawSignalStrengthInDBm(),
229 _peripherals[updatedPeripheral->address()] = updatedPeripheral;
232 if (updatedPeripheral)
234 notify(updatedPeripheral);
242 void notify(
const std::shared_ptr<ScannedPeripheral>& peripheral)
244 if (_onPeripheralDiscovered &&
245 (_requestedServices.empty() || Internal::isOverlapping(_requestedServices, peripheral->services())))
247 _onPeripheralDiscovered(peripheral);
253 BluetoothLEAdvertisementWatcher
const& _watcher,
254 BluetoothLEAdvertisementWatcherStoppedEventArgs
const& args)