This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Disconnected: 0 BLEHci.remote_user_terminated_connection [using pc_ble_driver_py]

Hello,

I am using the nordic nRF52840-DK and trying to connect to a nRF52840-Dongle and sending/receiving data to custom services and characteristics using pc_ble_driver_py. I modified the heart rate collector.

But the problem is that when I am connected to the Dongle the connection last 25 to 30 secondes and I receive a message : "Disconnected: 0 BLEHci.remote_user_terminated_connection" and the error message is : "line 477, in write_req attr_handle = self.db_conns[conn_handle].get_char_value_handle(uuid) KeyError: 0". However, when I use the nRF connect mobile/PC version I don't have this problem so I think it is a problem with my code. I check it out if there is some time out equal to like 25_30 secondes but I didn't find any solution.

Could someone help me please to find some solution.

Thanks in advance.

Cordially

Joe

  • from time import sleep
    from queue import Queue, Empty
    from pc_ble_driver_py.observers import *
    
    global config, BLEDriver, BLEAdvData, BLEEvtID, BLEAdapter, BLEEnableParams, BLEGapTimeoutSrc, BLEUUID, BLEUUIDBase, BLEConfigCommon, BLEConfig, BLEConfigConnGatt, BLEGapScanParams
    from pc_ble_driver_py import config
    
    config.__conn_ic_id__ = "NRF52"
    
    from pc_ble_driver_py.ble_driver import (
        BLEDriver,
        BLEAdvData,
        BLEEvtID,
        BLEEnableParams,
        BLEGapTimeoutSrc,
        BLEUUID,
        BLEUUIDBase,
        BLEGapScanParams,
        BLEConfigCommon,
        BLEConfig,
        BLEConfigConnGatt,
    )
    # noinspection PyUnresolvedReferences
    from pc_ble_driver_py.ble_adapter import BLEAdapter
    
    # Look at the example below
    # E4:3A:4F:B8:C6:FC --> [228, 58, 79, 184, 198, 252]
    TARGET_PEER_ADDR = [216, 96, 176, 219, 226, 122]
    CONNECTIONS = 1
    CFG_TAG = 1
    nrf_sd_ble_api_ver = config.sd_api_ver_get()
    
    
    class HR(BLEDriverObserver, BLEAdapterObserver):
    
        def __init__(self, adapter):
            super(HR, self).__init__()
            self.adapter = adapter
            self.conn_q = Queue()
            self.adapter.observer_register(self)
            self.adapter.driver.observer_register(self)
            self.adapter.default_mtu = 250
    
        def open(self):
            self.adapter.driver.open()
            gatt_cfg = BLEConfigConnGatt()
            gatt_cfg.att_mtu = self.adapter.default_mtu
            gatt_cfg.tag = CFG_TAG
            self.adapter.driver.ble_cfg_set(BLEConfig.conn_gatt, gatt_cfg)
            self.adapter.driver.ble_enable()
    
        def close(self):
            self.adapter.driver.close()
    
        def connect_and_discover(self):
            scan_duration = 180
            params = BLEGapScanParams(interval_ms=200, window_ms=150, timeout_s=scan_duration)
    
            self.adapter.driver.ble_gap_scan_start(scan_params=params)
    
            try:
                new_conn = self.conn_q.get(timeout=scan_duration)
                self.adapter.service_discovery(new_conn)
                for s in self.adapter.db_conns[new_conn].services:
                    print(str(s))
                    for c in s.chars:
                        print(str(c))
    
                return new_conn
            except Empty:
                print("No Device found.")
                return None
    
        def on_gap_evt_connected(self, ble_driver, conn_handle, peer_addr, role, conn_params):
            print("New connection: {}".format(conn_handle))
            self.conn_q.put(conn_handle)
    
        def on_gap_evt_disconnected(self, ble_driver, conn_handle, reason):
            print("Disconnected: {} {}".format(conn_handle, reason))
    
        def on_gap_evt_adv_report(self, ble_driver, conn_handle, peer_addr, rssi, adv_type, adv_data):
            if BLEAdvData.Types.complete_local_name in adv_data.records:
                dev_name_list = adv_data.records[BLEAdvData.Types.complete_local_name]
    
            elif BLEAdvData.Types.short_local_name in adv_data.records:
                dev_name_list = adv_data.records[BLEAdvData.Types.short_local_name]
    
            else:
                return
            print(dev_name_list)
            dev_name = "".join(chr(e) for e in dev_name_list)
            address_string = ":".join("{0:02X}".format(b) for b in peer_addr.addr)
            print(f"Received advertisment report, address: {address_string}, device_name: {dev_name}")
            if peer_addr.addr == TARGET_PEER_ADDR:
                self.adapter.connect(peer_addr, tag=1)
    
        def on_notification(self, ble_adapter, conn_handle, uuid, data):
            if len(data) > 32:
                data = "({}...)".format(data[0:10])
            print("Connection: {}, {} = {}".format(conn_handle, uuid, data))
            print("NUS_RX: " + ''.join(map(chr, data)))
    
    
    def main(selected_serial_port):
        print("Serial port used: {}".format(selected_serial_port))
        driver = BLEDriver(serial_port=selected_serial_port, auto_flash=False, baud_rate=1000000, log_severity_level="info")
        adapter = BLEAdapter(driver)
        collector = HR(adapter)
        collector.open()
        conn = collector.connect_and_discover()
    
        if conn is not None:
            while True:
                pass
    
        collector.close()
    
    
    if __name__ == "__main__":
        main("COM9")  # for me it is COM9
    

    You can see this example below in the file for more clarification.

  • Disconnected: 0 BLEHci.remote_user_terminated_connectio

    This means that  sd_ble_gap_disconnect() was called on the peer, with the reason BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION. If you can debug your peer you should be able to find where this is called.

    Kenneth

  • I searched in debugging mode but I didn't found that the function was called. However, on the peer I receive the messages below :

    ERROR:pc_ble_driver_py.ble_driver:Exception: MTU exchange reply failed. Common causes are: missing att_mtu setting in ble_cfg_set, different config tags used in ble_cfg_set and adv_start.
    ERROR:pc_ble_driver_py.ble_driver:<FrameSummary file C:xxxx\lib\site-packages\pc_ble_driver_py\ble_driver.py, line 2701 in ble_event_handler_sync>
    ERROR:pc_ble_driver_py.ble_driver:<FrameSummary file C:xxxx\lib\site-packages\pc_ble_driver_py\ble_adapter.py, line 772 in on_gatts_evt_exchange_mtu_request>
    ERROR:pc_ble_driver_py.ble_driver:

    Thanks

    Joe

  • It should be possible to search through your project for sd_ble_gap_disconnect(), I don't expect it is used many places.

    Looking at your pc ble driver log it may seem realted to MTU settings, you can for test simply comment out on_connected_evt() that is called in nrf_ble_gatt_on_ble_evt() from nrf_ble_gatt.c. This is far fetched, but could be worth a try.

    Do you by any chance have an on-air sniffer log (e.g. nrf sniffer)?

    Kenneth

  • I will try to find a sniffer and comment the function on_connected_evt() . But could you please try to lunch my code in the attachements to see what will happens.

    Thanks

    Joe

Related