'Ble dbus python: advertise ServiceUUIDs information

Background: I want to use ble for server/client software. But in this case, the server should be the peripheral with multiple connections. For that i start multiple services, up to 10. I think that's the limit for peripheral connections on my chip. The different services are the same in functionality but should connect to only one client. I see no other possibility to differentiate the clients in the notification function.

Problem: For that i restart the advertising after each connection. In the advertisement, I set the uuid information field “ServiceUUIDs” for the next free service to connect. This is working after restarting my pc. In my flutter app, I’m able to read this field perfectly in the advertisment. But when I restart the python script, the uuid is no longer advertised and the field “ServiceUUIDs” is empty although {'Type': 'peripheral', 'ServiceUUIDs': dbus.Array(['0000ac01-0000-1000-8000-00805f9b34fb'], signature=dbus.Signature('s')), 'LocalName': dbus.String('Hello'), 'Discoverable': dbus.Boolean(True)} is set in the bluetooth_constants.ADVERTISING_MANAGER_INTERFACE. Also restarting the bluetooth module is not working. Therefore I must restart my pc everytime I want to restart my server... After connecting to the server, the client can scan all services and does not know, which one of the 10 services is free to connect.

My python code is the same as in the dbus tutorial:

    class Advertisement(dbus.service.Object):
        PATH_BASE = '/org/bluez/ldsg/advertisement'
    
        def __init__(self, bus, index, advertising_type):
            self.path = self.PATH_BASE + str(index)
            self.bus = bus
            self.ad_type = advertising_type
            self.service_uuids = ['0000ac01-0000-1000-8000-00805f9b34fb']
            self.manufacturer_data = None
            self.solicit_uuids = None
            self.service_data = None
            self.local_name = 'Hello'
            self.include_tx_power = False
            self.data = None #{0x26: dbus.Array([0x01, 0x01, 0x01], signature='y')}
            self.discoverable = True
            dbus.service.Object.__init__(self, bus, self.path)
    
        def get_properties(self):
            properties = dict()
            properties['Type'] = self.ad_type
            if self.service_uuids is not None:
                properties['ServiceUUIDs'] = dbus.Array(self.service_uuids,
                                                        signature='s')
            if self.solicit_uuids is not None:
                properties['SolicitUUIDs'] = dbus.Array(self.solicit_uuids,
                                                        signature='s')
            if self.manufacturer_data is not None:
                properties['ManufacturerData'] = dbus.Dictionary(
                    self.manufacturer_data, signature='qv')
            if self.service_data is not None:
                properties['ServiceData'] = dbus.Dictionary(self.service_data,
                                                            signature='sv')
            if self.local_name is not None:
                properties['LocalName'] = dbus.String(self.local_name)
            if self.discoverable is not None and self.discoverable == True:
                properties['Discoverable'] = dbus.Boolean(self.discoverable)
            if self.include_tx_power:
                properties['Includes'] = dbus.Array(["tx-power"], signature='s')
    
            if self.data is not None:
                properties['Data'] = dbus.Dictionary(
                    self.data, signature='yv')
            print(properties)
            return {bluetooth_constants.ADVERTISING_MANAGER_INTERFACE: properties}
    
    
    def start_advertising():
        global adv
        global adv_mgr_interface
        # we're only registering one advertisement object so index (arg2) is hard coded as 0
        print("Registering advertisement",adv.get_path())
        adv_mgr_interface.RegisterAdvertisement(adv.get_path(), {},
                                            reply_handler=register_ad_cb,
                                            error_handler=register_ad_error_cb)
    
    bus = dbus.SystemBus()
    adv_mgr_interface = dbus.Interface(bus.get_object(bluetooth_constants.BLUEZ_SERVICE_NAME,adapter_path), bluetooth_constants.ADVERTISING_MANAGER_INTERFACE)
    adv = Advertisement(bus, 0, 'peripheral')  
    start_advertising()

Maybe there is an other way to send additional information in the advertisment? I also tried "Data" and "ServiceData" but then the advertisement throws an error. I haven't found a good tutorial for this. I'm only looking for a stable way to give the additional information for the next free service in the advertisment.

Thank You!



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source