• 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!

  • 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