iPhone does not discover Services on a Bluetooth LE tag on reconnection

I am working on a Bluetooth LE application for iOS. I am using the Core Bluetooth framework within iOS to handle all communications.

Question & Description:

When I use a single tag, despite numerous connections and disconnections, the single tag connects seamlessly and the phone discovers it services. Also, when multiple Bluetooth LE tags connect for the first time, they connect seamlessly and the phone discovers their services. When the tags get disconnected and then reconnect to the phone, the tags connect fine. But one of the two tags (either one) does not seem to advertise its services. i.e when the app is open and the tag reconnects, the DiscoverServices method does not call the didDiscoverServices delegate.

Why is this happening only when connection with multiple devices takes place.

I have set the peripheral.delegate correctly. I have tried everything, including doing repeated re-connect, repeated DiscoverServices calls to the tag. Nothing seems to work.

How can I re-connect to multiple tags to the phone and still discover all services. Please help Thanks, Manju

I had the same problem but realized that I wasn't setting the delegate to CBPeripheral after didConnectPeripheral is called.

- (void) centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    NSLog(@"Peripheral Connected: %@", peripheral.name);

    peripheral.delegate = self;

    if (peripheral.services) {
        [self peripheral:peripheral didDiscoverServices:nil];
    } else {
        [peripheral discoverServices:@[[CBUUID UUIDWithString:CUSTOM_UUID]]];
    }  
}

iPhone does not discover Services on a Bluetooth LE tag , iPhone does not discover Services on a Bluetooth LE tag on reconnection. Question. I am working on a Bluetooth LE application for iOS. I am using the Core​  At arkulpa, we built an app for a customer where — after the initial setup — it was necessary to stay connected to an external BLE device as much as possible without the user having to do

I was facing a similar issue with CoreBluetooth to connect to Bluetooth LE devices, in my case connecting to iOS devices (peripherals) from my Mac (central).

If I get you correctly, the pattern is quite consistent, the first time I run my Mac app for debuging, it always detected and connected to any bluetooth LE devices (peripherals), most importantly, it also discover their services/characteristics fine. The problem starts on the second run (for example, change some code, hit cmd-R to relaunch the debug). The central still detects peripherals and connects to them, but, it fails to discover any services/characteristics. In other words, the delegate peripheral:didDiscoverServices: and peripheral:didDiscoverCharacteristicsForService:error: never get called.

The solution after a lot of trial and errors, is surprisingly simple. It seems that CoreBluetooth caches services and characteristics for peripherals that are still connected, although locally it looks like it had been disconnected to the app, the peripheral still maintains a bluetooth connection to the system. For these type of connections, there is no need to (re)discover the services and characteristics, just access them directly from the peripheral object, check for nil to know if you should discover them. Also, as mentioned, since the peripheral is in a state that is in between connections, it is best to call cancelPeripheralConnection: right before attempting to connect. The gist of it as following, assuming we already discovered the peripheral to connects to:

-(void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
    [central cancelPeripheralConnection:peripheral]; //IMPORTANT, to clear off any pending connections    
    [central connectPeripheral:peripheral options:nil];
}

-(void) centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    peripheral.delegate = self;

    if(peripheral.services)
        [self peripheral:peripheral didDiscoverServices:nil]; //already discovered services, DO NOT re-discover. Just pass along the peripheral.
    else
        [peripheral discoverServices:nil]; //yet to discover, normal path. Discover your services needed
}

-(void) peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
    for(CBService* svc in peripheral.services)
    {
        if(svc.characteristics)
            [self peripheral:peripheral didDiscoverCharacteristicsForService:svc error:nil]; //already discovered characteristic before, DO NOT do it again
        else
            [peripheral discoverCharacteristics:nil
                                     forService:svc]; //need to discover characteristics
    }
}

-(void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    for(CBCharacteristic* c in service.characteristics)
    {
        //Do some work with the characteristic...
    }
}

This works well for me for a CBCentralManager in Mac app. Never tested it in iOS, but I assume it should be quite similar.

