未能在 iOS 中发现蓝牙 LE 服务通告
Failing To Discover Bluetooth LE Service Advertisement in iOS
我创建了两个 iOS 应用;一个是宣传服务的蓝牙 LE 外围设备,另一个是扫描广告服务的蓝牙 LE 中央设备。我的 iPhone5s 上的外围设备是 运行,我的 iPad Mini 上的中央设备是 运行。我最初将中央设置为扫描特定广告服务,但后来将其更改为侦听任何服务。在任何一种情况下,作为中心的 iPad 迷你应用程序都不会检测到任何广告服务。我不确定是我设置外围管理器进行广告的方式有问题,还是我设置中央管理器进行扫描的方式有问题,或者是设备配置问题。请提供我可以执行的建议或测试以使其正常工作。
以下是iPhone5s app作为外设的相关代码:
CBPeripheralManager *peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil options:nil];
CBUUID *immediateAlertServiceUUID = [CBUUID UUIDWithString: IMMEDIATE_ALERT_SERVICE_UUID];
CBUUID *alertLevelCharacteristicUUID = [CBUUID UUIDWithString: ALERT_LEVEL_CHARACTERISTIC_UUID];
CBUUID *myCustomCharacteristicUUID = [CBUUID UUIDWithString: MY_CUSTOM_CHARACTERISTIC_UUID];
alertLevelCharacteristic =
[[CBMutableCharacteristic alloc] initWithType:alertLevelCharacteristicUUID
properties:CBCharacteristicPropertyRead
value: nil permissions:CBAttributePermissionsReadable];
myCustomCharacteristic =
[[CBMutableCharacteristic alloc] initWithType:myCustomCharacteristicUUID
properties:CBCharacteristicPropertyRead
value: nil permissions:CBAttributePermissionsReadable];
NSArray *myCharacteristics = @[alertLevelCharacteristic, myCustomCharacteristic];
// Now setup the service
myService = [[CBMutableService alloc] initWithType:immediateAlertServiceUUID primary:YES];
// Finally, associate the characteristic with the service. This is an array of characteristics
myService.characteristics = myCharacteristics;
[peripheralManager addService:myService];
... wait for user to push button to start advertising ...
// Start Advertising
[peripheralManager startAdvertising:@{ CBAdvertisementDataLocalNameKey : @"My Service",
CBAdvertisementDataServiceUUIDsKey : @[myService.UUID] }];
这里是必要的委托方法。注意:委托方法 peripheralManagerDidUpdateState 触发并指示 "CoreBluetooth BLE hardware is powered on and ready"(中央端也是如此)。委托方法 peripheralManager:didAddService:error 无误地触发(见下面的输出)。并且委托方法 peripheralManagerDidStartAdvertising:error 会在没有错误的情况下触发)。这是从 didAddService 打印的服务信息:
<CBMutableService: 0x17008efb0 Primary = YES, UUID = 1802, Included Services = (null), Characteristics = (
"<CBMutableCharacteristic: 0x1702c1500 UUID = 2A06, Value = (null), Properties = 0x2, Permissions = 0x1, Descriptors = (null), SubscribedCentrals = (\n)>",
"<CBMutableCharacteristic: 0x1702c15e0 UUID = 66E613B5-7225-42C6-A9C2-11FADAE62899, Value = (null), Properties = 0x2, Permissions = 0x1, Descriptors = (null), SubscribedCentrals = (\n)>")>
CBPeripheralManager 委托方法(抱歉所有代码,只是试图完整。):
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
// Determine the state of the peripheral
if ([peripheral state] == CBPeripheralManagerStatePoweredOff) {
NSLog(@"CoreBluetooth BLE hardware is powered off");
}
else if ([peripheral state] == CBPeripheralManagerStatePoweredOn) {
NSLog(@"CoreBluetooth BLE hardware is powered on and ready");
}
else if ([peripheral state] == CBPeripheralManagerStateUnauthorized) {
NSLog(@"CoreBluetooth BLE state is unauthorized");
}
else if ([peripheral state] == CBPeripheralManagerStateUnknown) {
NSLog(@"CoreBluetooth BLE state is unknown");
}
else if ([peripheral state] == CBPeripheralManagerStateUnsupported) {
NSLog(@"CoreBluetooth BLE hardware is unsupported on this platform");
}
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral
didAddService:(CBService *)service
error:(NSError *)error {
if (error) {
NSLog(@"Error publishing service: %@", [error localizedDescription]);
return;
}
else {
NSLog(@"Hurray! Your Service has been successfully published as: %@", service);
}
}
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral
error:(NSError *)error {
if (error == nil) {
NSLog(@"Your service is now advertising");
}
else {
NSLog(@"In peripheralManagerDidStartAdvertising: Your service advertising failed with error: %@", error);
}
}
这里是在 iPad Mini 上运行的相关中央代码:
// Scan for all available CoreBluetooth LE devices
NSArray *services = @[[CBUUID UUIDWithString:IMMEDIATE_ALERT_SERVICE_UUID]];
CBCentralManager *centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
//[centralManager scanForPeripheralsWithServices:services options:nil];
[centralManager scanForPeripheralsWithServices:nil options:nil];
self.centralManager = centralManager;
这是中央委托方法之一。除了 centralManagerDidUpdateState:,none 的委托方法会触发。
// CBPeripheralDelegate - Invoked when you discover the peripheral's available services.
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
NSLog(@"Did Discover Services");
for (CBService *service in peripheral.services) {
[peripheral discoverCharacteristics:nil forService:service];
}
}
// CBCentralManagerDelegate - This is called with the CBPeripheral class as its main input parameter. This contains most of the information there is to know about a BLE peripheral.
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(@"Did Discover Peripheral");
NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];
if (![localName isEqual:@"My Service"]) {
// We found the Device
[self.centralManager stopScan];
self.myPeripheral = peripheral;
peripheral.delegate = self;
[self.centralManager connectPeripheral:peripheral options:nil];
}
}
最后一点,我质疑 BLE 是否能在我的设备上运行。我在 iPhone 和 iPad Mini 上加载了几个不同的 iBeacon 应用程序,看看我是否能让这两个设备识别 iBeacons(一个发送,一个接收),但它们也没有发现 iBeacons。我还尝试了两个 iPhones。我还关闭了蓝牙然后再打开。我还尝试为设备供电 off/on。两个设备都在前台 运行。仍然没有运气。请帮忙。
我将在这里串联所有评论:
使用 LightBlue 或 BLE Utility 等应用程序可以帮助您确定您的问题是出在外围还是中央,因为你自己在发展双方。
在查找 CBServices
之前,您必须连接到 CBPeripheral
。
方法你手头确实展示过,好像不是很明显。
此外,在使用 CBCentralManager
开始扫描之前,您必须检查它的 state
,它必须是 CBPeripheralManagerStatePoweredOn
.
我创建了两个 iOS 应用;一个是宣传服务的蓝牙 LE 外围设备,另一个是扫描广告服务的蓝牙 LE 中央设备。我的 iPhone5s 上的外围设备是 运行,我的 iPad Mini 上的中央设备是 运行。我最初将中央设置为扫描特定广告服务,但后来将其更改为侦听任何服务。在任何一种情况下,作为中心的 iPad 迷你应用程序都不会检测到任何广告服务。我不确定是我设置外围管理器进行广告的方式有问题,还是我设置中央管理器进行扫描的方式有问题,或者是设备配置问题。请提供我可以执行的建议或测试以使其正常工作。
以下是iPhone5s app作为外设的相关代码:
CBPeripheralManager *peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil options:nil];
CBUUID *immediateAlertServiceUUID = [CBUUID UUIDWithString: IMMEDIATE_ALERT_SERVICE_UUID];
CBUUID *alertLevelCharacteristicUUID = [CBUUID UUIDWithString: ALERT_LEVEL_CHARACTERISTIC_UUID];
CBUUID *myCustomCharacteristicUUID = [CBUUID UUIDWithString: MY_CUSTOM_CHARACTERISTIC_UUID];
alertLevelCharacteristic =
[[CBMutableCharacteristic alloc] initWithType:alertLevelCharacteristicUUID
properties:CBCharacteristicPropertyRead
value: nil permissions:CBAttributePermissionsReadable];
myCustomCharacteristic =
[[CBMutableCharacteristic alloc] initWithType:myCustomCharacteristicUUID
properties:CBCharacteristicPropertyRead
value: nil permissions:CBAttributePermissionsReadable];
NSArray *myCharacteristics = @[alertLevelCharacteristic, myCustomCharacteristic];
// Now setup the service
myService = [[CBMutableService alloc] initWithType:immediateAlertServiceUUID primary:YES];
// Finally, associate the characteristic with the service. This is an array of characteristics
myService.characteristics = myCharacteristics;
[peripheralManager addService:myService];
... wait for user to push button to start advertising ...
// Start Advertising
[peripheralManager startAdvertising:@{ CBAdvertisementDataLocalNameKey : @"My Service",
CBAdvertisementDataServiceUUIDsKey : @[myService.UUID] }];
这里是必要的委托方法。注意:委托方法 peripheralManagerDidUpdateState 触发并指示 "CoreBluetooth BLE hardware is powered on and ready"(中央端也是如此)。委托方法 peripheralManager:didAddService:error 无误地触发(见下面的输出)。并且委托方法 peripheralManagerDidStartAdvertising:error 会在没有错误的情况下触发)。这是从 didAddService 打印的服务信息:
<CBMutableService: 0x17008efb0 Primary = YES, UUID = 1802, Included Services = (null), Characteristics = (
"<CBMutableCharacteristic: 0x1702c1500 UUID = 2A06, Value = (null), Properties = 0x2, Permissions = 0x1, Descriptors = (null), SubscribedCentrals = (\n)>",
"<CBMutableCharacteristic: 0x1702c15e0 UUID = 66E613B5-7225-42C6-A9C2-11FADAE62899, Value = (null), Properties = 0x2, Permissions = 0x1, Descriptors = (null), SubscribedCentrals = (\n)>")>
CBPeripheralManager 委托方法(抱歉所有代码,只是试图完整。):
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
// Determine the state of the peripheral
if ([peripheral state] == CBPeripheralManagerStatePoweredOff) {
NSLog(@"CoreBluetooth BLE hardware is powered off");
}
else if ([peripheral state] == CBPeripheralManagerStatePoweredOn) {
NSLog(@"CoreBluetooth BLE hardware is powered on and ready");
}
else if ([peripheral state] == CBPeripheralManagerStateUnauthorized) {
NSLog(@"CoreBluetooth BLE state is unauthorized");
}
else if ([peripheral state] == CBPeripheralManagerStateUnknown) {
NSLog(@"CoreBluetooth BLE state is unknown");
}
else if ([peripheral state] == CBPeripheralManagerStateUnsupported) {
NSLog(@"CoreBluetooth BLE hardware is unsupported on this platform");
}
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral
didAddService:(CBService *)service
error:(NSError *)error {
if (error) {
NSLog(@"Error publishing service: %@", [error localizedDescription]);
return;
}
else {
NSLog(@"Hurray! Your Service has been successfully published as: %@", service);
}
}
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral
error:(NSError *)error {
if (error == nil) {
NSLog(@"Your service is now advertising");
}
else {
NSLog(@"In peripheralManagerDidStartAdvertising: Your service advertising failed with error: %@", error);
}
}
这里是在 iPad Mini 上运行的相关中央代码:
// Scan for all available CoreBluetooth LE devices
NSArray *services = @[[CBUUID UUIDWithString:IMMEDIATE_ALERT_SERVICE_UUID]];
CBCentralManager *centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
//[centralManager scanForPeripheralsWithServices:services options:nil];
[centralManager scanForPeripheralsWithServices:nil options:nil];
self.centralManager = centralManager;
这是中央委托方法之一。除了 centralManagerDidUpdateState:,none 的委托方法会触发。
// CBPeripheralDelegate - Invoked when you discover the peripheral's available services.
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
NSLog(@"Did Discover Services");
for (CBService *service in peripheral.services) {
[peripheral discoverCharacteristics:nil forService:service];
}
}
// CBCentralManagerDelegate - This is called with the CBPeripheral class as its main input parameter. This contains most of the information there is to know about a BLE peripheral.
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(@"Did Discover Peripheral");
NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];
if (![localName isEqual:@"My Service"]) {
// We found the Device
[self.centralManager stopScan];
self.myPeripheral = peripheral;
peripheral.delegate = self;
[self.centralManager connectPeripheral:peripheral options:nil];
}
}
最后一点,我质疑 BLE 是否能在我的设备上运行。我在 iPhone 和 iPad Mini 上加载了几个不同的 iBeacon 应用程序,看看我是否能让这两个设备识别 iBeacons(一个发送,一个接收),但它们也没有发现 iBeacons。我还尝试了两个 iPhones。我还关闭了蓝牙然后再打开。我还尝试为设备供电 off/on。两个设备都在前台 运行。仍然没有运气。请帮忙。
我将在这里串联所有评论:
使用 LightBlue 或 BLE Utility 等应用程序可以帮助您确定您的问题是出在外围还是中央,因为你自己在发展双方。
在查找 CBServices
之前,您必须连接到 CBPeripheral
。
方法你手头确实展示过,好像不是很明显。
此外,在使用 CBCentralManager
开始扫描之前,您必须检查它的 state
,它必须是 CBPeripheralManagerStatePoweredOn
.