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

Device Name shows garbage using pc_ble_driver_py

Using pc_ble_driver_py (version 0.15.0) to create a peripheral with a specific Device Name in characteristic 0x2A00 (Generic access service), the resulting device name is garbage. The class "BLEConfigGapDeviceName" is used to try setting the device name in the following way:

        configName = BLEConfigGapDeviceName(device_name="0000000000",device_name_read_only=False)
        ble_driver.ble_cfg_set(BLEConfig(driver.BLE_GAP_CFG_DEVICE_NAME), configName)
        ble_driver.ble_enable()

This is the result in nRF Connect:

In the log window the following is seen:

Attribute value read, handle: 0x03, value (0x): D4-03-00-20-00-00-00-00-D0-1C

 

This is the complete file:

import logging
import sys
import time
from threading import Condition, Lock
from pc_ble_driver_py.observers import BLEDriverObserver

BASE_UUID_DICT                 = {'BV_BASE_UUID': [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                               0x10, 0x00, 
                               0x80, 0x00, 
                               0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB]}
SERVICE1 = (("MyService1"      , 0x3000),
                                (("Char1"               , 0x3001, 1,   [0x00], "Desc"),
                                 ("Char2"                , 0x3002, 2,   [0x00], "Desc"),))

DEVICE_INFORMATION_SERVICE = (("Device Information"   , 0x180A),
                                (("Manufacturer name"    , 0x2A29, 20,   b"Name", None),
                                ("Model name"           , 0x2A24,  20,   b"Model1", None),
                                ("Firmware version"     , 0x2A26,  20,   b"v_0.0.1", None),))

SERVICES_CONFIG = ( DEVICE_INFORMATION_SERVICE,
                    SERVICE1,
                     )

logger = logging.getLogger(__name__)

def init(conn_ic_id):
    # noinspection PyGlobalUndefined
    global BLEAdapter, BLEDriver, BLEAdvData, BLEConfigGapDeviceName, BLEEvtID, BLEEnableParams, config, driver, BLEAdvData, BLEGattsHVXParams, BLEService, BLEUUIDBase, BLEUUID, BLEGattsAttr, BLEGattsAttrMD, BLEGattHandle, BLEGattsCharHandles, BLEGattsCharMD, BLEGattCharProps, BLEConfig, BLEConfigCommon
    from pc_ble_driver_py import config

    config.__conn_ic_id__ = conn_ic_id
    # noinspection PyUnresolvedReferences
    from pc_ble_driver_py.ble_driver import (
        BLEDriver,
        BLEAdvData,
        BLEConfigGapDeviceName,
        BLEEvtID,
        BLEEnableParams,
        BLEGattsHVXParams,
        BLEService,
        BLEUUIDBase,
        BLEUUID,
        BLEGattHandle,
        BLEGattsAttr,
        BLEGattsAttrMD,
        BLEGattsCharHandles,
        BLEGattsCharMD,
        BLEGattCharProps,
        BLEConfig,
        BLEConfigCommon,
        driver,
    )
        # noinspection PyUnresolvedReferences
    from pc_ble_driver_py.ble_adapter import BLEAdapter


class Peripheral:
    def __init__(self, adapter):
        self.adapter = adapter
        logger.info(
            "Peripheral adapter is %d",
            self.adapter.driver.rpc_adapter.internal,
        )
        self.char_128_handles_dict = {}
        self.serv_128_handle_dict = {}
        self.uuid_128_base_dict = {}
        self.serv_128_uuid_dict = {}

    def _add_char(self, base_uuid, service_uuid, char_uuid, max_len, value, user_desc_str):
        """Add characteristic"""
        char_128_handles = BLEGattsCharHandles()
        char_128_uuid = BLEUUID(char_uuid, self.uuid_128_base_dict[base_uuid] )
        
        max_len=16
        
        props = BLEGattCharProps(notify=True, read=True, write=True)
        if user_desc_str:
