Quality RTOS & Embedded Software

LIBRARIES
NOTE : The MQTT library and documentation are part of the FreeRTOS LTS Roadmap – the library will be released into the main FreeRTOS download with long term support (LTS) when the refactoring described on the LTS roadmap page is complete. This page presents a simple demo for the MQTT LTS rc1 library, which is now near completion.

Basic Demo Using MQTT LTS rc1 Lightweight API

Notice: For simplicity of understanding, this MQTT LTS rc1 demo does not use an encrypted network connection and is therefore not intended to demonstrate best practice. Production IoT devices should use a network connection that is both authenticated and encrypted, as demonstrated in the previously released MQTT TLS demos.


Introduction

The project presented on this page uses the FreeRTOS Windows port and builds using the free Community version of Visual Studio on Windows, enabling its use without the need for specific MCU hardware. It demonstrates the most basic use case for the MQTT LTS rc1 library’s lightweight API. There is also a separate project that uses the MQTT library’s managed API. Like the managed API, the lightweight API does not require dynamic memory allocation, nor does it have any dependencies on libraries other than the standard C library and a simple send/receive transport network interface. Unlike the managed API, the lightweight API does not maintain any internal state.

The instructions below describe how to connect to either the unsecured public Mosquitto test broker, or an MQTT broker running locally on the host. Connecting to a broker that requires an authenticated TLS connection, such as AWS IoT Core, requires the use of a different network transport interface.

As per the red text above, this demo is intended to be used as a learning exercise only. All MQTT messages are sent in plaintext and are not encrypted. Do NOT send any confidential information from your device to the MQTT broker. The MQTT broker is publicly hosted by a 3rd party that is not affiliated with FreeRTOS. This MQTT broker may be unavailable at any time, and it is not maintained by FreeRTOS. Production IoT devices should use a network connection that is both authenticated and encrypted, as demonstrated in the previously released MQTT TLS demos.


Build Instructions


Click to enlarge

The Visual Studio solution for the lightweight MQTT LTS rc1 demo is called mqtt_light_weight_demo.sln and is located in the FreeRTOS-Plus/Demo/FreeRTOS-IoT-Libraries-LTS-Beta2/mqtt/mqtt_light_weight/ directory of the LTS Development Snapshot download.


Configuring the Demo Project

The demo uses the FreeRTOS+TCP TCP/IP stack, so follow the instructions provided for the TCP/IP starter project to ensure you:
  1. Have the pre-requisite components installed (such as WinPCap).
  2. Optionally set a static or dynamic IP address, gateway address and netmask.
  3. Optionally set a MAC address.
  4. Select an Ethernet network interface on your host machine.
  5. …and importantly test your network connection before attempting to run the MQTT demo.
All of these settings should be set in the MQTT LTS rc1 demo project, not the TCP/IP starter project referenced from the same page! As delivered, the TCP/IP stack is configured to use a dynamic IP address.


Configuring the MQTT Broker Connection

Option 1: Using the publicly hosted Mosquitto MQTT broker (web hosted):

As delivered, the demo project is pre-configured to communicate with Mosquitto’s publicly hosted message broker at “test.mosqitto.org”. That should work if the network to which the demo is connected has a DHCP service and Internet access. Note the FreeRTOS Windows port only works with a wired Ethernet network adapter, which can be a virtual Ethernet adapter.

Use a separate MQTT client, such as MQTT.fx, to test the MQTT connection from your host machine to the public MQTT broker.

Option 2: Using a locally hosted Mosquitto MQTT message broker (host machine):

The Mosquitto broker can also run locally, either on your host machine (the machine used to build the demo application), or another machine on your local network. To do this:
  1. Follow the instructions on https://mosquitto.org/download/ to download and install Mosquitto locally.
  2. Open “mosquitto.conf”, which is located in the Mosquitto install directory, and set the contained “bind_address” to be correct for the network on which Mosquitto will listen for connection.
  3. Find the IP address of your host machine (run the ipconfig command on Windows, or ifconfig on Linux or macOS). Note the FreeRTOS Windows port only works with a wired Ethernet network adaptor, which can be a virtual Ethernet adapter.
  4. Open FreeRTOS-Plus/Demo/FreeRTOS-IoT-Libraries-LTS-Beta2/mqtt/mqtt_plain_text/demo_config.h.
  5. Add the following lines so democonfigMQTT_BROKER_ENDPOINT is set to the IP address of the machine on which Mosquitto is running, which must be a machine on the same subnet as the network to which the demo is connected:
    • #define democonfigMQTT_BROKER_ENDPOINT "w.x.y.z"
    • #define democonfigMQTT_BROKER_PORT ( 1883 )
