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?