mirror of
https://github.com/FreeRTOS/FreeRTOS.git
synced 2025-06-18 22:33:36 +08:00
Simplify the mqtt multitasking demo a little (#398)
This commit is contained in:
@ -24,26 +24,44 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Demo for showing use of the managed MQTT API shared between multiple tasks.
|
* This demo shows how to use coreMQTT in a multithreaded environment - it does not
|
||||||
* This demo uses a thread safe queue to hold commands for interacting with the
|
* yet go as far as encapsulating the MQTT library within its own agent (or daemon)
|
||||||
* MQTT API. There are four tasks to note in this demo:
|
* task - although the prvCommandLoop() function demonstrates how that might be done.
|
||||||
* - A command (main) task for processing commands from the command queue while
|
* In this task prvCommandLoop() is only executed from a single thread and is the
|
||||||
* other tasks enqueue them. This task enters a loop, during which it processes
|
* only function that is allowed to use the coreMQTT API directly. Anything else
|
||||||
* commands from the command queue. If a termination command is received, it
|
* needing to interact with the coreMQTT API does so by posting commands to
|
||||||
* will break from the loop.
|
* prvCommandLoop() via a queue. Future coreMQTT releases will build an agent into
|
||||||
* - A publisher task for synchronous publishes. This task creates a series of
|
* the library itself, and then encapsulate the queues into the implementation of a
|
||||||
* publish operations to push to the command queue, which are then executed
|
* thread safe coreMQTT API.
|
||||||
* by the command task. This task uses synchronous publishes, meaning it will
|
*
|
||||||
* wait for each publish to complete before scheduling the next one.
|
* To use this demo with TLS set democonfigUSE_TLS to 1. To use this demo without
|
||||||
* - A publisher task for asynchronous publishes. The difference between this
|
* TLS (so plain text) set democonfigUSE_TLS to 0. democonfigUSE_TLS is defined
|
||||||
* task and the previous is that it will not wait for completion before
|
* in demo_config.h.
|
||||||
* scheduling the next publish, and checks them after all publishes have been
|
*
|
||||||
* enqueued. Note that the distinction between synchronous and asynchronous
|
*!!! Plain text connections are only used for ease of demonstration. Do not send
|
||||||
* publishes is only in the behavior of the task, not in the actual publish
|
*!!! sensitive data on unencrypted connections. Production devices should used
|
||||||
* command.
|
*!!! mutually authenticated and encrypted connections.
|
||||||
* - A subscriber task that creates an MQTT subscription to a topic filter
|
*
|
||||||
* matching the topics published on by the publishers. It loops while waiting
|
* There are four tasks to note in this demo:
|
||||||
* for publish messages to be received.
|
* - prvMQTTDemoTask() manages multiple iterations of the demo. Each iteration
|
||||||
|
* creates the other tasks, calls prvCommandLoop() to handle the MQTT traffic,
|
||||||
|
* then cleans up ready for the next iteration.
|
||||||
|
* - prvSyncPublishTask() which demonstrates synchronous publishes. The task creates
|
||||||
|
* a series of publish operations that are sent over the command queue to be
|
||||||
|
* processed by prvCommandLoop(), waiting for each publish to complete before
|
||||||
|
* sending the next.
|
||||||
|
* - prvAsyncPublishTask() which demonstrates asynchronous publishes. Like
|
||||||
|
* prvSyncPublishTask(), the task creates a series of publish operations that are
|
||||||
|
* sent over the command queue to be processed by prvCommandLoop(), but unlike
|
||||||
|
* prvSyncPublishTask() this task does not wait for each publish to be complete
|
||||||
|
* until after all the publish commands are sent. Note that the distinction
|
||||||
|
* between synchronous and asynchronous publishes is only in the behavior of the
|
||||||
|
* task, not in the actual publish command.
|
||||||
|
* - prvSubscribeTask() which creates an MQTT subscription to a topic filter
|
||||||
|
* matching the topics published on by the two publishing tasks, and in doing so,
|
||||||
|
* ensures the demo received a publish command back for each publish command it
|
||||||
|
* sends. It loops while waiting for publish messages to be received.
|
||||||
|
*
|
||||||
* Tasks can have queues to hold received publish messages, and the command task
|
* Tasks can have queues to hold received publish messages, and the command task
|
||||||
* will push incoming publishes to the queue of each task that is subscribed to
|
* will push incoming publishes to the queue of each task that is subscribed to
|
||||||
* the incoming topic.
|
* the incoming topic.
|
||||||
@ -83,70 +101,6 @@
|
|||||||
/**
|
/**
|
||||||
* These configuration settings are required to run the demo.
|
* These configuration settings are required to run the demo.
|
||||||
*/
|
*/
|
||||||
#ifndef democonfigCLIENT_IDENTIFIER
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The MQTT client identifier used in this example. Each client identifier
|
|
||||||
* must be unique so edit as required to ensure no two clients connecting to the
|
|
||||||
* same broker use the same client identifier.
|
|
||||||
*
|
|
||||||
* @note Appending __TIME__ to the client id string will reduce the possibility of a
|
|
||||||
* client id collision in the broker. Note that the appended time is the compilation
|
|
||||||
* time. This client id can cause collision, if more than one instance of the same
|
|
||||||
* binary is used at the same time to connect to the broker.
|
|
||||||
*/
|
|
||||||
#define democonfigCLIENT_IDENTIFIER "testClient"__TIME__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Compile time error for some undefined configs, and provide default values
|
|
||||||
* for others. */
|
|
||||||
#ifndef democonfigMQTT_BROKER_ENDPOINT
|
|
||||||
#error "Please define democonfigMQTT_BROKER_ENDPOINT in demo_config.h."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined( democonfigUSE_TLS ) && ( democonfigUSE_TLS == 1 )
|
|
||||||
#ifndef democonfigROOT_CA_PEM
|
|
||||||
#error "Please define Root CA certificate of the MQTT broker(democonfigROOT_CA_PEM) in demo_config.h."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If no username is defined, then a client certificate/key is required. */
|
|
||||||
#ifndef democonfigCLIENT_USERNAME
|
|
||||||
|
|
||||||
/*
|
|
||||||
*!!! Please note democonfigCLIENT_PRIVATE_KEY_PEM in used for
|
|
||||||
*!!! convenience of demonstration only. Production devices should
|
|
||||||
*!!! store keys securely, such as within a secure element.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef democonfigCLIENT_CERTIFICATE_PEM
|
|
||||||
#error "Please define client certificate(democonfigCLIENT_CERTIFICATE_PEM) in demo_config.h."
|
|
||||||
#endif
|
|
||||||
#ifndef democonfigCLIENT_PRIVATE_KEY_PEM
|
|
||||||
#error "Please define client private key(democonfigCLIENT_PRIVATE_KEY_PEM) in demo_config.h."
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* If a username is defined, a client password also would need to be defined for
|
|
||||||
* client authentication. */
|
|
||||||
#ifndef democonfigCLIENT_PASSWORD
|
|
||||||
#error "Please define client password(democonfigCLIENT_PASSWORD) in demo_config.h for client authentication based on username/password."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* AWS IoT MQTT broker port needs to be 443 for client authentication based on
|
|
||||||
* username/password. */
|
|
||||||
#if defined( democonfigUSE_AWS_IOT_CORE_BROKER ) && democonfigMQTT_BROKER_PORT != 443
|
|
||||||
#error "Broker port(democonfigMQTT_BROKER_PORT) should be defined as 443 in demo_config.h for client authentication based on username/password in AWS IoT Core."
|
|
||||||
#endif
|
|
||||||
#endif /* ifndef democonfigCLIENT_USERNAME */
|
|
||||||
|
|
||||||
#ifndef democonfigMQTT_BROKER_PORT
|
|
||||||
#define democonfigMQTT_BROKER_PORT ( 8883 )
|
|
||||||
#endif
|
|
||||||
#else /* if defined( democonfigUSE_TLS ) && ( democonfigUSE_TLS == 1 ) */
|
|
||||||
#ifndef democonfigMQTT_BROKER_PORT
|
|
||||||
#define democonfigMQTT_BROKER_PORT ( 1883 )
|
|
||||||
#endif
|
|
||||||
#endif /* if defined( democonfigUSE_TLS ) && ( democonfigUSE_TLS == 1 ) */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The size to use for the network buffer.
|
* @brief The size to use for the network buffer.
|
||||||
@ -155,73 +109,6 @@
|
|||||||
#define mqttexampleNETWORK_BUFFER_SIZE ( 1024U )
|
#define mqttexampleNETWORK_BUFFER_SIZE ( 1024U )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief ALPN (Application-Layer Protocol Negotiation) protocol name for AWS IoT MQTT.
|
|
||||||
*
|
|
||||||
* This will be used if democonfigMQTT_BROKER_PORT is configured as 443 for the AWS IoT MQTT broker.
|
|
||||||
* Please see more details about the ALPN protocol for AWS IoT MQTT endpoint
|
|
||||||
* in the link below.
|
|
||||||
* https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/
|
|
||||||
*/
|
|
||||||
#define AWS_IOT_MQTT_ALPN "\x0ex-amzn-mqtt-ca"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This is the ALPN (Application-Layer Protocol Negotiation) string
|
|
||||||
* required by AWS IoT for password-based authentication using TCP port 443.
|
|
||||||
*/
|
|
||||||
#define AWS_IOT_CUSTOM_AUTH_ALPN "\x04mqtt"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide default values for undefined configuration settings.
|
|
||||||
*/
|
|
||||||
#ifndef democonfigOS_NAME
|
|
||||||
#define democonfigOS_NAME "FreeRTOS"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef democonfigOS_VERSION
|
|
||||||
#define democonfigOS_VERSION tskKERNEL_VERSION_NUMBER
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef democonfigHARDWARE_PLATFORM_NAME
|
|
||||||
#define democonfigHARDWARE_PLATFORM_NAME "WinSim"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef democonfigMQTT_LIB
|
|
||||||
#define democonfigMQTT_LIB "core-mqtt@1.0.0"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The MQTT metrics string expected by AWS IoT.
|
|
||||||
*/
|
|
||||||
#define AWS_IOT_METRICS_STRING \
|
|
||||||
"?SDK=" democonfigOS_NAME "&Version=" democonfigOS_VERSION \
|
|
||||||
"&Platform=" democonfigHARDWARE_PLATFORM_NAME "&MQTTLib=" democonfigMQTT_LIB
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The length of the MQTT metrics string expected by AWS IoT.
|
|
||||||
*/
|
|
||||||
#define AWS_IOT_METRICS_STRING_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_METRICS_STRING ) - 1 ) )
|
|
||||||
|
|
||||||
#ifdef democonfigCLIENT_USERNAME
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Append the username with the metrics string if #democonfigCLIENT_USERNAME is defined.
|
|
||||||
*
|
|
||||||
* This is to support both metrics reporting and username/password based client
|
|
||||||
* authentication by AWS IoT.
|
|
||||||
*/
|
|
||||||
#define CLIENT_USERNAME_WITH_METRICS democonfigCLIENT_USERNAME AWS_IOT_METRICS_STRING
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Length of client identifier.
|
|
||||||
*/
|
|
||||||
#define democonfigCLIENT_IDENTIFIER_LENGTH ( ( uint16_t ) ( sizeof( democonfigCLIENT_IDENTIFIER ) - 1 ) )
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Length of MQTT server host name.
|
|
||||||
*/
|
|
||||||
#define democonfigBROKER_ENDPOINT_LENGTH ( ( uint16_t ) ( sizeof( democonfigMQTT_BROKER_ENDPOINT ) - 1 ) )
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Timeout for receiving CONNACK packet in milliseconds.
|
* @brief Timeout for receiving CONNACK packet in milliseconds.
|
||||||
@ -532,13 +419,6 @@ static BaseType_t prvSocketDisconnect( NetworkContext_t * pxNetworkContext );
|
|||||||
*/
|
*/
|
||||||
static void prvMQTTClientSocketWakeupCallback( Socket_t pxSocket );
|
static void prvMQTTClientSocketWakeupCallback( Socket_t pxSocket );
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialize context for a command.
|
|
||||||
*
|
|
||||||
* @param[in] pxContext Context to initialize.
|
|
||||||
*/
|
|
||||||
static void prvInitializeCommandContext( CommandContext_t * pxContext );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Track an operation by adding it to a list, indicating it is anticipating
|
* @brief Track an operation by adding it to a list, indicating it is anticipating
|
||||||
* an acknowledgment.
|
* an acknowledgment.
|
||||||
@ -768,6 +648,14 @@ static void prvMQTTDemoTask( void * pvParameters );
|
|||||||
*/
|
*/
|
||||||
static uint32_t prvGetTimeMs( void );
|
static uint32_t prvGetTimeMs( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cleans any persistent sessions that may already exist
|
||||||
|
* This demo uses a persistent session that can be re-connected if disconnected.
|
||||||
|
* Clean any lingering sessions that may exist from previous executions of the
|
||||||
|
* demo.
|
||||||
|
*/
|
||||||
|
static void prvCleanExistingPersistentSession( void );
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1049,7 +937,7 @@ static MQTTStatus_t prvResumeSession( bool xSessionPresent )
|
|||||||
/* Resubscribe if needed. */
|
/* Resubscribe if needed. */
|
||||||
if( j > 0 )
|
if( j > 0 )
|
||||||
{
|
{
|
||||||
prvInitializeCommandContext( &xResubscribeContext );
|
memset( ( void * ) &xResubscribeContext, 0x00, sizeof( xResubscribeContext ) );
|
||||||
xResubscribeContext.pxSubscribeInfo = pxResendSubscriptions;
|
xResubscribeContext.pxSubscribeInfo = pxResendSubscriptions;
|
||||||
xResubscribeContext.ulSubscriptionCount = j;
|
xResubscribeContext.ulSubscriptionCount = j;
|
||||||
/* Set to NULL so existing queues will not be overwritten. */
|
/* Set to NULL so existing queues will not be overwritten. */
|
||||||
@ -1221,18 +1109,6 @@ static void prvMQTTClientSocketWakeupCallback( Socket_t pxSocket )
|
|||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvInitializeCommandContext( CommandContext_t * pxContext )
|
|
||||||
{
|
|
||||||
pxContext->xIsComplete = false;
|
|
||||||
pxContext->pxResponseQueue = NULL;
|
|
||||||
pxContext->xReturnStatus = MQTTSuccess;
|
|
||||||
pxContext->pxPublishInfo = NULL;
|
|
||||||
pxContext->pxSubscribeInfo = NULL;
|
|
||||||
pxContext->ulSubscriptionCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
static bool prvAddAwaitingOperation( uint16_t usPacketId,
|
static bool prvAddAwaitingOperation( uint16_t usPacketId,
|
||||||
Command_t * pxCommand )
|
Command_t * pxCommand )
|
||||||
{
|
{
|
||||||
@ -1742,7 +1618,6 @@ static void prvCommandLoop( void )
|
|||||||
{
|
{
|
||||||
Command_t xCommand;
|
Command_t xCommand;
|
||||||
Command_t xNewCommand;
|
Command_t xNewCommand;
|
||||||
Command_t * pxCommand;
|
|
||||||
MQTTStatus_t xStatus = MQTTSuccess;
|
MQTTStatus_t xStatus = MQTTSuccess;
|
||||||
static int lNumProcessed = 0;
|
static int lNumProcessed = 0;
|
||||||
bool xTerminateReceived = false;
|
bool xTerminateReceived = false;
|
||||||
@ -1758,9 +1633,7 @@ static void prvCommandLoop( void )
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxCommand = &xCommand;
|
xStatus = prvProcessCommand( &xCommand );
|
||||||
|
|
||||||
xStatus = prvProcessCommand( pxCommand );
|
|
||||||
|
|
||||||
/* Add connect operation to front of queue if status was not successful. */
|
/* Add connect operation to front of queue if status was not successful. */
|
||||||
if( xStatus != MQTTSuccess )
|
if( xStatus != MQTTSuccess )
|
||||||
@ -1778,15 +1651,17 @@ static void prvCommandLoop( void )
|
|||||||
|
|
||||||
/* Delay after sending a subscribe. This is to so that the broker
|
/* Delay after sending a subscribe. This is to so that the broker
|
||||||
* creates a subscription for us before processing our next publish,
|
* creates a subscription for us before processing our next publish,
|
||||||
* which should be immediately after this. */
|
* which should be immediately after this. Only required because the
|
||||||
if( pxCommand->xCommandType == SUBSCRIBE )
|
* subscribe and publish commands are coming from separate tasks, which
|
||||||
|
* would not normally be the case. */
|
||||||
|
if( xCommand.xCommandType == SUBSCRIBE )
|
||||||
{
|
{
|
||||||
LogDebug( ( "Sleeping for %d ms after sending SUBSCRIBE packet.", mqttexampleSUBSCRIBE_TASK_DELAY_MS ) );
|
LogDebug( ( "Sleeping for %d ms after sending SUBSCRIBE packet.", mqttexampleSUBSCRIBE_TASK_DELAY_MS ) );
|
||||||
vTaskDelay( mqttexampleSUBSCRIBE_TASK_DELAY_MS );
|
vTaskDelay( mqttexampleSUBSCRIBE_TASK_DELAY_MS );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Terminate the loop if we receive the termination command. */
|
/* Terminate the loop if we receive the termination command. */
|
||||||
if( pxCommand->xCommandType == TERMINATE )
|
if( xCommand.xCommandType == TERMINATE )
|
||||||
{
|
{
|
||||||
xTerminateReceived = true;
|
xTerminateReceived = true;
|
||||||
break;
|
break;
|
||||||
@ -1800,8 +1675,7 @@ static void prvCommandLoop( void )
|
|||||||
configASSERT( xTerminateReceived == true );
|
configASSERT( xTerminateReceived == true );
|
||||||
|
|
||||||
LogInfo( ( "Creating Disconnect operation." ) );
|
LogInfo( ( "Creating Disconnect operation." ) );
|
||||||
prvCreateCommand( DISCONNECT, NULL, NULL, &xNewCommand );
|
MQTT_Disconnect( &globalMqttContext );
|
||||||
prvProcessCommand( &xNewCommand );
|
|
||||||
LogInfo( ( "Disconnected from broker." ) );
|
LogInfo( ( "Disconnected from broker." ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1873,7 +1747,7 @@ void prvSyncPublishTask( void * pvParameters )
|
|||||||
snprintf( topicBuf, mqttexampleDEMO_BUFFER_SIZE, mqttexamplePUBLISH_TOPIC_FORMAT_STRING, "sync", i + 1 );
|
snprintf( topicBuf, mqttexampleDEMO_BUFFER_SIZE, mqttexamplePUBLISH_TOPIC_FORMAT_STRING, "sync", i + 1 );
|
||||||
xPublishInfo.topicNameLength = ( uint16_t ) strlen( topicBuf );
|
xPublishInfo.topicNameLength = ( uint16_t ) strlen( topicBuf );
|
||||||
|
|
||||||
prvInitializeCommandContext( &xContext );
|
memset( ( void * ) &xContext, 0x00, sizeof( xContext ) );
|
||||||
xContext.xTaskToNotify = xTaskGetCurrentTaskHandle();
|
xContext.xTaskToNotify = xTaskGetCurrentTaskHandle();
|
||||||
xContext.ulNotificationBit = 1 << i;
|
xContext.ulNotificationBit = 1 << i;
|
||||||
xContext.pxPublishInfo = &xPublishInfo;
|
xContext.pxPublishInfo = &xPublishInfo;
|
||||||
@ -1935,7 +1809,7 @@ void prvAsyncPublishTask( void * pvParameters )
|
|||||||
for( int i = 0; i < mqttexamplePUBLISH_COUNT / 2; i++ )
|
for( int i = 0; i < mqttexamplePUBLISH_COUNT / 2; i++ )
|
||||||
{
|
{
|
||||||
pxContexts[ i ] = ( CommandContext_t * ) pvPortMalloc( sizeof( CommandContext_t ) );
|
pxContexts[ i ] = ( CommandContext_t * ) pvPortMalloc( sizeof( CommandContext_t ) );
|
||||||
prvInitializeCommandContext( pxContexts[ i ] );
|
memset( ( void * ) pxContexts[ i ], 0x00, sizeof( pxContexts[ i ] ) );
|
||||||
pxContexts[ i ]->xTaskToNotify = xTaskGetCurrentTaskHandle();
|
pxContexts[ i ]->xTaskToNotify = xTaskGetCurrentTaskHandle();
|
||||||
|
|
||||||
/* Set the notification bit to be the publish number. This prevents this demo
|
/* Set the notification bit to be the publish number. This prevents this demo
|
||||||
@ -2023,7 +1897,7 @@ void prvSubscribeTask( void * pvParameters )
|
|||||||
LogInfo( ( "Topic filter: %.*s", xSubscribeInfo.topicFilterLength, xSubscribeInfo.pTopicFilter ) );
|
LogInfo( ( "Topic filter: %.*s", xSubscribeInfo.topicFilterLength, xSubscribeInfo.pTopicFilter ) );
|
||||||
|
|
||||||
/* Create the context and subscribe command. */
|
/* Create the context and subscribe command. */
|
||||||
prvInitializeCommandContext( &xContext );
|
memset( &xContext, 0x00, sizeof( xContext ) );
|
||||||
xContext.pxResponseQueue = xSubscriberResponseQueue;
|
xContext.pxResponseQueue = xSubscriberResponseQueue;
|
||||||
xContext.xTaskToNotify = xTaskGetCurrentTaskHandle();
|
xContext.xTaskToNotify = xTaskGetCurrentTaskHandle();
|
||||||
xContext.ulNotificationBit = mqttexampleSUBSCRIBE_COMPLETE_BIT;
|
xContext.ulNotificationBit = mqttexampleSUBSCRIBE_COMPLETE_BIT;
|
||||||
@ -2097,7 +1971,7 @@ void prvSubscribeTask( void * pvParameters )
|
|||||||
|
|
||||||
LogInfo( ( "Finished receiving\n" ) );
|
LogInfo( ( "Finished receiving\n" ) );
|
||||||
prvCreateCommand( UNSUBSCRIBE, &xContext, prvCommandCallback, &xCommand );
|
prvCreateCommand( UNSUBSCRIBE, &xContext, prvCommandCallback, &xCommand );
|
||||||
prvInitializeCommandContext( &xContext );
|
memset( ( void * ) &xContext, 0x00, sizeof( xContext ) );
|
||||||
xContext.pxResponseQueue = xSubscriberResponseQueue;
|
xContext.pxResponseQueue = xSubscriberResponseQueue;
|
||||||
xContext.xTaskToNotify = xTaskGetCurrentTaskHandle();
|
xContext.xTaskToNotify = xTaskGetCurrentTaskHandle();
|
||||||
xContext.ulNotificationBit = mqttexampleUNSUBSCRIBE_COMPLETE_BIT;
|
xContext.ulNotificationBit = mqttexampleUNSUBSCRIBE_COMPLETE_BIT;
|
||||||
@ -2131,12 +2005,38 @@ void prvSubscribeTask( void * pvParameters )
|
|||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvCleanExistingPersistentSession( void )
|
||||||
|
{
|
||||||
|
BaseType_t xNetworkStatus = pdFAIL;
|
||||||
|
MQTTStatus_t xMQTTStatus;
|
||||||
|
|
||||||
|
/* Connect to the broker. We connect here with the "clean session" flag set
|
||||||
|
* to true in order to clear any prior state in the broker. We will disconnect
|
||||||
|
* and later form a persistent session, so that it may be resumed if the
|
||||||
|
* network suddenly disconnects. */
|
||||||
|
xNetworkStatus = prvSocketConnect( &xNetworkContext );
|
||||||
|
configASSERT( xNetworkStatus == pdPASS );
|
||||||
|
LogInfo( ( "Creating a clean session to clear any broker state information." ) );
|
||||||
|
xMQTTStatus = prvMQTTInit( &globalMqttContext, &xNetworkContext );
|
||||||
|
configASSERT( xMQTTStatus == MQTTSuccess );
|
||||||
|
xMQTTStatus = prvMQTTConnect( &globalMqttContext, true );
|
||||||
|
configASSERT( xMQTTStatus == MQTTSuccess );
|
||||||
|
|
||||||
|
/* Disconnect. */
|
||||||
|
xMQTTStatus = MQTT_Disconnect( &globalMqttContext );
|
||||||
|
configASSERT( xMQTTStatus == MQTTSuccess );
|
||||||
|
xNetworkStatus = prvSocketDisconnect( &xNetworkContext );
|
||||||
|
configASSERT( xNetworkStatus == pdPASS );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvMQTTDemoTask( void * pvParameters )
|
static void prvMQTTDemoTask( void * pvParameters )
|
||||||
{
|
{
|
||||||
BaseType_t xNetworkStatus = pdFAIL;
|
BaseType_t xNetworkStatus = pdFAIL;
|
||||||
|
MQTTStatus_t xMQTTStatus;
|
||||||
BaseType_t xResult = pdFALSE;
|
BaseType_t xResult = pdFALSE;
|
||||||
uint32_t ulNotification = 0;
|
uint32_t ulNotification = 0;
|
||||||
MQTTStatus_t xMQTTStatus;
|
|
||||||
uint32_t ulExpectedNotifications = mqttexamplePUBLISHER_SYNC_COMPLETE_BIT |
|
uint32_t ulExpectedNotifications = mqttexamplePUBLISHER_SYNC_COMPLETE_BIT |
|
||||||
mqttexampleSUBSCRIBE_TASK_COMPLETE_BIT |
|
mqttexampleSUBSCRIBE_TASK_COMPLETE_BIT |
|
||||||
mqttexamplePUBLISHER_ASYNC_COMPLETE_BIT;
|
mqttexamplePUBLISHER_ASYNC_COMPLETE_BIT;
|
||||||
@ -2156,23 +2056,10 @@ static void prvMQTTDemoTask( void * pvParameters )
|
|||||||
* synchronization primitives. */
|
* synchronization primitives. */
|
||||||
xDefaultResponseQueue = xQueueCreate( 1, sizeof( PublishElement_t ) );
|
xDefaultResponseQueue = xQueueCreate( 1, sizeof( PublishElement_t ) );
|
||||||
|
|
||||||
/* Connect to the broker. We connect here with the "clean session" flag set
|
/* This demo uses a persistent session that can be re-connected if disconnected.
|
||||||
* to true in order to clear any prior state in the broker. We will disconnect
|
* Clean any lingering sessions that may exist from previous executions of the
|
||||||
* and later form a persistent session, so that it may be resumed if the
|
* demo. */
|
||||||
* network suddenly disconnects. */
|
prvCleanExistingPersistentSession();
|
||||||
xNetworkStatus = prvSocketConnect( &xNetworkContext );
|
|
||||||
configASSERT( xNetworkStatus == pdPASS );
|
|
||||||
LogInfo( ( "Creating a clean session to clear any broker state information." ) );
|
|
||||||
xMQTTStatus = prvMQTTInit( &globalMqttContext, &xNetworkContext );
|
|
||||||
configASSERT( xMQTTStatus == MQTTSuccess );
|
|
||||||
xMQTTStatus = prvMQTTConnect( &globalMqttContext, true );
|
|
||||||
configASSERT( xMQTTStatus == MQTTSuccess );
|
|
||||||
|
|
||||||
/* Disconnect. */
|
|
||||||
xMQTTStatus = MQTT_Disconnect( &globalMqttContext );
|
|
||||||
configASSERT( xMQTTStatus == MQTTSuccess );
|
|
||||||
xNetworkStatus = prvSocketDisconnect( &xNetworkContext );
|
|
||||||
configASSERT( xNetworkStatus == pdPASS );
|
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
@ -2188,8 +2075,9 @@ static void prvMQTTDemoTask( void * pvParameters )
|
|||||||
configASSERT( xMQTTStatus == MQTTSuccess );
|
configASSERT( xMQTTStatus == MQTTSuccess );
|
||||||
configASSERT( globalMqttContext.connectStatus == MQTTConnected );
|
configASSERT( globalMqttContext.connectStatus == MQTTConnected );
|
||||||
|
|
||||||
/* Give subscriber task higher priority so the subscribe will be processed before the first publish.
|
/* Give subscriber task higher priority so the subscribe will be processed
|
||||||
* This must be less than or equal to the priority of the main task. */
|
* before the first publish. This must be less than or equal to the priority of
|
||||||
|
* the main task. */
|
||||||
xResult = xTaskCreate( prvSubscribeTask, "Subscriber", democonfigDEMO_STACKSIZE, NULL, tskIDLE_PRIORITY + 1, &xSubscribeTask );
|
xResult = xTaskCreate( prvSubscribeTask, "Subscriber", democonfigDEMO_STACKSIZE, NULL, tskIDLE_PRIORITY + 1, &xSubscribeTask );
|
||||||
configASSERT( xResult == pdPASS );
|
configASSERT( xResult == pdPASS );
|
||||||
xResult = xTaskCreate( prvSyncPublishTask, "SyncPublisher", democonfigDEMO_STACKSIZE, NULL, tskIDLE_PRIORITY, &xSyncPublisherTask );
|
xResult = xTaskCreate( prvSyncPublishTask, "SyncPublisher", democonfigDEMO_STACKSIZE, NULL, tskIDLE_PRIORITY, &xSyncPublisherTask );
|
||||||
@ -2218,7 +2106,7 @@ static void prvMQTTDemoTask( void * pvParameters )
|
|||||||
xNetworkStatus = prvSocketDisconnect( &xNetworkContext );
|
xNetworkStatus = prvSocketDisconnect( &xNetworkContext );
|
||||||
configASSERT( xNetworkStatus == pdPASS );
|
configASSERT( xNetworkStatus == pdPASS );
|
||||||
|
|
||||||
LogInfo( ( "prvMQTTDemoTask() completed an iteration successfully. Total free heap is %u.\r\n", xPortGetFreeHeapSize() ) );
|
LogInfo( ( "\r\n\r\nprvMQTTDemoTask() completed an iteration successfully. Total free heap is %u.\r\n", xPortGetFreeHeapSize() ) );
|
||||||
LogInfo( ( "Demo completed successfully.\r\n" ) );
|
LogInfo( ( "Demo completed successfully.\r\n" ) );
|
||||||
LogInfo( ( "Short delay before starting the next iteration.... \r\n\r\n" ) );
|
LogInfo( ( "Short delay before starting the next iteration.... \r\n\r\n" ) );
|
||||||
vTaskDelay( mqttexampleDELAY_BETWEEN_DEMO_ITERATIONS );
|
vTaskDelay( mqttexampleDELAY_BETWEEN_DEMO_ITERATIONS );
|
||||||
|
@ -259,4 +259,146 @@ extern void vLoggingPrintf( const char * pcFormatString,
|
|||||||
*/
|
*/
|
||||||
#define democonfigDEMO_STACKSIZE configMINIMAL_STACK_SIZE
|
#define democonfigDEMO_STACKSIZE configMINIMAL_STACK_SIZE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************************
|
||||||
|
* Error checks and derived values only below here - do not edit below here. -----*
|
||||||
|
**********************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/* Compile time error for some undefined configs, and provide default values
|
||||||
|
* for others. */
|
||||||
|
#ifndef democonfigMQTT_BROKER_ENDPOINT
|
||||||
|
#error "Please define democonfigMQTT_BROKER_ENDPOINT in demo_config.h."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef democonfigCLIENT_IDENTIFIER
|
||||||
|
/**
|
||||||
|
* @brief The MQTT client identifier used in this example. Each client identifier
|
||||||
|
* must be unique so edit as required to ensure no two clients connecting to the
|
||||||
|
* same broker use the same client identifier. Using a #define is for convenience
|
||||||
|
* of demonstration only - production devices should use something unique to the
|
||||||
|
* device that can be read from software - such as a production serial number.
|
||||||
|
*/
|
||||||
|
#error "Please define democonfigCLIENT_IDENTIFIER in demo_config.h to something unique for this device."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined( democonfigUSE_TLS ) && ( democonfigUSE_TLS == 1 )
|
||||||
|
#ifndef democonfigROOT_CA_PEM
|
||||||
|
#error "Please define Root CA certificate of the MQTT broker(democonfigROOT_CA_PEM) in demo_config.h."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If no username is defined, then a client certificate/key is required. */
|
||||||
|
#ifndef democonfigCLIENT_USERNAME
|
||||||
|
|
||||||
|
/*
|
||||||
|
*!!! Please note democonfigCLIENT_PRIVATE_KEY_PEM in used for
|
||||||
|
*!!! convenience of demonstration only. Production devices should
|
||||||
|
*!!! store keys securely, such as within a secure element.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef democonfigCLIENT_CERTIFICATE_PEM
|
||||||
|
#error "Please define client certificate(democonfigCLIENT_CERTIFICATE_PEM) in demo_config.h."
|
||||||
|
#endif
|
||||||
|
#ifndef democonfigCLIENT_PRIVATE_KEY_PEM
|
||||||
|
#error "Please define client private key(democonfigCLIENT_PRIVATE_KEY_PEM) in demo_config.h."
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* If a username is defined, a client password also would need to be defined for
|
||||||
|
* client authentication. */
|
||||||
|
#ifndef democonfigCLIENT_PASSWORD
|
||||||
|
#error "Please define client password(democonfigCLIENT_PASSWORD) in demo_config.h for client authentication based on username/password."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* AWS IoT MQTT broker port needs to be 443 for client authentication based on
|
||||||
|
* username/password. */
|
||||||
|
#if defined( democonfigUSE_AWS_IOT_CORE_BROKER ) && democonfigMQTT_BROKER_PORT != 443
|
||||||
|
#error "Broker port(democonfigMQTT_BROKER_PORT) should be defined as 443 in demo_config.h for client authentication based on username/password in AWS IoT Core."
|
||||||
|
#endif
|
||||||
|
#endif /* ifndef democonfigCLIENT_USERNAME */
|
||||||
|
|
||||||
|
#ifndef democonfigMQTT_BROKER_PORT
|
||||||
|
#define democonfigMQTT_BROKER_PORT ( 8883 )
|
||||||
|
#endif
|
||||||
|
#else /* if defined( democonfigUSE_TLS ) && ( democonfigUSE_TLS == 1 ) */
|
||||||
|
#ifndef democonfigMQTT_BROKER_PORT
|
||||||
|
#define democonfigMQTT_BROKER_PORT ( 1883 )
|
||||||
|
#endif
|
||||||
|
#endif /* if defined( democonfigUSE_TLS ) && ( democonfigUSE_TLS == 1 ) */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ALPN (Application-Layer Protocol Negotiation) protocol name for AWS IoT MQTT.
|
||||||
|
*
|
||||||
|
* This will be used if democonfigMQTT_BROKER_PORT is configured as 443 for the AWS IoT MQTT broker.
|
||||||
|
* Please see more details about the ALPN protocol for AWS IoT MQTT endpoint
|
||||||
|
* in the link below.
|
||||||
|
* https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/
|
||||||
|
*/
|
||||||
|
#define AWS_IOT_MQTT_ALPN "\x0ex-amzn-mqtt-ca"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This is the ALPN (Application-Layer Protocol Negotiation) string
|
||||||
|
* required by AWS IoT for password-based authentication using TCP port 443.
|
||||||
|
*/
|
||||||
|
#define AWS_IOT_CUSTOM_AUTH_ALPN "\x04mqtt"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide default values for undefined configuration settings.
|
||||||
|
*/
|
||||||
|
#ifndef democonfigOS_NAME
|
||||||
|
#define democonfigOS_NAME "FreeRTOS"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef democonfigOS_VERSION
|
||||||
|
#define democonfigOS_VERSION tskKERNEL_VERSION_NUMBER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef democonfigHARDWARE_PLATFORM_NAME
|
||||||
|
#define democonfigHARDWARE_PLATFORM_NAME "WinSim"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef democonfigMQTT_LIB
|
||||||
|
#define democonfigMQTT_LIB "core-mqtt@1.0.0"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The MQTT metrics string expected by AWS IoT.
|
||||||
|
*/
|
||||||
|
#define AWS_IOT_METRICS_STRING \
|
||||||
|
"?SDK=" democonfigOS_NAME "&Version=" democonfigOS_VERSION \
|
||||||
|
"&Platform=" democonfigHARDWARE_PLATFORM_NAME "&MQTTLib=" democonfigMQTT_LIB
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The length of the MQTT metrics string expected by AWS IoT.
|
||||||
|
*/
|
||||||
|
#define AWS_IOT_METRICS_STRING_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_METRICS_STRING ) - 1 ) )
|
||||||
|
|
||||||
|
#ifdef democonfigCLIENT_USERNAME
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Append the username with the metrics string if #democonfigCLIENT_USERNAME is defined.
|
||||||
|
*
|
||||||
|
* This is to support both metrics reporting and username/password based client
|
||||||
|
* authentication by AWS IoT.
|
||||||
|
*/
|
||||||
|
#define CLIENT_USERNAME_WITH_METRICS democonfigCLIENT_USERNAME AWS_IOT_METRICS_STRING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Length of client identifier.
|
||||||
|
*/
|
||||||
|
#define democonfigCLIENT_IDENTIFIER_LENGTH ( ( uint16_t ) ( sizeof( democonfigCLIENT_IDENTIFIER ) - 1 ) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Length of MQTT server host name.
|
||||||
|
*/
|
||||||
|
#define democonfigBROKER_ENDPOINT_LENGTH ( ( uint16_t ) ( sizeof( democonfigMQTT_BROKER_ENDPOINT ) - 1 ) )
|
||||||
|
|
||||||
|
|
||||||
#endif /* DEMO_CONFIG_H */
|
#endif /* DEMO_CONFIG_H */
|
||||||
|
Reference in New Issue
Block a user