Kinetis W: [Thread] CoAP basics and hands on

Document created by Estephania Martinez Employee on Jan 19, 2017Last modified by Estephania Martinez Employee on Aug 2, 2018
Version 9Show Document
  • View in full screen mode

Thread provides basic services required for application frameworks implementation with the usage of Unicast and Multicast transmissions over UDP.

Thread specification is only focused on the network layer; many application layers can be designed to run without any problem as it is application layer agnostic. 

In this laboratory the user will work with the Constrain Application Protocol (CoAP) for this application layer as the Thread stack uses CoAP for most of the multi-hop network management and commissioning messages.

The Constrained Application Protocol (CoAP) is a specialized web transfer protocol to use with constrained nodes and constrained networks in the Internet of Thing.  It uses a binary RESTful protocol with four methods

  • POST
  • GET
  • PUT
  • DELETE

 

CoAP also uses ACK responses; CONfirmable (ACK requested) and NONconfirmable messages.

The Thread stack uses CoAP for the majority of multi-hop network management and commissioning messages

 

 

Objectives

Through this laboratory the user will modify the firmware to achieve the following list:

  • Add 2 new COAP URI resources “/resource1” and “/resource2”.
  • Send an ACK message in “/resource1” in case a CON request was received as specified by the CoAP standard. Include a default payload in the ACK message.
  • All packets destined to “/resource1” will trigger a NON POST packet reply (independent from the expected ACK packet) destined to “/resource2” URI path with a default payload.
  • Print in shell all CoAP transactions to fully understand when a request was sent and when a response was received, indicating the method and the resource, e.g.
  • If a CON POST was received, print on shell “‘NON’ packet received, ‘POST’ with payload of ‘<payload>’
  • If a NON POST was sent, print on shell “‘NON’ packet sent, ‘POST’ with payload ‘<payload>’

 

The process desired behavior by the laboratory is shown in figure 1.  

Figure 1 Diagram showing the desired behavior of the laboratory


 

Setup

In the following list, the components with a dash (—) will be the ones used to create this laboratory.

 

  • 2 FRDM-KW41Z

      — Rev.  A

  • Connectivity Software from the latest NXP release.

      — Thread Router Eligible Device project

  • Serial Terminal

      — TeraTerm

 

Figure 2 FRDM-KW41Z 


 

Modifying Firmware      

 

The following changes will be made in the router_eligible_device_app.c file. 

1. Define the URI path names that will be used in the shell to access the resources.

#define APP_RESOURCE1_URI_PATH                       "/resource1"

#define APP_RESOURCE2_URI_PATH                       "/resource2"

 

 

2. Declare the URI resources with coapUriPath_t. When using this struct the user must enter the length of the URI path and the path created in the last step.

const coapUriPath_t gAPP_RESOURCE1_URI_PATH = {SizeOfString(APP_RESOURCE1_URI_PATH), APP_RESOURCE1_URI_PATH};

const coapUriPath_t gAPP_RESOURCE2_URI_PATH = {SizeOfString(APP_RESOURCE2_URI_PATH), APP_RESOURCE2_URI_PATH};

 

 

3. Create the callbacks for the resources. This callbacks will handle the packet received and perform the desired action depending on the type of COAP method received.

static void APP_CoapResource1Cb(coapSessionStatus_t sessionStatus, void *pData, coapSession_t *pSession, uint32_t dataLen);

static void APP_CoapResource2Cb(coapSessionStatus_t sessionStatus, void *pData, coapSession_t *pSession, uint32_t dataLen);

 

 

 

4. Add the callback handler for the packet received, in this function it will be defined which action will be performed depending on the type of COAP method received.

  • APP_CoapResource1Cb

 

 

static void APP_CoapResource1Cb
(
coapSessionStatus_t sessionStatus,
void *pData,
coapSession_t *pSession,
uint32_t dataLen
)

