Trying to understand BLE advertising

Posted on
  • Hi All,
    I'm amazed by the capability of this little device and suspect I'm trying to have my cake and eat it, but I'm looking for a way to advertise an iBeacon, services and services data all at the same time. I'm almost there, but at the moment I can only have services and service data advertised, or service data and iBeacon.

    My application has the puck providing a number of services and characteristics including battery, light and temperature and a button service. These are set up with a call to NRF.setServices that specifies the advertising in the options e.g.

    {
      advertise: ['180A','180F','181A','87100001-703F-4AE­E-A323-9AE013D98E93']
    }
    

    I'm then using a call to NRF.setAdvertising to create the service data advertisement e.g.

    NRF.setAdvertising({
        0x1815 : [button.single, button.long],
        0x180F : [metrics.battery],
        0x1809 : [metrics.temperature],
        0x181A : [metrics.light]
      },{ interval : 375 });
    

    These two work together fine. I start the iBeacon using NRF.setScanResponse, e.g.

    NRF.setScanResponse(require("ble_ibeacon­").get({
        uuid : beaconUUID,    // iBeacon uuid
        major : beaconMajor,  // optional
        minor : beaconMinor,  // optional
        rssi : -59            // optional RSSI at 1 meter distance in dBm
      }));
    

    The beacon works but it seems to stomp on the advertisement for services specified in the NRF.setServices() options, as these disappear. (the service data advertisements continue).

    Is there some way I can use arrays in NRF.setAdvertising to specify all three advertisements, services, service data & iBeacon?

    Cheers
    Dave

  • Perhaps this helps: http://www.espruino.com/Puck.js+iBeacon (especially the last part)

  • ... or probably not if you have been there already.

  • Ahh - yes, that's a bit unfortunate... The extra services are advertised in the scan response, which gets overwritten when you use that last bit of code.

    The answer is yes, it is possible - but it's not very nice at the moment.

    Basically you can supply an array to setAdvertising, which will cause it to cycle through different advertisements: https://www.espruino.com/Reference#l_NRF­_setAdvertising

    The problem is that you need to specify all the data as arrays - so what you're currently doing (giving it the object) won't work. You'd have to manually make up the advertising packet yourself (you could use something like nRF Connect to read the packet, then just enter the bytes manually?).

    I hit this just a few days ago (I added the example code for iBeacon & setScanResponse literally just this week), but there wasn't a nice easy fix. I'll file an issue and will see if I can think of a nice way of getting around it... Maybe allowing something like this:

    NRF.setAdvertising([
    require("ble_ibeacon").get({
        uuid : beaconUUID,    // iBeacon uuid
        major : beaconMajor,  // optional
        minor : beaconMinor,  // optional
        rssi : -59            // optional RSSI at 1 meter distance in dBm
      }),
    {
        0x1815 : [button.single, button.long],
        0x180F : [metrics.battery],
        0x1809 : [metrics.temperature],
        0x181A : [metrics.light]
    }],{ interval : 375 });
    
  • hehe thanks, but that's where I started :)

  • Thanks Gordon, I didn't realise the services advertisement was part of the scan response rather than the 'advertisement' as such, but that makes sense now.

    I poked around in the source code to see if I could figure out how setAdvertising converts the object to an array, but my C fu is weak :)

    nRF Connect on my iPhone doesn't seem to display the raw scan response data, are you referring to the desktop version? If so, I'll have to buy a nordic dongle or wait to see if you come up with something in an update. In the meantime I'll live without the extra services advertisement.

    Thanks for your help!

    Incidentally if anyone reading this is struggling to understand how advertisements and scan responses fit together I found this article useful: http://www.argenox.com/a-ble-advertising­-primer/

  • Thanks for that - it is a great article.

  • It was the Android nRF Connect app that you could copy the data from when in the 'scan' tab... You could probably find something on desktop that'd get you the info too - but I haven't personally used anything.

    You don't have to put the services in the scan response, but because the 128 bit UUIDs can take up a bunch of space it made sense to just do it by default.

    The advertising data format is pretty simple I believe, but Espruino uses Nordic's libraries for it - a function called ble_advdata_set, which calls this function: https://github.com/espruino/Espruino/blo­b/059eb0a3e6031e065dea5bc1101561d4b95b8e­9c/targetlibs/nrf5x/components/ble/commo­n/ble_advdata.c#L474

    Hopefully I'll have some kind of solution for it soon though.

  • Ok, it's fixed :) If you try out a build from http://www.espruino.com/binaries/travis/­master/

    Then something like this should work fine:

    NRF.setAdvertising([
    require("ble_ibeacon").get({
        uuid : beaconUUID,    // iBeacon uuid
        major : beaconMajor,  // optional
        minor : beaconMinor,  // optional
        rssi : -59            // optional RSSI at 1 meter distance in dBm
      }),
    {
        0x1815 : [button.single, button.long],
        0x180F : [metrics.battery],
        0x1809 : [metrics.temperature],
        0x181A : [metrics.light]
    }],{ interval : 375 });
    
  • Thanks very much Gordon.

    I gave it a go but had mixed results. Using the code above the iBeacon worked as expected, but nRF Connect on my iPhone showed the Service Data from the NRF.setAdvertising call alternated on and off. I.e. as nRF Connect scanned, the ServiceData would alternately display the correct advertisement data (e.g. <0x181A...) and 'N/A'.

    I didn't see that behaviour when the iBeacon data was sent in the scan response previously.

    I tried turning on the advertising option in NRF.setServices to get iBeacon, Service Data and services simultaneously e.g.

    services = {....}
    
      options = {
          advertise: ['180A','180F','181A','87100001-703F-4AE­E-A323-9AE013D98E93'],
          uart: true,
      };
    
    function onInit() {
    
      NRF.setAdvertising([
          require("ble_ibeacon").get({
              uuid : beaconUUID,    // iBeacon uuid
              major : beaconMajor,  // optional
              minor : beaconMinor,  // optional
              rssi : -59            // optional RSSI at 1 meter distance in dBm
          }),
          {
              0x1815 : [button.single, button.long],
              0x180F : [metrics.battery],
              0x1809 : [metrics.temperature],
              0x181A : [metrics.light]
          }],{ interval : 375 });
    
        try {
          NRF.setServices(services, options);
        } catch(err) {
          // This always seem to throw BLE error 4 for some reason.
          console.log(err);
        }
    
    }
    

    iBeacon worked ok, service data still blinked in and out in nRF Connect and only one of the 4 services in the options.advertise array was shown in ServiceUUID in nRF Connect. Connecting to the Puck in nRF Connect only showed the Nordic UART service, not any of the other defined services.

    Interestingly, the 'LightBlue Explorer' app on the iPhone showed the correct services, but connecting still also only listed the Nordic UART service.

    I also tried reversing the order of the NRF.setServices and NRF.setAdvertising calls but it made no difference.

  • That BLE Error 4 is really strange - that's NRF_ERROR_NO_MEM - so that's the softdevice itself complaining that it has no memory left.

    What's in services? Does it work if you don't set as many services? If you're using a bunch of different 128 bit UUIDs I guess that could cause some problems.

    As far as how it shows up, I think you'd expect nRF Connect to flip between showing different things - but everything might still work properly?

    Otherwise I'm not sure what to suggest - apart from to try manually constructing your own advertising packets... It might just be that you can't do what you want to do with Bluetooth LE.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Trying to understand BLE advertising

Posted by Avatar for dave @dave

Actions