mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Add implementation for async BLE start scan/advertise
PiperOrigin-RevId: 559863656
This commit is contained in:
committed by
Copybara-Service
parent
91fb4a9a3e
commit
965cc0ecbc
@@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
#import <CoreBluetooth/CoreBluetooth.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEGATTCharacteristic.h"
|
||||
@@ -25,6 +26,7 @@ using Property = ::nearby::api::ble_v2::GattCharacteristic::Property;
|
||||
using Permission = ::nearby::api::ble_v2::GattCharacteristic::Permission;
|
||||
using WriteType = ::nearby::api::ble_v2::GattClient::WriteType;
|
||||
using Uuid = ::nearby::Uuid;
|
||||
using ByteArray = ::nearby::ByteArray;
|
||||
|
||||
@interface GNCBLEUtilsTest : XCTestCase
|
||||
@end
|
||||
@@ -120,6 +122,22 @@ using Uuid = ::nearby::Uuid;
|
||||
XCTAssertEqual(actual.properties, properties);
|
||||
}
|
||||
|
||||
- (void)testObjCServiceDataFromCpp {
|
||||
CBUUID *serviceUUID1 = [CBUUID UUIDWithString:@"0000FEF3-0000-1000-8000-00805F9B34FB"];
|
||||
CBUUID *serviceUUID2 = [CBUUID UUIDWithString:@"0000FEF4-0000-1000-8000-00805F9B34FB"];
|
||||
NSData *data1 = [@"one" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSData *data2 = [@"two" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
absl::flat_hash_map<Uuid, ByteArray> service_data;
|
||||
service_data[Uuid(0x0000FEF300001000, 0x800000805F9B34FB)] = ByteArray("one");
|
||||
service_data[Uuid(0x0000FEF400001000, 0x800000805F9B34FB)] = ByteArray("two");
|
||||
|
||||
NSMutableDictionary<CBUUID *, NSData *> *actual =
|
||||
::nearby::apple::ObjCServiceDataFromCPP(service_data);
|
||||
XCTAssertEqualObjects(actual[serviceUUID1], data1);
|
||||
XCTAssertEqualObjects(actual[serviceUUID2], data2);
|
||||
}
|
||||
|
||||
#pragma mark - Objective-C to C++
|
||||
|
||||
- (void)testCPPUUIDFromObjC16Bit {
|
||||
|
||||
@@ -48,8 +48,6 @@ class BleMedium : public api::ble_v2::BleMedium {
|
||||
BleMedium();
|
||||
~BleMedium() override = default;
|
||||
|
||||
// TODO(b/290385712): Not yet implemented.
|
||||
//
|
||||
// Async interface for StartAdvertising.
|
||||
//
|
||||
// Result status will be passed to start_advertising_result callback. To stop advertising, invoke
|
||||
@@ -72,8 +70,6 @@ class BleMedium : public api::ble_v2::BleMedium {
|
||||
// Returns whether or not advertising was successfully stopped.
|
||||
bool StopAdvertising() override;
|
||||
|
||||
// TODO(b/290385712): Not yet implemented.
|
||||
//
|
||||
// Async interface for StartScanning.
|
||||
//
|
||||
// Result status will be passed to start_scanning_result callback on a private queue. To stop
|
||||
@@ -147,6 +143,12 @@ class BleMedium : public api::ble_v2::BleMedium {
|
||||
api::ble_v2::BleMedium::GetRemotePeripheralCallback callback) override;
|
||||
|
||||
private:
|
||||
void HandleAdvertisementFound(
|
||||
id<GNCPeripheral> peripheral, NSDictionary<CBUUID *, NSData *> *serviceData,
|
||||
absl::AnyInvocable<void(api::ble_v2::BlePeripheral &peripheral,
|
||||
api::ble_v2::BleAdvertisementData advertisement_data)>
|
||||
callback);
|
||||
|
||||
GNCBLEMedium *medium_;
|
||||
|
||||
absl::Mutex peripherals_mutex_;
|
||||
|
||||
@@ -56,22 +56,31 @@ namespace apple {
|
||||
|
||||
BleMedium::BleMedium() : medium_([[GNCBLEMedium alloc] init]) {}
|
||||
|
||||
// TODO(b/290385712): Implement.
|
||||
std::unique_ptr<api::ble_v2::BleMedium::AdvertisingSession> BleMedium::StartAdvertising(
|
||||
const api::ble_v2::BleAdvertisementData &advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertise_set_parameters,
|
||||
api::ble_v2::BleMedium::AdvertisingCallback callback) {
|
||||
return nullptr;
|
||||
NSMutableDictionary<CBUUID *, NSData *> *serviceData =
|
||||
ObjCServiceDataFromCPP(advertising_data.service_data);
|
||||
|
||||
__block api::ble_v2::BleMedium::AdvertisingCallback blockCallback = std::move(callback);
|
||||
|
||||
[medium_ startAdvertisingData:serviceData
|
||||
completionHandler:^(NSError *error) {
|
||||
blockCallback.start_advertising_result(
|
||||
error == nil ? absl::OkStatus()
|
||||
: absl::InternalError(error.localizedDescription.UTF8String));
|
||||
}];
|
||||
|
||||
return std::make_unique<AdvertisingSession>(AdvertisingSession{.stop_advertising = [this] {
|
||||
return StopAdvertising() ? absl::OkStatus() : absl::InternalError("Failed to stop advertising");
|
||||
}});
|
||||
}
|
||||
|
||||
bool BleMedium::StartAdvertising(const api::ble_v2::BleAdvertisementData &advertising_data,
|
||||
api::ble_v2::AdvertiseParameters advertise_set_parameters) {
|
||||
NSMutableDictionary<CBUUID *, NSData *> *serviceData = [[NSMutableDictionary alloc] init];
|
||||
for (const auto &pair : advertising_data.service_data) {
|
||||
CBUUID *key = CBUUID16FromCPP(pair.first);
|
||||
NSData *data = NSDataFromByteArray(pair.second);
|
||||
[serviceData setObject:data forKey:key];
|
||||
}
|
||||
NSMutableDictionary<CBUUID *, NSData *> *serviceData =
|
||||
ObjCServiceDataFromCPP(advertising_data.service_data);
|
||||
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
__block NSError *blockError = nil;
|
||||
@@ -101,11 +110,54 @@ bool BleMedium::StopAdvertising() {
|
||||
return blockError == nil;
|
||||
}
|
||||
|
||||
// TODO(b/290385712): Implement.
|
||||
void BleMedium::HandleAdvertisementFound(
|
||||
id<GNCPeripheral> peripheral, NSDictionary<CBUUID *, NSData *> *serviceData,
|
||||
absl::AnyInvocable<void(api::ble_v2::BlePeripheral &peripheral,
|
||||
api::ble_v2::BleAdvertisementData advertisement_data)>
|
||||
callback) {
|
||||
absl::MutexLock lock(&peripherals_mutex_);
|
||||
[socketCentralManager_ retrievePeripheralWithIdentifier:peripheral.identifier
|
||||
advertisementData:@{}];
|
||||
|
||||
api::ble_v2::BleAdvertisementData data;
|
||||
for (CBUUID *key in serviceData.allKeys) {
|
||||
data.service_data[CPPUUIDFromObjC(key)] = ByteArrayFromNSData(serviceData[key]);
|
||||
}
|
||||
|
||||
// Add the peripheral to the map if we haven't discovered it yet.
|
||||
auto ble_peripheral = std::make_unique<BlePeripheral>(peripheral);
|
||||
auto unique_id = ble_peripheral->GetUniqueId();
|
||||
auto it = peripherals_.find(unique_id);
|
||||
if (it == peripherals_.end()) {
|
||||
peripherals_[unique_id] = std::move(ble_peripheral);
|
||||
}
|
||||
callback(*peripherals_[unique_id], data);
|
||||
}
|
||||
|
||||
std::unique_ptr<api::ble_v2::BleMedium::ScanningSession> BleMedium::StartScanning(
|
||||
const Uuid &service_uuid, api::ble_v2::TxPowerLevel tx_power_level,
|
||||
api::ble_v2::BleMedium::ScanningCallback callback) {
|
||||
return nullptr;
|
||||
CBUUID *serviceUUID = CBUUID128FromCPP(service_uuid);
|
||||
__block api::ble_v2::BleMedium::ScanningCallback blockCallback = std::move(callback);
|
||||
|
||||
socketCentralManager_ = [[GNSCentralManager alloc] initWithSocketServiceUUID:serviceUUID];
|
||||
[socketCentralManager_ startNoScanModeWithAdvertisedServiceUUIDs:@[ serviceUUID ]];
|
||||
|
||||
[medium_ startScanningForService:serviceUUID
|
||||
advertisementFoundHandler:^(id<GNCPeripheral> peripheral,
|
||||
NSDictionary<CBUUID *, NSData *> *serviceData) {
|
||||
HandleAdvertisementFound(peripheral, serviceData,
|
||||
std::move(blockCallback.advertisement_found_cb));
|
||||
}
|
||||
completionHandler:^(NSError *error) {
|
||||
blockCallback.start_scanning_result(
|
||||
error == nil ? absl::OkStatus()
|
||||
: absl::InternalError(error.localizedDescription.UTF8String));
|
||||
}];
|
||||
|
||||
return std::make_unique<ScanningSession>(ScanningSession{.stop_scanning = [this] {
|
||||
return StopScanning() ? absl::OkStatus() : absl::InternalError("Failed to stop scanning");
|
||||
}});
|
||||
}
|
||||
|
||||
bool BleMedium::StartScanning(const Uuid &service_uuid, api::ble_v2::TxPowerLevel tx_power_level,
|
||||
@@ -121,23 +173,8 @@ bool BleMedium::StartScanning(const Uuid &service_uuid, api::ble_v2::TxPowerLeve
|
||||
[medium_ startScanningForService:serviceUUID
|
||||
advertisementFoundHandler:^(id<GNCPeripheral> peripheral,
|
||||
NSDictionary<CBUUID *, NSData *> *serviceData) {
|
||||
absl::MutexLock lock(&peripherals_mutex_);
|
||||
[socketCentralManager_ retrievePeripheralWithIdentifier:peripheral.identifier
|
||||
advertisementData:@{}];
|
||||
|
||||
api::ble_v2::BleAdvertisementData data;
|
||||
for (CBUUID *key in serviceData.allKeys) {
|
||||
data.service_data[CPPUUIDFromObjC(key)] = ByteArrayFromNSData(serviceData[key]);
|
||||
}
|
||||
|
||||
// Add the peripheral to the map if we haven't discovered it yet.
|
||||
auto ble_peripheral = std::make_unique<BlePeripheral>(peripheral);
|
||||
auto unique_id = ble_peripheral->GetUniqueId();
|
||||
auto it = peripherals_.find(unique_id);
|
||||
if (it == peripherals_.end()) {
|
||||
peripherals_[unique_id] = std::move(ble_peripheral);
|
||||
}
|
||||
blockCallback.advertisement_found_cb(*peripherals_[unique_id], data);
|
||||
HandleAdvertisementFound(peripheral, serviceData,
|
||||
std::move(blockCallback.advertisement_found_cb));
|
||||
}
|
||||
completionHandler:^(NSError *error) {
|
||||
if (error != nil) {
|
||||
|
||||
@@ -56,6 +56,9 @@ CBCharacteristicProperties CBCharacteristicPropertiesFromCPP(
|
||||
/** Converts a C++ characteristic to an Objective-C characteristic. */
|
||||
GNCBLEGATTCharacteristic *ObjCGATTCharacteristicFromCPP(const api::ble_v2::GattCharacteristic &c);
|
||||
|
||||
NSMutableDictionary<CBUUID *, NSData *> *ObjCServiceDataFromCPP(
|
||||
const absl::flat_hash_map<Uuid, nearby::ByteArray> &sd);
|
||||
|
||||
/** Converts a 16 or 128 bit CoreBluetooth UUID to a C++ UUID. */
|
||||
Uuid CPPUUIDFromObjC(CBUUID *uuid);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <string>
|
||||
|
||||
#import "internal/platform/implementation/apple/Mediums/BLEv2/GNCBLEGATTCharacteristic.h"
|
||||
#import "internal/platform/implementation/apple/utils.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace apple {
|
||||
@@ -98,6 +99,17 @@ GNCBLEGATTCharacteristic *ObjCGATTCharacteristicFromCPP(const GattCharacteristic
|
||||
properties:properties];
|
||||
}
|
||||
|
||||
NSMutableDictionary<CBUUID *, NSData *> *ObjCServiceDataFromCPP(
|
||||
const absl::flat_hash_map<Uuid, nearby::ByteArray> &sd) {
|
||||
NSMutableDictionary<CBUUID *, NSData *> *serviceData = [NSMutableDictionary dictionary];
|
||||
for (const auto &pair : sd) {
|
||||
CBUUID *key = CBUUID16FromCPP(pair.first);
|
||||
NSData *data = NSDataFromByteArray(pair.second);
|
||||
[serviceData setObject:data forKey:key];
|
||||
}
|
||||
return serviceData;
|
||||
}
|
||||
|
||||
Uuid CPPUUIDFromObjC(CBUUID *uuid) {
|
||||
NSString *uuidString = uuid.UUIDString;
|
||||
if (uuidString.length == 4) {
|
||||
|
||||
Reference in New Issue
Block a user