This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Openthread COAP Client Server device reconnection failure

Hello,

I am having hard time using openthread NCS examples. Recently I was handed over a project based on NCS COAP client server example to resolve a issue but I am not able solve the issue.

Issue: We have 2 FTD device one running COAP client example which is basically reading data from sensor and sending values to COAP server. The sensor update is basically automated using zephyr kwork with delay so we don't have to press button instead it will submit kwork at fixed intervals. Now COAP server is just receiving data and printing data on terminal. 

That's it. Nothing new has been done if I compare with Nordic demo examples. At the start everything works fine. Both server and client are able to communicate with eachother but after say nealry 30-35 hours my COAP client device gets disconnected and not able to reconnect to my COAP server. And if I restart my COAP client device it gets connected. So what's really the issue here ? When I ask the same question on Google Open Thread group they advised me this could be possible issue with radio drivers. So I would like to know what's really the issue here ? And how to resolve this issue ?

When we started developing at my company, we decided to select openthread as mesh communication protocols because of it's benefits over other protocols and Nordic SOC because of it's production ready examples. But it's seems both selection are letting me down.

Also I would like to ask in COAP examples I have seen this lights, provisioning on which we are COAP client is sending turn on off commands. So in this examples does this light act as topic or what ? Also suppose if I have 2 COAP Clients interfaced with different sensors, now if I have to send data to server should I use 2 different topics (something like light1, light2 or sensor 1 and sensor2) instead of sending data on the same light services ? 