{
  static uint8_t pMySessionPayload[3]={0x31,0x32,0x33};
  static uint32_t pMyPayloadSize=3;
  coapSession_t *pMySession = NULL;
  pMySession = COAP_OpenSession(mAppCoapInstId);
  COAP_AddOptionToList(pMySession,COAP_URI_PATH_OPTION, APP_RESOURCE2_URI_PATH,SizeOfString(APP_RESOURCE2_URI_PATH));

    if (gCoapConfirmable_c == pSession->msgType)
  {
    if (gCoapGET_c == pSession->code)
    {
      shell_write("'CON' packet received 'GET' with payload: ");
    }
    if (gCoapPOST_c == pSession->code)
    {
      shell_write("'CON' packet received 'POST' with payload: ");
    }
    if (gCoapPUT_c == pSession->code)
    {
      shell_write("'CON' packet received 'PUT' with payload: ");
    }    
    if (gCoapFailure_c!=sessionStatus)
    {
      COAP_Send(pSession, gCoapMsgTypeAckSuccessChanged_c, pMySessionPayload, pMyPayloadSize);
    }
  }

  else if(gCoapNonConfirmable_c == pSession->msgType)
  {
    if (gCoapGET_c == pSession->code)
    {
      shell_write("'NON' packet received 'GET' with payload: ");
    }
    if (gCoapPOST_c == pSession->code)
    {
      shell_write("'NON' packet received 'POST' with payload: ");
    }
    if (gCoapPUT_c == pSession->code)
    {
      shell_write("'NON' packet received 'PUT' with payload: ");
    }   
  }
  shell_writeN(pData, dataLen);
  shell_write("\r\n");
  pMySession -> msgType=gCoapNonConfirmable_c;
  pMySession -> code= gCoapPOST_c;
  pMySession -> pCallback =NULL;
  FLib_MemCpy(&pMySession->remoteAddr,&gCoapDestAddress,sizeof(ipAddr_t));
  COAP_SendMsg(pMySession,  pMySessionPayload, pMyPayloadSize);
  shell_write("'NON' packet sent 'POST' with payload: ");
  shell_writeN((char*) pMySessionPayload, pMyPayloadSize);
  shell_write("\r\n");
}

 

There can be one COAP instance per UDP port, in case the application only uses one port, one instance will be enough.

There can be multiple COAP sessions per instance, a COAP session is per packet/transaction. In this case as the desired result was to have a different response of the ACK, it will be necessary to create a new session with the new resource.

 

  • APP_CoapResource2Cb

 

static void APP_CoapResource2Cb
(
coapSessionStatus_t sessionStatus,
void *pData,
coapSession_t *pSession,
uint32_t dataLen
)

{
  if (gCoapNonConfirmable_c == pSession->msgType)
  {
      shell_write("'NON' packet received 'POST' with payload: "); 
      shell_writeN(pData, dataLen);
      shell_write("\r\n");
  } 
}

 

5. After creating the callbacks, those must be registered in the CoAP callback array in the function APP_InitCoapDemo(void)

 

 

{APP_CoapResource1Cb, (coapUriPath_t*)&gAPP_RESOURCE1_URI_PATH},

{APP_CoapResource2Cb, (coapUriPath_t*)&gAPP_RESOURCE2_URI_PATH},

 

There are some things to mention of the usage of the CoAP library that were not used for this laboratory but might be useful for other types of applications.

When using COAP_SendMsg() the session will close automatically by default unless it is indicated with the usage of pSession->autoClose.

There are two options while sending the message:

Confirmable (CON): It waits for an ACK reply and until it gets the message it will close the session or it will close the session when retransmissions are exhausted.

Non-confirmable (NON): For NON, immediately after sending the message.

In case a message was sent and there was no response a retransmission will be sent each COAP_ACK_TIMEOUT (in miliseconds), the retransmissions are sent exponentially: first after random (2, 3) seconds, next doubles the timeout and so on, until COAP_MAX_RETRANSMIT is reached.

After retransmissions stop, the session is automatically closed and informs the application of failure the application callback will be called with status gCoapFailure_c.

When the callback is called the current session is still valid, but CoAP session will close it after exiting the function. There are two different work this out:

A new session must be created

Set pSession->autoClose = FALSE. If autoClose is set to FALSE, without forgetting to close the session from application, using COAP_CloseSession().

 

 

Running the demo   

 

1. Download the modified firmware in the boards

2. Open a serial terminal for each board with a baud rate of 115200

Figure 3 Serial terminal and its configuration 

3. In one of the board’s terminal type thr create, this board will be the leader.

Figure 4 Board 1 with command "thr create"

Figure 5 Board 1 after the command "thr create"

 

4. Once the network has been created type “thr join” in the second board’s terminal.

 

Figure 6 Board 2 with command "thr join"

Figure 7 Board 2 after command "thr join"

5. In both serial terminals type the command “ifconfig”. This command will display all the addresses of the board.

 

Figure 8 Board 1 after command "ifconfig"

Figure 9 Board 2 after command "ifconfig"

 

6. To test the callbacks created, a CoAP message must be sent. The following command must be typed;

 

coap <type> <method> <address> <URI> <payload>

                                                                                    

coap CON POST fe80::5df0:2bf0:d69b:1b3c  /resource1 hello

                                                                                    

Figure 10 CoAP command to send

7. The result of sending must look like :

 

— Board 1

The board 1 will request the board 2 the resource1

Figure 11 Board 1 before sending the CoAP command

As it was coded the other board will send an ACK and print the message.

Figure 12 Board 1 after sending the CoAP command

 Board 2

Figure 13 Board 2 after receiving the CoAP command

If using the CON message the requester board will receive a response, while if the message is a NON type it will not have the response.  

When using this types of messages independently of the package type when sending a message a new session will be open and it will send a NON type of message.

5 people found this helpful

Attachments

    Outcomes