BLE Driver Python Concurrent Notifications

Hi Guys,

I am currently using the ble driver for windows (Python) to get notifications from two Gatt services (Same Service/charac/descriptors/etc basically same application running on both devices). I think I am getting notifications from both the devices but I am unable to distinguish or confirm that owing to the lack of a specific device handle. In the on_hvx function, I get gattc_event which only has an event id and status. Could you please help me with how to identify which device handle I am getting the notifications from?

Example:

I am getting this now:

Received handle value notification, handle: 0x000E, value: 0x035A0E39ABFEC3E45A0216000000000000000000

However, I would like to have:

Received handle value notification,Device Name/HAndle:HRM1 handle: 0x000E, value: 0x035A0E39

Received handle value notification,Device Name/HAndle:HRM2 handle: 0x000E, value: 0x035A0E39

A second issue I am facing in python is that using the script, everytime I have to plug/unplug the Dongle to run the script again if I stop/close the process. I am aware that its because of not closing something somewhere so I tried closing ble_driver.sd_rpc_close() on errors but that did not work too . Could you'll please help me with that?

A third and last thing is while receiving notifications, is there a way to write to a characteristic on the Gatt server? Could you'll please guide me on that. For example, during notifications from two servers, I may want to write values to a control point heart rate characteristic .

I would be very grateful if you'll could help me with the above.I am using the driver as suggested by Stian devzone.nordicsemi.com/.../

Thanks and Regards, Neil

  • ###Get connection handle

    To know which handle you get the notifications from you can use ble_event.evt.gap_evt.conn_handle (documented here: developer.nordicsemi.com/.../a00124.html)

    In order to check this quickly you can print the conn_handle inside the ble_evt_handler(ble_event) function in main.py

     elif evt_id == ble_driver.BLE_GATTC_EVT_HVX:
        print "handler", ble_event.evt.gap_evt.conn_handle
        on_hvx(ble_event.evt.gattc_evt)
    

    Reset chip

    The second issue you are facing regarding the script to not be able to re-initiate the scanner after disconnect, is a common issue. I have not found any other solution than to reset the chip using the jlink debugger. I am using linux (JLinkExe) and call this script at the top of main() in order to reset:

    def reset_device():
        ble_driver.sd_rpc_close()
        cmd = "echo -e '\ndevice nrf51822\nw4 40000544 1\nsi 0\ntck0\nt0\nsleep 10\nt1\nexit\n' | JLinkExe"
        import subprocess
        pcmd = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell='/bin/sh')
        pcmd.wait()
        pout = pcmd.communicate()
        print pout[0]
    

    Write to characteristic

    If you want to write to a characteristic (assuming that you have implemented a write characteristic in the HRM service), you first need to capture the descriptor handle of that characteristic and store it to a global variable, then initiate a write request to that handle.

    In the on_descriptor_discovery_response() function you can add:

        global hrm_write_handle
        ....
            if descriptor.uuid.uuid == YOUR_WRITE_CHAR_UUID
                hrm_write_handle = descriptor.handle
    

    Now you will have the handle stored in hrm_write_handle, and this function will execute a write on that characteristic:

    def do_write(value):
        if hrm_write_handle == 0:
            print "Error. No LED handle has been found"
            return
    
        led_value = [value]
        led_array = util.list_to_uint8_array(led_value)
    
        write_params = ble_driver.ble_gattc_write_params_t()
        write_params.handle = hrm_write_handle
        write_params.len = 1
        write_params.p_value = led_array.cast()
        write_params.write_op = ble_driver.BLE_GATT_OP_WRITE_REQ
        write_params.offset = 0
    
        ble_driver.sd_ble_gattc_write(connection_handle, write_params)
    

    You can of course pass the connection_handle variable to this function as well to choose which peripheral you want to send the write to. You can call this function from on_hvx() to test.

    sd_ble_gattc_write is documented here: developer.nordicsemi.com/.../a00710.html

    And the sequence diagram for that function is here: developer.nordicsemi.com/.../a00607.html