Send data to SED devices

Hi, 

I have a functioning CoAP client/server based OpenThread mesh network. My clients are SEDs. I can send data from clients to the CoAP server. Now I want to do the opposite, to send data from server to the SED clients. I have the unicast IPV6 of the SEDs on server side. I am thinking of using 'coap_send_request ()' as used by the clients to send data packet from server. I am not clear how on clients side to receive this. On server side I can see 'srv_context' and 'otCoapResource' structures and 'otCoapStart' used to manage data transmitted by the client. But I dont think I can start another CoAP server on client side, and there is no need for that. May be what we need is a kernel thread to look into packets being received and then set an kernel event or something like that to indicate data receive. What would be the best way of moving foward.

Cheers,

Kaushalya

  • Hello Kaushalya,

    I have some initial thoughts and I will look further into this as soon as I can.

    You need to factor in when the SEDs radio is active for it to receive the data. Does your SEDs wake up periodically?

    What kind of data do you want to send from the server to the client?

    Best regards,

    Maria

  • Hi Maria,

    Thanks for your help. Yes my SED wakes up periodically and send the server some data. This is the time I think the server data can be delivered. I think that mechanism is workable. 

    I have gathered the IP6 info of the client (SED) from the data it is sending. I tried to use 'coap_send_request()' in the server, but it failed giving error code 9. I couldn't find what that error code means. I dont have a mechanism in the SED to receive data yet. I dont know if that is the reason for this failure.

    From ther server I can see it initiates server functionality by 'otCoapStart ()' in 'ot_coap_init()' in server FW. I am not sure I have to/can implement this same behavior in the SED. 

    What API mechanism should be used to receive data from a coap server?

    Thanks,

    Kaushalya

  • Hi Maria,

    I have looked at using coap get/put methods to send payloads to SED clients using CLI. 

    1. Client has to create a uri resource 

    2. The host get this resource using 'coap get'

    3. The host use the resource to send payloads to the SED client by using 'coap put'

    I tried decoding the cli_coap.cpp to extract the APIs needed for this. I am not 100% sure on how to do that. Could you please help here?

    Thanks,

    Kaushalya

  • Hi Kaushalya, 
    Maria is away and I am not Thread expert. I will try to get some help on this. Sorry for the delays caused so far.

  • Hi Susheel,

    Thanks. I think I managed to get it done. Still I dont know if the way I have done it is acceptable. So good to get some Thread expert run through this.

    What I have done is in the host or coap server

    static otCoapResource host_resource = {	
    	.mUriPath = HOST_URI_PATH,
    	.mHandler = NULL,
    	.mContext = NULL,
    	.mNext = NULL,
    };
    
    static const char *const host_option[] = {HOST_URI_PATH, NULL};
    
    static void sensor_send_handler(void *context, otMessage *message, const otMessageInfo *message_info) {
    ..
    }
    
    int ot_coap_init (...) {
    
        coap_init(AF_INET6, NULL);
        .
        .
        .
        srv_context.on_sensor_data_request = on_sensor_data_request;
        .
        srv_context.ot = openthread_get_default_instance();
        .
        host_resource.mContext = srv_context.ot;
    	host_resource.mHandler = sensor_send_handler;
    	.
    	otCoapAddResource(srv_context.ot, &sensor_resource);
    }
    
    

    On coap client side

    static otCoapResource host_resource = {
    	.mUriPath = HOST_URI_PATH,
    	.mHandler = NULL,
    	.mContext = NULL,
    	.mNext = NULL,
    };
    
    struct server_context {
    	struct otInstance *ot;
    	host_data_request_callback_t on_host_data_request;
    };
    
    static struct server_context srv_context = {
    	.ot = NULL,
    	.on_host_data_request = NULL
    };
    
    static void on_host_data_request (uint8_t host_msg_ID) {
    	switch (host_msg_ID) {
    	.
    	.
    	.
    }
    
    static void host_request_handler(void *context, otMessage *message, const otMessageInfo *message_info) {
    	uint8_t buff[50];
    	uint16_t msgLen=0;
    	uint16_t byteCnt=0;
    
    	msgLen =  otMessageGetLength (message)-otMessageGetOffset(message);
    	byteCnt = otMessageRead(message, otMessageGetOffset(message), buff, msgLen);	
    	LOG_INF ("Bytes Read %d", byteCnt);
    
    	srv_context.on_host_data_request (buff[1]);	// host message ID
    }
    
    static void coap_default_handler(void *context, otMessage *message, const otMessageInfo *message_info)
    {
    	ARG_UNUSED(context);
    	ARG_UNUSED(message);
    	ARG_UNUSED(message_info);
    
    	LOG_INF("Received CoAP message that does not match any request "
    		"or resource");
    }
    
    void coap_client_utils_init (...) {
        .
        .
        .
        srv_context.on_host_data_request = on_host_data_request;   
        srv_context.ot = openthread_get_default_instance();
        
        host_resource.mContext = srv_context.ot;
    	host_resource.mHandler = host_request_handler;
    	
    	otCoapSetDefaultHandler(srv_context.ot, coap_default_handler, NULL);
    	otCoapAddResource(srv_context.ot, &host_resource);		
    
    	err = otCoapStart(srv_context.ot, COAP_PORT);
    	if (err != OT_ERROR_NONE) {
    		LOG_ERR("Failed to start OT CoAP. Error: %d", err);
    	}
        
    }

    Basically I have done what the coap client has done on its side on coap server on initialization. I had to increase stack size for system workqueue to  2048 in prj.conf (may be this can be lowered but I havent tested it).

    Is this method acceptable?

    Cheers,

    Kaushalya

Related