/* * coreMQTT Agent v1.2.0 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * @file core_mqtt_agent.h * @brief Functions for running a coreMQTT client in a dedicated thread. */ #ifndef CORE_MQTT_AGENT_H #define CORE_MQTT_AGENT_H /* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif /* *INDENT-ON* */ /* MQTT library includes. */ #include "core_mqtt.h" #include "core_mqtt_state.h" #include "core_mqtt_agent_config_defaults.h" /* Command messaging interface include. */ #include "core_mqtt_agent_message_interface.h" /** * @ingroup mqtt_agent_enum_types * @brief A type of command for interacting with the MQTT API. */ typedef enum MQTTCommandType { 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(). */ CONNECT, /**< @brief Call MQTT_Connect(). */ DISCONNECT, /**< @brief Call MQTT_Disconnect(). */ TERMINATE, /**< @brief Exit the command loop and stop processing commands. */ NUM_COMMANDS /**< @brief The number of command types handled by the agent. */ } MQTTAgentCommandType_t; struct MQTTAgentContext; struct MQTTAgentCommandContext; /** * @ingroup mqtt_agent_struct_types * @brief Struct holding return codes and outputs from a command */ typedef struct MQTTAgentReturnInfo { MQTTStatus_t returnCode; /**< Return code of the MQTT command. */ uint8_t * pSubackCodes; /**< Array of SUBACK statuses, for a SUBSCRIBE command. */ } MQTTAgentReturnInfo_t; /** * @ingroup mqtt_agent_struct_types * @brief Struct containing context for a specific command. * * @note An instance of this struct and any variables it points to MUST stay * in scope until the associated command is processed, and its callback called. */ typedef struct MQTTAgentCommandContext MQTTAgentCommandContext_t; /** * @ingroup mqtt_agent_callback_types * @brief Callback function called when a command completes. * * @param[in] pCmdCallbackContext The callback context passed to the original command. * @param[in] pReturnInfo A struct of status codes and outputs from the command. * * @note A command should not be considered complete until this callback is * called, and the arguments that the command uses MUST stay in scope until such happens. * * @note The callback MUST NOT block as it runs in the context of the MQTT agent * task. If the callback calls any MQTT Agent API to enqueue a command, the * blocking time (blockTimeMs member of MQTTAgentCommandInfo_t) MUST be zero. If the * application wants to enqueue command(s) with non-zero blocking time, the * callback can notify a different task to enqueue command(s) to the MQTT agent. */ typedef void (* MQTTAgentCommandCallback_t )( MQTTAgentCommandContext_t * pCmdCallbackContext, MQTTAgentReturnInfo_t * pReturnInfo ); /** * @ingroup mqtt_agent_struct_types * @brief The commands sent from the APIs to the MQTT agent task. * * @note The structure used to pass information from the public facing API into the * agent task. */ struct MQTTAgentCommand { MQTTAgentCommandType_t commandType; /**< @brief Type of command. */ void * pArgs; /**< @brief Arguments of command. */ MQTTAgentCommandCallback_t pCommandCompleteCallback; /**< @brief Callback to invoke upon completion. */ MQTTAgentCommandContext_t * pCmdContext; /**< @brief Context for completion callback. */ }; /** * @ingroup mqtt_agent_struct_types * @brief Information for a pending MQTT ack packet expected by the agent. */ typedef struct MQTTAckInfo { uint16_t packetId; /**< Packet ID of the pending acknowledgment. */ MQTTAgentCommand_t * pOriginalCommand; /**< Command expecting acknowledgment. */ } MQTTAgentAckInfo_t; /** * @ingroup mqtt_agent_callback_types * @brief Callback function called when receiving a publish. * * @param[in] pMqttAgentContext The context of the MQTT agent. * @param[in] packetId The packet ID of the received publish. * @param[in] pPublishInfo Deserialized publish information. * * @note The callback MUST NOT block as it runs in the context of the MQTT agent * task. If the callback calls any MQTT Agent API to enqueue a command, the * blocking time (blockTimeMs member of MQTTAgentCommandInfo_t) MUST be zero. If the * application wants to enqueue command(s) with non-zero blocking time, the * callback can notify a different task to enqueue command(s) to the MQTT agent. */ typedef void (* MQTTAgentIncomingPublishCallback_t )( struct MQTTAgentContext * pMqttAgentContext, uint16_t packetId, MQTTPublishInfo_t * pPublishInfo ); /** * @ingroup mqtt_agent_struct_types * @brief Information used by each MQTT agent. A context will be initialized by * MQTTAgent_Init(), and every API function will accept a pointer to the * initalized struct. */ typedef struct MQTTAgentContext { MQTTContext_t mqttContext; /**< MQTT connection information used by coreMQTT. */ MQTTAgentMessageInterface_t agentInterface; /**< Struct of function pointers for agent messaging. */ MQTTAgentAckInfo_t pPendingAcks[ MQTT_AGENT_MAX_OUTSTANDING_ACKS ]; /**< List of pending acknowledgment packets. */ MQTTAgentIncomingPublishCallback_t pIncomingCallback; /**< Callback to invoke for incoming publishes. */ void * pIncomingCallbackContext; /**< Context for incoming publish callback. */ bool packetReceivedInLoop; /**< Whether a MQTT_ProcessLoop() call received a packet. */ } MQTTAgentContext_t; /** * @ingroup mqtt_agent_struct_types * @brief Struct holding arguments for a SUBSCRIBE or UNSUBSCRIBE call. */ typedef struct MQTTAgentSubscribeArgs { MQTTSubscribeInfo_t * pSubscribeInfo; /**< @brief List of MQTT subscriptions. */ size_t numSubscriptions; /**< @brief Number of elements in `pSubscribeInfo`. */ } MQTTAgentSubscribeArgs_t; /** * @ingroup mqtt_agent_struct_types * @brief Struct holding arguments for a CONNECT call. */ typedef struct MQTTAgentConnectArgs { MQTTConnectInfo_t * pConnectInfo; /**< @brief MQTT CONNECT packet information. */ MQTTPublishInfo_t * pWillInfo; /**< @brief Optional Last Will and Testament. */ uint32_t timeoutMs; /**< @brief Maximum timeout for a CONNACK packet. */ bool sessionPresent; /**< @brief Output flag set if a previous session was present. */ } MQTTAgentConnectArgs_t; /** * @ingroup mqtt_agent_struct_types * @brief Struct holding arguments that are common to every command. */ typedef struct MQTTAgentCommandInfo { MQTTAgentCommandCallback_t cmdCompleteCallback; /**< @brief Callback to invoke upon completion. */ MQTTAgentCommandContext_t * pCmdCompleteCallbackContext; /**< @brief Context for completion callback. */ uint32_t blockTimeMs; /**< @brief Maximum block time for enqueueing the command. */ } MQTTAgentCommandInfo_t; /*-----------------------------------------------------------*/ /** * @brief Perform any initialization the MQTT agent requires before it can * be used. Must be called before any other function. * * @param[in] pMqttAgentContext Pointer to struct to initialize. * @param[in] pMsgInterface Command interface to use for allocating and sending commands. * @param[in] pNetworkBuffer Pointer to network buffer to use. * @param[in] pTransportInterface Transport interface to use with the MQTT * library. See https://www.freertos.org/network-interface.html * @param[in] getCurrentTimeMs Pointer to a function that returns a count value * that increments every millisecond. * @param[in] incomingCallback The callback to execute when receiving publishes. * @param[in] pIncomingPacketContext A pointer to a context structure defined by * the application writer. * * @note The @p pIncomingPacketContext context provided for the incoming publish * callback MUST remain in scope throughout the period that the agent task is running. * * @return Appropriate status code from MQTT_Init(). * * Example * @code{c} * * // Function for obtaining a timestamp. * uint32_t getTimeStampMs(); * // Callback function for receiving packets. * void incomingPublishCallback( MQTTAgentContext_t * pMqttAgentContext, * uint16_t packetId, * MQTTPublishInfo_t * pPublishInfo ); * // Platform function for network send interface. * int32_t networkSend( NetworkContext_t * pContext, const void * pBuffer, size_t bytes ); * // Platform for network receive interface. * int32_t networkRecv( NetworkContext_t * pContext, void * pBuffer, size_t bytes ); * * // Platform function for Agent Message Send. * bool agentSendMessage( MQTTAgentMessageContext_t * pMsgCtx, * MQTTAgentCommand_t * const * pCommandToSend, * uint32_t blockTimeMs ); * // Platform function for Agent Message Receive. * bool agentReceiveMessage( MQTTAgentMessageContext_t * pMsgCtx, * MQTTAgentCommand_t ** pCommandToSend, * uint32_t blockTimeMs ); * // Platform function to Get Agent Command. * MQTTAgentCommand_t * getCommand( uint32_t blockTimeMs ); * // Platform function to Release Agent Command. * bool releaseCommand( MQTTAgentCommand_t * pCommandToRelease ); * * // Variables used in this example. * MQTTAgentMessageInterface_t messageInterface; * MQTTAgentMessageContext_t messageContext; * MQTTAgentContext_t agentContext; * TransportInterface_t transport; * // Buffer for storing outgoing and incoming MQTT packets. * MQTTFixedBuffer_t fixedBuffer; * uint8_t buffer[ 1024 ]; * MQTTStatus_t status; * * // Set transport interface members. * transport.pNetworkContext = &someTransportContext; * transport.send = networkSend; * transport.recv = networkRecv; * * // Set agent message interface members. * messageInterface.pMsgCtx = &messageContext; * messageInterface.send = agentSendMessage; * messageInterface.recv = agentReceiveMessage; * messageInterface.getCommand = getCommand; * messageInterface.releaseCommand = releaseCommand; * * // Set buffer members. * fixedBuffer.pBuffer = buffer; * fixedBuffer.size = 1024; * * status = MQTTAgent_Init( &agentContext, * &messageInterface, * &networkBuffer, * &transportInterface, * stubGetTime, * stubPublishCallback, * incomingPacketContext ); * * if( status == MQTTSuccess ) * { * // Do something with agentContext. The transport and message interfaces, and * // fixedBuffer structs were copied into the context, so the original structs * // do not need to stay in scope. * } * @endcode */ /* @[declare_mqtt_agent_init] */ MQTTStatus_t MQTTAgent_Init( MQTTAgentContext_t * pMqttAgentContext, const MQTTAgentMessageInterface_t * pMsgInterface, const MQTTFixedBuffer_t * pNetworkBuffer, const TransportInterface_t * pTransportInterface, MQTTGetCurrentTimeFunc_t getCurrentTimeMs, MQTTAgentIncomingPublishCallback_t incomingCallback, void * pIncomingPacketContext ); /* @[declare_mqtt_agent_init] */ /** * @brief Process commands from the command queue in a loop. * * @param[in] pMqttAgentContext The MQTT agent to use. * * @return appropriate error code, or #MQTTSuccess from a successful disconnect * or termination. * * Example * @code{c} * * // Variables used in this example. * MQTTStatus_t status; * MQTTAgentContext_t mqttAgentContext; * * status = MQTTAgent_CommandLoop( &mqttAgentContext ); * * // The function returns on either receiving a terminate command, * // undergoing network disconnection OR encountering an error. * if( ( status == MQTTSuccess ) && ( mqttAgentContext.mqttContext.connectStatus == MQTTNotConnected ) ) * { * // A terminate command was processed and MQTT connection was closed. * // Need to close socket connection. * Platform_DisconnectNetwork( mqttAgentContext.mqttContext.transportInterface.pNetworkContext ); * } * else if( status == MQTTSuccess ) * { * // Terminate command was processed but MQTT connection was not * // closed. Thus, need to close both MQTT and socket connections. * status = MQTT_Disconnect( &( mqttAgentContext.mqttContext ) ); * assert( status == MQTTSuccess ); * Platform_DisconnectNetwork( mqttAgentContext.mqttContext.transportInterface.pNetworkContext ); * } * else * { * // Handle error. * } * * @endcode */ /* @[declare_mqtt_agent_commandloop] */ MQTTStatus_t MQTTAgent_CommandLoop( MQTTAgentContext_t * pMqttAgentContext ); /* @[declare_mqtt_agent_commandloop] */ /** * @brief Resume a session by resending publishes if a session is present in * the broker, or clear state information if not. * * @param[in] pMqttAgentContext The MQTT agent to use. * @param[in] sessionPresent The session present flag from the broker. * * @note This function is NOT thread-safe and should only be called * from the context of the task responsible for #MQTTAgent_CommandLoop. * * @return #MQTTSuccess if it succeeds in resending publishes, else an * appropriate error code from `MQTT_Publish()` * * Example * @code{c} * * // Variables used in this example. * MQTTStatus_t status; * MQTTAgentContext_t mqttAgentContext; * MQTTConnectInfo_t connectInfo = { 0 }; * MQTTPublishInfo_t willInfo = { 0 }; * bool sessionPresent; * * // The example assumes that all variables have been filled with * // data for the MQTT_Connect call * // Refer to the MQTT_Connect API for a more detailed example. * * // Attempt to resume session with the broker. * status = MQTT_Connect( &( mqttAgentContext.mqttContext ), &connectInfo, &willInfo, 100, &sessionPresent ) * * if( status == MQTTSuccess ) * { * // Process the session present status sent by the broker. * status = MQTTAgent_ResumeSession( &mqttAgentContext, sessionPresent ); * } * @endcode */ /* @[declare_mqtt_agent_resumesession] */ MQTTStatus_t MQTTAgent_ResumeSession( MQTTAgentContext_t * pMqttAgentContext, bool sessionPresent ); /* @[declare_mqtt_agent_resumesession] */ /** * @brief Cancel all enqueued commands and those awaiting acknowledgment * while the command loop is not running. * * Canceled commands will be terminated with return code #MQTTRecvFailed. * * @param[in] pMqttAgentContext The MQTT agent to use. * * @note This function is NOT thread-safe and should only be called * from the context of the task responsible for #MQTTAgent_CommandLoop. * * @return #MQTTBadParameter if an invalid context is given, else #MQTTSuccess. * * Example * @code{c} * * // Variables used in this example. * MQTTStatus_t status; * MQTTAgentContext_t mqttAgentContext; * * status = MQTTAgent_CommandLoop( &mqttAgentContext ); * * //An error was returned, but reconnection is not desired. Cancel all commands * //that are in the queue or awaiting an acknowledgment. * if( status != MQTTSuccess ) * { * //Cancel commands so any completion callbacks will be invoked. * status = MQTTAgent_CancelAll( &mqttAgentContext ); * } * * Platform_DisconnectNetwork( mqttAgentContext.mqttContext.transportInterface.pNetworkContext ); * * @endcode */ /* @[declare_mqtt_agent_cancelall] */ MQTTStatus_t MQTTAgent_CancelAll( MQTTAgentContext_t * pMqttAgentContext ); /* @[declare_mqtt_agent_cancelall] */ /** * @brief Add a command to call MQTT_Subscribe() for an MQTT connection. * * @param[in] pMqttAgentContext The MQTT agent to use. * @param[in] pSubscriptionArgs Struct describing topic to subscribe to. * @param[in] pCommandInfo The information pertaining to the command, including: * - cmdCompleteCallback Optional callback to invoke when the command completes. * - pCmdCompleteCallbackContext Optional completion callback context. * - blockTimeMs The maximum amount of time in milliseconds to wait for the * command to be posted to the MQTT agent, should the agent's event queue * be full. Tasks wait in the Blocked state so don't use any CPU time. * * @note The context passed to the callback through pCmdContext member of * @p pCommandInfo parameter MUST remain in scope at least until the callback * has been executed by the agent task. * * @return #MQTTSuccess if the command was posted to the MQTT agent's event queue. * Otherwise an enumerated error code. * * Example * @code{c} * * // Variables used in this example. * MQTTAgentContext_t agentContext; * MQTTStatus_t status; * MQTTAgentCommandInfo_t commandInfo = { 0 }; * MQTTSubscribeInfo_t subscribeInfo = { 0 }; * MQTTAgentSubscribeArgs_t subscribeArgs = { 0 }; * * // Function for command complete callback. * void subscribeCmdCompleteCb( MQTTAgentCommandContext_t * pCmdCallbackContext, * MQTTAgentReturnInfo_t * pReturnInfo ); * * // Fill the command information. * commandInfo.CmdCompleteCallback = subscribeCmdCompleteCb; * commandInfo.blockTimeMs = 500; * * // Fill the information for topic filters to subscribe to. * subscribeInfo.qos = Qos1; * subscribeInfo.pTopicFilter = "/foo/bar"; * subscribeInfo.topicFilterLength = strlen("/foo/bar"); * subscribeArgs.pSubscribeInfo = &subscribeInfo; * subscribeArgs.numSubscriptions = 1U; * * status = MQTTAgent_Subscribe( &agentContext, &subscribeArgs, &commandInfo ); * * if( status == MQTTSuccess ) * { * // Command to send subscribe request to the server has been queued. Notification * // about completion of the subscribe operation will be notified to application * // through invocation of subscribeCmdCompleteCb(). * } * * @endcode */ /* @[declare_mqtt_agent_subscribe] */ MQTTStatus_t MQTTAgent_Subscribe( const MQTTAgentContext_t * pMqttAgentContext, MQTTAgentSubscribeArgs_t * pSubscriptionArgs, const MQTTAgentCommandInfo_t * pCommandInfo ); /* @[declare_mqtt_agent_subscribe] */ /** * @brief Add a command to call MQTT_Unsubscribe() for an MQTT connection. * * @param[in] pMqttAgentContext The MQTT agent to use. * @param[in] pSubscriptionArgs List of topics to unsubscribe from. * @param[in] pCommandInfo The information pertaining to the command, including: * - cmdCompleteCallback Optional callback to invoke when the command completes. * - pCmdCompleteCallbackContext Optional completion callback context. * - blockTimeMs The maximum amount of time in milliseconds to wait for the * command to be posted to the MQTT agent, should the agent's event queue * be full. Tasks wait in the Blocked state so don't use any CPU time. * * @note The context passed to the callback through pCmdContext member of * @p pCommandInfo parameter MUST remain in scope at least until the callback * has been executed by the agent task. * * @return #MQTTSuccess if the command was posted to the MQTT agent's event queue. * Otherwise an enumerated error code. * * Example * @code{c} * * // Variables used in this example. * MQTTAgentContext_t agentContext; * MQTTStatus_t status; * MQTTAgentCommandInfo_t commandInfo = { 0 }; * MQTTSubscribeInfo_t unsubscribeInfo = { 0 }; * MQTTAgentSubscribeArgs_t unsubscribeArgs = { 0 }; * * // Function for command complete callback. * void unsubscribeCmdCompleteCb( MQTTAgentCommandContext_t * pCmdCallbackContext, * MQTTAgentReturnInfo_t * pReturnInfo ); * * // Fill the command information. * commandInfo.cmdCompleteCallback = unsubscribeCmdCompleteCb; * commandInfo.blockTimeMs = 500; * * // Fill the information for topics to unsubscribe from. * unsubscribeInfo.pTopicFilter = "/foo/bar"; * unsubscribeInfo.topicFilterLength = strlen("/foo/bar"); * unsubscribeArgs.pSubscribeInfo = &unsubscribeInfo; * unsubscribeArgs.numSubscriptions = 1U; * * status = MQTTAgent_Unsubscribe( &agentContext, &unsubscribeArgs, &commandInfo ); * * if( status == MQTTSuccess ) * { * // Command to send Unsubscribe request to the server has been queued. Notification * // about completion of the Unsubscribe operation will be notified to application * // through invocation of unsubscribeCompleteCb(). * } * * @endcode */ /* @[declare_mqtt_agent_unsubscribe] */ MQTTStatus_t MQTTAgent_Unsubscribe( const MQTTAgentContext_t * pMqttAgentContext, MQTTAgentSubscribeArgs_t * pSubscriptionArgs, const MQTTAgentCommandInfo_t * pCommandInfo ); /* @[declare_mqtt_agent_unsubscribe] */ /** * @brief Add a command to call MQTT_Publish() for an MQTT connection. * * @param[in] pMqttAgentContext The MQTT agent to use. * @param[in] pPublishInfo MQTT PUBLISH information. * @param[in] pCommandInfo The information pertaining to the command, including: * - cmdCompleteCallback Optional callback to invoke when the command completes. * - pCmdCompleteCallbackContext Optional completion callback context. * - blockTimeMs The maximum amount of time in milliseconds to wait for the * command to be posted to the MQTT agent, should the agent's event queue * be full. Tasks wait in the Blocked state so don't use any CPU time. * * @note The context passed to the callback through pCmdContext member of * @p pCommandInfo parameter MUST remain in scope at least until the callback * has been executed by the agent task. * * @return #MQTTSuccess if the command was posted to the MQTT agent's event queue. * Otherwise an enumerated error code. * * Example * @code{c} * * // Variables used in this example. * MQTTAgentContext_t agentContext; * MQTTStatus_t status; * MQTTAgentCommandInfo_t commandInfo = { 0 }; * MQTTPublishInfo_t publishInfo = { 0 }; * * // Function for command complete callback. * void publishCmdCompleteCb( MQTTAgentCommandContext_t * pCmdCallbackContext, * MQTTAgentReturnInfo_t * pReturnInfo ); * * // Fill the command information. * commandInfo.cmdCompleteCallback = publishCmdCompleteCb; * commandInfo.blockTimeMs = 500; * * // Fill the information for publish operation. * publishInfo.qos = MQTTQoS1; * publishInfo.pTopicName = "/some/topic/name"; * publishInfo.topicNameLength = strlen( publishInfo.pTopicName ); * publishInfo.pPayload = "Hello World!"; * publishInfo.payloadLength = strlen( "Hello World!" ); * * status = MQTTAgent_Publish( &agentContext, &publishInfo, &commandInfo ); * * if( status == MQTTSuccess ) * { * // Command to publish message to broker has been queued. * // The event of publish operation completion will be notified with * // the invocation of the publishCmdCompleteCb(). * } * * @endcode */ /* @[declare_mqtt_agent_publish] */ MQTTStatus_t MQTTAgent_Publish( const MQTTAgentContext_t * pMqttAgentContext, MQTTPublishInfo_t * pPublishInfo, const MQTTAgentCommandInfo_t * pCommandInfo ); /* @[declare_mqtt_agent_publish] */ /** * @brief Send a message to the MQTT agent purely to trigger an iteration of its loop, * which will result in a call to MQTT_ProcessLoop(). This function can be used to * wake the MQTT agent task when it is known data may be available on the connected * socket. * * @param[in] pMqttAgentContext The MQTT agent to use. * @param[in] pCommandInfo The information pertaining to the command, including: * - cmdCompleteCallback Optional callback to invoke when the command completes. * - pCmdCompleteCallbackContext Optional completion callback context. * - blockTimeMs The maximum amount of time in milliseconds to wait for the * command to be posted to the MQTT agent, should the agent's event queue * be full. Tasks wait in the Blocked state so don't use any CPU time. * * @return #MQTTSuccess if the command was posted to the MQTT agent's event queue. * Otherwise an enumerated error code. * * Example * @code{c} * * // Variables used in this example. * MQTTAgentContext_t agentContext; * MQTTStatus_t status; * MQTTAgentCommandInfo_t commandInfo = { 0 }; * * // Function for command complete callback. * void cmdCompleteCb( MQTTAgentCommandContext_t * pCmdCallbackContext, * MQTTAgentReturnInfo_t * pReturnInfo ); * * // Fill the command information. * commandInfo.cmdCompleteCallback = cmdCompleteCb; * commandInfo.blockTimeMs = 500; * * status = MQTTAgent_ProcessLoop( &agentContext, &commandInfo ); * * if( status == MQTTSuccess ) * { * // Command to call MQTT_ProcessLoop() has been queued. * // After processing the command, if an incoming publish is received, * // the event will be notified with invocation of the incoming publish * // callback configured in the agent context. * } * * @endcode */ /* @[declare_mqtt_agent_processloop] */ MQTTStatus_t MQTTAgent_ProcessLoop( const MQTTAgentContext_t * pMqttAgentContext, const MQTTAgentCommandInfo_t * pCommandInfo ); /* @[declare_mqtt_agent_processloop] */ /** * @brief Add a command to call MQTT_Ping() for an MQTT connection. * * @note This API function ONLY enqueues a command to send a ping request to the server, * and DOES NOT wait for a ping response to be received from the server. To detect whether * a Ping Response, has not been received from the server, the @ref MQTTAgent_CommandLoop * function SHOULD be used, which returns the #MQTTKeepAliveTimeout return code on a ping * response (or keep-alive) timeout. * * @param[in] pMqttAgentContext The MQTT agent to use. * @param[in] pCommandInfo The information pertaining to the command, including: * - cmdCompleteCallback Optional callback to invoke when the command completes. * - pCmdCompleteCallbackContext Optional completion callback context. * - blockTimeMs The maximum amount of time in milliseconds to wait for the * command to be posted to the MQTT agent, should the agent's event queue * be full. Tasks wait in the Blocked state so don't use any CPU time. * * @note The context passed to the callback through pCmdContext member of * @p pCommandInfo parameter MUST remain in scope at least until the callback * has been executed by the agent task. * * @return #MQTTSuccess if the command was posted to the MQTT agent's event queue. * Otherwise an enumerated error code. * * Example * @code{c} * * // Variables used in this example. * MQTTAgentContext_t agentContext; * MQTTStatus_t status; * MQTTAgentCommandInfo_t commandInfo = { 0 }; * * // Function for command complete callback. * void pingRequestCompleteCb( MQTTAgentCommandContext_t * pCmdCallbackContext, * MQTTAgentReturnInfo_t * pReturnInfo ); * * // Fill the command information. * commandInfo.cmdCompleteCallback = pingRequestCompleteCb; * commandInfo.blockTimeMs = 500; * * status = MQTTAgent_Ping( &agentContext, &commandInfo ); * * if( status == MQTTSuccess ) * { * // Command for sending request has been queued. Application can * // handle keep-alive timeout if detected through return value of * // MQTTAgent_CommandLoop in the task running the agent. * } * * @endcode */ /* @[declare_mqtt_agent_ping] */ MQTTStatus_t MQTTAgent_Ping( const MQTTAgentContext_t * pMqttAgentContext, const MQTTAgentCommandInfo_t * pCommandInfo ); /* @[declare_mqtt_agent_ping] */ /** * @brief Add a command to call MQTT_Connect() for an MQTT connection. If a session * is resumed with the broker, it will also resend the necessary QoS1/2 publishes. * * @note The MQTTAgent_Connect function is provided to give a thread safe equivalent * to the MQTT_Connect API. However, it is RECOMMENDED that instead of the application * tasks (i.e. tasks other than the agent task), the agent be responsible for creating * the MQTT connection (by calling MQTT_Connect) before starting the command loop (with * the MQTTAgent_CommandLoop() call). In that case, the agent SHOULD also be responsible * for disconnecting the MQTT connection after the command loop has terminated (through * an MQTTAgent_Terminate() call from an application task). * * @param[in] pMqttAgentContext The MQTT agent to use. * @param[in, out] pConnectArgs Struct holding args for MQTT_Connect(). On a successful * connection after the command is processed, the sessionPresent member will be filled * to indicate whether the broker resumed an existing session. * @param[in] pCommandInfo The information pertaining to the command, including: * - cmdCompleteCallback Optional callback to invoke when the command completes. * - pCmdCompleteCallbackContext Optional completion callback context. * - blockTimeMs The maximum amount of time in milliseconds to wait for the * command to be posted to the MQTT agent, should the agent's event queue * be full. Tasks wait in the Blocked state so don't use any CPU time. * * @note The context passed to the callback through pCmdContext member of * @p pCommandInfo parameter MUST remain in scope at least until the callback * has been executed by the agent task. * * @return #MQTTSuccess if the command was posted to the MQTT agent's event queue. * Otherwise an enumerated error code. * * Example * @code{c} * * // Variables used in this example. * MQTTAgentContext_t agentContext; * MQTTStatus_t status; * MQTTConnectInfo_t connectInfo = { 0 }; * MQTTPublishInfo_t willInfo = { 0 }; * MQTTAgentConnectArgs_t connectionArgs; * MQTTAgentCommandInfo_t commandInfo = { 0 }; * * // True for creating a new session with broker, false if we want to resume an old one. * connectInfo.cleanSession = true; * // Client ID must be unique to broker. This field is required. * connectInfo.pClientIdentifier = "someClientID"; * connectInfo.clientIdentifierLength = strlen( connectInfo.pClientIdentifier ); * * // Value for keep alive. * connectInfo.keepAliveSeconds = 60; * // The following fields are optional. * // Optional username and password. * connectInfo.pUserName = "someUserName"; * connectInfo.userNameLength = strlen( connectInfo.pUserName ); * connectInfo.pPassword = "somePassword"; * connectInfo.passwordLength = strlen( connectInfo.pPassword ); * * // The last will and testament is optional, it will be published by the broker * // should this client disconnect without sending a DISCONNECT packet. * willInfo.qos = MQTTQoS0; * willInfo.pTopicName = "/lwt/topic/name"; * willInfo.topicNameLength = strlen( willInfo.pTopicName ); * willInfo.pPayload = "LWT Message"; * willInfo.payloadLength = strlen( "LWT Message" ); * * // Fill the MQTTAgentConnectArgs_t structure. * connectArgs.pConnectInfo = &connectInfo; * connectArgs.pWillInfo = &willInfo; * // Time to block for CONNACK response when command is processed. * connectArgs.timeoutMs = 500; * * // Function for command complete callback. * void connectCmdCallback( MQTTAgentCommandContext_t * pCmdCallbackContext, * MQTTAgentReturnInfo_t * pReturnInfo ); * * // Fill the command information. * commandInfo.cmdCompleteCallback = connectCmdCallback; * commandInfo.blockTimeMs = 500; * * status = MQTTAgent_Connect( &agentContext, &connectArgs, &commandInfo ); * * if( status == MQTTSuccess ) * { * // Command for creating the MQTT connection has been queued. * // The MQTT connection event will be notified through the * // invocation of connectCmdCallback(). * } * @endcode */ /* @[declare_mqtt_agent_connect] */ MQTTStatus_t MQTTAgent_Connect( const MQTTAgentContext_t * pMqttAgentContext, MQTTAgentConnectArgs_t * pConnectArgs, const MQTTAgentCommandInfo_t * pCommandInfo ); /* @[declare_mqtt_agent_connect] */ /** * @brief Add a command to disconnect an MQTT connection. * * @note #MQTTAgent_CommandLoop will return after processing a #DISCONNECT * command to allow the network connection to be disconnected. However, any * pending commands in the queue, as well as those waiting for an acknowledgment, * will NOT be terminated. * * @note The MQTTAgent_Disconnect function is provided to give a thread safe * equivalent to the MQTT_Disconnect API. However, if the agent task is responsible * for creating the MQTT connection (before calling MQTTAgent_CommandLoop()), then * it is RECOMMENDED that an application task (i.e. a task other than the agent task) * use MQTTAgent_Terminate to terminate the command loop in the agent, and the agent * task be responsible for disconnecting the MQTT connection. * * @param[in] pMqttAgentContext The MQTT agent to use. * @param[in] pCommandInfo The information pertaining to the command, including: * - cmdCompleteCallback Optional callback to invoke when the command completes. * - pCmdCompleteCallbackContext Optional completion callback context. * - blockTimeMs The maximum amount of time in milliseconds to wait for the * command to be posted to the MQTT agent, should the agent's event queue * be full. Tasks wait in the Blocked state so don't use any CPU time. * * @note The context passed to the callback through pCmdContext member of * @p pCommandInfo parameter MUST remain in scope at least until the callback * has been executed by the agent task. * * @return #MQTTSuccess if the command was posted to the MQTT agent's event queue. * Otherwise an enumerated error code. * * Example * @code{c} * * // Variables used in this example. * MQTTAgentContext_t agentContext; * MQTTStatus_t status; * MQTTAgentCommandInfo_t commandInfo = { 0 }; * * // Function for command complete callback. * void disconnectCmdCallback( MQTTAgentCommandContext_t * pCmdCallbackContext, * MQTTAgentReturnInfo_t * pReturnInfo ); * * // Fill the command information. * commandInfo.cmdCompleteCallback = disconnectCmdCallback; * commandInfo.blockTimeMs = 500; * * status = MQTTAgent_Disconnect( &agentContext, &commandInfo ); * * if( status == MQTTSuccess ) * { * // Command for closing the MQTT connection has been queued. * // The MQTT disconnection event will be notified through the * // invocation of disconnectCmdCallback(). * } * * @endcode */ /* @[declare_mqtt_agent_disconnect] */ MQTTStatus_t MQTTAgent_Disconnect( const MQTTAgentContext_t * pMqttAgentContext, const MQTTAgentCommandInfo_t * pCommandInfo ); /* @[declare_mqtt_agent_disconnect] */ /** * @brief Add a termination command to the command queue. * * On command loop termination, all pending commands in the queue, as well * as those waiting for an acknowledgment, will be terminated with error code * #MQTTRecvFailed. * * @note Commands may still be posted to the command queue after #MQTTAgent_CommandLoop * has returned. It is the responsibility of the application to cancel any * commands that are posted while the command loop is not running, such as by * invoking #MQTTAgent_CancelAll. * * @note We RECOMMEND that this function is used from application task(s), * that is a task not running the agent, to terminate the agent loop instead * of calling MQTTAgent_Disconnect, so that the logic for creating and closing * MQTT connection is owned by the agent task. * * @param[in] pMqttAgentContext The MQTT agent to use. * @param[in] pCommandInfo The information pertaining to the command, including: * - cmdCompleteCallback Optional callback to invoke when the command completes. * - pCmdCompleteCallbackContext Optional completion callback context. * - blockTimeMs The maximum amount of time in milliseconds to wait for the * command to be posted to the MQTT agent, should the agent's event queue * be full. Tasks wait in the Blocked state so don't use any CPU time. * * @note The context passed to the callback through pCmdContext member of * @p pCommandInfo parameter MUST remain in scope at least until the callback * has been executed by the agent task. * * @return #MQTTSuccess if the command was posted to the MQTT agent's event queue. * Otherwise an enumerated error code. * * Example * @code{c} * * // Variables used in this example. * MQTTAgentContext_t agentContext; * MQTTStatus_t status; * MQTTAgentCommandInfo_t commandInfo = { 0 }; * * // Function for command complete callback. * void terminateCallback( MQTTAgentCommandContext_t * pCmdCallbackContext, * MQTTAgentReturnInfo_t * pReturnInfo ); * * // Fill the command information. * commandInfo.cmdCompleteCallback = terminateCallback; * commandInfo.blockTimeMs = 500; * * status = MQTTAgent_Terminate( &agentContext, &commandInfo ); * * if( status == MQTTSuccess ) * { * // Command to terminate the agent loop has been queued. * } * * @endcode * */ /* @[declare_mqtt_agent_terminate] */ MQTTStatus_t MQTTAgent_Terminate( const MQTTAgentContext_t * pMqttAgentContext, const MQTTAgentCommandInfo_t * pCommandInfo ); /* @[declare_mqtt_agent_terminate] */ /* *INDENT-OFF* */ #ifdef __cplusplus } #endif /* *INDENT-ON* */ #endif /* CORE_MQTT_AGENT_H */