#            user_desc = list(user_desc_str.encode())
#            desc_md = BLEGattCharProps(read=True)
#            char_md = BLEGattsCharMD(char_props=props, user_desc=user_desc, desc_md=desc_md)
            char_md = BLEGattsCharMD(char_props=props)            
        else:
            char_md = BLEGattsCharMD(char_props=props)            
        
       
        attr_md = BLEGattsAttrMD()
        attr = BLEGattsAttr(uuid=char_128_uuid, attr_md=attr_md,
                            max_len=max_len, value=value)
        self.adapter.driver.ble_gatts_characteristic_add(
                            self.serv_128_handle_dict[service_uuid].handle,
                            char_md, attr, char_128_handles)
        self.char_128_handles_dict[char_uuid] = char_128_handles

    def _add_service(self, base_uuid, service_uuid):
        """Add specific service"""       
        if not base_uuid in self.uuid_128_base_dict:
            uuid_128_base = BLEUUIDBase(BASE_UUID_DICT[base_uuid])
            self.uuid_128_base_dict[base_uuid] = uuid_128_base
            self.adapter.driver.ble_vs_uuid_add(self.uuid_128_base_dict[base_uuid])

        self.serv_128_handle_dict[service_uuid]= BLEGattHandle()
        self.serv_128_uuid_dict[service_uuid] = BLEUUID(service_uuid, self.uuid_128_base_dict[base_uuid])
  
        self.adapter.driver.ble_gatts_service_add(
            driver.BLE_GATTS_SRVC_TYPE_PRIMARY, self.serv_128_uuid_dict[service_uuid], self.serv_128_handle_dict[service_uuid])
 
    def setup_services_128bit(self):
        """Setup services"""
        for (_, service_uuid), chars in SERVICES_CONFIG:
            self._add_service(base_uuid='BV_BASE_UUID', service_uuid=service_uuid)
            for (_, char_uuid, max_len, value, user_desc_str) in chars:
                self._add_char(base_uuid='BV_BASE_UUID', 
                           service_uuid=service_uuid, 
                           char_uuid=char_uuid, max_len=max_len, value=value,
                           user_desc_str=user_desc_str)
def main(serial_port):
    print("Serial port used: {}".format(serial_port))
    ble_driver = BLEDriver(serial_port=serial_port, 
                       baud_rate=1000000,
                       auto_flash=True,
                       log_severity_level="debug")
    adapter = BLEAdapter(ble_driver)
    observer = TimeoutObserver()

    adv_data = BLEAdvData(short_local_name="MyDevice")

    ble_driver.observer_register(observer)
    ble_driver.open()
    if config.__conn_ic_id__.upper() == "NRF51":
        ble_driver.ble_enable(
            BLEEnableParams(
                vs_uuid_count=0,
                service_changed=0,
                periph_conn_count=1,
                central_conn_count=0,
                central_sec_count=0,
            )
        )
    elif config.__conn_ic_id__.upper() == "NRF52":
#         configCommon = BLEConfigCommon()
#         configCommon.vs_uuid_count = 1
#         driver.ble_cfg_set(BLEConfig.uuid_count, configCommon)
#         cfg = BLEConfigGap()
#         cfg.device_name = "test123"
#         cfg.device_name_read_only = False
#        ble_tester.driver.ble_cfg_set(BLEConfig.device_name, cfg)
        
        configName = BLEConfigGapDeviceName(device_name="0000000000",device_name_read_only=False)
        ble_driver.ble_cfg_set(BLEConfig(driver.BLE_GAP_CFG_DEVICE_NAME), configName)
#         ble_driver.ble_cfg_set(BLEConfig.device_name, cfg)
        #sd_ble_gap_device_name_set()
        ble_driver.ble_enable()
        
    peripheral = Peripheral(adapter)
    peripheral.setup_services_128bit()
       
    ble_driver.ble_gap_adv_data_set(adv_data)
    ble_driver.ble_gap_adv_start()
    observer.wait_for_timeout()

    while(True):
        time.sleep(10)
    print("Closing")
    ble_driver.close()