Use a separate MQTT client, such as MQTT.fx, to test the MQTT connection from your host machine to the local MQTT broker.

Note: Port number 1883 is the default port number for unencrypted MQTT. If you cannot use that port (for example if it is blocked by your IT security policy), then change the port used by Mosquitto to a high port number (for example something in the 50000 to 55000 range), and set democonfigMQTT_BROKER_PORT accordingly. The port number used by Mosquitto is set by the “port” parameter in “mosquitto.conf”, which is located in the Mosquitto install directory.

Option 3: Any other unencrypted MQTT broker of your choosing:

Any MQTT broker that supports unencrypted TCP/IP communication can also be used with this demo. To do this:
  1. Open FreeRTOS-Plus/Demo/FreeRTOS-IoT-Libraries-LTS-Beta2/mqtt/mqtt_plain_text/demo_config.h.
  2. Add the following lines with respect to your chosen broker:
    • #define democonfigMQTT_BROKER_ENDPOINT "your-desired-endpoint"
    • #define democonfigMQTT_BROKER_PORT ( 1883 )


Building the Demo Project

The demo project uses the free community edition of Visual Studio. To build the demo:
  1. Open the mqtt_plain_text_demo.sln Visual Studio solution file from within the Visual Studio IDE
  2. Select Build Solution from the IDE’s Build menu

Note: If you are using Microsoft Visual Studio 2017 or earlier, then you must select a Platform Toolset compatible with your version: Project -> RTOSDemos Properties -> Platform Toolset


Functionality

Note this demo uses the lightweight MQTT API in its most basic use case – from within a single thread. The final version of the MQTT library’s managed API demo will include more complex multi-threaded demos.

Functionality

Note this demo uses the lightweight MQTT API in its most basic use case – from within a single thread. The final version of the MQTT library’s managed API demo will include more complex multi-threaded demos.

The demo creates a single application task that loops through a set of examples that demonstrate how to connect to the broker, subscribe to a topic on the broker, publish to a topic on the broker, then finally, disconnect from the broker. The demo application both subscribes to and publishes to the same topic. Each time the demo publishes a message to the MQTT broker the broker sends the same message back to the demo application. The structure of the demo is shown below:


