Your First CoAP Server for Windows 10 IoT Core on Raspberry Pi

Your First CoAP Server for Windows 10 IoT Core on Raspberry Pi

How to write a simple CoAP server for Windows 10 IoT Core on Raspberry Pi

Off-late, we have been getting a lot of requests from users of CoAPSharp library around how to build CoAP based systems on Raspberry Pi running Windows 10 IoT Core. Since everyone was connecting to us via either e-mail, or through various forums, we decided to give you a primer on how to get started. Remember, this example uses the experimental release of CoAPSharp for Windows 10 IoT Core [Download]

Pre-Requisites:

  1. You need a Raspberry Pi running Windows 10 IoT Core. We will run the CoAP server on this device.
  2. You need Visual Studio 2015 Community edition or higher. We will use this to build the code.
  3. If you have a Netduino Plus 2 (with Ethernet) then we will use this to run the client. Alternatively, you can write a CoAP client and run it on your PC (more on this later)
  4. Both Raspberry Pi and client PC (or Netduino) having network connectivity and are in the same network.

About the implementation: 

We will write a simple CoAP server that will run in a background task on the Raspberry Pi. This server will listen for a CoAP request with message type CON and message code as GET. When it receives the request, it will respond back with a CoAP response with message type ACK and message code CONTENT. The payload will be “Tick” value (number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001). That’s it!

The client application will simply construct a CoAP request and send it to the server. It waits for a response, and then prints the response in the debug console.

