Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

pc-ble-driver-js disconnects after 30 seconds for no reason

Hi,

I'm trying to incorporate pc-ble-driver-js into NodeJS based server.

For some reason, after connecting to a peripheral with a custom service, although the connection get established correctly, notifications do not work and the connection will auto terminate after 30 seconds or so.

I've create a sample project (based on the `heart_rate_collector.js` example) which scan and connects to `ble_app_uart` from the `nrf5_sdk` examples.

The code is present at pc-ble-driver-js-test should run out of the box by issuing:

nvm use 12
yarn install

node central.js <comport> v5

It will connect, subscribe for the TX event - but will not receive notifications and will disconnect for some reason after 30 seconds (look in the log for `connectionTime`) 

I've verified subscription works by adding the following to `nus_data_handler` in `main.c` 

    else if (p_evt->type == BLE_NUS_EVT_COMM_STARTED)
    {
        NRF_LOG_INFO("BLE_NUS_EVT_COMM_STARTED");
    }
    else if (p_evt->type == BLE_NUS_EVT_COMM_STOPPED)
    {
        NRF_LOG_INFO("BLE_NUS_EVT_COMM_STOPPED");
    }

Few additional notes:

I've tested it on Windows10 and macOS Catalina with NodeJS v10 and v12 (v14 is not supported by the pc-ble-driver-js).

Needless to say, the same firmware on the nRF52840 works fine with the nRF Connect Bluetooth Low Energy Application (which programs the connectivity firmware)

Is there anything special done on the pc-nrfconnect-ble code to keep the connection alive? Some undocumented API?

Update 1: this is the link for the issue on GitHub How do i maintain connect after called connect method? #249

Update 2: Modified testing code to see if the suggestion in Connecting to device using pc-ble-driver-py causes disconnect after 60 seconds helps in any way. No matter which `FIRST_CONN_PARAMS_UPDATE_DELAY` or `NEXT_CONN_PARAMS_UPDATE_DELAY` values I put in - I'm still getting 30 seconds. which might indicate the disconnect is coming from somewhere else maybe?

Parents
  • Hi,

    This sounds a lot like there is a request from the peer device that does not get handled, leading to the peer device timing out and disconnecting after the 30 seconds has passed.

    The perhaps easiest way to figure out which event, is to get a sniffer trace. Other alternatives are if the peer device is logging you can check the log, or you can print some debug info about each event received by pc-ble-driver-js, in order to see what is going on.

    Regards,
    Terje

  • Hi,

    Terje, thanks for the quick response.

    Your suggestion is similar to what I've done(used the js code, simpler to follow than the sniffer...) and managed to resolve the issue.

    The issue is that some firmwares send MTU and Data Length requests - and if no response it received, it will disconnect the central - those requests (which are common!) but are not documented in the pc-ble-driver-js central example and also not exposed in the `index.d.ts` file.

    adapter.on('attMtuRequest', (device, newMtu) => {
        adapter.attMtuReply(device.instanceId, newMtu, (err, mtu) => {});
    });
    
    adapter.on('dataLengthUpdateRequest', (device, newOctets) => {
        adapter.dataLengthUpdate(device.instanceId, newOctets, () => {});
    });

    For who ever looking for a solution for discovering which events your code "forgets" to answer to and you're still getting disconnected (after adding those two events I documented above)

    The fastest way IMHO to discover which requests you are not responding to is as follows:

    • Open `node_modules/pc-ble-driver-js/api/adapter.js`
    • Locate `in _eventCallback(eventArray)` and add this event IDs array which defines logs you want to avoid printing (otherwise it's overwhelming)
      const filterLog = [
       this._bleDriver.BLE_GATTC_EVT_CHAR_DISC_RSP, 
       this._bleDriver.BLE_GAP_EVT_ADV_REPORT,
       this._bleDriver.BLE_GATTC_EVT_READ_RSP,
       this._bleDriver.BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP,
      ];
    • Then add just below `this.emit('logMessage', logLevel.DEBUG, text.toString());` the following:
      if (filterLog.includes(event.id) === false) {
          console.log(text.toString());
      }
    • Now try and follow which events you are not responding to and getting disconnected or timed-out on (reason).

Reply
  • Hi,

    Terje, thanks for the quick response.

    Your suggestion is similar to what I've done(used the js code, simpler to follow than the sniffer...) and managed to resolve the issue.

    The issue is that some firmwares send MTU and Data Length requests - and if no response it received, it will disconnect the central - those requests (which are common!) but are not documented in the pc-ble-driver-js central example and also not exposed in the `index.d.ts` file.

    adapter.on('attMtuRequest', (device, newMtu) => {
        adapter.attMtuReply(device.instanceId, newMtu, (err, mtu) => {});
    });
    
    adapter.on('dataLengthUpdateRequest', (device, newOctets) => {
        adapter.dataLengthUpdate(device.instanceId, newOctets, () => {});
    });

    For who ever looking for a solution for discovering which events your code "forgets" to answer to and you're still getting disconnected (after adding those two events I documented above)

    The fastest way IMHO to discover which requests you are not responding to is as follows:

    • Open `node_modules/pc-ble-driver-js/api/adapter.js`
    • Locate `in _eventCallback(eventArray)` and add this event IDs array which defines logs you want to avoid printing (otherwise it's overwhelming)
      const filterLog = [
       this._bleDriver.BLE_GATTC_EVT_CHAR_DISC_RSP, 
       this._bleDriver.BLE_GAP_EVT_ADV_REPORT,
       this._bleDriver.BLE_GATTC_EVT_READ_RSP,
       this._bleDriver.BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP,
      ];
    • Then add just below `this.emit('logMessage', logLevel.DEBUG, text.toString());` the following:
      if (filterLog.includes(event.id) === false) {
          console.log(text.toString());
      }
    • Now try and follow which events you are not responding to and getting disconnected or timed-out on (reason).

Children
No Data
Related