static void prvMQTTDemoTask( void * pvParameters )
{
Socket_t xMQTTSocket;
uint32_t ulPublishCount = 0U;
const uint32_t ulMaxPublishCount = 5UL;

/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;

for( ; ; )
{
/****************************** Connect. ******************************/



/* Establish a TCP connection with the MQTT broker. This example connects to

* the MQTT broker as specified in democonfigMQTT_BROKER_ENDPOINT and

* democonfigMQTT_BROKER_PORT at the top of this file. */

LogInfo( ( “Create a TCP connection to %s.\r\n”, democonfigMQTT_BROKER_ENDPOINT ) );
xMQTTSocket = prvCreateTCPConnectionToBroker();



/* Sends an MQTT Connect packet over the already connected TCP socket

* xMQTTSocket, and waits for connection acknowledgment (CONNACK) packet. */

LogInfo( ( “Creating an MQTT connection to %s.\r\n”, democonfigMQTT_BROKER_ENDPOINT ) );
prvCreateMQTTConnectionWithBroker( xMQTTSocket );

/**************************** Subscribe. ******************************/



/* The client is now connected to the broker. Subscribe to the topic

* as specified in mqttexampleTOPIC at the top of this file by sending a

* subscribe packet then waiting for a subscribe acknowledgment (SUBACK).

* This client will then publish to the same topic it subscribed to, so it

* will expect all the messages it sends to the broker to be sent back to it

* from the broker. This demo uses QOS0 in Subscribe, therefore, the

* Publish messages received from the broker will have QOS0. */

LogInfo( ( “Attempt to subscribed to the MQTT topic %s.\r\n”, mqttexampleTOPIC ) );
prvMQTTSubscribeToTopic( xMQTTSocket );



/* Process incoming packet from the broker. After sending the subscribe, the

* client may receive a publish before it receives a subscribe ack. Therefore,

* call generic incoming packet processing function. Since this demo is

* subscribing to the topic to which no one is publishing, probability of

* receiving Publish message before subscribe ack is zero; but application

* must be ready to receive any packet. This demo uses the generic packet

* processing function everywhere to highlight this fact. */

prvMQTTProcessIncomingPacket( xMQTTSocket );

/******************* Publish and Keep Alive Loop. *********************/

/* Publish messages with QOS0, send and process Keep alive messages. */

for( ulPublishCount = 0; ulPublishCount < ulMaxPublishCount; ulPublishCount++ )
{
LogInfo( ( “Publish to the MQTT topic %s.\r\n”, mqttexampleTOPIC ) );
prvMQTTPublishToTopic( xMQTTSocket );



/* Process incoming publish echo, since application subscribed to the same

* topic the broker will send publish message back to the application. */

LogInfo( ( “Attempt to receive publish message from broker.\r\n” ) );
prvMQTTProcessIncomingPacket( xMQTTSocket );

/* Leave Connection Idle for some time */
LogInfo( ( “Keeping Connection Idle.\r\n\r\n” ) );
vTaskDelay( mqttexampleKEEP_ALIVE_DELAY );

/* Send Ping request to broker and receive ping response */
LogInfo( ( “Sending Ping Request to the broker.\r\n” ) );
prvMQTTKeepAlive( xMQTTSocket );

/* Process Incoming packet from the broker */
prvMQTTProcessIncomingPacket( xMQTTSocket );
}

/******************** Unsubscribe from the topic. *********************/
LogInfo( ( “Unsubscribe from the MQTT topic %s.\r\n”, mqttexampleTOPIC ) );
prvMQTTUnsubscribeFromTopic( xMQTTSocket );

/* Process Incoming packet from the broker. */
prvMQTTProcessIncomingPacket( xMQTTSocket );

/************************* Disconnect. ********************************/



/* Send an MQTT Disconnect packet over the already connected TCP socket.

* There is no corresponding response for the disconnect packet. After sending

* disconnect, client must close the network connection. */

LogInfo( ( “Disconnecting the MQTT connection with %s.\r\n”, democonfigMQTT_BROKER_ENDPOINT ) );
prvMQTTDisconnect( xMQTTSocket );

/* Close the network connection. */
prvGracefulShutDown( xMQTTSocket );



/* Wait for some time between two iterations to ensure that we do not

* bombard the public test mosquitto broker. */

LogInfo( ( “prvMQTTDemoTask() completed an iteration successfully. Total free heap is %u.\r\n”, xPortGetFreeHeapSize() ) );
LogInfo( ( “Demo completed successfully.\r\n” ) );
LogInfo( ( “Short delay before starting the next iteration…. \r\n\r\n” ) );
vTaskDelay( mqttexampleDELAY_BETWEEN_DEMO_ITERATIONS );
}
}

The screenshot below shows the expected output when the demo is executing correctly.

Click to enlarge

Connecting to the MQTT Broker

The function prvCreateMQTTConnectionWithBroker() demonstrates how to establish an unencrypted connection to a MQTT broker with clean session. The definition of prvCreateMQTTConnectionWithBroker() is shown below:


