iOS8 and BTLE | CBCentralManager unable to find peripherals - ios

I have an iOS app that is connecting to a device (arduino) using a BTLE. Everything is working fine on my iPad iOS 7. After upgrading to iOS 8, the CBCentralManager is not finding any peripherals.
- (void)startScanningForSupportedUUIDs
{
[self.centralManager scanForPeripheralsWithServices:nil options:nil];
}
I don't know what can be the problem.

I have the solution, for some reason in iOS 8 there is some delay after instantiate your CBManager. You need to start to scan when the CBCentralManager is on, in this method:
-(void)centralManagerDidUpdateState:(CBCentralManager *)central{
switch (central.state) {
case CBCentralManagerStatePoweredOff:
NSLog(#"CoreBluetooth BLE hardware is powered off");
break;
case CBCentralManagerStatePoweredOn:
{
NSLog(#"CoreBluetooth BLE hardware is powered on and ready");
NSArray *uuidArray = [NSArray arrayWithObjects:[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID], nil];
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
[centralManager scanForPeripheralsWithServices:uuidArray options:options];
}
break;
case CBCentralManagerStateResetting:
NSLog(#"CoreBluetooth BLE hardware is resetting");
break;
case CBCentralManagerStateUnauthorized:
NSLog(#"CoreBluetooth BLE state is unauthorized");
break;
case CBCentralManagerStateUnknown:
NSLog(#"CoreBluetooth BLE state is unknown");
break;
case CBCentralManagerStateUnsupported:
NSLog(#"CoreBluetooth BLE hardware is unsupported on this platform");
break;
default:
break;
}

In IOS 7 you could get away by starting a BLE scan even before the CBCentralManager was ready. IOS 7 used to spit out a warning in such cases -
CoreBluetooth[API MISUSE] can only accept commands while in the powered on state
With IOS8 - the warning no more appears and the scan does not actually start. To overcome the problem, wait for the CBCentral to power on - ie, wait for CBCentral manager to get to the "CBCentralManagerStatePoweredOn" state and then start the scan. It works fine with that change:)

Related

iOS11 bluetooth has something strange

When I switch off the Bluetooth in setting, then I use CBCentralManager to get the state of the Bluetooth like this:
self.bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
the system will display a alert like this: system alert
The current state of Bluetooth is CBManagerStatePoweredOff. But when I switch off the Bluetooth in control center, this alert is not show anymore even if the current state of Bluetooth is still CBManagerStatePoweredOff.
How could I remind the user to switch on the Bluetooth in this situation?
You can remind the users by implementing the following delegate method.
//Bluetooth state delegation
#pragma mark - CBCentralManagerDelegate
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
NSString *stateString = nil;
switch(self.CBManager.state)
{
case CBManagerStateResetting:
stateString = #"The connection with the system service was momentarily lost, update imminent.";
break;
case CBManagerStateUnsupported:
stateString = #"The platform doesn't support Bluetooth Low Energy."; break;
case CBManagerStateUnauthorized: stateString = #"The app is not authorized to use Bluetooth Low Energy.";
break;
case CBManagerStatePoweredOff:
stateString = #"Bluetooth is currently powered off.";
break;
case CBManagerStatePoweredOn:
[self.beaconManager startMonitoringForRegion:self.museumsRegion];
[self.beaconManager startRangingBeaconsInRegion: self.museumsRegion];
break;
case CBManagerStateUnknown:
stateString = #"State unknown, update imminent.";
break;
}
NSLog(#"%#", stateString);
}
Now the user should be informed automatically.
You can disable system BlueTooth alert by using CBCentralManagerOptionShowPowerAlertKey in options dict.
NSDictionary *options = #{CBCentralManagerOptionShowPowerAlertKey: #NO};
self.bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:options];
Then you can using deleget method centralManagerDidUpdateState: to popup you custom alert.

Detecting Apple Watch Using CoreBluetooth

I am discovering bluetooth devices using Core Bluetooth from my iPhone, but it does not pick up the Apple Watch. Is there something I'm missing? Here is the code I'm using below:
#pragma mark - CBCentralManagerDelegate
// method called whenever you have successfully connected to the BLE peripheral
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
}
// 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(#"%#", [peripheral name]);
}
// method called whenever the device state changes.
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch ([central state])
{
case CBCentralManagerStatePoweredOff:
NSLog(#"CoreBluetooth BLE hardware is powered off");
break;
case CBCentralManagerStatePoweredOn:
NSLog(#"CoreBluetooth BLE hardware is powered on and ready");
[[self bluetoothManager] scanForPeripheralsWithServices:nil options:nil];
break;
case CBCentralManagerStateResetting:
NSLog(#"CoreBluetooth BLE hardware is resetting");
break;
case CBCentralManagerStateUnauthorized:
NSLog(#"CoreBluetooth BLE state is unauthorized");
break;
case CBCentralManagerStateUnknown:
NSLog(#"CoreBluetooth BLE state is unknown");
break;
case CBCentralManagerStateUnsupported:
NSLog(#"CoreBluetooth BLE hardware is unsupported on this platform");
break;
default:
break;
}
}
My Apple Watch shows up when I run the following code:
[self.centralManager retrieveConnectedPeripheralsWithServices:#[[CBUUID UUIDWithString:#"180A"]]];
180A is the Device Information service.
Not sure which characteristics you can discover and subscribe to, if any, but you can definitely detect the watch's presence.
U do not use Core Bluetooth to connect to Apple Watch you use another framework called connectivity
https://developer.apple.com/documentation/watchconnectivity/using_watch_connectivity_to_communicate_between_your_apple_watch_app_and_iphone_app

Unable to discover peripheral Bluetooth Low Energy devices

I recently upgraded my phone to the iOS Beta version 8 and installed my iOS app . Unfortunately my app no longer is able to discover my peripheral BLE device. I checked for any documentation which says if there has been any change but found none. Has there been any known API changes that have been introduced as part of iOS 8 ? I am testing on iPhone 5s
My code was working earlier on IOS version 7.xx
Relevant piece of code :
[self.CM scanForPeripheralsWithServices:nil options:nil];
Where are you launching the scan?
You should call
self.CM = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
in the viewDidLoad or anywhere else you need to to that, and then scan for peripherals only when the centralmanager state is on:
-(void)centralManagerDidUpdateState:(CBCentralManager *)central{ switch (central.state) {
case CBCentralManagerStatePoweredOff:
NSLog(#"CoreBluetooth BLE hardware is powered off");
break;
case CBCentralManagerStatePoweredOn:
{
NSLog(#"CoreBluetooth BLE hardware is powered on and ready");
[self.CM scanForPeripheralsWithServices:nil options:nil];
}
break;
case CBCentralManagerStateResetting:
NSLog(#"CoreBluetooth BLE hardware is resetting");
break;
case CBCentralManagerStateUnauthorized:
NSLog(#"CoreBluetooth BLE state is unauthorized");
break;
case CBCentralManagerStateUnknown:
NSLog(#"CoreBluetooth BLE state is unknown");
break;
case CBCentralManagerStateUnsupported:
NSLog(#"CoreBluetooth BLE hardware is unsupported on this platform");
break;
default:
break; }

Couldn't Discover Peripheral in Core Bluetooth

I've iPhone app and I want to connect with bluetooth device to get Glucose Measurements. You can find the device from here.
After reading Apple documentation about Core Bluetooth I started reading these tutorial. Also I get the services ID's for bluetooth devices from these link here
So I started to code like in the tutorial after understanding the basics.
And these my Code:
#define POLARH7_HRM_DEVICE_INFO_SERVICE_UUID #"180A" // for Device Information service.
#define POLARH7_HRM_HEART_RATE_SERVICE_UUID #"1808" // For Glucose service.
NSArray *services = #[[CBUUID UUIDWithString:POLARH7_HRM_HEART_RATE_SERVICE_UUID], [CBUUID UUIDWithString:POLARH7_HRM_DEVICE_INFO_SERVICE_UUID]];
CBCentralManager *centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
[centralManager scanForPeripheralsWithServices:services options:nil];
self.centralManager = centralManager;
And I've implemented the delegates for CBCentralManagerDelegate and CBPeripheralDelegate
I receive a notification for centralManagerDidUpdateState
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
// Determine the state of the peripheral
if ([central state] == CBCentralManagerStatePoweredOff) {
NSLog(#"CoreBluetooth BLE hardware is powered off");
}
else if ([central state] == CBCentralManagerStatePoweredOn) {
NSLog(#"CoreBluetooth BLE hardware is powered on and ready");
}
else if ([central state] == CBCentralManagerStateUnauthorized) {
NSLog(#"CoreBluetooth BLE state is unauthorized");
}
else if ([central state] == CBCentralManagerStateUnknown) {
NSLog(#"CoreBluetooth BLE state is unknown");
}
else if ([central state] == CBCentralManagerStateUnsupported) {
NSLog(#"CoreBluetooth BLE hardware is unsupported on this platform");
}
}
My NSLog logs : CoreBluetooth BLE hardware is powered on and ready.
But I did not receive a notification for central didDiscoverPeripheral.
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];
if ([localName length] > 0) {
NSLog(#"Found the heart rate monitor: %#", localName);
[self.centralManager stopScan];
self.polarH7HRMPeripheral = peripheral;
peripheral.delegate = self;
[self.centralManager connectPeripheral:peripheral options:nil];
}
}
These method is not being called.
So the central (my iPhone) couldn't discover the Peripheral which is my Glucose device.
I couldn't find the device when I search for it from Setting ->Bluetooth.
If centralManager:didDiscoverPeripheral:advertisementData:RSSI: is never called, this likely means that there is no peripheral with one of provided CBUUIDs. You could try to provide nil instead of the services-array and check if there is any peripheral available (don't do this in production mode).
OK, I think I figured out the problem after sending email to TaiDoc company they told me that these device dose not support iPhone bluetooth integration.
I tried to connect with Tom-Tom GPS watch and it's connected successfully :)
So I think the problem of the issue is a Hardware issue.

How to get list of available Bluetooth devices?

I'm currently creating an iPhone app (Xcode 4.3.1, IOS 5) that could use Bluetooth devices! Main goal of this application is indoor navigation (GPS inside buildings isn't really accurate).
The only solution I see here (to keep my app on AppStore) is to try scan for available bluetooth devices!
I tried to use CoreBluetooth framework, but I don't get list of available devices!
Maybe I don't use these functions correctly
#import <UIKit/UIKit.h>
#import <CoreBluetooth/CoreBluetooth.h>
#interface AboutBhyperView : UIViewController <CBPeripheralDelegate, CBCentralManagerDelegate>
{
CBCentralManager *mgr;
}
#property (readwrite, nonatomic) CBCentralManager *mgr;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
mgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog([NSString stringWithFormat:#"%#",[advertisementData description]]);
}
-(void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals{
NSLog(#"This is it!");
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
NSString *messtoshow;
switch (central.state) {
case CBCentralManagerStateUnknown:
{
messtoshow=[NSString stringWithFormat:#"State unknown, update imminent."];
break;
}
case CBCentralManagerStateResetting:
{
messtoshow=[NSString stringWithFormat:#"The connection with the system service was momentarily lost, update imminent."];
break;
}
case CBCentralManagerStateUnsupported:
{
messtoshow=[NSString stringWithFormat:#"The platform doesn't support Bluetooth Low Energy"];
break;
}
case CBCentralManagerStateUnauthorized:
{
messtoshow=[NSString stringWithFormat:#"The app is not authorized to use Bluetooth Low Energy"];
break;
}
case CBCentralManagerStatePoweredOff:
{
messtoshow=[NSString stringWithFormat:#"Bluetooth is currently powered off."];
break;
}
case CBCentralManagerStatePoweredOn:
{
messtoshow=[NSString stringWithFormat:#"Bluetooth is currently powered on and available to use."];
[mgr scanForPeripheralsWithServices:nil options:nil];
//[mgr retrieveConnectedPeripherals];
//--- it works, I Do get in this area!
break;
}
}
NSLog(messtoshow);
}
I'm not sure about this line, how to pass correct parameters?
[mgr scanForPeripheralsWithServices:nil options:nil];
I took a look into apple reference .. and I still don't understand what's that CBUUID ???
Every device has some bluetooth id? where can I find it?
- (void)scanForPeripheralsWithServices:(NSArray *)serviceUUIDs options:(NSDictionary *)options;
Parameters
serviceUUIDs - An array of CBUUIDs the app is interested in.
options - A dictionary to customize the scan, see CBCentralManagerScanOptionAllowDuplicatesKey.
Is there any other way to use Bluetooth on IOS? I mean, older frameworks that don't use BLE 4.0!
any advice would be appreciated!
thanks!
This guide looks promising for Bluetooth 3.0. Remember that the CoreBluetooth framework is ONLY for Bluetooth Low Energy (4.0). At bluetooth.com's dev-pages you can see some examples of globally defined services, and as Guan Yang mentionen, you can see that the heart rate service is 0x180D. UUID`s of the unit is defined by the manufacturer.
Here's a code snippet to maybe help you along the way.
// Initialize a private variable with the heart rate service UUID
CBUUID *heartRate = [CBUUID UUIDWithString:#"180D"];
// Create a dictionary for passing down to the scan with service method
NSDictionary *scanOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
// Tell the central manager (cm) to scan for the heart rate service
[cm scanForPeripheralsWithServices:[NSArray arrayWithObject:heartRate] options:scanOptions]
in Bluetooth, there are "Services". A device publishes 1..N services, and each service has 1..M characteristics. Each service has an unique identifier, called UUID.
For example, a heart rate Bluetooth Sensor that offers the service "heart rate", publishes a service with UUID 0x180D.
(more services here)
So when you perform a search, you must provide a UUID as the criteria, telling which service to search.
You should take a look at one of the examples. Here’s the relevant line:
[manager scanForPeripheralsWithServices:[NSArray arrayWithObject:[CBUUID UUIDWithString:#"180D"]] options:nil];
(I know this is a Mac OS X example, but the iOS CoreBluetooth API is very similar.)
CBUUID identifies services you are interested in, not devices. Standard services have a 16-bit UUID, in this case 0x180d for the heart rate monitor or perhaps 0x180a for device information, while proprietary services have a 128-bit UUID (16 bytes).
Most devices implement the device information service, so if you are just looking for any device, you could try [CBUUID UUIDWithString:#"180A"].
Try giving this while you are scanning for devices
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
[self.centralManager scanForPeripheralsWithServices:nil options:options];
you will be able to get the list of devices at didDiscoverPeripheral delegate method
Keep calm and use https://github.com/l0gg3r/LGBluetooth
All you need to do
[[LGCentralManager sharedInstance] scanForPeripheralsByInterval:4
completion:^(NSArray *peripherals) {
}];

Resources