• The BluetoothRemoteGATTCharacteristic.startN­otifications() works fine when in Android program I configure characteristic to send notifications (PROPERTY_NOTIFY).
    Bangle does not receive anything when I set to send indications (PROPERTY_INDICATE)
    Android code:

    // Current Time characteristic
            BluetoothGattCharacteristic currentTime = new BluetoothGattCharacteristic(CURRENT_TIME­,
                    //Read-only characteristic, supports notifications
                      // | BluetoothGattCharacteristic.PROPERTY_NOT­IFY,
                        | BluetoothGattCharacteristic.PROPERTY_IND­ICATE,

    Bangle code:

    var in_connection_setup = false;
    function connection_setup() {
      if(in_connection_setup) return;
      in_connection_setup = true;
      E.showMessage("Scanning for CSC sensor...");
      NRF.requestDevice({filters:[{services:["­1805"]}]}).then(function(d) {
        device = d;
        console.log("Found device: "+d.name);
        E.showMessage("Found device"+d.name);
        return device.gatt.connect();
      }).then(function(ga) {
        gatt = ga;
        return gatt.getPrimaryService("1805");
      }).then(function(s) {
        service = s;
        return service.getCharacteristic("2a2b");
      }).then(function(c) {
        characteristic = c;
        characteristic.on('characteristicvaluech­anged', (event)=>updateTime(event));
        return characteristic.startNotifications();
      }).then(function() {
        console.log("Notifications subsribed");
        E.showMessage("Notifications subsribed");
      }).catch(function(e) {
        E.showMessage(e.toString(), "ERROR");
      in_connection_setup = false;

    Am I doing something wrong?
    Is there a way to receive indications?

  • Actually it works. I had to add in another place in Android to capture and process indications requests.

  • Well. Actually it does not work. Additionally to setting PROPERTY_INDICATE to the characteristc, the actual notification call BluetoothDevice.notifyCharacteristicChan­ged had hardcoded confirm=false parameter.
    After I've set it to True, the BJS2 NRF receives the indication just first time after the connection and subscription established. Then it does not receive indications.
    chracteristic in Bangle shows:

    =BluetoothRemoteGATTCharacteristic: {
      uuid: "0x2a2b",
      handle_value: 42, handle_decl: 41,
      properties: { broadcast: false, read: true, writeWithoutResponse: false, write: false,
        notify: false, indicate: true, authenticatedSignedWrites: false },
      "#oncharacteristicvaluechanged": function (event) { ... },
      handle_cccd: 43,
      value: DataView: {
        buffer: new Uint8Array([230, 7, 7, 12, 18, 43, 16, 2, 1, 0]).buffer,
        byteOffset: 0, byteLength: 10 }

    Do I have to send indication acknowledgements from the Bangle code, like from the event handler that is my updateTime(event) func? If so how to do it?

  • So you're saying that if in android you choose to send indications, with confirm=true, it then doesn't work?

    It's entirely possible that Espruino doesn't send a response for indications automatically - Notifications seem to be the preferred options, with Indications kind of a legacy thing, so as a result extremely few people use them.

    If you can show me what needs to be added in Espruino to get this working then I'm happy to include it, however as it seems you control both sides of this connection, unless there's a very good reason to use indications you may be better off using Notifications as that does seem to be the preferred way to do this kind of thing in Bluetooth now anyway.

  • Hi Gordon,
    yes, when I choose to send indications, with confirm=true, it then doesn't work. It looks like Espruino does not respond with confirmation. And in BLE the initiator of an indication cannot send another indication if it has not received the confirmation.
    I read what I could find in Google, some say that confirmation should be send by Client app, some say that it is a part of ATT stack and should be sent automatically.
    I've found this func from Nordic API https://infocenter.nordicsemi.com/index.­jsp?topic=%2Fcom.nordic.infocenter.s132.­api.v5.0.0%2Fgroup___b_l_e___g_a_t_t_c__­_f_u_n_c_t_i_o_n_s.html&cp=2_3_1_1_0_2_2­_2_7&anchor=ga173e2d16c9bbd24dcf2c724ded­6708a5
    uint32_t sd_ble_gattc_hv_confirm ( uint16_t conn_handle, uint16_t handle )
    Is it what is needed?

    In my case I control the both sides. But I want to make the sides maximally standard. For example my Bangle "Speed display" should work not only with mine Android GATT Location and Navigation service but with any other GATT Location and Navigation service that other GNSS devices can provide.
    And there in the GATT specs https://www.bluetooth.org/DocMan/handler­s/DownloadDoc.ashx?doc_id=271997 is stated

    3.4 LN Control Point
    If the LN Control Point is supported, profiles utilizing this service are required to ensure
    that the Client configures the LN Control Point characteristic for indications (i.e., via the
    Client Characteristic Configuration descriptor) at the first connection.

    The Server should use indications in other transactions as well, where Client writes values to the server, for example - "The response shall be indicated when the route has been selected using the Response Code Op Code, the Request Op Code along with “Success” or other appropriate Response Value."

    I've found a good article with clarification of how the confirmations work.

    So, it looks like the App should issue the confirmation. I assume it should be done from a notification/indication handler function.
    If I am correct, we need just to introduce a new function in NRF, something like confirmIndication(event).

  • Thanks! Yes, it looks like sd_ble_gattc_hv_confirm needs to be sent. I think realistically it makes sense for Espruino to do that automatically. I've just updated Espruino to include this, so I'd hope that if you use the cutting edge build 2v14.52 or later it might work now?

  • Great! Just one thing. I read different opinions how the confirmation should work:
    A - automatically, as soon as an indication received
    B - automatically, after an indication handler finished
    C - manually, inside an indication handler where App can do some checks.

    I thought C should be universally cover all cases. But, of course, it will require to manually place the confirmation call. Which is not a big deal.

    On the diagram from KBA_BT_0104: Acknowledged vs Unacknowledged GATT operations
    the response goes from App level, not from stack. I understand the NRF wrapper lib is not a BLE stack, but it is not an App either.

  • I think as far as Bluetooth is concerned, Espruino is the 'app'. Doing it in the handler matches what we do for other Bluetooth events too (eg write response), and also what other Nordic example code does.

    IMO it's got to be 'A'. We can't have just the first indication sending and then subsequent ones just not working without any warning to the user - that's going to be extremely frustrating for pretty much all users.

    ... and even if you did send a response in JS, if for some reason your code had an exception before calling it, it'd 'lock up' the connection until you reconnected.

  • 'A' does make sense.
    I just thought 'C' would be more flexible. So 'C' can be 'A', can be 'B', or even something in between. Like:

    function myRespondASAPHandler(event){
      //do something ...
    function myRespondAfterDoneHandler(event){
      //do something
     characteristic.on('characteristicvaluech­anged', (event)=>myRespondAfterDoneHandler(event­));

    Response "After Done" will serve scenarios where processing of a message may take time. So it will prevent flooding the Client by too frequent indications. Otherwise some additional synchronization logic should be done, like skipping next coming indications if a current one is still in processing.

  • Yes, it could be more flexible (but also super easy for someone to have it just 'not work')... However it seems you're the first person to use indications with confirmations in 5+ years or someone else would have reported issues, so while it's really good to fix it, I feel like it's probably not worth putting too much extra development work into ;)

    If someone comes along and actually really needs the functionality then it could be added, but right now there are definitely higher priority things :)

  • I am confused. Does it mean that "auto-confirmation" is implemented starting with build 2v14.52 and you, for time being, just do not want to change it to the "manual confirmation"?
    I am Ok with that. It will be much better than without confirmation at all. :)

  • I am confused. Does it mean that "auto-confirmation" is implemented starting with build 2v14.52 and you, for time being, just do not want to change it to the "manual confirmation"?

    That's correct, yes :)

  • Hi Gordon,
    I've loaded the cutting edge build 2v14.64.
    Now it shows the devices but fails to device.gatt.connect();
    It shows:

    var device;
    var gatt;
    NRF.requestDevice({filters:[{services:["­1805"]}]}).then(function(d) {
        device = d;
        console.log("Found device: "+d.name);
        return device.gatt.connect();
      }).then(function(ga) {
        gatt = ga;
      }).catch(function(e) {
    WARNING: Unknown phy "undefined"
    Found device: Pixel 4a
  • Argh, sorry about that - I've just put a fix in so it should be sorted in 2v14.65

    For now, NRF.requestDevice({phy:"1mbps",filters:[­{services:["1805"]}]}).then(function(d) { would work around it.

  • Great! The warning gone with the workaround.
    But the ERR 0x7 is still there.

  • Sorry - I see this here now too.

    I've just put fix in, and it should be in espruino_2v14.91_banglejs2.zip

  • You are SUPER!

  • Supporting confirmations seems great ! I didn't test it but it could happen soon. By the way, I just wondered, is there any way for the application that just sent an Indication packet (NRF.updateServices called with option indicate: true) to be "notified" (either with a callback or promise or ? ) when the confirmation has been received from the other side?
    I have some ideas in mind that would need to use as much bandwidth as possible without loosing data...

  • I don't think there's anything in there at the moment. If the nRF SDK actually exposes an event when the response to an indication is received then it could almost certainly be exposed somewhere in JS though.

  • it looks like something is done here. Moreover, in release 2v15, the changelog says nRF5x: Call sd_ble_gattc_hv_confirm in response to BLE indications
    After that I am a bit lost, is it possible that this event is currently lost but could be exposed in JS by calling ? jsble_queue_pending() with a new enum of type BLEPending ?

  • Actually I misunderstood the behavior of the BLE stack. sd_ble_gattc_hv_confirm is to be called on client side to send an application level acknowledge of an incoming "indication" packet.
    Server side, however, the BLE stack will emit an BLE_GATTS_EVT_HVC event upon reception of such an application level acklowledge sent by the peer. While this mecanism seems to be used in some specific BLE services, it seems that this BLE_GATTS_EVT_HVC event is not available for a custom BLE service. Do anyone know how and where should I try to add this event in such a way for the server application to be able to react on it?

  • You could try just adding a handler here and see what happens? https://github.com/espruino/Espruino/blo­b/5be68a80baeca1ab4e6ab31b9d78244afd2092­c1/targets/nrf5x/bluetooth.c#L1445

    Even if you only printed to the console you might be able to see if it is at least getting called?

  • The modification has been done in this way:

            // Peripheral's Characteristic was written to
            const ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
            // TODO: detect if this was a nus write. If so, DO NOT create an event for it!
            // We got a param write event - add this to the bluetooth event queue
            jsiConsolePrintf("indication confirmed!");
            jsble_queue_pending_buf(BLEP_WRITE, p_evt_write->handle, (char*)p_evt_write->data, p_evt_write->len);
            jsble_peripheral_activity(); // flag that we've been busy

    Everytime an BLE_GATTS_EVT_HVC event is raised from the softdevice, indication confirmed! is printed in the console. This is a really good start.

    Now I just need to understand how to update this in order to be able to react on this event on the JS layer. If anyone has a clue, Please share :-)

  • Looks from that mod like you're just responding to BLE_GATTS_EVT_WRITE in that code, not BLE_GATTS_EVT_HVC?

    But I'd create a new BLE_INDICATION (or similar) enum and then do jsble_queue_pending and create a handler for it like is done for BLEP_WRITE

  • Sorry I just mixed up the 2 events actually.
    I made the update you proposed.

    here is a proposal: https://github.com/espruino/Espruino/pul­l/2299

    Feel free to reject it and ask me to modify it if needed.


    NRF.on('indicateconfirmed', function() {console.log("JS HVC!");});
  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

BluetoothRemoteGATTCharacteristic.startNotifications() does not capture indications.

Posted by Avatar for Mark_M @Mark_M