Steps for the Server: 

  1. Download the CoAPSharp experimental release for Windows 10 IoT Core and extract it to a location.
  2. Create a new project in Visual Studio, choose the template as “Windows IoT Core” and select application type as “Background Application (IoT)”. You can also select “Universal” template and choose “Blank App” template. We chose the “Background Application(IoT)” template, because most of our library users were using this type of project and facing issues.
  3. Now, add the CoAPSharp project as a reference. Simply build the solution to ensure all items are in place and build succeeds.
  4. If you have not customized any further, you should have a class named “StartupTask” in your project. The startup task class contains the “Run” method. This method gets executed and when the method exits, the application exits. Therefore, you must ensure, that for all times, this method does not exit.(more on this later). Open the startup class.
  5. First step is to define the CoAP server channel class instance.
    #region Implementation
    /// <summary>
    /// Instance of CoAP server channel
    /// </summary>
    private CoAPServerChannel _coapServer = null;
    #endregion
  6. Now, in the “Run” method, initialize and setup the server for listening on to the port.
    /// <summary>
    /// This method is called to run the background task.
    /// If this method exits, the background task exits
    /// </summary>
    /// <param name="taskInstance">IBackgroundTaskInstance</param>
    public void Run(IBackgroundTaskInstance taskInstance)
    {
        this._coapServer = new CoAPServerChannel();
        this._coapServer.Initialize(null, 5683);
        this._coapServer.CoAPRequestReceived += OnRequestReceived;
        this._coapServer.CoAPError += OnError;
        this._coapServer.CoAPResponseReceived += OnResponseReceived;
        //We must ensure this thread does not exit, else the whole background thread will stop
        while (true)
            Task.Delay(5000);
    }

    Notice carefully, in the code above, towards the end, there is an infinite loop with a delay. This way, the “Run” method does not exit and also does not block the CPU.

  7. Next, we need to define the event handlers for Request received, Response received and error.
    /// <summary>
    /// This is called when a response is sent by a remote client.
    /// Such cases are possible on Observable scenarios . Not used in this sample
    /// </summary>
    /// <param name="coapResp">CoAPResponse</param>
    private void OnResponseReceived(CoAPResponse coapResp)
    {
        Debug.WriteLine("CoAP Response object::" + coapResp.ToString());
    }
    
    /// <summary>
    /// Called when an error happens in processing of the request/response
    /// </summary>
    /// <param name="e">Exception</param>
    /// <param name="associatedMsg">AbstractCoAPMessage</param>
    private void OnError(Exception e, AbstractCoAPMessage associatedMsg)
    {
        Debug.WriteLine("Exception::" + e.ToString());
    }
  8. In the code below, we have defined the request handler. The client will send a CoAP request. When the request is parsed successfully by the server, it will raise this method. In this method, we simply check the message type and message code and on a CON/GET we send a response back.
    /// <summary>
    /// This method is called when a request is received.
    /// This sample, returns an ACK response, only if the request is of type CON/GET
    /// </summary>
    /// <param name="coapReq">CoAPRequest</param>
    private async void OnRequestReceived(CoAPRequest coapReq)
    {
        Debug.WriteLine("Request received :: " + coapReq.ToString());
        if(coapReq.MessageType.Value == CoAPMessageType.CON && coapReq.Code.Value == CoAPMessageCode.GET)
        {
            //Create a new response...
            CoAPResponse coapResp = new CoAPResponse(CoAPMessageType.ACK, CoAPMessageCode.CONTENT, coapReq);
            string payload = DateTime.UtcNow.Ticks.ToString();
            coapResp.AddPayload(payload);//just a dummy payload to indicate new responses (since time value will change)
            await this._coapServer.Send(coapResp);//send response back
        }
    }
  9. The step above will complete our server implementation. But this is not the end ! You first need to check, if the Windows 10 IoT firewall has blocked the port or not. To do so, you need to user PowerShell to connect to Raspberry Pi from your development PC and then issue some commands. A good reference can be found here. Start the powershell with administrator privileges. Then, run the following commands in the sequence given below (the commands assume that the Raspberry Pi device name is minwinpc):
    1. net start WinRM (this will start the WinRM service on your desktop to enable remote connections)
    2. Next, add the Raspberry Pi device to trusted hosts by issuing the command
      Set-Item WSMan:\localhost\Client\TrustedHosts -Value minwinpc
      If a question is asked , enter Y
    3. Finally, start a remote session with the Raspberry Pi device
      Enter-PSSession -ComputerName minwinpc -Credential minwinpc\Administrator
      In the credentials dialog, enter the password for your Raspberry Pi device. If you have not changed the password then the default value is p@ssw0rd
    4. If everything goes well, you should see the prompt
      [minwinpc]: PS C:\Users\Administrator\Documents>
  10. Now, run the application on the Raspberry Pi from Visual Studio. After the application starts, check if the port was opened successfully. To do so, issue the command in the powershell as
    netstat -nap UDP
    This will list down all open UDP ports. Check if you can see the entry 0.0.0.0:5683 under local address column. If yes, then you are good (else, Google and find out why !)
  11. The next step is to allow incoming connections on the port 5683. For this, you need to add a rule to the firewall. Issue the command as show below
    netsh advfirewall firewall add rule name=”CoAP Port” dir=in action=allow protocol=UDP localport=5683
    After a while, you should see “OK” on the console. This means, that the rule was added. Now you device can accept incoming connections from external clients. Ensure your server is running on the device and now move to write the client.

Steps for the Client: 

You can write the client in a Netduino Plus 2 (or something similar) or you can write the client on your PC. The assumption is that the PC/Netduino P2 and the Raspberry Pi are connected to the same LAN.

  1. Download the CoAPSharp library source
  2. Create a new project for .NET Micro Framework
  3. Add the CoAPSharp project to your solution
  4. Reference the CoAPSharp project in your project
  5. Open the Program.cs file and in the main method, add the code given below
    try
    {    
        CoAPSyncClientChannel client = new CoAPSyncClientChannel();
        client.Initialize("minwinpc", 5683);
        CoAPRequest req = new CoAPRequest(CoAPMessageType.CON, CoAPMessageCode.GET, (ushort)DateTime.UtcNow.Second);
        client.Send(req);
        bool timedOut = false;
        CoAPResponse coapResp = (CoAPResponse)client.ReceiveMessage(10000, ref timedOut);
        if (coapResp != null && timedOut == false)
            Debug.Print(coapResp.ToString());
        client.Shutdown();
    }
    catch (Exception e)
    {
        Debug.Print(e.ToString());
    }

    Please ensure, your machine running the client code can resolve the name “minwinpc” (or just put the IP address of the Raspberry Pi device running the server. In the code above, we are simply sending a CoAP message of type CON/GET and waiting for a response. If we received a response (and no timeout), we are printing the response. That’s it!

Happy IoT-ing ….:-)

 

 

Comments are closed.