mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 22:56:12 -04:00
[BLE Refactor] Implement iOS Advertising modules.
PiperOrigin-RevId: 455005322
This commit is contained in:
committed by
Copybara-Service
parent
a9d7061794
commit
160a224510
@@ -168,7 +168,7 @@ class GattServer final {
|
||||
return impl_->UpdateCharacteristic(characteristic, value);
|
||||
}
|
||||
|
||||
void Stop() { return impl_->Stop(); }
|
||||
void Stop() { if (impl_) return impl_->Stop(); }
|
||||
|
||||
// Returns true if a gatt_server is usable. If this method returns false,
|
||||
// it is not safe to call any other method.
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#ifndef PLATFORM_API_BLE_V2_H_
|
||||
#define PLATFORM_API_BLE_V2_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
@@ -113,14 +114,24 @@ struct GattCharacteristic {
|
||||
|
||||
Uuid uuid;
|
||||
Uuid service_uuid;
|
||||
std::vector<Permission> permissions;
|
||||
std::vector<Property> properties;
|
||||
|
||||
// Hashable
|
||||
template <typename H>
|
||||
friend H AbslHashValue(H h, const GattCharacteristic& s) {
|
||||
return H::combine(std::move(h), s.uuid, s.service_uuid);
|
||||
return H::combine(std::move(h), s.uuid, s.service_uuid, s.permissions,
|
||||
s.properties);
|
||||
}
|
||||
bool operator==(const GattCharacteristic& rhs) const {
|
||||
return this->uuid == rhs.uuid && this->service_uuid == rhs.service_uuid;
|
||||
bool has_equal_permissions =
|
||||
std::is_permutation(this->permissions.begin(), this->permissions.end(),
|
||||
rhs.permissions.begin(), rhs.permissions.end());
|
||||
bool has_equal_properties =
|
||||
std::is_permutation(this->properties.begin(), this->properties.end(),
|
||||
rhs.properties.begin(), rhs.properties.end());
|
||||
return this->uuid == rhs.uuid && this->service_uuid == rhs.service_uuid &&
|
||||
has_equal_permissions && has_equal_properties;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@ objc_library(
|
||||
"GNCUtils.h",
|
||||
],
|
||||
deps = [
|
||||
"//third_party/objective_c/google_toolbox_for_mac:GTM_StringEncoding",
|
||||
"@aappleby_smhasher//:libmurmur3",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <CoreBluetooth/CoreBluetooth.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class CBCharacteristic;
|
||||
@class CBUUID;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -26,16 +29,43 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@interface GNCMBlePeripheral : NSObject
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Initializes an `GNCMBlePeripheral` object.
|
||||
* Adds GATT CBService.
|
||||
*
|
||||
* @param serviceUUID A GATT service ID to advertise for.
|
||||
*/
|
||||
- (void)addCBServiceWithUUID:(CBUUID *)serviceUUID;
|
||||
|
||||
/**
|
||||
* Adds GATT CBCharacteristic.
|
||||
*
|
||||
* @param characteristic A characteristic CBUUID.
|
||||
*/
|
||||
- (void)addCharacteristic:(CBCharacteristic *)characteristic;
|
||||
|
||||
/**
|
||||
* Updates GATT CBCharacteristic with value.
|
||||
*
|
||||
* @param value The NSData to advertise.
|
||||
* @param characteristicUUID A characteristic CBUUID.
|
||||
*/
|
||||
- (void)updateValue:(NSData *)value forCharacteristic:(CBUUID *)characteristicUUID;
|
||||
|
||||
/**
|
||||
* Stops GATT server service.
|
||||
*/
|
||||
- (void)stopGATTService;
|
||||
|
||||
/**
|
||||
* Starts advertising with service UUID and advertisement data.
|
||||
*
|
||||
* @param serviceUUID A string that uniquely identifies the advertised service to search for.
|
||||
* @param advertisementData The data to advertise.
|
||||
*/
|
||||
- (instancetype)initWithServiceUUID:(NSString *)serviceUUID
|
||||
advertisementData:(NSData *)advertisementData NS_DESIGNATED_INITIALIZER;
|
||||
- (BOOL)startAdvertisingWithServiceUUID:(NSString *)serviceUUID
|
||||
advertisementData:(NSData *)advertisementData;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -14,34 +14,41 @@
|
||||
|
||||
#import "internal/platform/implementation/ios/Mediums/Ble/GNCMBlePeripheral.h"
|
||||
|
||||
#include <CoreBluetooth/CoreBluetooth.h>
|
||||
#import <CoreBluetooth/CoreBluetooth.h>
|
||||
|
||||
#import "internal/platform/implementation/ios/GNCUtils.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_ENUM(NSUInteger, GNCMPeripheralState) {
|
||||
GNCMPeripheralStateStopped,
|
||||
GNCMPeripheralStateAdvertising,
|
||||
};
|
||||
|
||||
@interface GNCMBlePeripheral () <CBPeripheralManagerDelegate>
|
||||
@end
|
||||
|
||||
@implementation GNCMBlePeripheral {
|
||||
/** GATT service for advertisement. */
|
||||
/** Service UUID for advertisement. */
|
||||
CBMutableService *_advertisementService;
|
||||
/** GATT service for GATT connection. */
|
||||
CBMutableService *_GATTService;
|
||||
/** GATT characteristics for GATT connection. */
|
||||
NSMutableArray<CBCharacteristic *> *_gattCharacteristics;
|
||||
/** CBUUID characteristic to NSData value dictionary for GATT connection. */
|
||||
NSMutableDictionary<CBUUID *, NSData *> *_gattCharacteristicValues;
|
||||
/** Data to be advertised. */
|
||||
NSData *_advertisementData;
|
||||
/** Peripheral manager used to advertise or connect to peripherals. */
|
||||
CBPeripheralManager *_peripheralManager;
|
||||
/** Serial background queue for |peripheralManager|. */
|
||||
dispatch_queue_t _selfQueue;
|
||||
/** Peripheral state for stop or advertising. */
|
||||
GNCMPeripheralState _state;
|
||||
}
|
||||
|
||||
- (instancetype)initWithServiceUUID:(NSString *)serviceUUID
|
||||
advertisementData:(NSData *)advertisementData {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_advertisementService =
|
||||
[[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:serviceUUID] primary:YES];
|
||||
_advertisementData = [advertisementData copy];
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
// To make this class thread-safe, use a serial queue for all state changes, and have Core
|
||||
// Bluetooth also use this queue.
|
||||
_selfQueue = dispatch_queue_create("GNCPeripheralManagerQueue", DISPATCH_QUEUE_SERIAL);
|
||||
@@ -51,6 +58,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
initWithDelegate:self
|
||||
queue:_selfQueue
|
||||
options:@{CBPeripheralManagerOptionShowPowerAlertKey : @NO}];
|
||||
_state = GNCMPeripheralStateStopped;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -60,22 +68,68 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// dispatch_sync. This means delloc must be called from an external queue, which means |self|
|
||||
// must never be captured by any escaping block used in this class.
|
||||
dispatch_sync(_selfQueue, ^{
|
||||
[self stopAdvertising];
|
||||
[self stopAdvertisingInternal];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)addCBServiceWithUUID:(CBUUID *)serviceUUID {
|
||||
if (!_GATTService) {
|
||||
// If it has been called, then don't do it again. Initialize one time.
|
||||
_GATTService = [[CBMutableService alloc] initWithType:serviceUUID primary:YES];
|
||||
_gattCharacteristics = [[NSMutableArray alloc] init];
|
||||
_gattCharacteristicValues = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addCharacteristic:(CBCharacteristic *)characteristic {
|
||||
if (_gattCharacteristics) {
|
||||
[_gattCharacteristics addObject:characteristic];
|
||||
}
|
||||
if (_gattCharacteristicValues) {
|
||||
[_gattCharacteristicValues setObject:[[NSData alloc] init] forKey:characteristic.UUID];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateValue:(NSData *)value forCharacteristic:(CBUUID *)characteristicUUID {
|
||||
if ([_gattCharacteristicValues objectForKey:characteristicUUID]) {
|
||||
[_gattCharacteristicValues setObject:value forKey:characteristicUUID];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopGATTService {
|
||||
if (!_GATTService) return;
|
||||
dispatch_sync(_selfQueue, ^{
|
||||
[_peripheralManager removeService:_GATTService];
|
||||
});
|
||||
}
|
||||
|
||||
- (BOOL)startAdvertisingWithServiceUUID:(NSString *)serviceUUID
|
||||
advertisementData:(NSData *)advertisementData {
|
||||
NSLog(@"[NEARBY] Client rquests startAdvertising");
|
||||
_advertisementService = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:serviceUUID]
|
||||
primary:YES];
|
||||
_advertisementData = [advertisementData copy];
|
||||
|
||||
if (_GATTService) {
|
||||
if (_gattCharacteristics && _gattCharacteristics.count > 0) {
|
||||
_GATTService.characteristics = _gattCharacteristics;
|
||||
}
|
||||
}
|
||||
_state = GNCMPeripheralStateAdvertising;
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark CBPeripheralManagerDelegate
|
||||
|
||||
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
|
||||
if (peripheral.state == CBManagerStatePoweredOn) {
|
||||
NSLog(@"[NEARBY] peripheralManagerDidUpdateState %li", (long)peripheral.state);
|
||||
if (peripheral.state == CBManagerStatePoweredOn && !peripheral.isAdvertising &&
|
||||
_state == GNCMPeripheralStateAdvertising) {
|
||||
NSLog(@"[NEARBY] CBPeripheralManager powered on; starting advertising");
|
||||
[_peripheralManager startAdvertising:@{
|
||||
CBAdvertisementDataServiceUUIDsKey : @[ _advertisementService.UUID ],
|
||||
CBAdvertisementDataLocalNameKey : _advertisementData
|
||||
}];
|
||||
[self startAdvertisingInternal];
|
||||
} else {
|
||||
NSLog(@"[NEARBY] CBPeripheralManager not powered on; stopping advertising");
|
||||
[self stopAdvertising];
|
||||
[self stopAdvertisingInternal];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +139,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
NSLog(@"[NEARBY] Error starting advertising: %@,", [error localizedDescription]);
|
||||
return;
|
||||
}
|
||||
if (_peripheralManager.state != CBPeripheralManagerStatePoweredOn) {
|
||||
if (_peripheralManager.state != CBManagerStatePoweredOn) {
|
||||
NSLog(@"[NEARBY] Error starting advertising: peripheral manager not on!");
|
||||
return;
|
||||
}
|
||||
@@ -93,11 +147,53 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
NSLog(@"[NEARBY] Peripheral manager started advertising");
|
||||
}
|
||||
|
||||
- (void)peripheralManager:(CBPeripheralManager *)peripheral
|
||||
didReceiveReadRequest:(CBATTRequest *)request {
|
||||
NSLog(@"[NEARBY] peripheralManager:didReceiveReadRequest");
|
||||
// This is called when a central asks to read a characteristic's value.
|
||||
CBATTError error = CBATTErrorAttributeNotFound;
|
||||
NSData *value = _gattCharacteristicValues[request.characteristic.UUID];
|
||||
if (value != nil && value.length > 0) {
|
||||
if (request.offset > value.length) {
|
||||
error = CBATTErrorInvalidOffset;
|
||||
} else {
|
||||
// Reply with the advertisement data.
|
||||
NSRange rangeFromOffset = NSMakeRange(request.offset, value.length - request.offset);
|
||||
request.value = [value subdataWithRange:rangeFromOffset];
|
||||
error = CBATTErrorSuccess;
|
||||
}
|
||||
}
|
||||
[_peripheralManager respondToRequest:request withResult:error];
|
||||
}
|
||||
|
||||
#pragma mark Private
|
||||
|
||||
/** Signals the peripheral manager to start advertising. Must be called on _selfQueue */
|
||||
- (void)startAdvertisingInternal {
|
||||
if (![_peripheralManager isAdvertising]) {
|
||||
NSLog(@"[NEARBY] startAdvertisingInternal");
|
||||
|
||||
if (_GATTService) {
|
||||
[_peripheralManager addService:_GATTService];
|
||||
}
|
||||
[_peripheralManager startAdvertising:@{
|
||||
CBAdvertisementDataServiceUUIDsKey : @[ _advertisementService.UUID ],
|
||||
CBAdvertisementDataLocalNameKey : _advertisementData
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
/** Signals the peripheral manager to stop advertising. Must be called on _selfQueue */
|
||||
- (void)stopAdvertising {
|
||||
[_peripheralManager stopAdvertising];
|
||||
- (void)stopAdvertisingInternal {
|
||||
if ([_peripheralManager isAdvertising]) {
|
||||
NSLog(@"[NEARBY] stopAdvertisingInternal");
|
||||
_state = GNCMPeripheralStateStopped;
|
||||
|
||||
if (_GATTService) {
|
||||
[_peripheralManager removeService:_GATTService];
|
||||
}
|
||||
[_peripheralManager stopAdvertising];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -28,6 +28,7 @@ using ::location::nearby::api::BluetoothAdapter;
|
||||
using ::location::nearby::api::ImplementationPlatform;
|
||||
using ::location::nearby::api::ble_v2::BleAdvertisementData;
|
||||
using ::location::nearby::api::ble_v2::BleMedium;
|
||||
using ::location::nearby::api::ble_v2::GattCharacteristic;
|
||||
using ::location::nearby::api::ble_v2::TxPowerLevel;
|
||||
|
||||
static const char *const kAdvertisementString = "\x0a\x0b\x0c\x0d";
|
||||
@@ -74,4 +75,30 @@ static const TxPowerLevel kTxPowerLevel = TxPowerLevel::kHigh;
|
||||
XCTAssertTrue(_ble->StopScanning());
|
||||
}
|
||||
|
||||
- (void)testGattServerWorking {
|
||||
// Test creating gatt_server.
|
||||
auto gatt_server = _ble->StartGattServer(/*ServerGattConnectionCallback=*/{});
|
||||
XCTAssert(gatt_server != nullptr);
|
||||
|
||||
// Test creating characteristic.
|
||||
Uuid service_uuid(1234, 5678);
|
||||
Uuid characteristic_uuid(5678, 1234);
|
||||
std::vector<GattCharacteristic::Permission> permissions = {
|
||||
GattCharacteristic::Permission::kRead};
|
||||
std::vector<GattCharacteristic::Property> properties = {
|
||||
GattCharacteristic::Property::kRead};
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
absl::optional<GattCharacteristic> gatt_characteristic =
|
||||
gatt_server->CreateCharacteristic(service_uuid, characteristic_uuid, permissions, properties);
|
||||
XCTAssertTrue(gatt_characteristic.has_value());
|
||||
|
||||
// Test updating characteristic.
|
||||
ByteArray any_byte("any");
|
||||
XCTAssertTrue(
|
||||
gatt_server->UpdateCharacteristic(gatt_characteristic.value(), any_byte));
|
||||
|
||||
gatt_server->Stop();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -15,10 +15,12 @@
|
||||
#ifndef THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_IOS_BLE_H_
|
||||
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_IOS_BLE_H_
|
||||
|
||||
#import <CoreBluetooth/CoreBluetooth.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/bluetooth_adapter.h"
|
||||
@@ -56,6 +58,25 @@ class BleMedium : public api::ble_v2::BleMedium {
|
||||
bool IsExtendedAdvertisementsAvailable() override;
|
||||
|
||||
private:
|
||||
// A concrete implemenation for GattServer.
|
||||
class GattServer : public api::ble_v2::GattServer {
|
||||
public:
|
||||
GattServer() = default;
|
||||
explicit GattServer(GNCMBlePeripheral* peripheral) : peripheral_(peripheral) {}
|
||||
|
||||
absl::optional<api::ble_v2::GattCharacteristic> CreateCharacteristic(
|
||||
const Uuid& service_uuid, const Uuid& characteristic_uuid,
|
||||
const std::vector<api::ble_v2::GattCharacteristic::Permission>& permissions,
|
||||
const std::vector<api::ble_v2::GattCharacteristic::Property>& properties) override;
|
||||
|
||||
bool UpdateCharacteristic(const api::ble_v2::GattCharacteristic& characteristic,
|
||||
const location::nearby::ByteArray& value) override;
|
||||
void Stop() override;
|
||||
|
||||
private:
|
||||
GNCMBlePeripheral* peripheral_;
|
||||
};
|
||||
|
||||
BluetoothAdapter* adapter_;
|
||||
GNCMBlePeripheral* peripheral_;
|
||||
GNCMBleCentral* central_;
|
||||
|
||||
@@ -27,6 +27,51 @@ namespace location {
|
||||
namespace nearby {
|
||||
namespace ios {
|
||||
|
||||
namespace {
|
||||
|
||||
CBAttributePermissions PermissionToCBPermissions(
|
||||
const std::vector<api::ble_v2::GattCharacteristic::Permission>& permissions) {
|
||||
CBAttributePermissions characteristPermissions = 0;
|
||||
for (const auto& permission : permissions) {
|
||||
switch (permission) {
|
||||
case api::ble_v2::GattCharacteristic::Permission::kRead:
|
||||
characteristPermissions |= CBAttributePermissionsReadable;
|
||||
break;
|
||||
case api::ble_v2::GattCharacteristic::Permission::kWrite:
|
||||
characteristPermissions |= CBAttributePermissionsWriteable;
|
||||
break;
|
||||
case api::ble_v2::GattCharacteristic::Permission::kLast:
|
||||
case api::ble_v2::GattCharacteristic::Permission::kUnknown:
|
||||
default:; // fall through
|
||||
}
|
||||
}
|
||||
return characteristPermissions;
|
||||
}
|
||||
|
||||
CBCharacteristicProperties PropertiesToCBProperties(
|
||||
const std::vector<api::ble_v2::GattCharacteristic::Property>& properties) {
|
||||
CBCharacteristicProperties characteristicProperties = 0;
|
||||
for (const auto& property : properties) {
|
||||
switch (property) {
|
||||
case api::ble_v2::GattCharacteristic::Property::kRead:
|
||||
characteristicProperties |= CBCharacteristicPropertyRead;
|
||||
break;
|
||||
case api::ble_v2::GattCharacteristic::Property::kWrite:
|
||||
characteristicProperties |= CBCharacteristicPropertyWrite;
|
||||
break;
|
||||
case api::ble_v2::GattCharacteristic::Property::kIndicate:
|
||||
characteristicProperties |= CBCharacteristicPropertyIndicate;
|
||||
break;
|
||||
case api::ble_v2::GattCharacteristic::Property::kLast:
|
||||
case api::ble_v2::GattCharacteristic::Property::kUnknown:
|
||||
default:; // fall through
|
||||
}
|
||||
}
|
||||
return characteristicProperties;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
using ::location::nearby::api::ble_v2::BleAdvertisementData;
|
||||
using ::location::nearby::api::ble_v2::TxPowerLevel;
|
||||
using ScanCallback = ::location::nearby::api::ble_v2::BleMedium::ScanCallback;
|
||||
@@ -40,12 +85,15 @@ bool BleMedium::StartAdvertising(
|
||||
if (advertising_data.service_data.empty()) {
|
||||
return false;
|
||||
}
|
||||
const std::string& service_uuid = advertising_data.service_data.begin()->first.Get16BitAsString();
|
||||
const auto& service_uuid = advertising_data.service_data.begin()->first.Get16BitAsString();
|
||||
const ByteArray& service_data_bytes = advertising_data.service_data.begin()->second;
|
||||
peripheral_ =
|
||||
[[GNCMBlePeripheral alloc] initWithServiceUUID:ObjCStringFromCppString(service_uuid)
|
||||
advertisementData:NSDataFromByteArray(service_data_bytes)];
|
||||
|
||||
if (!peripheral_) {
|
||||
peripheral_ = [[GNCMBlePeripheral alloc] init];
|
||||
}
|
||||
|
||||
[peripheral_ startAdvertisingWithServiceUUID:ObjCStringFromCppString(service_uuid)
|
||||
advertisementData:NSDataFromByteArray(service_data_bytes)];
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -72,7 +120,10 @@ bool BleMedium::StopScanning() {
|
||||
|
||||
std::unique_ptr<api::ble_v2::GattServer> BleMedium::StartGattServer(
|
||||
api::ble_v2::ServerGattConnectionCallback callback) {
|
||||
return nullptr;
|
||||
if (!peripheral_) {
|
||||
peripheral_ = [[GNCMBlePeripheral alloc] init];
|
||||
}
|
||||
return std::make_unique<GattServer>(peripheral_);
|
||||
}
|
||||
|
||||
std::unique_ptr<api::ble_v2::GattClient> BleMedium::ConnectToGattServer(
|
||||
@@ -95,6 +146,42 @@ std::unique_ptr<api::ble_v2::BleSocket> BleMedium::Connect(const std::string& se
|
||||
|
||||
bool BleMedium::IsExtendedAdvertisementsAvailable() { return false; }
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
absl::optional<api::ble_v2::GattCharacteristic> BleMedium::GattServer::CreateCharacteristic(
|
||||
const Uuid& service_uuid, const Uuid& characteristic_uuid,
|
||||
const std::vector<api::ble_v2::GattCharacteristic::Permission>& permissions,
|
||||
const std::vector<api::ble_v2::GattCharacteristic::Property>& properties) {
|
||||
api::ble_v2::GattCharacteristic characteristic = {.uuid = characteristic_uuid,
|
||||
.service_uuid = service_uuid,
|
||||
.permissions = permissions,
|
||||
.properties = properties};
|
||||
[peripheral_
|
||||
addCBServiceWithUUID:[CBUUID
|
||||
UUIDWithString:ObjCStringFromCppString(
|
||||
characteristic.service_uuid.Get16BitAsString())]];
|
||||
[peripheral_
|
||||
addCharacteristic:[[CBMutableCharacteristic alloc]
|
||||
initWithType:[CBUUID UUIDWithString:ObjCStringFromCppString(std::string(
|
||||
characteristic.uuid))]
|
||||
properties:PropertiesToCBProperties(characteristic.properties)
|
||||
value:nil
|
||||
permissions:PermissionToCBPermissions(characteristic.permissions)]];
|
||||
return characteristic;
|
||||
}
|
||||
|
||||
bool BleMedium::GattServer::UpdateCharacteristic(
|
||||
const api::ble_v2::GattCharacteristic& characteristic,
|
||||
const location::nearby::ByteArray& value) {
|
||||
[peripheral_ updateValue:NSDataFromByteArray(value)
|
||||
forCharacteristic:[CBUUID UUIDWithString:ObjCStringFromCppString(
|
||||
std::string(characteristic.uuid))]];
|
||||
return true;
|
||||
}
|
||||
|
||||
void BleMedium::GattServer::Stop() {
|
||||
[peripheral_ stopGATTService];
|
||||
}
|
||||
|
||||
} // namespace ios
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
Reference in New Issue
Block a user