iOS 13.4 beta 4 bluetooth disconnects |Apple Developer Forums, Peripheral is an ESP32 with Bluedroid BLE stack after a connection event, our app reads the device info service even though this does not happen on iOS 13.3.1, nor do we attempt Tags: none (add) bluetooth le However, since these messages are triggered by the OS during discovery, it's outside  One of the main features of the Bluetooth 4 specification is Bluetooth Low Energy (BLE). Also called Bluetooth smart, this technology allows peripherals to communicate by consuming much less energy than regular Bluetooth. Another major advantage is that the user does not need to manually pair with the device using the system settings.

Turns out that there was command I was issuing to the device in the"didDiscovercharacteristicsForService" delegate method which was causing the connection instability. If you are facing similar issues, I suggest you to let the delegate method complete without any intervention (of any kind) and pass the CBPeripheral to another function designed by you to pass any values / issue a command to the devices. Thanks anyway Wilhemsen.

So the steps are as follows.. 1> Search for Tag, 2> If in range, CONNECT to Tag 3> If Connected, call DISCOVER services method (do not interrupt) 4> IN DidDiscoverServices, call DISCOVER Characteristics Method .. In DidDiscoverCharacteristics Method, wait until all Characteristics are discovered.. Then , at the end, call a function in your code that will do the necessary setup.. ... Code Sample

-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{

    for (int i=0; i < peripheral.services.count; i++) {
        CBService *s = [peripheral.services objectAtIndex:i];
        printf("Fetching characteristics for service with UUID : %s\r\n",[self CBUUIDToString:s.UUID]);
        [peripheral discoverCharacteristics:nil forService:s];
    }

}


- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{        
    if (!error)
    {
        CBService *s = [peripheral.services objectAtIndex:(peripheral.services.count - 1)];
        if([self compareCBUUID:service.UUID UUID2:s.UUID])
        {
           // This is when the **Tag** is completely connected to the Phone and is in a mode where it can accept Instructions from Device well.

            printf("Finished discovering characteristics");
           // Now Do the Setup of the Tag
            [self setupPeripheralForUse:peripheral];

        }
    }

    else
    {
        printf("Characteristic discorvery unsuccessfull !\r\n");
    }
}

-(void) setupPeripheralForUse:(CBPeripheral *)peripheral
{

    // DO all your setup in this function. Separate Perpiheral Setup from the process that synchronizes the tag and the phone. 

}

How to clear BLE cache in IOS ? |Apple Developer Forums, As per the iOS Bluetooth Framework, iOS device cache the BLE peripheral services. Tags: none (add) bluetooth low energy when reconnecting (even after re-scanning for peripherals in range), CoreBluetooth is still caching the When enter into DFU mode,iphone can not find the newly added service. The watch works perfect until I become out of Bluetooth range and thus my watch will lose connection, which is as expected. The problem comes when I’m back in Bluetooth range i.e. back with my phone the gear s3 will not automatically reconnect like other devices I have left it 30mins plus and it still won’t automatically reconnect.

I've been having the same issue. it seems to occur about 1/3 the time in my case. I tried the solution provided by P.L. but I had no success on iOS. There are perhaps many moving pieces at work here which can contribute to this problem (bluetooth device firmware, CoreBluetooth, etc.) but I solved it by simply keeping track of the devices which are pending service/characteristic discovery in an NSMutableDictionary and using GCD to check if it had completed it's discovery in a reasonable amount of time and trying again if necessary. So something like this:

- (void)requestDiscoverServicesForPeripheral:(CBPeripheral *)peripheral 
{
      peripheral.delegate = self;
      NSString *uuid =[self stringUUIDForUUID:peripheral.UUID];
      NSLog(@"discovering %d services ", self.interestingServices.count);
      [peripheral discoverServices:self.interestingServices];
      [self.pendingConnectionDevices setObject:peripheral forKey:uuid];
       __weak typeof(self) weakSelf = self;
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 *NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if ([weakSelf.pendingConnectionDevices objectForKey:uuid]) {

               //request discover services again
               NSLog(@"services did not discover, requesting again!");
               [weakSelf.btManager cancelPeripheralConnection:peripheral];
               [weakSelf.btManager connectPeripheral:peripheral options:nil];
         }
    });
 }