static void prvCreateMQTTConnectionWithBroker( Socket_t xMQTTSocket )
{
BaseType_t xStatus;
size_t xRemainingLength;
size_t xPacketSize;
MQTTStatus_t xResult;
MQTTPacketInfo_t xIncomingPacket;
MQTTConnectInfo_t xConnectInfo;
uint16_t usPacketId;
bool xSessionPresent;
NetworkContext_t xNetworkContext;



/***

* For readability, error handling in this function is restricted to the use of

* asserts().

***/


/* Many fields not used in this demo so start with everything at 0. */
memset( ( void * ) &xConnectInfo, 0x00, sizeof( xConnectInfo ) );



/* Start with a clean session i.e. direct the MQTT broker to discard any

* previous session data. Also, establishing a connection with clean session

* will ensure that the broker does not store any data when this client

* gets disconnected. */

xConnectInfo.cleanSession = true;



/* The client identifier is used to uniquely identify this MQTT client to

* the MQTT broker. In a production device the identifier can be something

* unique, such as a device serial number. */

xConnectInfo.pClientIdentifier = democonfigCLIENT_IDENTIFIER;
xConnectInfo.clientIdentifierLength = ( uint16_t ) strlen( democonfigCLIENT_IDENTIFIER );



/* Set MQTT keep-alive period. It is the responsibility of the application to

* ensure that the interval between Control Packets being sent does not exceed

* the Keep Alive value. In the absence of sending any other Control Packets,

* the Client MUST send a PINGREQ Packet. */

xConnectInfo.keepAliveSeconds = mqttexampleKEEP_ALIVE_TIMEOUT_SECONDS;



/* Get size requirement for the connect packet.

* Last Will and Testament is not used in this demo. It is passed as NULL. */

xResult = MQTT_GetConnectPacketSize( &xConnectInfo,
NULL,
&xRemainingLength,
&xPacketSize );

/* Make sure the packet size is less than static buffer size. */
configASSERT( xResult == MQTTSuccess );
configASSERT( xPacketSize < mqttexampleSHARED_BUFFER_SIZE );

/* Serialize MQTT connect packet into the provided buffer. */
xResult = MQTT_SerializeConnect( &xConnectInfo,
NULL,
xRemainingLength,
&xBuffer );
configASSERT( xResult == MQTTSuccess );

xStatus = FreeRTOS_send( xMQTTSocket,
( void * ) xBuffer.pBuffer,
xPacketSize,
0 );
configASSERT( xStatus == ( BaseType_t ) xPacketSize );

/* Reset all fields of the incoming packet structure. */
( void ) memset( ( void * ) &xIncomingPacket, 0x00, sizeof( MQTTPacketInfo_t ) );



/* Wait for connection acknowledgment. We cannot assume received data is the

* connection acknowledgment. Therefore this function reads type and remaining

* length of the received packet, before processing entire packet – although

* in this case to keep the example simple error checks are just performed

* by asserts.

*/

xNetworkContext.xTcpSocket = xMQTTSocket;
xResult = MQTT_GetIncomingPacketTypeAndLength( prvTransportRecv,
&xNetworkContext,
&xIncomingPacket );
configASSERT( xResult == MQTTSuccess );
configASSERT( xIncomingPacket.type == MQTT_PACKET_TYPE_CONNACK );
configASSERT( xIncomingPacket.remainingLength <= mqttexampleSHARED_BUFFER_SIZE );

/* Now receive the reset of the packet into the statically allocated buffer. */
xStatus = FreeRTOS_recv( xMQTTSocket,
( void * ) xBuffer.pBuffer,
xIncomingPacket.remainingLength,
0 );
configASSERT( xStatus == ( BaseType_t ) xIncomingPacket.remainingLength );

xIncomingPacket.pRemainingData = xBuffer.pBuffer;
xResult = MQTT_DeserializeAck( &xIncomingPacket,
&usPacketId,
&xSessionPresent );
configASSERT( xResult == MQTTSuccess );

if( xResult != MQTTSuccess )
{
LogInfo( ( “Connection with MQTT broker failed.\r\n” ) );
}
}
prvCreateMQTTConnectionWithBroker() demonstrates how to
establish an unencrypted connection to a MQTT broker with clean session

Subscribing to a MQTT Topic

The function prvMQTTSubscribeToTopic() demonstrates how to subscribe to a topic filter on the MQTT broker. The example demonstrates how to subscribe to one topic filter but it is possible to pass a list of topic filters in the same subscribe API call to subscribe to more than one topic filters. The definition of the function is shown below:


static void prvMQTTSubscribeToTopic( Socket_t xMQTTSocket )
{
MQTTStatus_t xResult;
MQTTSubscribeInfo_t xMQTTSubscription[ 1 ];
size_t xRemainingLength;
size_t xPacketSize;
BaseType_t xStatus;



/***

* For readability, error handling in this function is restricted to the use of

* asserts().

***/


/* Some fields not used by this demo so start with everything at 0. */
( void ) memset( ( void * ) &xMQTTSubscription, 0x00, sizeof( xMQTTSubscription ) );



/* Subscribe to the mqttexampleTOPIC topic filter. This example subscribes to

* only one topic and uses QOS0. */

xMQTTSubscription[ 0 ].qos = MQTTQoS0;
xMQTTSubscription[ 0 ].pTopicFilter = mqttexampleTOPIC;
xMQTTSubscription[ 0 ].topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC );

xResult = MQTT_GetSubscribePacketSize( xMQTTSubscription,
sizeof( xMQTTSubscription ) / sizeof( MQTTSubscribeInfo_t ),
&xRemainingLength,
&xPacketSize );

/* Make sure the packet size is less than static buffer size. */
configASSERT( xResult == MQTTSuccess );
configASSERT( xPacketSize < mqttexampleSHARED_BUFFER_SIZE );

/* Get a unique packet id. */
usSubscribePacketIdentifier = prvGetNextPacketIdentifier();
/* Make sure the packet id obtained is valid. */
configASSERT( usSubscribePacketIdentifier != 0 );

/* Serialize subscribe into statically allocated ucSharedBuffer. */
xResult = MQTT_SerializeSubscribe( xMQTTSubscription,
sizeof( xMQTTSubscription ) / sizeof( MQTTSubscribeInfo_t ),
usSubscribePacketIdentifier,
xRemainingLength,
&xBuffer );

configASSERT( xResult == MQTTSuccess );

/* Send Subscribe request to the broker. */
xStatus = FreeRTOS_send( xMQTTSocket,
( void * ) xBuffer.pBuffer,
xPacketSize,
0 );
configASSERT( xStatus == ( BaseType_t ) xPacketSize );
}

prvMQTTSubscribeToTopic() demonstrates how to
subscribe to a topic filter on the MQTT broker

Publishing to a Topic

The function prvMQTTPublishToTopic() demonstrates how to publish to a topic filter on the MQTT broker. The definition of the function is shown below:


static void prvMQTTPublishToTopic( Socket_t xMQTTSocket )
{
MQTTStatus_t xResult;
MQTTPublishInfo_t xMQTTPublishInfo;
size_t xRemainingLength;
size_t xPacketSize;
size_t xHeaderSize;
BaseType_t xStatus;



/***

* For readability, error handling in this function is restricted to the use of

* asserts().

***/


/* Some fields not used by this demo so start with everything at 0. */
( void ) memset( ( void * ) &xMQTTPublishInfo, 0x00, sizeof( xMQTTPublishInfo ) );

/* This demo uses QOS0 */
xMQTTPublishInfo.qos = MQTTQoS0;
xMQTTPublishInfo.retain = false;
xMQTTPublishInfo.pTopicName = mqttexampleTOPIC;
xMQTTPublishInfo.topicNameLength = ( uint16_t ) strlen( mqttexampleTOPIC );
xMQTTPublishInfo.pPayload = mqttexampleMESSAGE;
xMQTTPublishInfo.payloadLength = strlen( mqttexampleMESSAGE );

/* Find out length of Publish packet size. */
xResult = MQTT_GetPublishPacketSize( &xMQTTPublishInfo,
&xRemainingLength,
&xPacketSize );
configASSERT( xResult == MQTTSuccess );

/* Make sure the packet size is less than static buffer size. */
configASSERT( xPacketSize < mqttexampleSHARED_BUFFER_SIZE );



/* Serialize MQTT Publish packet header. The publish message payload will

* be sent directly in order to avoid copying it into the buffer.

* QOS0 does not make use of packet identifier, therefore value of 0 is used */

xResult = MQTT_SerializePublishHeader( &xMQTTPublishInfo,
0,
xRemainingLength,
&xBuffer,
&xHeaderSize );
configASSERT( xResult == MQTTSuccess );

/* Send Publish header to the broker. */
xStatus = FreeRTOS_send( xMQTTSocket,
( void * ) xBuffer.pBuffer,
xHeaderSize,
0 );
configASSERT( xStatus == ( BaseType_t ) xHeaderSize );

/* Send Publish payload to the broker. */
xStatus = FreeRTOS_send( xMQTTSocket,
( void * ) xMQTTPublishInfo.pPayload,
xMQTTPublishInfo.payloadLength,
0 );
configASSERT( xStatus == ( BaseType_t ) xMQTTPublishInfo.payloadLength );
}