class TimeoutObserver(BLEDriverObserver):
    def __init__(self, *args, **kwargs):
        super(BLEDriverObserver, self).__init__(*args, **kwargs)
        self.cond = Condition(Lock())

    def on_gap_evt_timeout(self, ble_driver, conn_handle, src):
        with self.cond:
            self.cond.notify_all()

    def on_gap_evt_disconnected(self, ble_driver, conn_handle, reason):
        with self.cond:
            self.cond.notify_all()

    def wait_for_timeout(self):
        with self.cond:
            self.cond.wait()


if __name__ == "__main__":
    logFormatter = logging.Formatter("%(asctime)s [%(levelname)-7s][%(name)s] %(message)s")
    rootLogger = logging.getLogger()
     
    fileHandler = logging.FileHandler("ble_test.log")
    fileHandler.setFormatter(logFormatter)
    rootLogger.addHandler(fileHandler)
     
    consoleHandler = logging.StreamHandler(sys.stdout)
    consoleHandler.setFormatter(logFormatter)
    rootLogger.addHandler(consoleHandler)
     
    rootLogger.setLevel(logging.DEBUG)
    
    id = "NRF52"
    serial_port = "/dev/ttyACM0"
    init(id)
    main(serial_port)

What am I doing wrong?

Parents Reply Children
  • Hehe, yes - only here it is called Vinterferie, but I assume it is essentially the same thing - a vacation to go skiing other snow activities with family and friends! :)
    Unfortunately a lot of the snow disappeared the last few days, but otherwise the weather has been great. Hope it is equally as nice where you are! 

  • Hello again gnf,

    Thank you for your patience with this.

    I have now checked whether there is a difference behind the scenes between calls to sd_ble_gap_device_name_set and sd_ble_cfg_set, and their primary difference is that sd_ble_cfg_set is used to configure the SoftDevice (before the BLE part of the SoftDevice is enabled, as per its API Reference), while the sd_ble_gap_device_name_set may be used to update the GATT db directly, also after the BLE part of the SoftDevice is initialized.
    I also spoke with the lead developer Bjørn today, and he told me that he had been in contact with you directly last week, which was possibly also related to some of your other PR's, as I understood it.

    Did this and you talk with Bjørn answer your questions here, or do you still have any questions related to this?

    Best regards,
    Karl

  • Hello Karl,

    I don't think me and Bjørn touched this issue when discussing the other PR's. What is missing for me regarding the device name issue is that I am looking for a working code snippet in Python on how to set the device name in the SoftDevice config, I guess  using BLEConfigGapDeviceName(). That is on line 148 in my file listing above. 

  • Sorry for the late reply here.

    gnf said:
    I don't think me and Bjørn touched this issue when discussing the other PR's.

    Aha, I must have misunderstood Bjørn then.

    gnf said:
    What is missing for me regarding the device name issue is that I am looking for a working code snippet in Python on how to set the device name in the SoftDevice config, I guess  using BLEConfigGapDeviceName().

    I will create such an example for you tomorrow, to illustrate how it can be implemented.

    Best regards,
    Karl

  • Hello gnf,

    I have worked on this today, and naturally discovered the same issue as you describe in your original ticket - with the device name turning into jibberish when attempting to set it with the following:

    config_device_name = BLEConfigGapDeviceName()
    error_code = driver.ble_cfg_set(BLEConfig.device_name, config_device_name)

    Closer investigation of the device name as transmitted over the BLE connection reveals that there is a trailing character in the transmitted name.
    The equivalent pc-ble-driver function works as expected, indicating that there is an error somewhere in the python-to-c casting of the device name.

    I have created an internal ticket for this, where I ask the developers to examine this more closely.

    Unfortunately, that leaves you with only the sd_ble_gap_device_name_set option for setting the device name, for the time being. Thank you for rooting out this bug for us, we will see it fixed!

    Best regards,
    Karl

Related