How to remove a service set by NRF.setServices() ?

Posted on
  • Running some tests with NRF.setServices() and tried to use reset() to remove this service, did not work.

    NRF.setServices({
      0x1809 : { // Health Thermometer
        0x2A6E : { 
          readable: true,
          value : [E.getTemperature().toFixed(2)]
    }}});
    
  • It should work (NRF.setServices({}) should do too) - but you need to disconnect from BLE and reconnect for it to take effect.

    The Nordic BLE stack doesn't let you remove services, so Espruino has to shut down and restart all of BLE to do it - it can't be done while you're connected so it waits until you have disconnected.

  • Running this Puck on 1v90

    Sorry, no success with NRF.setServices({}), 0x1809 is still visible ...

  • Maybe it's some issue with reset - try:

    NRF.setServices({
      0x1809 : { // Health Thermometer
        0x2A6E : { 
          readable: true,
          value : [E.getTemperature().toFixed(2)]
    }}});
    NRF.setServices({});
    

    It should say something like already connected. queueing update for later - and then when you disconnect everything will be fine.

  • Yes, that works, tested it back and force - Thanks.

    >NRF.setServices({
    :  0x1809 : { // Health Thermometer
    :    0x2A6E: {  // Temperature
    :      readable: true,
    :      value : [E.getTemperature().toFixed(2)]
    :  }},
    :  0x180F : { // Battery Service
    :    0x2A19: {  // Battery Level
    :      readable: true,
    :      value : [Puck.getBatteryPercentage().toFixed(0)]­
    :}}});
    BLE Connected, so queueing service update for later
    =undefined
    >NRF.setServices({});
    BLE Connected, so queueing service update for later
    =undefined
    >
    Disconnected
     
    
  • As a drop of bitterness: I had to switch iOS BT off and on to make the service changes in the apps happen, even for nRF connect :(

  • Thanks - I'll try and remember that - I imagine that's going to catch a lot of people out.

    I don't think BLE devices are supposed to change their services on the fly (or if they do they are supposed to send out a special notification), so I guess some things like iOS don't cope with it very well.

  • Thanks for this post. I was also struggling to see the new services I was adding until I read this a second time and 'saw' the iOS qualifier. I was so focused on the Pixl that I forgot about the iPhone's bluetooth 'memory'. My bluetooth scanner (nRF Connect) is also on the phone so it didn't 'see' any change and kept reporting the service I deleted.

  • I'll update the NRF.setServices documentation to mention this - nRF Connect should really display a message on iOS mentioning that the services it shows may be out of date though.

  • Here's a complication to the issue that I stumbled into. I'm saving code to RAM (Pixl 2v01) and in the code I have block setting the NRF services (with 4 characteristics using the short hex UUIDs), just as in the example in the API documentation. I then update the services when a button is pressed using NRF.updateServices which works as expected, until the device is restarted.
    On restarting it adds a second instance of the same service (as seen by nRF Connect and LightBlue). Restarting again (e.g. by running a load() command) I get a third instance of the same service at which point I'm running into BLE Data Size errors when I try to update the service.

    I've resolved it by putting a NRF.setServices({}) in the init() function, blanking the services and setting the services again right afterwards but it seems wrong that the peripheral can advertise multiple instances of the same service (same name, same characteristics). It also makes updating the code tricky as you have to make sure that there is no definition of the services in RAM that might be appended to the new code when it is saved.

    I can understand that where you want to change the characteristics of a service you need to delete and re-instantiate it but should there not be a check that prevents the same service being advertised multiple times?

  • NRF.setServices should have the effect of replacing all services with what you supply in the argument - not appending to them, so that sounds like a bug. I've never come across it before.

    Do you think you paste up a full example of some code that causes this and the exact steps you took so I can reproduce it at my end?

    I tried uploading:

    NRF.setServices({
      0xBCDE : {
        0xABCD : {
          value : "Hello",
          readable : true
        }
      }
    });
    

    to RAM, then doing save() and then load() a few times, and I couldn't get it to duplicate the services.

  • Sorry, been trying to recreate it for the last hour but can't. This is strange as I was even resorting to erasing entirely the flash before loading code to ensure there was no residual old code interfering with the setup and still I was getting the multiple identical services and the BLE Data Size error.
    I've removed the NRF.setServices({}) from init() and will monitor to see if it happens again.

  • Ok, have it again and the sequence that got me there. I'll ensure consistent reproducibility and provide the sequence.

  • This is really difficult to pin down. It's occurs when an NRF.updateServices is called while there is a queued BLE restart. It doesn't seem to be a problem with one or two characteristics, but the heavier the load the more it occurs. I've tried moving the updates out of init() but it seems not to make a difference.

  • Hi, Thanks for trying to pin this down.

    Interesting about the queued updateServices - I wonder if that somehow clears some flags.

    Do you have any code you could post that even reproduces this 50% of the time?

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

How to remove a service set by NRF.setServices() ?

Posted by Avatar for MaBe @MaBe

Actions