prvMQTTPublishToTopic() demonstrates how to
publish to a topic on the MQTT broker.

Unsubscribing from a Topic

The function prvMQTTUnsubscribeFromTopic() demonstrates how to unsubscribe to a topic filter on the MQTT broker. The example demonstrates how to unsubscribe to one topic filter but it possible to pass a list of topic filters in the same unsubscribe API call to unsubscribe to more than one topic filters. The definition of the function is shown below:


static void prvMQTTUnsubscribeFromTopic( Socket_t xMQTTSocket )
{
MQTTStatus_t xResult;
MQTTSubscribeInfo_t xMQTTSubscription[ 1 ];
size_t xRemainingLength;
size_t xPacketSize;
BaseType_t xStatus;

/* Some fields not used by this demo so start with everything at 0. */
memset( ( void * ) &xMQTTSubscription, 0x00, sizeof( xMQTTSubscription ) );



/* Unsubscribe to the mqttexampleTOPIC topic filter. The task handle is passed

* as the callback context which is used by the callback to send a task

* notification to this task.*/

xMQTTSubscription[ 0 ].qos = MQTTQoS0;
xMQTTSubscription[ 0 ].pTopicFilter = mqttexampleTOPIC;
xMQTTSubscription[ 0 ].topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC );

xResult = MQTT_GetUnsubscribePacketSize( xMQTTSubscription,
sizeof( xMQTTSubscription ) / sizeof( MQTTSubscribeInfo_t ),
&xRemainingLength,
&xPacketSize );
configASSERT( xResult == MQTTSuccess );
/* Make sure the packet size is less than static buffer size */
configASSERT( xPacketSize < mqttexampleSHARED_BUFFER_SIZE );

/* Get next unique packet identifier */
usUnsubscribePacketIdentifier = prvGetNextPacketIdentifier();
/* Make sure the packet id obtained is valid. */
configASSERT( usUnsubscribePacketIdentifier != 0 );

xResult = MQTT_SerializeUnsubscribe( xMQTTSubscription,
sizeof( xMQTTSubscription ) / sizeof( MQTTSubscribeInfo_t ),
usUnsubscribePacketIdentifier,
xRemainingLength,
&xBuffer );
configASSERT( xResult == MQTTSuccess );

/* Send Unsubscribe request to the broker. */
xStatus = FreeRTOS_send( xMQTTSocket, ( void * ) xBuffer.pBuffer, xPacketSize, 0 );
configASSERT( xStatus == ( BaseType_t ) xPacketSize );
}

prvMQTTUnsubscribeFromTopic() demonstrates
how to unsubscribe from a topic on the MQTT broker.

Processing Incoming MQTT Publish Packets

The function prvMQTTProcessIncomingPublish() demonstrates how to process a PUBLISH packet from the MQTT broker. The definition of the function is shown below:


static void prvMQTTProcessIncomingPublish( MQTTPublishInfo_t * pxPublishInfo )
{
configASSERT( pxPublishInfo != NULL );

/* Process incoming Publish. */
LogInfo( ( “Incoming QOS : %d\n”, pxPublishInfo->qos ) );

/* Verify the received publish is for the we have subscribed to. */
if( ( pxPublishInfo->topicNameLength == strlen( mqttexampleTOPIC ) ) &&
( 0 == strncmp( mqttexampleTOPIC,
pxPublishInfo->pTopicName,
pxPublishInfo->topicNameLength ) ) )
{
LogInfo( ( “\r\nIncoming Publish Topic Name: %.*s matches subscribed topic.\r\n”
“Incoming Publish Message : %.*s\r\n”,
pxPublishInfo->topicNameLength,
pxPublishInfo->pTopicName,
pxPublishInfo->payloadLength,
pxPublishInfo->pPayload ) );
}
else
{
LogInfo( ( “Incoming Publish Topic Name: %.*s does not match subscribed topic.\r\n”,
pxPublishInfo->topicNameLength,
pxPublishInfo->pTopicName ) );
}
}

