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

  • Hello again gnf,

    I just wanted to let you know that the developers in question is currently out of office this week for the national winter's break in Norway. They should be back again on Monday, and I will resume my discussion with them then.

    I will update you as soon as I heard back from them on this issue.

    Best regards,
    Karl

Reply Children
Related