运行iOS 6设备作为一个外围设备。

时间:2021-08-23 19:03:04

As we know, iOS 6 support running devices (iPhone 4s and above, and new iPad) as a BLE peripheral. There is a demo in WWDC 2012 Session 705 called "advanced core bluetooth". I asked for the source code from Apple. They sent me a modified version of source code (BTLE_Transfer_Draft). Then I:

正如我们所知道的,iOS 6支持将运行设备(iPhone 4s及以上,以及新的iPad)作为一种可替代的外围设备。在WWDC 2012年705会议上有一个名为“高级核心蓝牙”的演示。我问了苹果公司的源代码。他们给我发了一个修改后的源代码(BTLE_Transfer_Draft)。然后我:

  • Run the app in iPhone 5 (iOS 6) in "Peripheral Mode" and start "Advertising"
  • 在“外围模式”中运行iPhone 5 (iOS 6)中的应用,开始“广告”
  • Run the app in new iPad (iOS 5.1.1) in "Central Mode"
  • 在新iPad (iOS 5.1.1)的“*模式”下运行app

The problem is that the peripheral is never been discovered at all. So I use other testing applications including some downloaded from App Store. All failed to discover peripherals. I think the problem should be in BTLE_Transfer_Draft. Because I'm not sure whether I'm allowed to present the whole source code. So I just show the "peripheral mode" part here:

问题是这些外围设备根本就没有被发现。所以我使用其他测试应用程序,包括从App Store下载的一些。都没有发现外围设备。我认为问题应该在BTLE_Transfer_Draft中。因为我不确定是否允许我展示整个源代码。这里我只展示了"外围模式"部分

- (void)viewDidLoad {
    [super viewDidLoad];

    // Start up the CBPeripheralManager
    _peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
}

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
    // Opt out from any other state
    if (peripheral.state != CBPeripheralManagerStatePoweredOn) {
        return;
    }

    // We're in CBPeripheralManagerStatePoweredOn state...
    NSLog(@"self.peripheralManager powered on.");

    // ... so build our service.

    // Start with the CBMutableCharacteristic
    self.transferCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]
                                                                  properties:CBCharacteristicPropertyNotify
                                                                       value:nil
                                                                 permissions:CBAttributePermissionsReadable];

    // Then the service
    CBMutableService *transferService = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]
                                                                    primary:YES];

    // Add the characteristic to the service
    transferService.characteristics = @[self.transferCharacteristic];

    // And add it to the peripheral manager
    [self.peripheralManager addService:transferService];
}

/** Start advertising
 */
- (IBAction)switchChanged:(id)sender
{
    if (self.advertisingSwitch.on) {
        // All we advertise is our service's UUID
        [self.peripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] }];
    }
    else {
        [self.peripheralManager stopAdvertising];
    }
}

The BLE is in powered on status and the startAdvertising is called. But the BLE central can never discover it.

The BLE isin power on status and The startAdvertising is called. The BLE isin power on status and The startAdvertising is called。但BLE central永远无法发现它。

Post updated:

文章更新:

According to mttrb's suggestion I added "CBAdvertisementDataLocalNameKey" when I startAdvertising. But my service is still can't be discovered by most of the apps including some apps from app store. The only one app can discover my service is an app from app store called "BLE scanner".

根据mttrb的建议,我在开始做广告时添加了“CBAdvertisementDataLocalNameKey”。但我的服务仍然无法被大多数应用程序发现,包括一些来自app store的应用程序。唯一能发现我的服务的应用是app store里的一款名为“BLE scanner”的应用。

My question is: does this mean my application is working as a peripheral? But why my own code can't discover the service? How am I supposed to debug it ?

我的问题是:这是否意味着我的应用程序作为外围设备工作?但是为什么我自己的代码不能发现服务呢?我应该如何调试它?

My code in Central Mode is like this:

我在*模式下的代码是这样的:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Start up the CBCentralManager
    _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}

- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    if (central.state != CBCentralManagerStatePoweredOn) {
        return;
    }
    [self.centralManager scanForPeripheralsWithServices:nil options:nil];
}

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
......
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
    if (error) {
        NSLog(@"Error discovering services: %@", [error localizedDescription]);
        return;
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    // Deal with errors (if any)
    if (error) {
        NSLog(@"Error discovering characteristics: %@", [error localizedDescription]);
        return;
    }
}

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    NSLog(@"Peripheral Disconnected");
    self.discoveredPeripheral = nil;
}

The didDiscoverPeripheral and didDiscoverServices are never called. What could be wrong? Any idea? Thanks

从未调用diddiscover外围设备和didDiscoverServices。可能是错的呢?任何想法?谢谢

5 个解决方案

#1


12  

There is also a high quality free app called LightBlue that you can use to test your code with. It should be able to pick up all devices advertising in peripheral mode and it can even turn itself into an advertising peripheral if you want to make sure your device is working properly.

还有一个高质量的免费应用叫做LightBlue,你可以用它来测试你的代码。如果你想确保你的设备正常工作,它应该能够接收所有在外围模式下做广告的设备,甚至可以把自己变成一个广告外围设备。

#2


3  

I would try moving the startAdvertising: method call up and into the end of your peripheralManagerDidUpdateState: delegate method and see if that helps.

我将尝试移动startAdvertising:方法调用,并进入你的外围管理器didupdatestate: delegate方法,看看是否有用。

I would also add a CBAdvertisementDataLocalNameKey key-value pair to your startAdvertising: method call. I found things were unreliable when the advertisement didn't have a name.

