Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS - How to discover unadvertised services on a BLE peripheral

I got this Nordic nRF52 BLE peripheral which doesn't advertise its services. I'm able to connect to it, but can't discover services on iOS. Since I know the service UUIDs, I've tried to pass them to the discoverServices function. But this does not work.

After about 30 seconds it finally disconnects.

On the peripheral the GAP advertising flag is set to General Discoverable. Using apps like LightBlue or nRF Connect I see the name and UUID of the peripheral but no service. When connecting with the LightBlue app, after a few seconds an error (Timeout interrogating the peripheral) is shown.

On Android discovering the unadvertised services works just fine.

As of the Core Bluetooth Programming Guide, it should basically work:

After you have established a connection to a peripheral, you can explore its data. The first step in exploring what a peripheral has to offer is discovering its available services. Because there are size restrictions on the amount of data a peripheral can advertise, you may discover that a peripheral has more services than what it advertises (in its advertising packets). You can discover all of the services that a peripheral offers by calling the peripheral’s discoverServices: method, like this: [peripheral discoverServices:nil];

Does anyone know what the differences in the SDKs are and if there is a possibility to discover unadvertised services on iOS like Android does?

I've read that iOS is capable of connecting directly, skipping the discovery process, when the peripheral is cached. But having the peripheral cached, it needs to be paired once. Is there maybe a way to set the cache manually?

Appreciate any help, thanks!

like image 657
ya man Avatar asked Jan 29 '23 17:01

ya man


1 Answers

This sounds more like a problem in your firmware on the NRF52. I have been using NRF51 and NRF52 series for some years now and they definitely work with both iOS and Android devices.

BLE advertising and service discovery

Some general information on BLE advertising and service discovery:

A BLE advertising packet is very limited in size (31 bytes to be precise, not including the overflow area). That means you cannot advertise all the services your peripheral supports and the space might be shared with other information as well (appearance, name, manufacturer data, etc.). You do not even have to advertise any service at all or can even advertise services that your peripheral does not support. The service discovery works regardless of the advertised services.

Debugging

Some ideas for troubleshooting your problem:

  1. iOS caches discovered services, characteristics and descriptors once they have been discovered until the next power cycle (turning Bluetooth off and on again or restarting the iOS device). This can lead to some unexpected behaviour if you have changed the underlying services etc. in your firmware but have not used the Services Changed Flag to indicate the change. Therefore, make sure that you send the Services Changed flag from your peripheral accordingly.

  2. Try some of the examples that come with the NRF5 SDK and check if they work. If the examples work (which they should) there is definitely something wrong with your firmware.

  3. Make sure that you handle the GAP and GATT events properly in your firmware. Both iOS and Android devices are not 100% compliant with the Bluetooth 4.0+ standard. Nordic Semiconductor has already taken into account some of those quirks in their SDK and SoftDevice. You should definitely check the logs of the GAP and GATT events (basically the ble_evt_handler in your firmware) and refer to the Nordic Devzone where most of those quirks have been resolved already.

  4. Check the permissions for reading and writing the service and characteristic metadata in your firmware. I had a similar problem where I accidentally set the read permission of my characteristics to no access.

Hope that helps.

like image 108
Jens Meder Avatar answered Feb 04 '23 02:02

Jens Meder