CoAP Server that Sends Separate Response

CoAP Server that Sends Separate Response

Sending Separate Response to Client

We are assuming that you are familiar with the concept of “Separate Response”. If not, please read the CoAP specification, or at-least the primer tutorial.

Pre-Requisites:

  1. You need Microsoft .NET Micro Framework 4.2
  2. You need Visual Studio 2010 or higher (even an express edition will do)
  3. This tutorial will use the emulator, but if you wish, you can download this to a Netduino 2 Plus board. For working with Netduino, please visit their website

Example Scenario: 

Let’s take an example based on which this CoAP server will be built. Let’s assume we have a set of sensors installed in the conference room of your office, that is measuring the temperature constantly across different points. Another controller, that is responsible to take actions to ensure that the cooling system adjusts the cooling now needs to know the temperature at all points. So, the controller is the CoAP client and the temperature monitor in the conference room is the server. The controller sends a CON request to know the temperature. The server, since it has to read many sensors, asks for time from the client. Once the server completes reading all the sensors, it sends the response back.

Key Concepts Covered:

  1. How to use CoAPSharp library to build a CoAP server
  2. How to listen for requests
  3. How to check message types (e.g. CON)
  4. How to check message codes (e.g. GET)
  5. How to extract the requested URI and take action
  6. How to inform client that server will send a separate response
  7. How to queue the request and handle it later
  8. How to handle time consuming tasks in a separate thread
  9. How to extract the queued request, once the time consuming task is complete and respond back.

 

Steps: 

  1. Create a console project in Microsoft .NET Micro framework (or a Netduino 2 Plus Application for Netduino boards)
    SelectProject_ConsoleApp
  2. Now, pickup the CoAPSharp binary and add that as a reference
  3. First step is to define the CoAP server channel class instance.
    public class Program
    {
        /// <summary>
        /// Holds the instance of the server channel
        /// </summary>
        private CoAPServerChannel _server = null;
  4. Now, write a method named “StartServer”, which is where we will create a new instance of the server and wire up all event handlers.
    /// <summary>
    /// Start the server
    /// </summary>
    public void StartServer()
    {
        this._server = new CoAPServerChannel();
        this._server.Initialize("localhost", 5683);
        this._server.CoAPError += new CoAPErrorHandler(OnCoAPError);
        this._server.CoAPRequestReceived += new CoAPRequestReceivedHandler(OnCoAPRequestReceived);
        this._server.CoAPResponseReceived += new CoAPResponseReceivedHandler(OnCoAPResponseReceived);
    }
  5. In this sample, we will only focus on the event “CoAPRequestReceived”. This is where we need to handle the CON request. The code is given below. We will explain this code in a moment.
    /// <summary>
    /// Called when CON/NON message is received
    /// </summary>
    /// <param name="coapReq">CoAPRequest</param>
    void OnCoAPRequestReceived(CoAPRequest coapReq)
    {
    string reqPath = (coapReq.GetPath() != null) ? coapReq.GetPath().ToLower() : "";
    
    //Separate response is only for CON messages
    if (coapReq.MessageType.Value == CoAPMessageType.CON)
    {
        //In this example, we only support GET for this separate response
        if (coapReq.Code.Value != CoAPMessageCode.GET)
        {
            CoAPResponse resp = new CoAPResponse(CoAPMessageType.RST,
                                                CoAPMessageCode.METHOD_NOT_ALLOWED,
                                                coapReq /*Copy all necessary values from request in the response*/);
            //When you use the constructor that accepts a request, then automatically
            //the message id , token and remote sender values are copied over to the response
            this._server.Send(resp);
        }
        else if (reqPath != "sensors/temp/separate")
        {
            //We do not understand this..
            CoAPResponse resp = new CoAPResponse(CoAPMessageType.RST,
                                                    CoAPMessageCode.NOT_FOUND,
                                                    coapReq /*Copy all necessary values from request in the response*/);
            this._server.Send(resp);
        }
        else
        {
            //Everything is good...send an empty ACK message to the client
            //indicating, "please wait..we are processing your request and will get back to you soon"
            CoAPResponse resp = new CoAPResponse(CoAPMessageType.ACK,
                                                CoAPMessageCode.EMPTY,
                                                coapReq.ID.Value /*Copy over request message Id*/);
            //Add the remote sender details..this is used internally by CoAPSharp
            resp.RemoteSender = coapReq.RemoteSender;
            //send it
            this._server.Send(resp);
            /*
                * After we have sent the empty ACK, we need to add this message to the 
                * "Separate Response" queue. Post this addition, let's start a new thread to 
                * process the received message. We are creating a new thread to ensure we do not
                * block this thread...
                */
            this._server.AddToPendingSeparateResponse(coapReq);
            Thread heavyWork = new Thread(new ThreadStart( this.DoTimeTakingTask ));
            heavyWork.Start();
        }
    }
  6. In the above code, the heavy work is being done in a separate thread. The thread procedure code is given below
    /// <summary>
    /// Simulation of a time taking task.
    /// Once this task is complete, we will send the separate response back
    /// </summary>
    private void DoTimeTakingTask()
    {
        Thread.Sleep(10000);//simulate a time taking task
        CoAPRequest sepReq = this._server.GetNextRequestPendingSeparateResponse();//This is a Q and can have many reqs...
        //Handling only one request in this sample
        if (sepReq != null)
        {
            //Send the response back as another CON request
            CoAPRequest req = new CoAPRequest(CoAPMessageType.CON, CoAPMessageCode.CONTENT, sepReq.ID.Value);
            //Copy over needed values
            req.RemoteSender = sepReq.RemoteSender;
            req.Token = sepReq.Token;
            //Add some value that is the result of this heavy work
            req.AddOption(CoAPHeaderOption.CONTENT_FORMAT, AbstractByteUtils.GetBytes(CoAPContentFormatOption.TEXT_PLAIN));
            req.AddPayload("Result of heavy work");
            this._server.Send(req);
        }
    }

Now let’s explain what is happening in the request handler.

  • The received request is first checked and we address only those requests that are of type CON.
  • The we check the method, it must be GET
  • Finally we check the path. Please note, the path “sensors/temp/separate” has the word separate in it. This is only to make it clear that this is a separate response. Nothing else. You can use any path.
  • Once we find that everything is OK, we send an empty ACK back to the client. Now, we must process to find out the result and return the value to the client. For this, the request must be stored somewhere. CoAPSharp gives a simple Queue mechanism to store the requests in sequential fashion. If you need anything complex, you can devise your own mechanism for storing the CON requests that will require separate response. Also, to initiate processing of client’s request, we have instantiated another thread.
  • The thread procedure named “DoTimeTakingTask”, simulates a time consuming task. Once it is finished, the pending request is extracted from the queue and another CON request is constructed. This is the request that is sent to the client. Once client receives this request, it is expected to send back an ACK.

That’s it…download the client and server code for separate response… 

2 Responses so far.

  1. IoT says:

    Hi

    I am trying to run the above code but visual studio is identifying an error in “RemoteSender” Part. I don’t know how to solve it. I am just implementing the server code for windows 10 IoT core. Do I need to mention any remote sender/receiver details?

    Error: CS1061 ‘CoAPResponse’ does not contain a definition for ‘RemoteSender’ and no extension method ‘RemoteSender’ accepting a first argument of type ‘CoAPResponse’ could be found (are you missing a using directive or an assembly reference?)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>