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

Device Name changing with nRF52840 using sd_ble_gap_device_name_set in Python

Hi,

I'm trying to make a script in Python using the nRF52840 dongle, to make some BLE advertising.

I'm using:

- Python 3.7.2 (32 bit)

- pc_ble_driver_py library

- Windows 10

- Visual Code

nRF52840 dongle with USB CDC ACM FW

Now I would like to set a name to my device as I can see it through nRF APP on my mobile phone.

Searching through similar issues in other posts, I've found this function sd_ble_gap_device_name_set, which defined as follow:

def sd_ble_gap_device_name_set(adapter, p_write_perm, p_dev_name, len):
 return _nrf_ble_driver_sd_api_v2.sd_ble_gap_device_name_set(adapter, p_write_perm, p_dev_name, len)

To figure out how to use it, I've searched in some tutorials and found Bluetooth low energy Advertising, a beginner's tutorial which are written in C;

The function in C is declared as follow:

uint32_t sd_ble_gap_device_name_set	(	ble_gap_conn_sec_mode_t const * 	p_write_perm,
                                        uint8_t const * 	p_dev_name,
                                        uint16_t 	len 
                                    )	

In my script, the function is used as follow:

    # Device Name Change
    device_name = split_str(DEVICE_NAME)
    gap_device_name = [hex(ord(x)) for x in device_name]
    str_length = len(DEVICE_NAME.encode(encoding='utf_8'))
    driver.sd_ble_gap_device_name_set(
            peripheral.adapter.driver.rpc_adapter,
            None,
            DEVICE_NAME.encode(encoding='utf_8'),
            str_length
            )

when in Debug mode with Visual Code, I receive this message:
Can anyone help me to solve this issue?
Thanx,
Fabio
Parents Reply
  • Hello again.

    Fabio Ballanti said:
    Yes, I've seen it now (I was set on mind for uint16_t), sorry if didn't check before and I missed it...

    No problem at all Fabio, it happens to all of us sometimes :)

    Fabio Ballanti said:
    Reading well the other screenshots, and seeing this last one, it seems that the real problem now is on formatting DEVICE_NAME.encode(encoding='utf_8')

    Yes, this again is a TypeError. What is the type of the DEVICE_NAME.encode(encoding='utf_8') argument you are supplying? 
    As you see from the sd_ble_gap_device_name_set function documentation, and the error message, the argument needs to be a uint8_t const pointer.

    As I understand it you are now using the pc-ble-driver-py in your python project, correct?
    If so you should check out the advertising example and how they use the pc-ble-driver-py to configure the device name there.

    Best regards,
    Karl

Children
  • Hi Karl,

    thank you again for your support!

    What is the type of the DEVICE_NAME.encode(encoding='utf_8') argument you are supplying? 

    The variable DEVICE_NAME is a string (intended as array of chars), and following the example in Bluetooth low energy Advertising, a beginner's tutorial I've named it in  the same way:

    DEVICE_NAME = "HelloWorld"

    in the example code (written in C), there's a point which is called this function:

        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *)DEVICE_NAME,
                                              strlen(DEVICE_NAME));

    where is passed a pointer type cast (const uint8_t *);

    so, thought was a best practice to pass in the Python function the string DEVICE_NAME encoded in utf_8:

    >>>print(DEVICE_NAME.encode(encoding='utf_8'))
    b'HelloWorld'

    But, I have to find out how to convert a string in a uint8_t const pointer...

    As I understand it you are now using the pc-ble-driver-py in your python project, correct?

    Yes, correct! I've made for the Python interpreter the pip install pc-ble-driver-py command.

    If so you should check out the advertising example and how they use the pc-ble-driver-py to configure the device name there.

    PERFECT! I'll study it and let you know!

     

  • Hello again,

    Fabio Ballanti said:
    thank you again for your support!

    No problem at all Fabio, I am happy to help!

    Fabio Ballanti said:
    PERFECT! I'll study it and let you know!

    Great, I am happy to hear that!
    That sounds like a good plan - let me know if you should encounter any issues or questions while doing so!

    Best regards,
    Karl 

  • Hello again,

    In the advertising example, there is a useful method, very simple than mine:

    adv_data = BLEAdvData(complete_local_name="pc_ble_driver_py")

    and then

    driver.ble_gap_adv_data_set(adv_data)

    So, using those lines of code in my script

        adv_data=BLEAdvData(complete_local_name="Nod If You Can Here Me!")
        peripheral.adapter.driver.ble_gap_adv_data_set(adv_data)

    and the result is:

    Nevertheless, even if the result is the desired one, the advertising data previously entered and displayed for the Manufacturer Data with this method disappear...

  • Fabio Ballanti said:
    In the advertising example, there is a useful method, very simple than mine:

    That is great, I am happy to hear that you found the example useful!

    Fabio Ballanti said:
    Nevertheless, even if the result is the desired one, the advertising data previously entered and displayed for the Manufacturer Data with this method disappear...

    That is because you with the first line is creating a new - empty - instance of the BLEAdvData class, to which you only provide the complete_local_name variable.
    If you would like to use this approach to change only the device name - and keep the previously provided advertising data the same - you will need to keep records of the other data currently being advertised, and provide that along with the new name to the new object. Try this, and let me know if you are able to update the device name this way.

    You could then create a function that does all this for you, to which you only need to provide the new name ( if you intend to change name often ).

    Please do not hesitate to let me know if something should be unclear, or if you should encounter any other questions!

    Best regards,
    Karl

  • Hello Karl,

    you will need to keep records of the other data currently being advertised, and provide that along with the new name to the new object. Try this, and let me know if you are able to update the device name this way

    Ok, I grabbed the concept, but I'm afraid I'm starting to get lost... 

    So, my target is to set Complete Local Name and Manufactuer Data at the same time and I have stored this last one in list, for example:

    # Manifacturer Data
    data = ['0x2', '0x1', '0x6', '0x12', '0xff', '0x59', '0xfe', '0xba', '0xcc', '0x53', '0x72', '0xaa', '0xdd', '0x55', '0x37', '0x6f', '0xcc', '0x55', '0x33', '0xaa', '0x66', '0xff']
    adv_data_manufacturer = util.list_to_uint8_array(data)

    where list_to_uint8_array Converts a python list to uint8_array.

    After that, set this array and name:

        # Complete Local Name and Manifacturer Data Set
        adv_data=BLEAdvData(complete_local_name         ="Nod If You Can Hear Me!",
                            manufacturer_specific_data  =adv_data_manufacturer
        )
    
        peripheral.adapter.driver.ble_gap_adv_data_set(adv_data)

    Running this script, there's this exception:

    Looking at the function ble_gap_adv_data_set , len() is not an input parameter... 

        @NordicSemiErrorCheck
        @wrapt.synchronized(api_lock)
        def ble_gap_adv_data_set(self, adv_data=BLEAdvData(), scan_data=BLEAdvData()):
            assert isinstance(adv_data, BLEAdvData), "Invalid argument type"
            assert isinstance(scan_data, BLEAdvData), "Invalid argument type"
            (adv_data_len, p_adv_data) = adv_data.to_c()
            (scan_data_len, p_scan_data) = scan_data.to_c()
    
            return driver.sd_ble_gap_adv_data_set(
                self.rpc_adapter, p_adv_data, adv_data_len, p_scan_data, scan_data_len
            )

    Probably it's something that I'm missing, and still don't understand... Is that what you've tried to explain me?

    Even though I'm starting to have a terrible mess in my head Scream, I'm able by the way to set or the Manufacturer Data or the Local Device Name

    Thank you!

    Fabio

Related