Increase Functionality of MQTT by adding Packet Handling

Last modified by Microchip on 2023/11/09 09:03

First, this generated example wasn’t designed to receive data, so if you want to make the device receive data, you will need to add two lines of code in a lower level of programming:

Add Line in socketHandler()

Add the next line in mqtt_example.c, right before the last break in the definition of socketHandler(), as shown in the picture:

recv(sock, recvBuffer, sizeof(recvBuffer), 0);

Add the next line in mqtt_example.c

 
Without that line, the program wouldn’t detect any received packet, except Connect packet.

Back to Top

Add Line in MQTT_ReceptionHandler()

In mqtt_core.c, right before the last return in the definition of MQTT_ReceptionHandler(), add the next line, as shown in the picture:

lastReceivedPacketHeader = receivedPacketHeader;

lastRecievedPacketHeader shown in Code

MQTT_ReceptionHandler() detects and processes the received packet.  The information for what type of packet has been received is in the header of the packet. MQTT_ReceptionHandler() stores that header in the receivedPacketHeader variable. Once the function is completed, that variable disappears. The line that we wrote allows us to save that value in the lastReceivedPacketHeader variable, which is the one that we will use, through the MQTT_GetLastReceivedPacketHeader() function.

Without that line, we would not be able to know what type of packet we received and processed.

Back to Top

Write code for Processing Received Packets

Declare this new global variable at the top of mqtt_example.c . It will be used to store the value of the last received packet’s header:

mqttHeaderFlags last_received_header;            //stores the value of the header of the last received packet

mqttHeaderFlags last_received_header; shown in code

Add this next code in any part of the PROCESS_LAST_PACKET state for receiving and processing packets:

mqttConnnectionInfo = MQTT_GetClientConnectionInfo();      //actualize MQTT connection information
MQTT_ReceptionHandler(mqttConnnectionInfo);                //detects received packet and processes it
last_received_header = MQTT_GetLastReceivedPacketHeader(); //save the value of the header
if (last_received_header.controlPacketType == CONNACK)     // if connack received  
           {        
             PORTD.OUT=PORTD.OUT & 0xFB;                   //turn second LED on (Green)
           }
if (last_received_header.controlPacketType == SUBACK)      // if suback received   
         {                                     
          PORTD.OUT=PORTD.OUT & 0xFD;                      //turn third LED on (Yellow)
          }

Code View of case PROCESS_LAST_PACKET

  • If the CONNACK has been received, last_received_header.controlPacketType is CONNACK and the second LED is turned on.
  • If the received message was a SUBACK, last_received_header.controlPacketType is SUBACK and the third LED would be turned on.

    Take into account that once last_received_header.controlPacketType takes a value, it won’t reset until another packet is received.  To see what type of SUBACK can be received, see the top lines of mqtt_core.h

Top lines of mqtt_core.h showing types of Suback that can be recieved

Back to Top

Read Received Message

Declare Variables

Write these two lines at the top of mqtt_example.c . These are the variables where we are going to save the value of the topic and the message of the received message.

volatile uint8_t last_received_topic[PUBLISH_TOPIC_SIZE];
volatile uint8_t last_received_message[PAYLOAD_SIZE];

Declare Callback

Write these two lines at the top of mqtt_example.c, but after the declaration of the equalize_arrays() function. This declares the function that we will set up as our callback for when we receive a publish.

void MQTT_publish_handler_cb(uint8_t *topic, uint8_t *payload)
{
equalize_arrays(last_received_topic,topic);
equalize_arrays(last_received_message, payload);  
}

If you didn’t define the equalize_arrays() function previously, as in the Publish Different Messages example, you can write any code inside of the MQTT_publish_handler_cb function that makes last_received_topic array equal to topic, and last_received_message equal to payload.

Define Callback

Write this line at the start of the definition of app_mqttScheduler(), in mqtt_example.c . This line will set the MQTT_publish_handler_cb() function, the one we defined in the previous section, as a callback. This means that the function will be executed every time we receive a publish packet.

MQTT_SetPublishReceptionCallback(MQTT_publish_handler_cb);

Testing Result

There are many ways to see if we have read the message correctly. The easiest way would be to see what is in the last_received_topic and last_received_message variables using debug mode. It can be done by publishing any message via MyMQTT app, with “subscribing/topic” (or whatever value was in t[]) as the topic.

Watch Window in MPLAB

You should see this window after receiving a publishing in debug mode and then stopping the program.

Another possible way would be to publish the same message the device just received. There are many ways of doing it, but you can take this example code, which modifies what is inside of the PUBLISHING state.

Example code that modifies what is inside of the PUBLISHING state.
 

if (last_received_message!=NULL){             //goes in if there was a new last received message
  equalize_arrays(mqttPublishMsg, last_received_message);  //makes message to be published=received message
  app_buildPublishPacket();                  //build the packet to be sent
  last_received_message[0]='\0';             //deletes the first character of  last_received_message, so next time, won't detect it as a new message
   }
   else{                                      //if no new received message
   app_buildPublishPacket();                  //simply build the packet to be sent
   }

This way, when you send a message using MyMQTT, you can see how the broker receives it. This message is then sent to all devices that are subscribed to a specific topic. Similarly, when the AVR-IoT WG (a specific device in the network) sends a message, it is also received by the broker. This message is then sent out to all devices that are subscribed to the topic "mchp/iot/events". So, in essence, the broker's job is to receive messages and then distribute them to the right devices based on their topic subscriptions.
 

MyMQTT view:  Broker receive and publish messages

Nothing to Process

As said above, in the last paragraph of the Write Code for Processing Received Packets section, the last_received_header.controlPacketType variable will remain the same until a different packet is received. If you want your program to do something when no packet is received, you can write in MQTT_ReceptionHandler()’s declaration in mqtt_core, right before switch(mqttState), where nothing has been written yet.

Location in code to perform action if no packet is recieved

Back to Top