Skip to content

Commit

Permalink
[darwin] Update BLEScannerDelegate interface to have both a add and a…
Browse files Browse the repository at this point in the history
… remove method (#26001)
  • Loading branch information
vivien-apple authored Apr 18, 2023
1 parent 8809801 commit 19909ce
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 22 deletions.
4 changes: 3 additions & 1 deletion examples/chip-tool/commands/common/DeviceScanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void DeviceScanner::OnNodeDiscovered(const DiscoveredNodeData & nodeData)
}

#if CHIP_TOOL_DEVICE_SCANNER_USE_BLE
void DeviceScanner::OnBleScanResult(BLE_CONNECTION_OBJECT connObj, const ChipBLEDeviceIdentificationInfo & info)
void DeviceScanner::OnBleScanAdd(BLE_CONNECTION_OBJECT connObj, const ChipBLEDeviceIdentificationInfo & info)
{
auto discriminator = info.GetDeviceDiscriminator();
auto vendorId = static_cast<VendorId>(info.GetVendorId());
Expand All @@ -85,6 +85,8 @@ void DeviceScanner::OnBleScanResult(BLE_CONNECTION_OBJECT connObj, const ChipBLE
DeviceScannerResult result = { params, vendorId, productId, discriminator };
mDiscoveredResults.push_back(result);
}

void DeviceScanner::OnBleScanRemove(BLE_CONNECTION_OBJECT connObj) {}
#endif // CHIP_TOOL_DEVICE_SCANNER_USE_BLE

CHIP_ERROR DeviceScanner::Get(uint16_t index, RendezvousParameters & params)
Expand Down
3 changes: 2 additions & 1 deletion examples/chip-tool/commands/common/DeviceScanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ class DeviceScanner : public chip::Dnssd::CommissioningResolveDelegate

#if CHIP_TOOL_DEVICE_SCANNER_USE_BLE
/////////// BleScannerDelegate Interface /////////
void OnBleScanResult(BLE_CONNECTION_OBJECT connObj, const chip::Ble::ChipBLEDeviceIdentificationInfo & info) override;
void OnBleScanAdd(BLE_CONNECTION_OBJECT connObj, const chip::Ble::ChipBLEDeviceIdentificationInfo & info) override;
void OnBleScanRemove(BLE_CONNECTION_OBJECT connObj) override;
#endif // CHIP_TOOL_DEVICE_SCANNER_USE_BLE

private:
Expand Down
89 changes: 70 additions & 19 deletions src/platform/Darwin/BleConnectionDelegateImpl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@

constexpr uint64_t kScanningWithDiscriminatorTimeoutInSeconds = 60;
constexpr uint64_t kScanningWithoutDelegateTimeoutInSeconds = 120;
constexpr uint64_t kCachePeripheralTimeoutInSeconds
= static_cast<uint64_t>(CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX / 1000.0 * 8.0 * 0.625);
constexpr const char * kBleWorkQueueName = "org.csa-iot.matter.framework.ble.workqueue";

typedef NS_ENUM(uint8_t, BleConnectionMode) {
Expand All @@ -60,7 +62,7 @@ @interface BleConnection : NSObject <CBCentralManagerDelegate, CBPeripheralDeleg
@property (strong, nonatomic) CBUUID * shortServiceUUID;
@property (nonatomic, readonly, nullable) dispatch_source_t timer;
@property (nonatomic, readonly) BleConnectionMode currentMode;
@property (strong, nonatomic) NSMutableDictionary * cachedPeripherals;
@property (strong, nonatomic) NSMutableDictionary<CBPeripheral *, NSDictionary *> * cachedPeripherals;
@property (unsafe_unretained, nonatomic) bool found;
@property (unsafe_unretained, nonatomic) chip::SetupDiscriminator deviceDiscriminator;
@property (unsafe_unretained, nonatomic) void * appState;
Expand All @@ -81,6 +83,9 @@ - (void)updateWithPeripheral:(CBPeripheral *)peripheral;
- (BOOL)isScanningWithoutDelegate;
- (BOOL)isScanning;
- (BOOL)isConnecting;
- (void)addPeripheralToCache:(CBPeripheral *)peripheral data:(NSData *)data;
- (void)removePeripheralFromCache:(CBPeripheral *)peripheral;
- (void)removePeripheralsFromCache;

@end

Expand Down Expand Up @@ -379,18 +384,7 @@ - (void)centralManager:(CBCentralManager *)central
}

if (![self isConnecting]) {
if ([_cachedPeripherals objectForKey:peripheral] == nil) {
ChipLogProgress(Ble, "Storing device %p with discriminator: %d", peripheral, discriminator);
if (_scannerDelegate) {
dispatch_async(_chipWorkQueue, ^{
ChipBLEDeviceIdentificationInfo info;
memcpy(&info, bytes, sizeof(info));
_scannerDelegate->OnBleScanResult((__bridge void *) peripheral, info);
});
}
}

_cachedPeripherals[peripheral] = serviceData;
[self addPeripheralToCache:peripheral data:serviceData];
}
}