Parents
No Data
Reply
  • Hey Charlie,

    I would like to know is there any update about above issue.

    I also tried to develop a project with multiple resources on COAP servers, as i think transmitting data from different sensor on same light topic won't be a right idea and might result in problems in future. The COAP client example for multiple resource was easy to implement as i just have to pass URI path in COAP send request. But what are the task i need to carry out in COAP server example.

    Can you please guide me through it.

    Below are the steps which i have taken till now.

    COAP Client Example

    In coap_client_utils.c file,

    /* Options supported by the server */
    static const char *const sensor1[] = { "sensor1", NULL };
    static const char *const sensor2[] = { "sensor2", NULL };
    static const char *const provisioning_option[] = { PROVISIONING_URI_PATH,
    						   NULL };
    						   
    						   
    						   
    static void toggle_mesh_lights(struct k_work *item)
    {
      if(snode1)
      {
    	static uint8_t command1 = (uint8_t)THREAD_COAP_UTILS_LIGHT_CMD_OFF;
    
    	ARG_UNUSED(item);
    
    	command1 = ((command1 == THREAD_COAP_UTILS_LIGHT_CMD_OFF) ?
    			   THREAD_COAP_UTILS_LIGHT_CMD_ON :
    			   THREAD_COAP_UTILS_LIGHT_CMD_OFF);
          
    	LOG_INF("Send multicast mesh 'light' request");
    	coap_send_request(COAP_METHOD_PUT,
    			  (const struct sockaddr *)&multicast_local_addr,
    			  sensor1, &command1, sizeof(command1), NULL);  
      }
    
      else if(snode2)
      {
      	static uint8_t command2 = (uint8_t)THREAD_COAP_UTILS_LIGHT_CMD_OFF;
    
    	ARG_UNUSED(item);
    
    	command2 = ((command2 == THREAD_COAP_UTILS_LIGHT_CMD_OFF) ?
    			   THREAD_COAP_UTILS_LIGHT_CMD_ON :
    			   THREAD_COAP_UTILS_LIGHT_CMD_OFF);
    
    	LOG_INF("Send multicast mesh 'light' request");
    	coap_send_request(COAP_METHOD_PUT,
    			  (const struct sockaddr *)&multicast_local_addr,
    			  sensor2, &command2, sizeof(command2), NULL);  
      }
            
    
    }
    						   

    In coap_client.c file

    static void upload(struct k_work *item)
    {
        ARG_UNUSED(item);
        
        /*
        if(is_connected)
        {
          
          //Custom code
        
        }
      */
        coap_client_toggle_mesh_lights();
        k_delayed_work_submit(&coapcloud_work, SENSOR_UPDATE_INTERVAL);
    }
    
    
    
    void main(void)
    {
    	int ret;
    
    	LOG_INF("Start CoAP-client sample");
    
    	if (IS_ENABLED(CONFIG_RAM_POWER_DOWN_LIBRARY)) {
    		power_down_unused_ram();
    	}
    
    
    	ret = dk_buttons_init(on_button_changed);
    	if (ret) {
    		LOG_ERR("Cannot init buttons (error: %d)", ret);
    		return;
    	}
    
    	ret = dk_leds_init();
    	if (ret) {
    		LOG_ERR("Cannot init leds, (error: %d)", ret);
    		return;
    	}
    
    
            k_delayed_work_init(&coapcloud_work, upload);
            k_delayed_work_submit(&coapcloud_work, K_NO_WAIT); //UPDATE SENSOR DATA INTERVAL
    
    
    #if CONFIG_BT_NUS
    	struct bt_nus_cb nus_clbs = {
    		.received = on_nus_received,
    		.sent = NULL,
    	};
    
    	ret = ble_utils_init(&nus_clbs, on_ble_connect, on_ble_disconnect);
    	if (ret) {
    		LOG_ERR("Cannot init BLE utilities");
    		return;
    	}
    
    #endif /* CONFIG_BT_NUS */
    
    	coap_client_utils_init(on_ot_connect, on_ot_disconnect,
    			       on_mtd_mode_toggle);
    }
    

    COAP Server Example

    In ot_coap_utils.c apart from light i had made two more resources as shown below.  I don't know whether i have to make changes in the structure server_context

    /**@brief Definition of CoAP resources for light. */
    static otCoapResource light_resource = {
    	.mUriPath = LIGHT_URI_PATH,
    	.mHandler = NULL,
    	.mContext = NULL,
    	.mNext = NULL,
    };
    
    static otCoapResource sensor1 = {
    	.mUriPath = "sensor1",
    	.mHandler = NULL,
    	.mContext = NULL,
    	.mNext = NULL,
    };
    
    static otCoapResource sensor2 = {
    	.mUriPath = "sensor2",
    	.mHandler = NULL,
    	.mContext = NULL,
    	.mNext = NULL,
    };
    

    Than i have create request handler just like light request handler.

    static void light_request_handler(void *context, otMessage *message,
    				  const otMessageInfo *message_info)
    {
    	uint8_t command;
    
    	ARG_UNUSED(context);
    
    	if (otCoapMessageGetType(message) != OT_COAP_TYPE_NON_CONFIRMABLE) {
    		LOG_ERR("Light handler - Unexpected type of message");
    		goto end;
    	}
    
    	if (otCoapMessageGetCode(message) != OT_COAP_CODE_PUT) {
    		LOG_ERR("Light handler - Unexpected CoAP code");
    		goto end;
    	}
    
    	if (otMessageRead(message, otMessageGetOffset(message), &command, 1) !=
    	    1) {
    		LOG_ERR("Light handler - Missing light command");
    		goto end;
    	}
    
    	LOG_INF("Received light request: %c", command);
    
    	srv_context.on_light_request(command);
    
    end:
    	return;
    }
    
    
    static void sensor1_led_handler(void *context, otMessage *message,
    				  const otMessageInfo *message_info)
    {
    	uint8_t command;
    
    	ARG_UNUSED(context);
    
    	if (otCoapMessageGetType(message) != OT_COAP_TYPE_NON_CONFIRMABLE) {
    		LOG_ERR("Light handler - Unexpected type of message");
    		goto end;
    	}
    
    	if (otCoapMessageGetCode(message) != OT_COAP_CODE_PUT) {
    		LOG_ERR("Light handler - Unexpected CoAP code");
    		goto end;
    	}
    
    	if (otMessageRead(message, otMessageGetOffset(message), &command, 1) !=
    	    1) {
    		LOG_ERR("Light handler - Missing light command");
    		goto end;
    	}
    
    	LOG_INF("Received light request: %c", command);
    
    	//srv_context.on_light_request(command);
            snode1_light_request();
            
    end:
    	return;
    }
    
    static void sensor2_led_handler(void *context, otMessage *message,
    				  const otMessageInfo *message_info)
    {
    	uint8_t command;
    
    	ARG_UNUSED(context);
    
    	if (otCoapMessageGetType(message) != OT_COAP_TYPE_NON_CONFIRMABLE) {
    		LOG_ERR("Light handler - Unexpected type of message");
    		goto end;
    	}
    
    	if (otCoapMessageGetCode(message) != OT_COAP_CODE_PUT) {
    		LOG_ERR("Light handler - Unexpected CoAP code");
    		goto end;
    	}
    
    	if (otMessageRead(message, otMessageGetOffset(message), &command, 1) !=
    	    1) {
    		LOG_ERR("Light handler - Missing light command");
    		goto end;
    	}
    
    	LOG_INF("Received light request: %c", command);
    
    	//srv_context.on_light_request(command);
            snode2_light_request();
    
    end:
    	return;
    }
    

    Than here is my COAP Init function. I don't know whether i have to change this function declaration now as i have now 2 more resource now to implement.

    int ot_coap_init(provisioning_request_callback_t on_provisioning_request,
    		 light_request_callback_t on_light_request)
    {
    	otError error;
    
    	srv_context.provisioning_enabled = false;
    	srv_context.on_provisioning_request = on_provisioning_request;
    	srv_context.on_light_request = on_light_request;
    
    	srv_context.ot = openthread_get_default_instance();
    	if (!srv_context.ot) {
    		LOG_ERR("There is no valid OpenThread instance");
    		error = OT_ERROR_FAILED;
    		goto end;
    	}
    
    	provisioning_resource.mContext = srv_context.ot;
    	provisioning_resource.mHandler = provisioning_request_handler;
    
    	light_resource.mContext = srv_context.ot;
    	light_resource.mHandler = light_request_handler;
    
            //SNode Led 1
    	sensor1.mContext = srv_context.ot;
    	sensor1.mHandler = sensor1_led_handler;
    
            //SNode Led 2
    	sensor2.mContext = srv_context.ot;
    	sensor2.mHandler = sensor2_led_handler;
    
    	otCoapSetDefaultHandler(srv_context.ot, coap_default_handler, NULL);
    	otCoapAddResource(srv_context.ot, &light_resource);
    	otCoapAddResource(srv_context.ot, &provisioning_resource);
    	otCoapAddResource(srv_context.ot, &sensor1);
    	otCoapAddResource(srv_context.ot, &sensor1);
    
    
    	error = otCoapStart(srv_context.ot, COAP_PORT);
    	if (error != OT_ERROR_NONE) {
    		LOG_ERR("Failed to start OT CoAP. Error: %d", error);
    		goto end;
    	}
    
    end:
    	return error == OT_ERROR_NONE ? 0 : 1;
    }
    

    And in COAP Server.c file here are the functions that's been called by request handler

    void snode1_light_request(uint8_t command);
    void snode2_light_request(uint8_t command);
    
    
    void snode1_light_request(uint8_t command)
    {
    	static uint8_t val;
    
    	switch (command) {
    	case THREAD_COAP_UTILS_LIGHT_CMD_ON:
    		dk_set_led_on(LIGHT_LED1);
    		val = 1;
    		break;
    
    	case THREAD_COAP_UTILS_LIGHT_CMD_OFF:
    		dk_set_led_off(LIGHT_LED1);
    		val = 0;
    		break;
    
    	case THREAD_COAP_UTILS_LIGHT_CMD_TOGGLE:
    		val = !val;
    		dk_set_led(LIGHT_LED1, val);
    		break;
    
    	default:
    		break;
    	}
    }
    
    void snode2_light_request(uint8_t command)
    {
    	static uint8_t val;
    
    	switch (command) {
    	case THREAD_COAP_UTILS_LIGHT_CMD_ON:
    		dk_set_led_on(LIGHT_LED2);
    		val = 1;
    		break;
    
    	case THREAD_COAP_UTILS_LIGHT_CMD_OFF:
    		dk_set_led_off(LIGHT_LED2);
    		val = 0;
    		break;
    
    	case THREAD_COAP_UTILS_LIGHT_CMD_TOGGLE:
    		val = !val;
    		dk_set_led(LIGHT_LED2, val);
    		break;
    
    	default:
    		break;
    	}
    }

    Can you tell me where i am going wrong. Or can you try to implement the same where you have multiple resource on COAP server for controlling different LEDs. It will surely help others as well looking for multiple resource implementation on COAP server.

