I have a custom object BLEDevice which has a weak reference to a CBPeripheral object. I maintain a dictionary that keeps the associations between the peripherals and my custom objects:
- (void)setDeviceForPeripheral:(CBPeripheral *)peripheral {
// New device: sets a new 'BLEDevice' instance
BLEDevice *new = [[BLEDevice alloc] initWithPeripheral:peripheral];
new.name = peripheral.name;
new.peripheral.delegate = self;
[associations setObject:new forKey:peripheral];
}
When I discover a new peripheral in the nearbies, I perform the following operations:
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI {
if (![associations objectForKey:peripheral]) {
NSLog(#"Found peripheral: %#", peripheral.name);
[self setDeviceForPeripheral:peripheral];
[[NSNotificationCenter defaultCenter] postNotificationName:#"BLEDeviceFound" object:nil];
}
}
At this point, I define a custom method to connect to my device:
- (void)connect:(BLEDevice *)device {
// Connects with the peripheral
[manager connectPeripheral:device.peripheral options:nil];
}
Here everything works just fine: my peripheral gets connected and I start performing operations on services and characteristics inside the delegate method centralManager:didConnectPeripheral:.
Now my troubles come. When I want to disconnect to my peripheral, I perform the following operations:
- (void)disconnect:(BLEDevice *)device {
// Unsubscribes from all the characteristics in services
for (CBService *service in device.peripheral.services) {
for (CBCharacteristic *characteristic in service.characteristics)
[device.peripheral setNotifyValue:NO forCharacteristic:characteristic];
}
[manager cancelPeripheralConnection:device.peripheral];
}
When I call this method, my peripheral device confirms me that the disconnection was successful. Anyway, the delegate method centralManager:didDisconnectPeripheral: is not getting called. Can someone please explain me why?
I discovered that the solution is really simple. I just called the wrong delegate method. The correct signature is
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error.
This shit has been driving me crazy since weeks!
The method is not called when you disconnect the peripherals as the name of it tells. What you want is the following.
- centralManager:didDisconnectPeripheral:error:
The document says:
Invoked when an existing connection with a peripheral is torn down.
The delegate method will be called when you disconnect the peripherals.
Related
i’m trying to perform the following operations with the Core Bluetooth Framework of iOS:
1) Connection to peripheral
2) Services Discovery
3) Characteristics Discovery
4) Start Notify on a particular characteristic
These operations have to be triggered in background, when a callback not related to Core Bluetooth (Core Location Framework) fires up.
I have correctly set the Bluetooth Background settings for the app and when the application is put in background through the central button, all is ok: core location callback fires up and the core bluetooth steps are executed correctly.
The problem comes when the application is killed by swiping up with the task manager: in this case when the core location callback fires up the phone is able to connect to the peripheral (1) but it does not discover services.
I’m using iPhone 6 with iOS 10.3.1 and micro nrf51822.
Here is my code:
CBCentralManager initialization (viewDidLoad)
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:#{ CBCentralManagerOptionRestoreIdentifierKey:#“myCentralManagerIdentifier”}];
Core Location Callback:
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{
NSLog(#“*** enter region”);
dispatch_async(dispatch_get_main_queue(), ^{
NSString *savedUuid = [[NSUserDefaults standardUserDefaults]stringForKey:#“preferenceUuid”];
if (savedUuid!=NULL){
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:savedUuid];
NSArray *arrayUuid = [NSArray arrayWithObjects:uuid, nil];
_knownPeripheral = [[self.centralManager retrievePeripheralsWithIdentifiers:arrayUuid] objectAtIndex:0];
}
if (_knownPeripheral!=NULL){
[self.centralManager connectPeripheral:_knownPeripheral options:nil];
}
});
}
CoreBluetooth Callbacks:
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral(CBPeripheral *)peripheral {
[self.knownPeripheral discoverServices:nil];
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
//Core Bluetooth creates an array of CBService objects —- one for each service that is discovered on the peripheral.
for (CBService *service in peripheral.services) {
if (([service.UUID isEqual:[CBUUID UUIDWithString:K_BT_SERVICE_BATTERY]])) {
[peripheral discoverCharacteristics:nil forService:service];
}
}
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
for (CBCharacteristic *characteristic in service.characteristics) {
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:K_BT_CHARACTERISTIC_BATTERY]]) {
[self.sensorTag setNotifyValue:YES forCharacteristic:characteristic];
}
}
}
How can i perform correctly the steps from 1) to 4) when the application is awaked from a killed state?
Thank you
I want use CoreBluetooth.framework in IOS8 to achieve data transfer, i did discover peripheral in the follow method and try connect the peripheral.
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(#"Discover name : %#", peripheral.name);
[self.centralManager connectPeripheral:peripheral options:nil];
}
But it did not call the delegate methods didFailToConnectPeripheral or didConnectPeripheral , I waner what's wrong with it, is the code error or IOS8 need some extra things ? How to deal it, thank in advance!
here is my code in github ,I write a Program to be server and another be Central.
#Sj comment solved it for me, copying it into an answer in case someone will miss it:
Did u tried storing the peripheral object in an ivar and then connect to it? ie self.discoveredPeripheral = peripheral; [self.centralManager connectPeripheral:self.discoveredPeripheral options:nil];
I am using TemperatureSensor iOS sample app which didDiscoverPeripheral did not called. By reference the flow of Heart Rate Monitor Mac sample app. Please make sure the run sequence of code is:
1. centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
2. - (void) centralManagerDidUpdateState:(CBCentralManager *)central
3. [centralManager scanForPeripheralsWithServices:...
- (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:... will be called afterwards.
Call the connect method only once and wait for the connection delegate response. The above code which you posted will call the connect method more often (when ever it discover the peripheral)
if(!self.detectedBLE){
[self.centralManager stopScan];
self.detectedBLE = peripheral;
[self.centralManager connectPeripheral:self.detectedBLE options:nil];
}
It seems this question was "answered" here, but without any code to show what they did differently I'm having to ask a new question.
I have my own code with the same behaviour, where scanning for specific CBUUIDs using Core Bluetooth's CBCentralManager on OS X doesn't discover an iOS device acting as a peripheral with CBPeripheralManager (unless it and its services have previously been discovered). To see if it's something wrong in my code, I downloaded Apple's sample code. Running the sample code on two iOS devices works as intended, however when copying the CBCentralManager code to an OS X app, it fails to find the iOS device.
I've uploaded an Xcode project for the OS X app, it's hosted on WikiUpload as that seems to be the least dodgy. There's also a copy on my hosting, if people prefer.
Here's the AppDelegate.m code in the OS X project also (the CoreBluetooth framework is linked in the project):
#import <CoreBluetooth/CoreBluetooth.h>
#interface AppDelegate () <CBCentralManagerDelegate, CBPeripheralDelegate>
#property (strong, nonatomic) CBCentralManager *centralManager;
#property (strong, nonatomic) CBPeripheral *discoveredPeripheral;
#property (strong, nonatomic) NSMutableData *data;
#property (weak) IBOutlet NSWindow *window;
#end
#implementation AppDelegate
#synthesize centralManager = _centralManager, discoveredPeripheral = _discoveredPeripheral, data = _data;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
// Start up the CBCentralManager
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
// And somewhere to store the incoming data
_data = [[NSMutableData alloc] init];
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
#pragma mark - Central Methods
/** centralManagerDidUpdateState is a required protocol method.
* Usually, you'd check for other states to make sure the current device supports LE, is powered on, etc.
* In this instance, we're just using it to wait for CBCentralManagerStatePoweredOn, which indicates
* the Central is ready to be used.
*/
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
if (central.state != CBCentralManagerStatePoweredOn) {
// In a real app, you'd deal with all the states correctly
return;
}
// The state must be CBCentralManagerStatePoweredOn...
// ... so start scanning
[self scan];
}
/** Scan for peripherals - specifically for our service's 128bit CBUUID
*/
- (void)scan
{
// This brings up nothing, unlike on iOS where it finds the device straight away
[self.centralManager scanForPeripheralsWithServices:#[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]
options:#{ CBCentralManagerScanOptionAllowDuplicatesKey : #YES }];
// [self.centralManager scanForPeripheralsWithServices:nil
// options:#{ CBCentralManagerScanOptionAllowDuplicatesKey : #YES }];
NSLog(#"Scanning started");
}
/** This callback comes whenever a peripheral that is advertising the TRANSFER_SERVICE_UUID is discovered.
* We check the RSSI, to make sure it's close enough that we're interested in it, and if it is,
* we start the connection process
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(#"Discovered %# at %#", peripheral.name, RSSI);
//Took out RSSI check
if (self.discoveredPeripheral != peripheral) {
// Save a local copy of the peripheral, so CoreBluetooth doesn't get rid of it
self.discoveredPeripheral = peripheral;
// And connect
NSLog(#"Connecting to peripheral %#", peripheral);
[self.centralManager connectPeripheral:peripheral options:nil];
}
}
/** If the connection fails for whatever reason, we need to deal with it.
*/
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
NSLog(#"Failed to connect to %#. (%#)", peripheral, [error localizedDescription]);
[self cleanup];
}
/** We've connected to the peripheral, now we need to discover the services and characteristics to find the 'transfer' characteristic.
*/
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(#"Peripheral Connected");
// Stop scanning
[self.centralManager stopScan];
NSLog(#"Scanning stopped");
// Clear the data that we may already have
[self.data setLength:0];
// Make sure we get the discovery callbacks
peripheral.delegate = self;
// Search only for services that match our UUID
[peripheral discoverServices:#[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]];
}
/** The Transfer Service was discovered
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
if (error) {
NSLog(#"Error discovering services: %#", [error localizedDescription]);
[self cleanup];
return;
}
// Discover the characteristic we want...
// Loop through the newly filled peripheral.services array, just in case there's more than one.
for (CBService *service in peripheral.services) {
[peripheral discoverCharacteristics:#[[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]] forService:service];
}
}
/** The Transfer characteristic was discovered.
* Once this has been found, we want to subscribe to it, which lets the peripheral know we want the data it contains
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
// Deal with errors (if any)
if (error) {
NSLog(#"Error discovering characteristics: %#", [error localizedDescription]);
[self cleanup];
return;
}
// Again, we loop through the array, just in case.
for (CBCharacteristic *characteristic in service.characteristics) {
// And check if it's the right one
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
// If it is, subscribe to it
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
}
// Once this is complete, we just need to wait for the data to come in.
}
/** This callback lets us know more data has arrived via notification on the characteristic
*/
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error) {
NSLog(#"Error discovering characteristics: %#", [error localizedDescription]);
return;
}
NSString *stringFromData = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
// Have we got everything we need?
if ([stringFromData isEqualToString:#"EOM"]) {
// We have, so show the data,
//[self.textview setText:[[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding]];
NSLog(#"Text: %#", [[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding]);
// Cancel our subscription to the characteristic
[peripheral setNotifyValue:NO forCharacteristic:characteristic];
// and disconnect from the peripehral
[self.centralManager cancelPeripheralConnection:peripheral];
}
// Otherwise, just add the data on to what we already have
[self.data appendData:characteristic.value];
// Log it
NSLog(#"Received: %#", stringFromData);
}
/** The peripheral letting us know whether our subscribe/unsubscribe happened or not
*/
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error) {
NSLog(#"Error changing notification state: %#", error.localizedDescription);
}
// Exit if it's not the transfer characteristic
if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
return;
}
// Notification has started
if (characteristic.isNotifying) {
NSLog(#"Notification began on %#", characteristic);
}
// Notification has stopped
else {
// so disconnect from the peripheral
NSLog(#"Notification stopped on %#. Disconnecting", characteristic);
[self.centralManager cancelPeripheralConnection:peripheral];
}
}
/** Once the disconnection happens, we need to clean up our local copy of the peripheral
*/
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
NSLog(#"Peripheral Disconnected");
self.discoveredPeripheral = nil;
// We're disconnected, so start scanning again
[self scan];
}
/** Call this when things either go wrong, or you're done with the connection.
* This cancels any subscriptions if there are any, or straight disconnects if not.
* (didUpdateNotificationStateForCharacteristic will cancel the connection if a subscription is involved)
*/
- (void)cleanup
{
// Don't do anything if we're not connected
if (!self.discoveredPeripheral.isConnected) {
return;
}
// See if we are subscribed to a characteristic on the peripheral
if (self.discoveredPeripheral.services != nil) {
for (CBService *service in self.discoveredPeripheral.services) {
if (service.characteristics != nil) {
for (CBCharacteristic *characteristic in service.characteristics) {
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
if (characteristic.isNotifying) {
// It is notifying, so unsubscribe
[self.discoveredPeripheral setNotifyValue:NO forCharacteristic:characteristic];
// And we're done.
return;
}
}
}
}
}
}
// If we've got this far, we're connected, but we're not subscribed, so we just disconnect
[self.centralManager cancelPeripheralConnection:self.discoveredPeripheral];
}
And in AppDelegate.h there's the UUID definitions:
#ifndef LE_Transfer_TransferService_h
#define LE_Transfer_TransferService_h
#define TRANSFER_SERVICE_UUID #"E20A39F4-73F5-4BC4-A12F-17D1AD07A961"
#define TRANSFER_CHARACTERISTIC_UUID #"08590F7E-DB05-467E-8757-72F6FAEB13D4"
#endif
What's the problem here? According to the above linked question the service has to be part of the advertising packet, but as far as I can see that's exactly what the iOS peripheral is doing with
[self.peripheralManager startAdvertising:#{ CBAdvertisementDataServiceUUIDsKey : #[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] }];
CoreBluetooth can be very frustrating. Here are a couple things to try:
#1: A peripheral that has been connected to stops advertising. If you make a successful connection to the peripheral, you'll need to restart advertising.
#2: iOS caches discovered status and provided services. There's no programmatic way to refresh / clear the cache. Try disabling BT on the iOS device and on the Mac and re-enabling it. Then attempt another connection.
#3: There's a problem with your UUIDs. Try scanning for peripherals with the UUID parameter set to nil. You should then discover all peripherals in range.
#4: The BT connection on a Mac can be finicky if the Wifi is on. Try disabling Wifi on your Mac and try again. I've found BTLE completely unusable with Wifi enabled so I've had to use ethernet when doing any BTLE dev on my MacBook.
I have multiple BLE devices which have same services and characteristics. I can scan and connect multiple devices. After connections, when I try to distinguish each one by sending command it doesn't work. It works perfectly with a single device. Is it something like socket connection ? Like A server spawns child threads and each client can maintain a connection through threads.
Please provide some tips on how to scan each device when other device is reading the data from the device.
-(void) scanDevice {
centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
[centralManager scanForPeripheralsWithServices:nil options:0];
[AppDelegate app].cbCentral = centralManager;
}
-(void) stopScan {
[[AppDelegate app].cbCentral stopScan];
}
-(void)connectToDevice:(CBPeripheral *)peripheral{
[[AppDelegate app] cbCentral].delegate = self;
[[[AppDelegate app] cbCentral] connectPeripheral:peripheral options:nil];
}
-(void)calldiscoverServicesForPeripheral:(CBPeripheral *)peripheral{
[peripheral setDelegate:self];
[peripheral discoverServices:nil];
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
NSLog(#"Connected PERIPHERAL %d",peripheral.state);
[delegate getConnectedPeripheral:peripheral];
NSLog(#"Connected peripheral %#",peripheral);
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
NSLog(#"Discovered servicea: %#", peripheral.services);
for (CBService *service in peripheral.services) {
NSLog(#"Discovered service: %#", [service.UUID data]);
[peripheral discoverCharacteristics:nil forService:service];
}
}
I will explain in detail,
I have table view, that contains BLE devices. For the first time it is empty, so i will search for the devices by calling a class "Scan Devices".
This "Scan devices" class contains all the Corebluetooth methods like CBCentralManager allocation, CBperipheral delegate methods.
After search, I will display the device in table view and connect to the BLE device. I am getting some data from "Scan Device" class.
Now, I want to search more devices to connect and get the data. For this, I will call [[CBCentralManager alloc] initWithDelegate:self] in "ScanDevices" class. At this time, for previous device(connected and reading) is showing the warning "is not a valid peripheral" and new device is connecting and reading data from the device.
But I want read the data from both devices at a time
Please help me...
Thanks
You shouldn't keep creating a new CBCentral - doing so will cause your previous CBCentral to be deallocated and therefore invalidate the existing peripherals.
You should activate your scanning once, say in viewWillAppear and deactivate it in viewWillDisappear.
Once you have initiated scanning and set your delegate in your ScanDevices class, it will call [delegate getConnectedPeripheral:] each time a new peripheral is found and connected.
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:
Run the app in iPhone 5 (iOS 6) in "Peripheral Mode" and start "Advertising"
Run the app in new iPad (iOS 5.1.1) in "Central Mode"
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:
- (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.
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".
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
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.
I would try moving the startAdvertising: method call up and into the end of your peripheralManagerDidUpdateState: delegate method and see if that helps.
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.
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.
This Git hub project also throws some light on the CBPeripheralManager API. Called PeripheralModeTest.
This line is particularly useful for setting the advertising data
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.
The BTLE Transfer example has this piece of (odd) code, which may cause some troubles:
- (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!
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.
I do not know witch version of BTLE Central Peripheral Transfer you did actually test but current version has iOS 6 as requirement.
So I would suggest to test linkage against iOS 5.1 to see what compatibility issues it shows.