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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions