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

Regarding Python Scripts for nrf52840 to connect and transfer data.

Hi ,

What I am trying:- 

-connect the custom board with nrf52840 chip using nrf52 dongle on pc with python.

-Already set some commands on custom board so when my pc (via dongle) connects to custom board, I want to send some commands and accordingly receive the response.

For this I got my hands-on nrf dongle to give my laptop a BLE access.

And I am trying to access the board using dongle (using python script) and I am getting below error,


raise NordicSemiException('Failed to {}. Error code: {}'.format(wrapped.__name__, err_code))
pc_ble_driver_py.exceptions.NordicSemiException: Failed to open. Error code: 13.

Would anyone able to tell me how do i resolve this. 

I want to have python code that can connect and do some data transfer over BLE using Dongle connected to my pc and I have tried with hart_rate_monitor unsuccessfully. 

EDIT 1:- I am able to scan and connect my board using the nRF Connect windows app. Same I wanted to implement over python.

Thanks,

Hinesh

  • Hi,

    BLEUUID is a class, and you use BLEUUID() to create an instance of that class. I.e., you use the BLEUUID() function to generate a BLEUUID object.

    BLEUUID takes one or two arguments. The first argument is the 16 bit UUID. The second argument is optional, and is the base UUID, of type BLEUUIDBase. If the second argument is not provided then a 16 bit UUID is generated (using the special Bluetooth SIG assigned base UUID to be used with 16 bit UUIDs.)

    I did find an example using both standard (16 bit) UUIDs and user generated (128 bit) UUIDs, as part of pc-nrfutil:

        BASE_UUID = BLEUUIDBase([0x8E, 0xC9, 0x00, 0x00, 0xF3, 0x15, 0x4F, 0x60,
                                 0x9F, 0xB8, 0x83, 0x88, 0x30, 0xDA, 0xEA, 0x50])
                                 
        # Buttonless characteristics
        BLE_DFU_BUTTONLESS_CHAR_UUID        = BLEUUID(0x0003, BASE_UUID)
        BLE_DFU_BUTTONLESS_BONDED_CHAR_UUID = BLEUUID(0x0004, BASE_UUID)
        SERVICE_CHANGED_UUID                = BLEUUID(0x2A05)

    Notice how in order to create a custom UUID, you first use BLEUUIDBase() to generate the BLEUUIDBase, and then provide that BLEUUIDBase object as the second argument to BLEUUID().

    Regards,
    Terje

  • Hi 

    MY_UUID = '00001111-0000-1000-8000-00805f9b34fb'
    

    My UUID is as above, And I have used as per your prev. comment. I checked with nrf connect mobile app.
    Still I was getting error.

    Below is my console output after I used

    BLE_DFU_BUTTONLESS_CHAR_UUID = BLEUUID(0x0003, BASE_UUID)

    in

    self.adapter.enable_notification(new_conn, BLEUUID(0x0003, MY_UUID)

    Serial port used: COM10
    Enabling larger ATT MTUs
    Received advertisment report, address: 0x5031ADC0000A, device_name: POC1_2-3
    New connection: 0
    ATT MTU exchanged: conn_handle=0 att_mtu=23
    ATT MTU exchange response: conn_handle=0
    Traceback (most recent call last):
      File "C:\Program Files\JetBrains\PyCharm Community Edition 2018.1.3\helpers\pydev\pydevd.py", line 1664, in <module>
        main()
      File "C:\Program Files\JetBrains\PyCharm Community Edition 2018.1.3\helpers\pydev\pydevd.py", line 1658, in main
        globals = debugger.run(setup['file'], None, None, is_module)
      File "C:\Program Files\JetBrains\PyCharm Community Edition 2018.1.3\helpers\pydev\pydevd.py", line 1068, in run
        pydev_imports.execfile(file, globals, locals)  # execute the script
      File "C:/My_Projects/Script.py", line 263, in <module>
        main(serial_port)
      File "C:/My_Projects/Script.py", line 244, in main
        conn_handle = collector.connect_and_discover()
      File "C:/My_Projects/Script.py", line 194, in connect_and_discover
        self.adapter.enable_notification(new_conn, BLEUUID(0x0003, DC_SERVICE_UUID))#BLEUUID(BLEUUID.Standard.battery_level))
      File "C:\Python27\lib\site-packages\pc_ble_driver_py\ble_driver.py", line 882, in __init__
        assert isinstance(base, BLEUUIDBase), 'Invalid argument type'
    AssertionError: Invalid argument type
    

    Still the error.

    I am attaching my script so that you can check and provide input.

    This is for your information on how I am trying to implement.

    import Queue
    
    import json
    import time
    import sys
    
    from datetime import datetime, timedelta
    from bitstruct import *
    from pprint import pformat
    import binascii
    from pc_ble_driver_py.observers import *
    from nordicsemi.ble_adapter import *
    
    try:
        with open("Config_Files/Connection_Settings.json")as conn:
            config = json.load(conn)
    except Exception as e:
        print str(e)
        print 'Could not open settings file'
        raw_input("Press ENTER to exit...")
        quit()
    
    
    DEV_MAC = config['dev_mac']
    
    
    REPEAT_COUNT = 25
    
    RAW_TYPE = TEMP  # Temp sensor
    RAW_COUNT = 10  # Sample count
    RAW_RATE = 0  # Sampling freq
    
    TARGET_DEV_NAME ="50:31:AD:C0:00:0A"
    port_enter = "COM10"
    device = "NRF52"
    CONNECTIONS = 1
    serial_port = "COM10"
    dev_name = "50:31:AD:C0:00:0A"
    # Creating command packet
    temp = pack('u8u16f32', RAW_TYPE, RAW_COUNT, RAW_RATE)
    pkt = byteswap('124', temp)
    
    HEADER_SIZE = 3
    
    _EOT_T = 'u1'
    _TYPE_T = 'u3'
    _TID_T = 'u4'
    _SEQ_NUM_T = 'u16'
    
    __BYTEALIGN = '12'
    
    __DATA_FORMAT = _TID_T + _TYPE_T + _EOT_T + _SEQ_NUM_T
    
    sensorType = RAW_TYPE
    sampleCount = RAW_COUNT
    samplingFreq = RAW_RATE
    ##
    #Data saving part 
    ##
    
    ##### NRF PART ################
    
    CCCD_UUID = '00002902-0000-1000-8000-00805f9b34fb'
    
    DC_SERVICE_UUID = '00001111-0000-1000-8000-00805f9b34fb'
    
    BASE_UUID = BLEUUIDBase([0x8E, 0xC9, 0x00, 0x00, 0xF3, 0x15, 0x4F, 0x60,
                             0x9F, 0xB8, 0x83, 0x88, 0x30, 0xDA, 0xEA, 0x50])
    
    # Buttonless characteristics
    BLE_DFU_BUTTONLESS_CHAR_UUID = BLEUUID(0x0003, BASE_UUID)
    BLE_DFU_BUTTONLESS_BONDED_CHAR_UUID = BLEUUID(0x0004, BASE_UUID)
    SERVICE_CHANGED_UUID = BLEUUID(0x2A05)
    def init(conn_ic_id):
        global BLEDriver, BLEAdvData, BLEEvtID, BLEAdapter, BLEEnableParams, BLEGapTimeoutSrc, BLEUUID
        from pc_ble_driver_py import config
        config.__conn_ic_id__ = conn_ic_id
        from pc_ble_driver_py.ble_driver import BLEDriver, BLEAdvData, BLEEvtID, BLEEnableParams, BLEGapTimeoutSrc, BLEUUID
        from pc_ble_driver_py.ble_adapter import BLEAdapter
        global nrf_sd_ble_api_ver
        nrf_sd_ble_api_ver = config.sd_api_ver_get()
    
    
    class HRCollector(BLEDriverObserver, BLEAdapterObserver):
        def __init__(self, adapter):
            super(HRCollector, self).__init__()
            self.adapter = adapter
            self.conn_q = Queue.Queue()
            self.adapter.observer_register(self)
            self.adapter.driver.observer_register(self)
    
        def open(self):
            self.adapter.driver.open()
    
            ble_enable_params = BLEEnableParams(vs_uuid_count=1,
                                                service_changed=False,
                                                periph_conn_count=0,
                                                central_conn_count=CONNECTIONS,
                                                central_sec_count=CONNECTIONS)
            if nrf_sd_ble_api_ver >= 3:
                print("Enabling larger ATT MTUs")
                ble_enable_params.att_mtu = 50
    
            self.adapter.driver.ble_enable(ble_enable_params)
    
        def close(self):
            self.adapter.driver.close()
    
        @property
        def connect_and_discover(self):
            self.adapter.driver.ble_gap_scan_start()
            new_conn = self.conn_q.get(timeout=60)
    
            if nrf_sd_ble_api_ver >= 3:
                att_mtu = self.adapter.att_mtu_exchange(new_conn)
    
            self.adapter.service_discovery(new_conn)
            self.adapter.enable_notification(new_conn, BLEUUID(0x0003, DC_SERVICE_UUID))#BLEUUID(BLEUUID.Standard.battery_level))
            # self.adapter.enable_notification(new_conn, BLEUUID(BLEUUID.Standard.heart_rate))
            return new_conn
    
        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_timeout(self, ble_driver, conn_handle, src):
            if src == BLEGapTimeoutSrc.scan:
                ble_driver.ble_gap_scan_start()
    
        def on_gap_evt_adv_report(self, ble_driver, conn_handle, peer_addr, rssi, adv_type, adv_data):
            dev_name_list = None
            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
    
            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('Received advertisment report, address: 0x{}, device_name: {}'.format(address_string,
                                                                                        dev_name))
    
            if (dev_name == TARGET_DEV_NAME):
                self.adapter.connect(peer_addr)
    
        def on_notification(self, ble_adapter, conn_handle, uuid, data):
            print('Connection: {}, {} = {}'.format(conn_handle, uuid, data))
    
        def on_att_mtu_exchanged(self, ble_driver, conn_handle, att_mtu):
            print('ATT MTU exchanged: conn_handle={} att_mtu={}'.format(conn_handle, att_mtu))
    
        def on_gattc_evt_exchange_mtu_rsp(self, ble_driver, conn_handle, **kwargs):
            print('ATT MTU exchange response: conn_handle={}'.format(conn_handle))
    
    
    def main(serial_port):
        print('Serial port used: {}'.format(serial_port))
        driver = BLEDriver(serial_port=serial_port, auto_flash=True)
        adapter = BLEAdapter(driver)
        collector = HRCollector(adapter)
        collector.open()
        conn_handle = collector.connect_and_discover()
        # adapter.write_req(conn_handle, CCCD_UUID, [3])#RAW_TYPE)
        # collector.connect_and_discover()
       
    
    
    if __name__ == "__main__":
        serial_port = None
        # if len(sys.argv) < 2:
        #     print("Please specify connectivity IC identifier (NRF51, NRF52)")
        #     exit(1)
        init("NRF52")
        if len(sys.argv) == 3:
            serial_port = sys.argv[2]
        else:
            descs = BLEDriver.enum_serial_ports()
            choices = ['{}: {}'.format(d.port, d.serial_number) for d in descs]
            choice = '0'  # item_choose(choices)
            serial_port = port_enter  # "COM12" #descs[choice].port
            main(serial_port)
            quit()
    
    ##### NRF PART ###### #########
    

    Thnaks,

  • Hi,

    You need to make the DC_SERVICE_UUID in the same way as the BLE_DFU_BUTTONLESS_CHAR_UUID was made in the example code. (You should not just copy and paste the code, as you are using different UUIDs than what was used in the example code.)

    More specifically, on the line "self.adapter.enable_notification(new_conn, BLEUUID(0x0003, DC_SERVICE_UUID))" you provide DC_SERVICE_UUID, which should be a BLEUUIDBase object and not a string.

    Regards,
    Terje

  • Hi,

    Also, on the line I mentioned, you use the value 0x0003, but that should be byte 12 and 13 of the full UUID, and what you call DC_SERVICE_UUID should really be called DC_SERVICE_BASE_UUID. Those two parts together are used by BLEUUID to generate the full UUID.

    Regards,
    Terje

  • Hi

    You have explained well.

    But two questions:-

    1. How do I convert UUID to BLEUUDIBase Format? just separating  with '0x00' will not work (I think).

    2. This is for writing, once this command given , device will start transmitting data. So I have to initiate a reader thread/function as well. is there any read function as I was not able to find in examples.

    Thanks,

    Hinesh

Related