Skip to content

Joining a network fail - bad PDU #187

@aeron169

Description

@aeron169

I have a client and server using python-bluetooth-mesh but everytime i try to provision the server with the client, the server just fail to join with a bad-pdu error from dbus.

This error is happening when i'm using a python-bluetooth-mesh prov, with mesh-cfgclient the server is provisioned.

Here is my client code that i think is related to the error:

Class MainElement(Element):
    LOCATION = GATTNamespaceDescriptor.MAIN
    MODELS = [
        ConfigClient,
        GenericOnOffClient,
        GenericOnOffServerHandler,
    ]


class SampleApplication(Application):
    COMPANY_ID = 0x0136  # Silvair
    PRODUCT_ID = 1
    VERSION_ID = 1
    ELEMENTS = {
        0: MainElement,
    }
    CRPL = 32768
    PATH = "/com/silvair/sample"

    uuid_buffer = []

    def __init__(self, loop):
        super().__init__(loop)
        self.address = 0x0001

    @property
    def dev_key(self):
        return DeviceKey(bytes.fromhex('9cfc5dd76b36902b7da2187bebd45f06'))
    

    @property
    def primary_net_key(self):
        return 0, NetworkKey(bytes.fromhex('4696cead19afc4c876677e18bfcf6522'))

    @property
    def app_keys(self):
        return [(0, 0, ApplicationKey(bytes.fromhex('f2ae98a541ca4f04814da82195bb3dc4')))]
    
    # This function is called when a node has been detected
    def scan_result(self, rssi: int, data: bytes, options: dict):

        #remove the useless 2 bytes at the end of the data
        data = data[:-2].hex()
        print(f'Scan result: rssi: {rssi}, uuid: {data}, options: {options}.')
        uuid_to_add = UUID(data)
        print('Adding node: ', uuid_to_add)

        # Add the node to the network
        loop = asyncio.get_running_loop()
        loop.create_task(self.management_interface.add_node(uuid_to_add))
        

    def request_prov_data(self, count: int) -> Tuple[int, int]:
        print('Requesting prov data')
        return [0, count+1]
    def add_node_complete(self, uuid: bytes, unicast: int, count: int):
        print('Added node: ', uuid, unicast, count)

    def add_node_failed(self, uuid: bytes, reason: str):
        print('Failed to add node: ', uuid, reason)
    
    # This function create the network and app keys and send them to the deamon
    async def configure(self):

        print('Configuring node...')

        status = await self.add_net_key(self.primary_net_key[0], self.primary_net_key[1])
        print('Add net key status: ', status)

        status = await self.add_app_key(0, 0, self.app_keys[0][2])
        print('Add app key status: ', status)

        status = await self.bind_app_key(0, self.elements[0][GenericOnOffClient])
        print('Bind app key status: ', status)
        status = await self.bind_app_key(0, self.elements[0][GenericOnOffServerHandler])
        print('Bind app key status: ', status)
    
    # We created a custom function to send and get the local onoff status for testing
    # local node (inside the node no communication using the mesh network) communication
    # beetween 2 models (GenericOnOffClient and GenericOnOffServerHandler)
    async def send_and_get_local_onoff(self, onoff: int):
        print('Sending and getting local onoff status')
        client = self.elements[0][GenericOnOffClient]

        status = await client.get_light_status([self.address], 0)
        
        # set the light status to on without getting a response
        status = await client.set_onoff_unack(self.address, 0, onoff=onoff, retransmissions=1)
        await asyncio.sleep(1)

        # get the light status
        status = await client.get_light_status([self.address], 0)
        print('Light status: ', status)

    async def run(self):
        async with self:
            self.logger.info('Connecting with address: %s, uuid: %s and token: %s', self.address, self.uuid, self.token_ring.token)
            await self.connect()
            await self.configure()

            print('Starting app')
            client = self.elements[0][GenericOnOffClient]
            server = self.elements[0][GenericOnOffServerHandler]
            
            await asyncio.sleep(5)
            logging.info('Scanning for unprovisioned devices')

            # the scan_result function is called for each node detected
            await self.management_interface.unprovisioned_scan(seconds=5)

            # await self.management_interface.add_node(UUID('014f9331-fb9d-5245-9926-daa7fcd3d4e5'))

            # await asyncio.sleep(2)

            while True:
                await asyncio.sleep(2)
            

            

def main():
    
    loop = asyncio.get_event_loop()
    app = SampleApplication(loop)

    with suppress(KeyboardInterrupt):
        loop.run_until_complete(app.run())

if __name__ == '__main__':
    main()

And here the debug_logs from bluez:

mesh/util.c:print_packet() 31034.333 ECDHSecret: 59d9d2875828bd01b7a72f3449d5061dda5803f51e65c4d8c7ca079a970d6b23
mesh/util.c:print_packet() 31034.333 LocalRandom: beec0f0e26ad241a73c1dd221109f1d7
mesh/util.c:print_packet() 31034.333 ConfirmationSalt: 89643a2bbbd2012a587e60a8f4027bf3
mesh/util.c:print_packet() 31034.333 ConfirmationKey: ba0a8239669e370959b0874e298335ab
mesh/pb-adv.c:send_adv_segs() Sending 3 fragments for 65 octets
mesh/pb-adv.c:send_adv_segs() max_seg: 02
mesh/pb-adv.c:send_adv_segs() size: 41, CRC: e3
mesh/pb-adv.c:pb_adv_packet() PB-ADV start with 0 fragments, 17 octets
mesh/prov-acceptor.c:acp_prov_rx() Provisioning packet received type: 05 (17 octets)
mesh/pb-adv.c:send_adv_segs() Sending 1 fragments for 17 octets
mesh/pb-adv.c:send_adv_segs() max_seg: 00
mesh/pb-adv.c:send_adv_segs() size: 11, CRC: f2
mesh/pb-adv.c:pb_adv_packet() PB-ADV start with 0 fragments, 17 octets
mesh/prov-acceptor.c:acp_prov_rx() Provisioning packet received type: 06 (17 octets)
mesh/pb-adv.c:send_adv_segs() Sending 1 fragments for 17 octets
mesh/pb-adv.c:send_adv_segs() max_seg: 00
mesh/pb-adv.c:send_adv_segs() size: 11, CRC: 81
mesh/pb-adv.c:pb_adv_packet() PB-ADV start with 0 fragments, 2 octets
mesh/prov-acceptor.c:acp_prov_rx() Provisioning packet received type: 09 (2 octets)
Expected 07, Got:09
mesh/mesh.c:prov_complete_cb() Provisioning complete bad-pdu
mesh/mesh-config-json.c:mesh_config_destroy_nvm() Delete node config /var/lib/bluetooth/mesh/014f9331fb9d52459926daa7fcd3d4e5
mesh/util.c:del_fobject() RMDIR /var/lib/bluetooth/mesh/014f9331fb9d52459926daa7fcd3d4e5/rpl
mesh/util.c:del_fobject() RM /var/lib/bluetooth/mesh/014f9331fb9d52459926daa7fcd3d4e5/node.json
mesh/util.c:del_fobject() RMDIR /var/lib/bluetooth/mesh/014f9331fb9d52459926daa7fcd3d4e5
mesh/pb-adv.c:send_adv_segs() Sending 1 fragments for 2 octets
mesh/pb-adv.c:send_adv_segs() max_seg: 00
mesh/pb-adv.c:send_adv_segs() size: 02, CRC: e1
mesh/pb-adv.c:pb_adv_packet() Link closed notification: 00

In the bluez code Expected 07, got 09, says that instead of prov_data we got prov_failed, but why does the meshd deamon got prov_failed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions