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
  • I found the function "sd_ble_gap_device_name_set". I created a pull request for implementing this feature in pc_ble_driver_py as using it seems to work:

    https://github.com/NordicSemiconductor/pc-ble-driver-py/pull/189

    But then, when should sd_ble_gap_device_name_set be used and when should BLEConfigGapDeviceName be used?

  • Hello gnf,

    Thank you for your patience.

    gnf said:
    I found the function "sd_ble_gap_device_name_set". I created a pull request for implementing this feature in pc_ble_driver_py as using it seems to work:

    I am happy to hear that you were able to figure out a way to achieve this. Thank you for submitting the pull request, and sharing the complete code you used to produce this - this will make the debugging part much easier.

    gnf said:
    But then, when should sd_ble_gap_device_name_set be used and when should BLEConfigGapDeviceName be used?

    I've passed this question on to the developers of the pc-ble-driver-py, and I will let you know as soon as they get back to me on this.
    The pc-ble-driver-py is just a python layer for the the pc-ble-driver, which is a serialized version of the SoftDevice API. So, I suppose the difference here really comes down to either using the sd_ble_gap_device_name_set function directly, or using the sd_ble_cfg_set function - this is my initial though anyways, but we will know more once the developers gets back to me.

    Best regards,
    Karl

Reply
  • Hello gnf,

    Thank you for your patience.

    gnf said:
    I found the function "sd_ble_gap_device_name_set". I created a pull request for implementing this feature in pc_ble_driver_py as using it seems to work:

    I am happy to hear that you were able to figure out a way to achieve this. Thank you for submitting the pull request, and sharing the complete code you used to produce this - this will make the debugging part much easier.

    gnf said:
    But then, when should sd_ble_gap_device_name_set be used and when should BLEConfigGapDeviceName be used?

    I've passed this question on to the developers of the pc-ble-driver-py, and I will let you know as soon as they get back to me on this.
    The pc-ble-driver-py is just a python layer for the the pc-ble-driver, which is a serialized version of the SoftDevice API. So, I suppose the difference here really comes down to either using the sd_ble_gap_device_name_set function directly, or using the sd_ble_cfg_set function - this is my initial though anyways, but we will know more once the developers gets back to me.

    Best regards,
    Karl

Children
Related