MQTT_ProcessLoop vs MQTTAgent_CommandLoop (or coreMQTT vs FreeRTOS-Plus-MQTT)

I’m sorry I ask this again but I think my question was lost in the previous question thread (How to get MQTT disconnected callbacks in an application based on the Shadow demo (202011))

I’m a bit confuse regarding the best practice implementation of a shadow handler application where I’m update the shadow based on internal device status changes in parallel to possible asynchronous delta message from the core that origin from user inputs.

I’m porting my existing application FW that is based on 202002, this application creates a global MQTT handler when it starts (using IotMqtt_Connect) and then I handle the various callbacs:

  • MQTT Disconnect messages via disconnectCallback
  • Shadow update messages via AwsIotShadow_SetUpdatedCallback
  • Shadow delta messages via AwsIotShadow_SetDeltaCallback

I also use this global MQTT connection to handle OTA.

Now, when I’m porting to 202012 I need to preserve the main application concept of handling the shadow and the OTA, so my question is, should I use the FreeRTOS-Plus-MQTT as it is in the MQTT agent demo, that is, using the MQTTAgent_CommandLoop as the main MQTT handler in a stand alone task (prvMQTTAgentTask) and handle the rest of shadow and OTA activities in a different tasks?

I’m aware to the fact that FreeRTOS-Plus-MQTT is not officially release yet and I can use the coreMQTT directly (that is using MQTT_ProcessLoop) but I don’t want to restructure the code again in a month or so when the FreeRTOS-Plus-MQTT will be released.

Please advise,

1 Like

Hi @EyalG,

Since you’ve stated you want to handle both Shadow and OTA on the same connection, and it sounds like you want to use separate tasks, I would recommend using the MQTT Agent. The MQTT agent is also more similar to the prior MQTT implementation, since it allows an MQTT connection to be shared amongst multiple tasks. So, it might be easier to port your existing application to the agent.

With that said, the main benefit of the agent code is to allow multiple tasks to use the same MQTT connection. If you do not need to use separate tasks in your application for shadow and OTA, and no other tasks will be using that MQTT connections, then you can just use coreMQTT directly, and it may even be simpler to do so for that case. It depends on your application if a single threaded approach will work or not.

Does this answer your question?

I can take a bad crack at this…

MQTT_ProcessLoop() - a CoreMQTT function that handles the incoming packets/data. This is where the ACKs are received and command callbacks you asked for will trigger from. I forget if this happens right here or not, but it’s the eventual effect. Processes incoming data.

MQTTAgent_CommandLoop() - This is the main task when you use the new Agent (Labs, or RB pet or whatever it is, I suspect this is the Agent going forward, but very new and have no idea). This task will simply check a command queue for things to do next. Those things are

    NONE = 0,    /**< @brief No command received.  Must be zero (its memset() value). */
    PROCESSLOOP, /**< @brief Call MQTT_ProcessLoop(). */
    PUBLISH,     /**< @brief Call MQTT_Publish(). */
    SUBSCRIBE,   /**< @brief Call MQTT_Subscribe(). */
    UNSUBSCRIBE, /**< @brief Call MQTT_Unsubscribe(). */
    PING,        /**< @brief Call MQTT_Ping(). */
    DISCONNECT,  /**< @brief Call MQTT_Disconnect(). */
    FREE,        /**< @brief Remove a mapping from an MQTT Context to the agent. */
    TERMINATE    /**< @brief Exit the command loop and stop processing commands. */

So, this command loop does nothing until you load one of these into it’s command queue. The way that works is calling any of the outgoing Agent functions like MQTTAgent_Publish() or you asking for a ping or connect or etc. Those are outgoing things that will add that. However… That doesn’t mean CommandLoop is all outgoing. The second enum is PROCESSLOOP, which you already know about. The way that PROCESSLOOP is added to that queue is by MQTTAgent_TriggerProcessLoop( mqttexampleMQTT_CONTEXT_HANDLE, 0 );

So what you want is that your network functions that went to CoreMQTT when you set in the inits here (see the connection_manager.c example where the inits are set). That is, your AWS Network will have transport functions send and recv function pointers. What you’ll need is when you know you have incoming data, to call that MQTTAgent_TriggerProcessLoop() to get the PROCESSLOOP command added to that queue. Which will then get to Core’s ProcessLoop() to run and call you recv network function.

For me, and the BLE transport, data comes in over BLE, when it’s assembled, I’ll have to get that data ready (deserialize) and add a call to MQTTAgent_TriggerProcessLoop(), that will “wake” my CommandLoop task up and have CoreMQTT call check my recv function and get that data out of there.

I haven’t made my mind up if this is a system I like or not. I see why some of things are being done the way they are. I have gripes, but overall, it’s complicated to read, but seems like it’ll be fairly fast to execute.

So… It’s not one vs the other. It’s MQTTAgent_CommandLoop() is your Agent task and MQTT_ProcessLoop is the CoreMQTT incoming handler. You pretty much need them both if you’re going to use the Agent.

Hope that helps.

Yes, thank you, this answer my question (so far…), one thing I need to ask is when this MQTT Agent will be release officially? Does the current API I see in the LAB is what I should expect to see going forward?