Appkey always equals 0 in my custom model in BT mesh

Hello everyone,

I'm currently trying to create Bluetooth mesh custom client and server with the nrf connect sdk. 

The purpose of my application is to make my server send data automatically to my client when it receives a particular message from it.

A very common type of communication between a server and a client !

To send a message to my server, my client use the model publication context configurated by the Configuration Client Model. (so I use publish function)
To send a message to my client, my server use the publication context of my client request to respond to the client. (So I use send function)

My problem is that my server failed to respond to my client because the Appkey that it receives from my client always equals zero, and it doesn't recognize it. I have this error :

"E : Model don't bound to AppKey 0x000"

After this error, my server is no longer able to receive messages from my client.

I use the phone app nrf mesh to provision my node and to provide an AppKey to my Client and my Server.

If you have any idea about what can cause this problem it would be very helpful !

  • Hi, 

    I will see if I can find someone who can explain how Appkeys work better than me and can explain both of us how it works. Unfortunately we hit a bit of a bad timing where we have an overlap where most of the Mesh experts are out on vacation this week, but nonetheless I've asked the team for some input. I can hopefully return you with an answer and an explaination on Monday/early next week.

    I hope the delayed response time does not cause any issues for you,

    Kind regards,
    Andreas

  • Hi,

    thank you very much for your answer !

    After analysis it seems that it is "Appkey index" and not the Appkey that I am returning... The value "0" that I have would therefore correspond to the Appkey at index 0 of the Appkey list related to my model. In my case I only assigned one appkey to my model. But that's just my theory...

    In any case I have a problem with my thread... I give it the value "ctx" as an argument and this value is modified automatically in my thread !

    The value of ctx->app_idx is indeed equal to 0 in my reception function "bt_mesh_handle_message_request" but once in the thread "My_thread" the value rx_ctx->app_idx is equal to 0x2000... I don't understand why the value of ctx changes without my intervention. I tried to put the ctx value as a global variable and thus not pass ctx as an argument of my thread, but the result is the same, once in the thread rx_ctx->app_idx = 0x2000....

    I fully understand that no one is available to answer me during this holiday period and thank you for your time! I can wait for the beginning of next week to have a solution

    King regards

  • Hi,

    I have some additional information/update for you.

    You might already know this, but I am adding this nonetheless to cl

    An application key is used in the network to separate acess rights to the different applications in a network. Every application has their own key. When a Mesh pack is sendt in the network, it will be encrypted with an application key, and unless the model is bound with the correct application key, then a node will not be able to decrypt the message.

    lalum said:
    The value of ctx->app_idx is indeed equal to 0 in my reception function "bt_mesh_handle_message_request" but once in the thread "My_thread" the value rx_ctx->app_idx is equal to 0x2000... I don't understand why the value of ctx changes without my intervention. I tried to put the ctx value as a global variable and thus not pass ctx as an argument of my thread, but the result is the same, once in the thread rx_ctx->app_idx = 0x2000....

    As for why this is happening I will need to ask around some more. Let me know if you've managed it to work in the mean while, and thank you for your patience so far

    Kind regards,
    Andreas

  • Hi Andreas,

    Thank you for the additional information. It confirms what I understood. To make my communication works, I decided to retrieve only the destination address and to pass it as an argument of my thread.

    static int bt_mesh_handle_message_request(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf){
        printk("SERVER : receive request message \n");
    	uint32_t receive_offset = net_buf_simple_pull_le32(buf);
    	size_t receive_size = net_buf_simple_pull_le32(buf);
    	printk("SERVER : receive offset = %d and size = %zu \n", receive_offset, receive_size);
    
    	struct bt_mesh_datas_state datas_state_srv = {
    		.address = SHARED_RAM_ADDRESS + receive_offset,
    		.datas = (uint32_t *) datas_state_srv.address,
    		.remaining_datas = receive_size 
    	};
    
    	struct k_thread my_thread_data;
    	printk("DEBUG : create thread \n");
    	uint16_t addr = ctx->addr;
    	k_thread_create(&my_thread_data, &my_thread_stack, STACKSIZE, thread, model, addr, &datas_state_srv, PRIORITY, 0, K_NO_WAIT);
    	return 0;
    }

    and in my thread I recreate a publication context :  

    void My_thread(struct bt_mesh_model *model, uint16_t address, struct bt_mesh_datas_state *datas_state_srv){
    
    	printk("DEBUG : Thread created \n");
    	struct bt_mesh_msg_ctx ctx = {
    		.addr = address,
    		.app_idx = model->keys[0],
    		.send_ttl = BT_MESH_TTL_DEFAULT,
    	};
    	
    	BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_OP_DATAS, 1);
    	bt_mesh_model_msg_init(&msg, BT_MESH_OP_DATAS);
    
    	net_buf_simple_add(&msg, 5);
    	(void) bt_mesh_model_send(model, ctx, &msg, NULL, NULL);
    	printk("DEBUG : send message ok \n");
    
    	while(1){
    
    		printk("DEBUG : thread finished \n");
    		k_usleep(100000000000);
    	}	
    	return;

    It works ... but It doesn't explain why the first code doesn't work ...
    I hope somebody in your team have the explanation !

    Kind regards

  • AHaug said:
    The value of ctx->app_idx is indeed equal to 0 in my reception function "bt_mesh_handle_message_request" but once in the thread "My_thread" the value rx_ctx->app_idx is equal to 0x2000... I don't understand why the value of ctx changes without my intervention. I tried to put the ctx value as a global variable and thus not pass ctx as an argument of my thread, but the result is the same, once in the thread rx_ctx->app_idx = 0x2000....

    I got a reply with regards to this: 

    Rx context is the local variable from here: https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/bluetooth/mesh/net.c#L371-L391 
    However, it is not correct to use a pointer to the local variable from the stack of one thread as incoming data for another thread. This might result in some bugs further down in development that is hard to solve. To be sure that you do this properly, I would recommend taking a look at how Zephyr does threading, context switching, stack allocation and make sure you understand it quite thoroughly before doing "tricks" like what you're attempting right now

    In addition, topic 7 and 8 in this course is a great entry level overview over multithread applications if that that  topic is new to you, as well as Zephyr's thread documentationthread API and thread samples

    Kind regards,
    Andreas

Related