Then, when peripheral:didDiscoverServices:error calls back I remove it from my pendingConnectionDevices dictionary. This seems to work pretty well. I've seen it try to discover services up to 3 times before succeeding. I hope this helps.

6. Bluetooth Low Energy, MetaSensors DO NOT work with ANT, ZIGBEE, WIFI, LORAN or any other There are plenty of wireless protocols but what makes Bluetooth Low Energy (​BLE) iOS, Windows and Android devices support a Bluetooth connection for up to 7 a connection can be established and GATT services and characteristics can be  When the tags get disconnected and then reconnect to the phone, the tags connect fine. But one of the two tags (either one) does not seem to advertise its services. i.e when the app is open and the tag reconnects, the DiscoverServices method does not call the didDiscoverServices delegate.

Sometimes it's hardware issue. I just encountered a case that the hardware will enter a sleeping mode which is scannable, connectable, but not calling back at all for discoverServices.

Also there's a situation that happened to me when developing BLE all night and suddenly, the device become silence for discoverServices no matter what I did. Finally I found it will become normal if I reboot my iPhone5s.

And one day the bluetooth hardware engineer told me that the spec of BLE only says device must be connectable again within 30 seconds. So if I connect and disconnect over and over again, it may not working as expected... Which I still doubt it.

Connecting to a Peripheral, Discovering Services. Once the peripheral's services are successfully discovered​, the central manager will call the didDiscoverServices()  One of those applications is tiny Bluetooth trackers wherein you can attach small tags to your keys, purse, or insert them into gear containers, instrument cases, or other objects you wish to keep track of (and not be separated from). The tags are linked to your smartphone (and potentially to a tracking service hosted by the manufacturer) via BLE and form a radio-based link between you and your stuff.

iOS: stay connected to an external BLE device as much as possible, If you want to find the BLE device when your app is in the background, do not use all Apps that have specified the bluetooth-central background mode are allowed to That said, they must explicitly scan for one or more services by specifying connection requests do not time out, the iOS device will reconnect when the  Q. Does this support Bluetooth v2? No - please read about bluetooth specifications before using this library. LE (Low Energy) is part of the v4.0 specification. Q. Why can't I disconnect devices selectively in the GATT server? On android, you can, but exposing this functionality in xplat proves challenging since iOS does not support A LOT of

Issue #31 · WebBluetoothCG/web-bluetooth, Do we expect app to re-connect manually to proximity profile tag? BlueZ and iOS don't have APIs for apps to pass an auto-connect flag, though BlueZ the app needs to know the connection RSSI + TxPower GATT service and If the device is not in range, the re-connection will be triggered once the  Restart your iPhone, iPad, or iPod touch. Try a different location or switch to a different Wi-Fi network. Location Services uses GPS, Bluetooth, crowd-sourced Wi-Fi hotspots, and cellular towers to determine your location. Learn more about Location Services on your iOS device.

[PDF] Three flavors of Bluetooth®: Which one to , tant thing to note is that Bluetooth Smart devices by definition cannot medical and healthcare, in novel new use-cases such as proximity tags, the Bluetooth low energy PHY only has 37 channels and does discovery on three are used for reconnection means that reconnection is much faster than “classic” Bluetooth,​  Select Bluetooth Devices, and then Pair A New Device. Next time you want to connect, enable Bluetooth on your phone or Bluetooth speaker and say, "Pair Bluetooth." Once the initial pairing is complete, certain Bluetooth devices may automatically reconnect to your Echo when in range.

Comments
  • You should post some code for this. corebluetooth is a bit buggy, and I have myself had trouble with this callback.
  • Weird how I came back here :P Still the same problem for me, could you ellaborate on what command you issued? Or how your callback now looks like? It would be really helpful, thank you. PS: Glad to see you solved it :)
  • Hey Wilhelmsen, ,<br> The main solution to the code is that we dont setup our preferences on the tag while the services and the characteristics are being discovered. Once all the services and its characteristics are discovered, then we can call a setupPeripheral call.. I will add my code as another answer..
  • Hi Mark, One thing to watch out is that the BTLE radio follows a certain pattern where it interacts with one device connection query at a time. Perhaps you could run the discovery and services recognition functions on a string of NsOperation using a NsOperationQueue on a separate thread ? This has helped us a lot