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.
Related
I'm trying to write a toy app to get up to speed on BLE. I have a peripheral device (it's a Tile) that I would like to scan its services. However, I do not know what services it is offering (and I don't see this anywhere in the product's technical specifications). So, I got a list of services from the Bluetooth specs, and am trying to scan for all of them. I'm only assuming that this list is exhaustive, since it doesn't say one way or another.
Here is my code:
- (void)viewDidLoad {
[super viewDidLoad];
// Scan for all available CoreBluetooth LE devices
_services = #[[CBUUID UUIDWithString:#"1811"],
[CBUUID UUIDWithString:#"1815"],
[CBUUID UUIDWithString:#"180F"],
[CBUUID UUIDWithString:#"1810"],
[CBUUID UUIDWithString:#"181B"],
[CBUUID UUIDWithString:#"181E"],
[CBUUID UUIDWithString:#"181F"],
[CBUUID UUIDWithString:#"1805"],
[CBUUID UUIDWithString:#"1818"],
[CBUUID UUIDWithString:#"1816"],
[CBUUID UUIDWithString:#"180A"],
[CBUUID UUIDWithString:#"181A"],
[CBUUID UUIDWithString:#"1800"],
[CBUUID UUIDWithString:#"1801"],
[CBUUID UUIDWithString:#"1808"],
[CBUUID UUIDWithString:#"1809"],
[CBUUID UUIDWithString:#"180D"],
[CBUUID UUIDWithString:#"1823"],
[CBUUID UUIDWithString:#"1812"],
[CBUUID UUIDWithString:#"1802"],
[CBUUID UUIDWithString:#"1821"],
[CBUUID UUIDWithString:#"1820"],
[CBUUID UUIDWithString:#"1803"],
[CBUUID UUIDWithString:#"1819"],
[CBUUID UUIDWithString:#"1807"],
[CBUUID UUIDWithString:#"1825"],
[CBUUID UUIDWithString:#"180E"],
[CBUUID UUIDWithString:#"1822"],
[CBUUID UUIDWithString:#"1806"],
[CBUUID UUIDWithString:#"1814"],
[CBUUID UUIDWithString:#"1813"],
[CBUUID UUIDWithString:#"1824"],
[CBUUID UUIDWithString:#"1804"],
[CBUUID UUIDWithString:#"181C"],
[CBUUID UUIDWithString:#"181D"]];
CBCentralManager *centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
[centralManager scanForPeripheralsWithServices:_services options:nil];
self.centralManager = centralManager;
}
- (IBAction)scanForDevices:(UIButton *)sender {
[_centralManager scanForPeripheralsWithServices:_services options:nil];
}
// 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
{
NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];
if ([localName length] > 0) {
NSLog(#"Found the heart rate monitor: %#", localName);
[self.centralManager stopScan];
_hRMPeripheral = peripheral;
peripheral.delegate = self;
[self.centralManager connectPeripheral:peripheral options:nil];
}
}
// method called whenever the device state changes.
- (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");
}
}
The only log output that I get is this:
CoreBluetooth BLE hardware is powered on and ready
Otherwise, the app runs fine. No errors or warnings. But it never finds the peripheral device.
What am I doing wrong? Is there a different service that I should be scanning for?
Thanks!
EDIT
Using a suggestion below, I scanned the peripheral using the LightBlue app. I now know that there is an advertised service that uses this UUID:
84100CBF-D622-8FF7-C8B8-300FDB52B92D
I changed my array to look like this:
_services = #[[CBUUID UUIDWithString:#"84100CBF-D622-8FF7-C8B8-300FDB52B92D"]];
but still nothing gets output in the log. I also tried passing nil but still nothing.
As pointed out by Paulw, just send nil instead of a service list, and you will get all peripherals in range, whatever the service(s) they advertise.
Note that:
this will only work in the foreground. Background scanning requires you to provide services to scan for
in your approach, it would not be possible to list all services. Beyond the services with short UUIDs you listed (which are actually shortcuts to full UUIDs), a device can advertise services with any "full" UUID. There are 2^128 possible values...
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
I have created two iOS apps; one a Bluetooth LE peripheral that advertises a service, and one a Bluetooth LE central that scans for the advertised service. The peripheral is running on my iPhone5s, and the central is running on my iPad Mini. I initially set the central up to scan for the specific advertised service, but later changed it to listen to any service. In either case, the iPad Mini app acting as a central never detects any advertised service. I am uncertain whether its a problem with the way I setup the peripheral manager to advertise, or if its a problem with the way I setup the central manager to scan, or a device configuration problem. Please offer suggestions or tests I can perform to get this working.
The following is the relevant code for the iPhone5s app acting as a peripheral:
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] }];
And here are the necessary delegate methods. NOTE: delegate method peripheralManagerDidUpdateState fires and indicates that "CoreBluetooth BLE hardware is powered on and ready" (same is true on the central side). Delegate method peripheralManager:didAddService:error fires without error (see output below). And delegate method peripheralManagerDidStartAdvertising:error fires without an error). Here is the service info printed from 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 Delegate Methods (sorry for all the code, just trying to be complete.):
- (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);
}
}
And here is the relevant central code that runs on the 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;
And here is one of the Central delegate methods. Except for centralManagerDidUpdateState:, none of the delegate methods fire.
// 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];
}
}
As a final note, I question whether BLE even works on my devices. I loaded a couple different iBeacon apps on the iPhone and iPad Mini to see if I can get the two devices to recognize iBeacons (one transmits, one receives), but they did not discover iBeacons either. I also tried with two iPhones. I also turned Bluetooth off then on. I also tried powering the devices off/on. Both devices are running in the foreground. Still no luck. Please help.
I'll concatenate all the comments here:
Using apps like LightBlue or BLE Utility can help you to find if your issue is on the peripheral side or central one, since you're developing both sides yourself.
Before looking for CBServices, you have to connect to a CBPeripheral.
Method that you did show before hand, and seems that it wasn't obvious.
Also, before starting a scan with the CBCentralManager you have to check its state, and it has to be CBPeripheralManagerStatePoweredOn.
I am using Core Bluetooth Framework in my app.
I know how to scan for peripherals and getting values from it.(like Heart Rate Monitor)
But what I want is to retrieve the surrounding iPhone Devices list that supports BLE 4.0 and Bluetooth Enabled ones.
I referred below links..
Uses IOBluetooth Framework
Uses CoreBluetooth For Getting Peripherals not the Devices List
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
// I'm not sure how to make this work
NSLog (#"Discovered peripheral: %#", [peripheral name]);
[self.list addObject:peripheral.name]; // add peripheral name to foundarray
NSLog (#"UUID peripheral: %#", [peripheral UUID]);
NSLog (#"peripheral services before connected: %#", [peripheral services]);
NSLog(#"adversting data %#",[NSString stringWithFormat:#"%#",[advertisementData description]]);
NSLog(#"foundArray is %#", self.list);
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
NSLog(#"Central manager's state is updated to: %#", central);
if(central.state == CBCentralManagerStatePoweredOn)
{
//okay your good to go and can now scan
}
else
{
//Unable to use CentralManager methods so print out the central.state and find out why
}
}
I dont know whether Apple provides this or not..
Any Suggestions or Ideas will be appreciated..
Thank In Advance..
Try below code checkBluetoothAccess and requestBluetoothAccess method
- (void)checkBluetoothAccess {
if(!self.cbManager) {
self.cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
/*
We can ask the bluetooth manager ahead of time what the authorization status is for our bundle and take the appropriate action.
*/
CBCentralManagerState state = [self.cbManager state];
if(state == CBCentralManagerStateUnknown) {
[self alertViewWithDataClass:Bluetooth status:NSLocalizedString(#"UNKNOWN", #"")];
}
else if(state == CBCentralManagerStateUnauthorized) {
[self alertViewWithDataClass:Bluetooth status:NSLocalizedString(#"DENIED", #"")];
}
else {
[self alertViewWithDataClass:Bluetooth status:NSLocalizedString(#"GRANTED", #"")];
}
}
- (void)requestBluetoothAccess {
if(!self.cbManager) {
self.cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
/*
When the application requests to start scanning for bluetooth devices that is when the user is presented with a consent dialog.
*/
[self.cbManager scanForPeripheralsWithServices:nil options:nil];
}
You can only retrieve the surrounding iOS devices that support Bluetooth 4.0 if they are also advertising a specific service to identify them. You can't just see all iOS devices that are powered on and nearby. If they are advertising, you can just scan for nil and that will return the advertisement packets being seen.
Note: if you care about retrieving BLE devices currently connected from other apps, you can use the retrieveConnectedPeripheralsWithServices: method.
I am working on a small project related to BLE. I have a requirement that I need to re-connect the device in background after manual turn off and then off bluetooth from iPhone->Settings->Bluetooth.
Just store the peripheral identifier or (UUID for < iOS 7), retrieve the peripheral, and call connect on it when the centralManager updates state to powered on.
For iOS 7:
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
if(central.state == CBCentralManagerStatePoweredOn)
{
NSUUID *uuid = [[NSUUID alloc]initWithUUIDString:savedUUID];//where savedUUID is the string version of the NSUUID you've saved somewhere
NSArray *peripherals = [_cbCentralManager retrievePeripheralsWithIdentifiers:#[uuid]];
for(CBPeripheral *periph in peripherals)
{
[_cbCentralManager connectPeripheral:periph options:nil];
}
}
}
For iOS 6:
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
if(central.state == CBCentralManagerStatePoweredOn)
{
CFUUIDRef uuid;//the cfuuidref you've previously saved
[central retrievePeripherals:#[(id)uuid]];//now wait for the delegate callback below
}
}
- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals
{
for(CBPeripheral *periph in peripherals)
{
[_centralManager connectPeripheral:periph options:nil];
}
}
NOTE: these are just code snippets. You should also monitor CBCentralManagerStatePoweredOff (among others) and cancel all current peripheral connections when you get that update.