prvMQTTProcessIncomingPublish() demonstrates how
process an incoming MQTT publish packet

Processing Incoming MQTT Packets

The function prvMQTTProcessIncomingPacket() demonstrates how to process an incoming packet from the MQTT broker. The definition of the function is shown below:


static void prvMQTTProcessIncomingPacket( Socket_t xMQTTSocket )
{
MQTTStatus_t xResult;
MQTTPacketInfo_t xIncomingPacket;
BaseType_t xStatus;
MQTTPublishInfo_t xPublishInfo;
uint16_t usPacketId;
NetworkContext_t xNetworkContext;



/***

* For readability, error handling in this function is restricted to the use of

* asserts().

***/



( void ) memset( ( void * ) &xIncomingPacket, 0x00, sizeof( MQTTPacketInfo_t ) );

/* Determine incoming packet type and remaining length. */
xNetworkContext.xTcpSocket = xMQTTSocket;
xResult = MQTT_GetIncomingPacketTypeAndLength( prvTransportRecv,
&xNetworkContext,
&xIncomingPacket );
configASSERT( xResult == MQTTSuccess );
configASSERT( xIncomingPacket.remainingLength <= mqttexampleSHARED_BUFFER_SIZE );



/* Current implementation expects an incoming Publish and three different

* responses ( SUBACK, PINGRESP and UNSUBACK ). */





/* Receive the remaining bytes. In case of PINGRESP, remaining length will be zero.

* Skip reading from network for remaining length zero. */

if( xIncomingPacket.remainingLength > 0 )
{
xStatus = FreeRTOS_recv( xMQTTSocket,
( void * ) xBuffer.pBuffer,
xIncomingPacket.remainingLength, 0 );
configASSERT( xStatus == ( BaseType_t ) xIncomingPacket.remainingLength );
xIncomingPacket.pRemainingData = xBuffer.pBuffer;
}

/* Check if the incoming packet is a publish packet. */
if( ( xIncomingPacket.type & 0xf0 ) == MQTT_PACKET_TYPE_PUBLISH )
{
xResult = MQTT_DeserializePublish( &xIncomingPacket, &usPacketId, &xPublishInfo );
configASSERT( xResult == MQTTSuccess );

/* Process incoming Publish message. */
prvMQTTProcessIncomingPublish( &xPublishInfo );
}
else
{


/* If the received packet is not a Publish message, then it is an ACK for one

* of the messages we sent out, verify that the ACK packet is a valid MQTT

* packet. Session present is only valid for a CONNACK. CONNACK is not

* expected to be received here. Hence pass NULL for pointer to session

* present. */

xResult = MQTT_DeserializeAck( &xIncomingPacket, &usPacketId, NULL );
configASSERT( xResult == MQTTSuccess );

/* Process the response. */
prvMQTTProcessResponse( &xIncomingPacket, usPacketId );
}
}
prvMQTTProcessIncomingPacket() demonstrates how to process an incoming MQTT
packet

Disconnecting from the MQTT Message Broker

The function prvMQTTDisconnect() demonstrates how to disconnect from the MQTT broker. The definition of the function is shown below:


static void prvMQTTDisconnect( Socket_t xMQTTSocket )
{
MQTTStatus_t xResult;
BaseType_t xStatus;
size_t xPacketSize;

/* Calculate DISCONNECT packet size. */
xResult = MQTT_GetDisconnectPacketSize( &xPacketSize );
configASSERT( xResult == MQTTSuccess );
configASSERT( xPacketSize <= mqttexampleSHARED_BUFFER_SIZE );

xResult = MQTT_SerializeDisconnect( &xBuffer );
configASSERT( xResult == MQTTSuccess );

xStatus = FreeRTOS_send( xMQTTSocket,
( void * ) xBuffer.pBuffer,
xPacketSize,
0 );
configASSERT( xStatus == ( BaseType_t ) xPacketSize );
}

prvMQTTDisconnect() demonstrates how to gracefully disconnect from the MQTT broker
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.