Expand Down Expand Up @@ -542,9 +536,9 @@ - (void)start
- (void)stop
{
[self stopScanning];
_scannerDelegate = nil;
[_cachedPeripherals removeAllObjects];
[self removePeripheralsFromCache];
_cachedPeripherals = nil;
_scannerDelegate = nil;

if (!_centralManager || !_peripheral) {
return;
Expand Down Expand Up @@ -597,17 +591,16 @@ - (void)connect:(CBPeripheral *)peripheral

- (void)updateWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate
{
[_cachedPeripherals removeAllObjects];
_scannerDelegate = delegate;
_currentMode = (delegate == nullptr) ? kScanningWithoutDelegate : kScanning;

if (_currentMode == kScanning) {
for (CBPeripheral * cachedPeripheral in _cachedPeripherals) {
NSData * serviceData = _cachedPeripherals[cachedPeripheral];
NSData * serviceData = _cachedPeripherals[cachedPeripheral][@"data"];
dispatch_async(_chipWorkQueue, ^{
ChipBLEDeviceIdentificationInfo info;
memcpy(&info, [serviceData bytes], sizeof(info));
_scannerDelegate->OnBleScanResult((__bridge void *) cachedPeripheral, info);
_scannerDelegate->OnBleScanAdd((__bridge void *) cachedPeripheral, info);
});
}
}
Expand All @@ -623,7 +616,7 @@ - (void)updateWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscrimi

CBPeripheral * peripheral = nil;
for (CBPeripheral * cachedPeripheral in _cachedPeripherals) {
NSData * serviceData = _cachedPeripherals[cachedPeripheral];
NSData * serviceData = _cachedPeripherals[cachedPeripheral][@"data"];
ChipBLEDeviceIdentificationInfo info;
memcpy(&info, [serviceData bytes], sizeof(info));

Expand All @@ -633,6 +626,8 @@ - (void)updateWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscrimi
}
}

[self removePeripheralsFromCache];

if (peripheral) {
ChipLogProgress(Ble, "Connecting to cached device: %p", peripheral);
[self connect:peripheral];
Expand All @@ -652,6 +647,62 @@ - (void)updateWithPeripheral:(CBPeripheral *)peripheral
[self stopScanning];
}

- (void)addPeripheralToCache:(CBPeripheral *)peripheral data:(NSData *)data
{
dispatch_source_t timeoutTimer;

if ([_cachedPeripherals objectForKey:peripheral]) {
timeoutTimer = _cachedPeripherals[peripheral][@"timer"];
} else {
auto delegate = _scannerDelegate;
if (delegate) {
dispatch_async(_chipWorkQueue, ^{
ChipBLEDeviceIdentificationInfo info;
auto bytes = (const uint8_t *) [data bytes];
memcpy(&info, bytes, sizeof(info));
delegate->OnBleScanAdd((__bridge void *) peripheral, info);
});
}

timeoutTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _workQueue);
dispatch_source_set_event_handler(timeoutTimer, ^{
[self removePeripheralFromCache:peripheral];
});
dispatch_resume(timeoutTimer);
}

auto timeout = static_cast<int64_t>(kCachePeripheralTimeoutInSeconds * NSEC_PER_SEC);
dispatch_source_set_timer(timeoutTimer, dispatch_walltime(nullptr, timeout), DISPATCH_TIME_FOREVER, 5 * NSEC_PER_SEC);

_cachedPeripherals[peripheral] = @{
@"data" : data,
@"timer" : timeoutTimer,
};
}

- (void)removePeripheralFromCache:(CBPeripheral *)peripheral
{
auto entry = [_cachedPeripherals objectForKey:peripheral];
if (entry) {
dispatch_source_cancel(entry[@"timer"]);
[_cachedPeripherals removeObjectForKey:peripheral];

auto delegate = _scannerDelegate;
if (delegate) {
dispatch_async(_chipWorkQueue, ^{
delegate->OnBleScanRemove((__bridge void *) peripheral);
});
}
}
}

- (void)removePeripheralsFromCache
{
for (CBPeripheral * peripheral in _cachedPeripherals) {
[self removePeripheralFromCache:peripheral];
}
}

/**
* private static method to copy service and characteristic UUIDs from CBCharacteristic to a pair of ChipBleUUID objects.
* this is used in calls into Chip layer to decouple it from CoreBluetooth
Expand Down
5 changes: 4 additions & 1 deletion src/platform/Darwin/BleScannerDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ class DLL_EXPORT BleScannerDelegate
virtual ~BleScannerDelegate() {}

// Called when a scan result is available.
virtual void OnBleScanResult(BLE_CONNECTION_OBJECT connObj, const Ble::ChipBLEDeviceIdentificationInfo & info) = 0;
virtual void OnBleScanAdd(BLE_CONNECTION_OBJECT connObj, const Ble::ChipBLEDeviceIdentificationInfo & info) = 0;

// Called when a scan result is not available anymore.
virtual void OnBleScanRemove(BLE_CONNECTION_OBJECT connObj) = 0;
};

} // namespace DeviceLayer
Expand Down

0 comments on commit 19909ce

Please sign in to comment.