Creating FreeRTOS+Nabto Applications
Part 2: Worked Examples


<<< Previous: Creating Applications Part 1 - Nabto Queries and the Event Handling C Function

Event handler function prototype

Part 1 of this integration guide described the interface between the FreeRTOS+Nabto C source files and the user's embedded application as a single event handling C function. The prototype of the C function is shown in Listing 1.

The event handler is called automatically each time a Nabto query is received. One of the handler's parameters is used to pass the query's request parameters into the C function, another parameter is used to pass any response parameters that might be generated out of the C function. The query ID is used to determine both the number of, and the format of, the request and response parameters.

Example implementations that handle the queries used in the live demo are provided on this page. /* * Parameters: * pxRequest A pointer to a structure that contains details of the query, * including the query's unique ID. * pxReadBuffer A buffer that contains the request parameters. Do not read from * the buffer directly. Access functions are provided. * pxWriteBuffer A buffer into which response parameters are written. Do not * write to the buffer directly. Access functions are provided. */ application_event_result_t application_event( application_request_t* pxRequest, buffer_read_t* pxReadBuffer, buffer_write_t* pxWriteBuffer ); Listing 1: The prototype of the FreeRTOS+Nabto application event handler



Worked examples from the live demo

This section provides an event handler implementation for each of the queries used in the live demo.


Live demo query #1: Get RTOS tick count

In the live demo query ID #1 is used to obtain the RTOS tick count.

Query ID #1: Get RTOS tick count
Request Parameters:  None 
Response Parameters:  The RTOS tick count value, transmitted as a 32-bit unsigned integer 


The source code that handles query #1 is shown in Listing 2. Notes:


/* Define a text constant for query ID #1. */ #define sysQUERY_TICK_VALUE 1 /* The standard function prototype as shown in list 1. */ application_event_result_t application_event( application_request_t* pxRequest, buffer_read_t* pxReadBuffer, buffer_write_t* pxWriteBuffer ) { application_event_result_t xReturn; /* * The bullet points directly above this code listing provide an explanation of * the following code. */ switch( request->query_id ) { case sysQUERY_TICK_VALUE: /* Write the response parameter to pxWriteBuffer. */ if( buffer_write_uint32( pxWriteBuffer, xTaskGetTickCount() ) == pdFAIL ) { /* The response parameter would not fit in the write buffer. */ xReturn = AER_REQ_RSP_TOO_LARGE; } else { /* The write buffer contains the value of the response parameter. */ xReturn = AER_REQ_RESPONSE_READY; } break; } return xReturn; } Listing 2: Source code to handle query #1



Live demo query #2: Get network statistic

In the live demo query ID #2 is used to obtain one of three different network statistics.

Query ID #2: Get network statistic
Request Parameters:  The ID of the statistic being queried, received as a 32-bit unsigned integer 
Response Parameters:  The value of the network statistic that corresponds to the ID received as the request parameter, transmitted as a 32-bit unsigned integer 


The source code that handles query #2 is shown in Listing 3. The notes above listing 2 are also relevant to listing 3. In addition:


/* Define a text constant for query ID #2. */ #define sysQUERY_NET_STAT 2 /* The standard function prototype as shown in list 1. */ application_event_result_t application_event( application_request_t* pxRequest, buffer_read_t* pxReadBuffer, buffer_write_t* pxWriteBuffer ) { application_event_result_t xReturn; unsigned long ulRequestParameter, ulStatValue; /* * The bullet points directly above this code listing provide an explanation * of the following code. */ switch( request->query_id ) { case sysQUERY_NET_STAT: /* Read the request parameter from pxReadBuffer. */ if( buffer_read_uint32( pxReadBuffer, &ulRequestParameter ) == pdFAIL ) { /* There are two few bytes remaining in pxReadBuffer to complete the read request. */ xReturn = AER_REQ_TOO_SMALL; } else { ulStatValue = prvGetNetworkStatistic( ulRequestParameter ); /* Write the response parameter to pxWriteBuffer. */ if( buffer_write_uint32( pxWriteBuffer, ulStatValue ) == pdFAIL ) { /* The response parameter would not fit in the write buffer. */ xReturn = AER_REQ_RSP_TOO_LARGE; } else { /* The write buffer contains the value of the response parameter. */ xReturn = AER_REQ_RESPONSE_READY; } } } return xReturn; } Listing 3: Source code to handle query #2




Live demo query #3: FreeRTOS command console

In the live demo query ID #3 is used to access the FreeRTOS command console.

Query ID #3: FreeRTOS command console
Request Parameters:  The command entered by the user, received as a raw data buffer 
Response Parameters:  The ascii text generated when the received command was executed, transmitted as a raw data buffer 


The source code that handles query #3 is shown in Listing 4. The notes above listing 2 and listing 3 are also relevant to listing 4. In addition:


/* Define a text constant for query ID #3. */ #define sysQUERY_COMMAND_STRING 3 /* Dimensions local buffers to be large enough to hold one line of input/output. */ #define sysMAX_LINE_LENGTH 128 /* The standard function prototype as shown in list 1. */ application_event_result_t application_event( application_request_t* pxRequest, buffer_read_t* pxReadBuffer, buffer_write_t* pxWriteBuffer ) { application_event_result_t xReturn; buffer_t xRawBuffer; static uint8_t ucLocalBuffer[ sysMAX_LINE_LENGTH ]; /* * The bullet points directly above this code listing provide an explanation * of the following code. */ switch( request->query_id ) { case sysQUERY_COMMAND_STRING: /* The locally declared raw buffer is used to point to the locally declared ucLocalBuffer array. */ xRawBuffer.data = ucLocalBuffer; xRawBuffer.size = sizeof( ucLocalBuffer ); /* Read raw data from pxReadBuffer into the buffer pointed to by pxReadBuffer (pxReadBuffer is pointing to ucLocalBuffer). */ if( buffer_read_raw( pxReadBuffer, &xRawBuffer ) != pdFALSE ) { /* ucLocalBuffer now holds the command string. Ensure it is terminated. */ ucLocalBuffer[ xRawBuffer.size ] = 0x00; /* Execute the command. xRawBuffer is now set to point to the output generated when the command was executed. */ xRawBuffer.data = prvProcessCommandString( ucLocalBuffer ); /* Update the length of data in the raw buffer to reflect the length of the string it now contains. */ xRawBuffer.size = strlen( xRawBuffer.data ); /* Write the raw buffer to the output buffer. */ if( buffer_write_raw( pxWriteBuffer, &xRawBuffer ) == pdFALSE ) { xReturn = AER_REQ_RSP_TOO_LARGE; } else { xReturn = AER_REQ_RESPONSE_READY; } } else { xReturn = AER_REQ_TOO_SMALL; } break; } return xReturn; } Listing 4: Source code to handle query #3