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
  • Hello Fabio,

    What is the type of your passed str_length variable?
    As you see in the sd_ble_gap_device_name_set the len parameter needs to be of type uint16_t, while then python len functions returns an int ( represented by 4 bytes ).
    I assume this is why you have got your type error.
    Please try to typecast the len variable to uint16_t, and see if this resolves your issue.

    Best regards,
    Karl

  • Hello Karl,

    Yes, the str_length variable is of course an int. 

    The variable DEVICE_NAME is a string "HelloWorld", which is converted and stored in device_name as ['H','e','l','l','o','W','o','r','l','d']

    Googling around there's the ctypes library which seems to have only ctypes.c_uint8 and ctypes.c_uint16, but no c_uint8_t or c_uint16_t. Trying to import ctypes library and using c_uint8 or c_uint16 it in my code, the answer is the same:
    Is there a better way to make a change name on the device?
    Thanx
  • 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

  • Hello Fabio,

    Fabio Ballanti said:
    Ok, I grabbed the concept, but I'm afraid I'm starting to get lost... 

    You are absolutely on the right path here! :)  

    Fabio Ballanti said:
    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:
    Fabio Ballanti said:
    where list_to_uint8_array Converts a python list to uint8_array.

    Normally, if you were to implement an interface between a C program and a python program on your own, you would be absolutely correct in your approach here!
    Fortunately, the pc-ble-driver-py does this for you. If you look into the particular function being called here - peripheral.adapter.driver.ble_gap_adv_data_set - you'll see that it takes an BLEAdvData object as its first parameter. Then, in this function, it checks whether it in fact is a BLEAdvData object, before calling the objects own .to_c() function. Looking into this function, you see that .to_c() actually does this very conversion to a uint8_t array, and returns both the pointer to the start of the array, and the length of the array.

    So, what you are doing wrong in your case is that you have provided the BLEAdvData with a uint8_t type array for its data already. This does not work, since BLEAdvData is a python object, which does not expect to work with uint8_t types. Instead, you should provide the data as usual to your BLEAdvData object, and let it do the conversion to uint8_t for you only when needed.

    Fabio Ballanti said:

    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

    In essence, the pc-ble-driver-py is created so that you do not in fact need to know that much C, to work with the SoftDevice(which is entirely in C).
    So, when working with pc-ble-driver-py, you can just go ahead and think of it strictly as python, and it will do the necessary conversions for you in the background, without you needing to intervene.
    The reason why you in your initial post had to look into uint8_t types ( and other C types ) is that you were trying to use the sd_ble_gap_device_name_set function directly, which is a C function.

    In conclusion, if you stick to using the supplies pc-ble-driver-py API, then you do not need to worry about C types and C conversions happening behind the scenes.
    I hope that what I have wrote makes sense. Please do not hesitate to ask if anything about my answer should be unclear! Slight smile

    Best regards,
    Karl

Reply
  • Hello Fabio,

    Fabio Ballanti said:
    Ok, I grabbed the concept, but I'm afraid I'm starting to get lost... 

    You are absolutely on the right path here! :)  

    Fabio Ballanti said:
    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:
    Fabio Ballanti said:
    where list_to_uint8_array Converts a python list to uint8_array.

    Normally, if you were to implement an interface between a C program and a python program on your own, you would be absolutely correct in your approach here!
    Fortunately, the pc-ble-driver-py does this for you. If you look into the particular function being called here - peripheral.adapter.driver.ble_gap_adv_data_set - you'll see that it takes an BLEAdvData object as its first parameter. Then, in this function, it checks whether it in fact is a BLEAdvData object, before calling the objects own .to_c() function. Looking into this function, you see that .to_c() actually does this very conversion to a uint8_t array, and returns both the pointer to the start of the array, and the length of the array.

    So, what you are doing wrong in your case is that you have provided the BLEAdvData with a uint8_t type array for its data already. This does not work, since BLEAdvData is a python object, which does not expect to work with uint8_t types. Instead, you should provide the data as usual to your BLEAdvData object, and let it do the conversion to uint8_t for you only when needed.

    Fabio Ballanti said:

    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

    In essence, the pc-ble-driver-py is created so that you do not in fact need to know that much C, to work with the SoftDevice(which is entirely in C).
    So, when working with pc-ble-driver-py, you can just go ahead and think of it strictly as python, and it will do the necessary conversions for you in the background, without you needing to intervene.
    The reason why you in your initial post had to look into uint8_t types ( and other C types ) is that you were trying to use the sd_ble_gap_device_name_set function directly, which is a C function.

    In conclusion, if you stick to using the supplies pc-ble-driver-py API, then you do not need to worry about C types and C conversions happening behind the scenes.
    I hope that what I have wrote makes sense. Please do not hesitate to ask if anything about my answer should be unclear! Slight smile

    Best regards,
    Karl

Children
No Data
Related