我还将向您的startAdvertising: method调用添加一个CBAdvertisementDataLocalNameKey键-value对。当广告没有名字时,我发现事情不可靠。

Finally, I would invest in the BLExplr app available in the App Store to help with scanning for your peripheral. It removes the assumption that your central is working correctly.

最后,我将投资于应用商店中可用的BLExplr应用程序,以帮助您扫描外围设备。它消除了您的中心正在正确工作的假设。

#3


3  

This Git hub project also throws some light on the CBPeripheralManager API. Called PeripheralModeTest. This line is particularly useful for setting the advertising data

这个Git hub项目还介绍了CBPeripheralManager API。叫PeripheralModeTest。这一行对设置广告数据特别有用

 NSDictionary *advertisingData = @{CBAdvertisementDataLocalNameKey : @"Device Name", CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:CBUUIDGenericAccessProfileString]]};

Though I can't see any official documentation in the Apple iOS Developer Library yet. More specifically anything about setting the repeat period for the advertising.

虽然我还没有在苹果iOS开发者库中看到任何官方文档。更具体地说,就是设定广告的重复周期。

#4


2  

The BTLE Transfer example has this piece of (odd) code, which may cause some troubles:

BTLE传输示例有这段(奇数)代码,这可能会引起一些麻烦:

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
    // Reject any where the value is above reasonable range
    if (RSSI.integerValue > -15) {
        return;
    }

    // Reject if the signal strength is too low to be close enough (Close is around -22dB)
    if (RSSI.integerValue < -35) {
        return;
    }

Just remove those two if-statements as it makes no sense!

删除这两个if语句,因为它毫无意义!

I have made a simplified version available here that can be used to test high volumes of messages being sent from peripheral to central.

我在这里提供了一个简化版本,可以用来测试从外围设备发送到中环的大量消息。

Please note that the CBPeripheralManager class was first introduced in iOS 6.0.

请注意,CBPeripheralManager类是在ios6.0中首次引入的。

#5


0  

I do not know witch version of BTLE Central Peripheral Transfer you did actually test but current version has iOS 6 as requirement.

我不知道你测试过的女巫版本的BTLE*外围设备传输,但是现在的版本有ios6作为要求。

So I would suggest to test linkage against iOS 5.1 to see what compatibility issues it shows.

因此,我建议对iOS 5.1进行链接测试,看看它显示了哪些兼容性问题。

#1


12  

There is also a high quality free app called LightBlue that you can use to test your code with. It should be able to pick up all devices advertising in peripheral mode and it can even turn itself into an advertising peripheral if you want to make sure your device is working properly.

还有一个高质量的免费应用叫做LightBlue,你可以用它来测试你的代码。如果你想确保你的设备正常工作,它应该能够接收所有在外围模式下做广告的设备,甚至可以把自己变成一个广告外围设备。

#2


3  

I would try moving the startAdvertising: method call up and into the end of your peripheralManagerDidUpdateState: delegate method and see if that helps.

我将尝试移动startAdvertising:方法调用,并进入你的外围管理器didupdatestate: delegate方法,看看是否有用。

I would also add a CBAdvertisementDataLocalNameKey key-value pair to your startAdvertising: method call. I found things were unreliable when the advertisement didn't have a name.

我还将向您的startAdvertising: method调用添加一个CBAdvertisementDataLocalNameKey键-value对。当广告没有名字时,我发现事情不可靠。

Finally, I would invest in the BLExplr app available in the App Store to help with scanning for your peripheral. It removes the assumption that your central is working correctly.

最后,我将投资于应用商店中可用的BLExplr应用程序,以帮助您扫描外围设备。它消除了您的中心正在正确工作的假设。

#3


3  

This Git hub project also throws some light on the CBPeripheralManager API. Called PeripheralModeTest. This line is particularly useful for setting the advertising data

这个Git hub项目还介绍了CBPeripheralManager API。叫PeripheralModeTest。这一行对设置广告数据特别有用

 NSDictionary *advertisingData = @{CBAdvertisementDataLocalNameKey : @"Device Name", CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:CBUUIDGenericAccessProfileString]]};

Though I can't see any official documentation in the Apple iOS Developer Library yet. More specifically anything about setting the repeat period for the advertising.

虽然我还没有在苹果iOS开发者库中看到任何官方文档。更具体地说,就是设定广告的重复周期。

#4


2  

The BTLE Transfer example has this piece of (odd) code, which may cause some troubles:

BTLE传输示例有这段(奇数)代码,这可能会引起一些麻烦:

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
    // Reject any where the value is above reasonable range
    if (RSSI.integerValue > -15) {
        return;
    }

    // Reject if the signal strength is too low to be close enough (Close is around -22dB)
    if (RSSI.integerValue < -35) {
        return;
    }

Just remove those two if-statements as it makes no sense!

删除这两个if语句,因为它毫无意义!

I have made a simplified version available here that can be used to test high volumes of messages being sent from peripheral to central.

我在这里提供了一个简化版本,可以用来测试从外围设备发送到中环的大量消息。

Please note that the CBPeripheralManager class was first introduced in iOS 6.0.

请注意,CBPeripheralManager类是在ios6.0中首次引入的。

#5


0  

I do not know witch version of BTLE Central Peripheral Transfer you did actually test but current version has iOS 6 as requirement.

我不知道你测试过的女巫版本的BTLE*外围设备传输,但是现在的版本有ios6作为要求。

So I would suggest to test linkage against iOS 5.1 to see what compatibility issues it shows.

因此,我建议对iOS 5.1进行链接测试,看看它显示了哪些兼容性问题。