Fix error on Windows scan (#146)
* Error on windows scan * Implement thread safe cache handling * Fix start scan method * Update windows/src/universal_ble_thread_safe.h Co-authored-by: Foti Dim <foti@navideck.com> --------- Co-authored-by: Rohit Sangwan <rohitsangwan647@gmail.com>
This commit is contained in:
@@ -44,6 +44,7 @@ list(APPEND PLUGIN_SOURCES
|
||||
"src/pin_entry.h"
|
||||
"src/universal_ble_filter_util.cpp"
|
||||
"src/universal_ble_filter_util.h"
|
||||
"src/universal_ble_thread_safe.h"
|
||||
)
|
||||
|
||||
add_library(${PLUGIN_NAME} SHARED
|
||||
|
||||
@@ -667,10 +667,10 @@ namespace universal_ble
|
||||
// if device is already discovered in deviceWatcher then merge the scan result
|
||||
void UniversalBlePlugin::pushUniversalScanResult(UniversalBleScanResult scanResult, bool isConnectable)
|
||||
{
|
||||
auto it = scanResults.find(scanResult.device_id());
|
||||
if (it != scanResults.end())
|
||||
std::optional<UniversalBleScanResult> it = scanResults.get(scanResult.device_id());
|
||||
if (it.has_value())
|
||||
{
|
||||
UniversalBleScanResult ¤tScanResult = it->second;
|
||||
UniversalBleScanResult ¤tScanResult = it.value();
|
||||
bool shouldUpdate = false;
|
||||
|
||||
// Check if current scanResult name is longer than the received scanResult name
|
||||
@@ -708,16 +708,13 @@ namespace universal_ble
|
||||
|
||||
// if nothing to update then return
|
||||
if (!shouldUpdate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// update the current scan result
|
||||
currentScanResult = scanResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if not present, insert the new scan result
|
||||
scanResults.insert(std::make_pair(scanResult.device_id(), scanResult));
|
||||
}
|
||||
// Update cache
|
||||
scanResults.insert_or_assign(scanResult.device_id(), scanResult);
|
||||
|
||||
// Filter final result before sending to Flutter
|
||||
if (isConnectable && filterDevice(scanResult))
|
||||
@@ -757,11 +754,13 @@ namespace universal_ble
|
||||
deviceWatcherUpdatedToken = deviceWatcher.Updated([this](DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate)
|
||||
{
|
||||
std::string deviceId = winrt::to_string(deviceInfoUpdate.Id());
|
||||
auto it = deviceWatcherDevices.find(deviceId);
|
||||
if (it != deviceWatcherDevices.end())
|
||||
auto it = deviceWatcherDevices.get(deviceId);
|
||||
if (it.has_value())
|
||||
{
|
||||
it->second.Update(deviceInfoUpdate);
|
||||
onDeviceInfoReceived(it->second);
|
||||
auto value = it.value();
|
||||
value.Update(deviceInfoUpdate);
|
||||
deviceWatcherDevices.insert_or_assign(deviceId, value);
|
||||
onDeviceInfoReceived(value);
|
||||
}
|
||||
// On Device Updated
|
||||
});
|
||||
@@ -769,7 +768,7 @@ namespace universal_ble
|
||||
deviceWatcherRemovedToken = deviceWatcher.Removed([this](DeviceWatcher sender, DeviceInformationUpdate args)
|
||||
{
|
||||
std::string deviceId = winrt::to_string(args.Id());
|
||||
deviceWatcherDevices.erase(deviceId);
|
||||
deviceWatcherDevices.remove(deviceId);
|
||||
// On Device Removed
|
||||
});
|
||||
|
||||
@@ -820,7 +819,7 @@ namespace universal_ble
|
||||
std::string deviceAddress = winrt::to_string(bluetoothAddressPropertyValue.GetString());
|
||||
|
||||
// Update device info if already discovered in advertisementWatcher
|
||||
if (scanResults.count(deviceAddress) > 0)
|
||||
if (scanResults.get(deviceAddress).has_value())
|
||||
{
|
||||
bool isPaired = deviceInfo.Pairing().IsPaired();
|
||||
if (properties.HasKey(isPairedKey))
|
||||
@@ -900,10 +899,10 @@ namespace universal_ble
|
||||
universalScanResult.set_services(services);
|
||||
|
||||
// check if this device already discovered in deviceWatcher
|
||||
auto it = deviceWatcherDevices.find(deviceId);
|
||||
if (it != deviceWatcherDevices.end())
|
||||
auto it = deviceWatcherDevices.get(deviceId);
|
||||
if (it.has_value())
|
||||
{
|
||||
auto &deviceInfo = it->second;
|
||||
auto &deviceInfo = it.value();
|
||||
auto properties = deviceInfo.Properties();
|
||||
|
||||
// Update Paired Status
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "helper/universal_ble_base.h"
|
||||
#include "generated/universal_ble.g.h"
|
||||
#include "ui_thread_handler.hpp"
|
||||
#include "universal_ble_thread_safe.h"
|
||||
|
||||
namespace universal_ble
|
||||
{
|
||||
@@ -92,8 +93,10 @@ namespace universal_ble
|
||||
RadioState oldRadioState = RadioState::Unknown;
|
||||
BluetoothLEAdvertisementWatcher bluetoothLEWatcher{nullptr};
|
||||
DeviceWatcher deviceWatcher{nullptr};
|
||||
|
||||
std::unordered_map<uint64_t, std::unique_ptr<BluetoothDeviceAgent>> connectedDevices{};
|
||||
std::unordered_map<std::string, DeviceInformation> deviceWatcherDevices{};
|
||||
ThreadSafeMap<std::string, DeviceInformation> deviceWatcherDevices{};
|
||||
ThreadSafeMap<std::string, UniversalBleScanResult> scanResults{};
|
||||
|
||||
winrt::event_token bluetoothLEWatcherReceivedToken;
|
||||
winrt::event_token deviceWatcherAddedToken;
|
||||
@@ -112,7 +115,6 @@ namespace universal_ble
|
||||
void onDeviceInfoReceived(DeviceInformation deviceInfo);
|
||||
|
||||
std::string GattCommunicationStatusToString(GattCommunicationStatus status);
|
||||
std::unordered_map<std::string, UniversalBleScanResult> scanResults{};
|
||||
winrt::event_revoker<IRadio> radioStateChangedRevoker;
|
||||
winrt::fire_and_forget ConnectAsync(uint64_t bluetoothAddress);
|
||||
void BluetoothLEDevice_ConnectionStatusChanged(BluetoothLEDevice sender, IInspectable args);
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <thread>
|
||||
|
||||
namespace universal_ble
|
||||
{
|
||||
// Thread Safe Map wrapper
|
||||
// Use only if you don't care about value ownership and it's OK to work with copies of the data.
|
||||
template <typename Key, typename Value>
|
||||
class ThreadSafeMap
|
||||
{
|
||||
private:
|
||||
std::unordered_map<Key, Value> data;
|
||||
mutable std::shared_mutex mutex;
|
||||
|
||||
public:
|
||||
void insert_or_assign(const Key &key, const Value &value)
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
data.insert_or_assign(key, value);
|
||||
}
|
||||
|
||||
bool remove(const Key &key)
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
return data.erase(key) > 0;
|
||||
}
|
||||
|
||||
std::optional<Value> get(const Key &key) const
|
||||
{
|
||||
std::shared_lock lock(mutex);
|
||||
auto it = data.find(key);
|
||||
return (it != data.end()) ? std::optional<Value>(it->second) : std::nullopt;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
data.clear();
|
||||
}
|
||||
|
||||
std::map<Key, Value> get_snapshot() const
|
||||
{
|
||||
std::shared_lock lock(mutex);
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace universal_ble
|
||||
Reference in New Issue
Block a user