Subscribing to Topics in MQTT

Last modified by Microchip on 2023/11/10 11:11

As you may know, for receiving data in MQTT your device needs to be subscribed to a topic. To do that, you will need to send a subscribe packet to your broker. For app_mqttExampleInit(),  you need to create a subscribe packet, and then execute MQTT_TransmissionHandler(mqttConnnectionInfo) to send it.

Create Subscribe Packet

In the generated example, there’s no function for creating a subscribe packet. So, instead, you can copy this one at the top of mqtt_example.c:

void create_MQTT_subscribe_packet(char *topic)
{
mqttSubscribePacket subscribe_packet;
   //fill the whole packet with 0:
   memset(&subscribe_packet, 0, sizeof(mqttSubscribePacket));
    subscribe_packet.subscribePayload->topic = topic;
    subscribe_packet.subscribePayload->topicLength = strlen(subscribe_packet.subscribePayload->topic);
    subscribe_packet.subscribePayload->requestedQoS = 0;
  
    subscribe_packet.packetIdentifierLSB = 1;
    subscribe_packet.packetIdentifierMSB = 0;
  
    MQTT_CreateSubscribePacket(&subscribe_packet);
}

This function just sets the parameters for the MQTT_CreateSubscribePacket() function, which will set the needed variables for creating a Subscribe packet to be sent. The only variable that you will need to choose is “topic”, which will be the topic that you want to subscribe to.

Back to Top

Send Subscribe Packet

Write these two lines in the SUBSCRIBING state for sending subscribe packets:

create_MQTT_subscribe_packet(t);
MQTT_TransmissionHandler(mqttConnnectionInfo);

Code View of SUBSCRIBING case

Then declare “t” as an array of uint8_t elements in mqtt_example.c. “t” will be the name of the topic that the device will subscribe to. For example:

uint8_t t[] = "subscribing/topic";

Declare “t” as an array of uint8_t elements in mqtt_example.c

Your device should now continuously subscribe, but you are making too many attempts. At some time, your program should collapse. This is explained in the next section.

Back to Top

Subscribe Just Once

It is recommended to only subscribe once. Doing it more than once would be useless unless you want to subscribe to different topics. Also, it is recommended to wait until the device has initialized everything, otherwise, it may not work.

Every time that you subscribe, you receive a Suback packet. You will need to process the Suback packet. This is explained in the next section, “Add receiving, processing and reading packets”. If you don’t process the Suback, the program won’t create more subscribe packets, and your program will end up collapsing. Try to execute the program to see what happens by yourself. You should see this if you are using Eclipse Mosquitto™:
Mosquitto Messages                                                 

The solution is to subscribe just once per topic, once the program has been fully initialized, and then receive and process the Suback packet. Once Suback has been processed, the program will try to subscribe again. You can add some lines to avoid it. Subscribing more than once to the same topic or subscribing before the program has been fully initialized shouldn’t be harmful, but the program would be more likely to crash.

In this example, to measure if the program is fully initialized, we create the only_once variable, where we would save how many times appMQTTPublishTimeoutOccured was true. This is, how many times the timer has been completed. When only_once is 3, this is, when the timer has been completed three times, we consider that the device is fully initialized and subscribed.

Create only_once variable

uint8_t only_once=0;        //counts how many times the timer was completed
 

Code View which counts number of times the timer was completed

case SUBSCRIBING:
{
   if(appMQTTPublishTimeoutOccured == true)   //checks if timer was completed
   {   
        only_once++;        //counts how many times the timer was completed
       if (only_once==3){  //if timer was completed 3 times, subscribe
       create_MQTT_subscribe_packet(t);
            MQTT_TransmissionHandler(mqttConnnectionInfo);
            only_once=4; //to avoid only_once overflow and reset to be 3 again
       }
    }
    changeState(PUBLISHING);
}

The final state should be like the command prompt showed before, but without the client being disconnected:

Command Prompt showing New Connection

Back to Top