Children
  • Hi McGregor,

    Issue1:

    30-35 hours my COAP client device gets disconnected and not able to reconnect to my COAP server

     Currently, I have a setup running around 48 hours now, and there is no issue so I do not know your problem. I can share my codes with you so you can check if there is anything different or repeat the experiment.

    This coap_client_repeat example is modified from the original coap_client example, it will multicast every 1 second to send out server led toggle message. I use RTT viewer to log the experiment logging message, you can find it from the attachments. It split into two parts due to I closed the RTT viewer by mistake, but the firmware keeps running.

    8623.coap_clinet_repeat.log

    1602.coap_clinet_repeat2.log

    4745.coap_client_repeat.zip

    Issue2: 

    McGregor said:
    multiple resources on COAP servers

     I try to assembly all the information related together, but I feel lost since they are so many. Just correct me If I have a miss understanding. Please try to keep one ticket focusing on only one issue, list and describe your problem use as few words as possible.

    Here is my understanding:

    1. Client1 runs coap_client, it has Sensor1, Sensor1 control resource Led1 on Server1 to turn on and off.

    2. Client2 runs coap_client, it has Sensor2, Sensor2, control resource Led2 on Server1 to turn on and off.

    3. Server1 runs coap_server, it has Led1 and Led2 as resources. 

    but your codes above show one coap_client contains two sensors and there are no other coap_client. The adding codes on coap_client_utils.c also have logic problem. Anyway, the codes shows you have an understanding on how to use coap URI now, so the next step on this issue for you is to correct my understanding of you application, and tell me what you want me to guide?

    Best regards,

    Charlie

Related