AWS IoT Over-the-air Update v3.4.0
Client library for AWS IoT OTA
ota_mqtt.c File Reference

Routines for supporting over the air updates using MQTT. More...

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "ota.h"
#include "ota_private.h"
#include "ota_cbor_private.h"
#include "ota_mqtt_private.h"
#include "ota_appversion32.h"
Include dependency graph for ota_mqtt.c:

Macros

#define OTA_CLIENT_TOKEN   "rdy"
 
#define OTA_STATUS_MSG_MAX_SIZE   128U
 
#define MQTT_API_THINGS   "$aws/things/"
 Topic strings used by the OTA process. More...
 
#define MQTT_API_JOBS_NEXT_GET   "/jobs/$next/get"
 
#define MQTT_API_JOBS_NOTIFY_NEXT   "/jobs/notify-next"
 
#define MQTT_API_JOBS   "/jobs/"
 
#define MQTT_API_UPDATE   "/update"
 
#define MQTT_API_STREAMS   "/streams/"
 
#define MQTT_API_DATA_CBOR   "/data/cbor"
 
#define MQTT_API_GET_CBOR   "/get/cbor"
 
#define JOBS_API_STATUS_IN_PROGRESS   "IN_PROGRESS"
 
#define JOBS_API_STATUS_FAILED   "FAILED"
 
#define JOBS_API_STATUS_SUCCEEDED   "SUCCEEDED"
 
#define JOBS_API_STATUS_REJECTED   "REJECTED"
 
#define U32_MAX_LEN   10U
 
#define JOB_NAME_MAX_LEN   128U
 
#define STREAM_NAME_MAX_LEN   44U
 
#define NULL_CHAR_LEN   1U
 
#define TOPIC_PLUS_THINGNAME_LEN(topic)   ( CONST_STRLEN( topic ) + otaconfigMAX_THINGNAME_LEN + NULL_CHAR_LEN )
 
#define TOPIC_GET_NEXT_BUFFER_SIZE   ( TOPIC_PLUS_THINGNAME_LEN( pOtaJobsGetNextTopicTemplate ) )
 
#define TOPIC_NOTIFY_NEXT_BUFFER_SIZE   ( TOPIC_PLUS_THINGNAME_LEN( pOtaJobsNotifyNextTopicTemplate ) )
 
#define TOPIC_JOB_STATUS_BUFFER_SIZE   ( TOPIC_PLUS_THINGNAME_LEN( pOtaJobStatusTopicTemplate ) + JOB_NAME_MAX_LEN )
 
#define TOPIC_STREAM_DATA_BUFFER_SIZE   ( TOPIC_PLUS_THINGNAME_LEN( pOtaStreamDataTopicTemplate ) + STREAM_NAME_MAX_LEN )
 
#define TOPIC_GET_STREAM_BUFFER_SIZE   ( TOPIC_PLUS_THINGNAME_LEN( pOtaGetStreamTopicTemplate ) + STREAM_NAME_MAX_LEN )
 
#define MSG_GET_NEXT_BUFFER_SIZE   ( TOPIC_PLUS_THINGNAME_LEN( pOtaGetNextJobMsgTemplate ) + U32_MAX_LEN )
 

Functions

static OtaMqttStatus_t subscribeToJobNotificationTopics (const OtaAgentContext_t *pAgentCtx)
 Subscribe to the jobs notification topic (i.e. New file version available). More...
 
static OtaMqttStatus_t unsubscribeFromDataStream (const OtaAgentContext_t *pAgentCtx)
 UnSubscribe from the firmware update receive topic. More...
 
static OtaMqttStatus_t unsubscribeFromJobNotificationTopic (const OtaAgentContext_t *pAgentCtx)
 UnSubscribe from the jobs notification topic. More...
 
static OtaMqttStatus_t publishStatusMessage (const OtaAgentContext_t *pAgentCtx, const char *pMsg, uint32_t msgSize, uint8_t qos)
 Publish a message to the job status topic. More...
 
static uint32_t buildStatusMessageReceiving (char *pMsgBuffer, size_t msgBufferSize, OtaJobStatus_t status, const OtaFileContext_t *pOTAFileCtx)
 Populate the message buffer with the job status message. More...
 
static uint32_t prvBuildStatusMessageSelfTest (char *pMsgBuffer, size_t msgBufferSize, OtaJobStatus_t status, int32_t reason)
 Populate the message buffer with the message to indicate device in self-test. More...
 
static uint32_t prvBuildStatusMessageFinish (char *pMsgBuffer, size_t msgBufferSize, OtaJobStatus_t status, int32_t reason, int32_t subReason, uint32_t previousVersion)
 Populate the response message with the status of the job. More...
 
static size_t stringBuilder (char *pBuffer, size_t bufferSizeBytes, const char *const strings[])
 Build a string from a set of strings. More...
 
static size_t stringBuilderUInt32Decimal (char *pBuffer, size_t bufferSizeBytes, uint32_t value)
 Build a string with the decimal representation of a uint32_t value. More...
 
static size_t stringBuilderUInt32Hex (char *pBuffer, size_t bufferSizeBytes, uint32_t value)
 Build a string with the hex representation of a uint32_t value. More...
 
OtaErr_t requestJob_Mqtt (const OtaAgentContext_t *pAgentCtx)
 Check for available OTA job over MQTT. More...
 
OtaErr_t updateJobStatus_Mqtt (const OtaAgentContext_t *pAgentCtx, OtaJobStatus_t status, int32_t reason, int32_t subReason)
 Update job status over MQTT. More...
 
OtaErr_t initFileTransfer_Mqtt (const OtaAgentContext_t *pAgentCtx)
 Initialize file transfer over MQTT. More...
 
OtaErr_t requestFileBlock_Mqtt (OtaAgentContext_t *pAgentCtx)
 Request File block over MQTT. More...
 
OtaErr_t decodeFileBlock_Mqtt (const uint8_t *pMessageBuffer, size_t messageSize, int32_t *pFileId, int32_t *pBlockId, int32_t *pBlockSize, uint8_t *const *pPayload, size_t *pPayloadSize)
 Decode a cbor encoded fileblock. More...
 
OtaErr_t cleanupControl_Mqtt (const OtaAgentContext_t *pAgentCtx)
 Cleanup related to OTA control plane over MQTT. More...
 
OtaErr_t cleanupData_Mqtt (const OtaAgentContext_t *pAgentCtx)
 Cleanup related to OTA data plane over MQTT. More...
 
const char * OTA_MQTT_strerror (OtaMqttStatus_t status)
 Status to string conversion for OTA MQTT interface status. More...
 

Variables

static const char pOtaJobsGetNextTopicTemplate [] = MQTT_API_THINGS "%s"MQTT_API_JOBS_NEXT_GET
 
static const char pOtaJobsNotifyNextTopicTemplate [] = MQTT_API_THINGS "%s"MQTT_API_JOBS_NOTIFY_NEXT
 
static const char pOtaJobStatusTopicTemplate [] = MQTT_API_THINGS "%s"MQTT_API_JOBS "%s"MQTT_API_UPDATE
 
static const char pOtaStreamDataTopicTemplate [] = MQTT_API_THINGS "%s"MQTT_API_STREAMS "%s"MQTT_API_DATA_CBOR
 
static const char pOtaGetStreamTopicTemplate [] = MQTT_API_THINGS "%s"MQTT_API_STREAMS "%s"MQTT_API_GET_CBOR
 
static const char pOtaGetNextJobMsgTemplate [] = "{\"clientToken\":\"%u:%s\"}"
 
static const char pOtaStringReceive [] = "\"receive\""
 
static const char * pOtaJobStatusStrings [NumJobStatusMappings]
 List of all the status cases a job can be in. More...
 
static const char * pOtaJobReasonStrings [NumJobReasons] = { "", "ready", "active", "accepted", "rejected", "aborted" }
 These are the associated statusDetails 'reason' codes that go along with the above enums during the OTA update process. The 'Receiving' state is updated with transfer progress as number of blocks received of total blocks.
 
static const char asciiDigits []
 These are used for both decimal and hex string conversions. More...
 

Detailed Description

Routines for supporting over the air updates using MQTT.

Macro Definition Documentation

◆ OTA_CLIENT_TOKEN

#define OTA_CLIENT_TOKEN   "rdy"

Arbitrary client token sent in the stream "GET" message.

◆ OTA_STATUS_MSG_MAX_SIZE

#define OTA_STATUS_MSG_MAX_SIZE   128U

Max length of a job status message to the service.

◆ MQTT_API_THINGS

#define MQTT_API_THINGS   "$aws/things/"

Topic strings used by the OTA process.

These first few are topic extensions to the dynamic base topic that includes the Thing name. Topic prefix for thing APIs.

◆ MQTT_API_JOBS_NEXT_GET

#define MQTT_API_JOBS_NEXT_GET   "/jobs/$next/get"

Topic suffix for job API.

◆ MQTT_API_JOBS_NOTIFY_NEXT

#define MQTT_API_JOBS_NOTIFY_NEXT   "/jobs/notify-next"

Topic suffix for job API.

◆ MQTT_API_JOBS

#define MQTT_API_JOBS   "/jobs/"

Job API identifier.

◆ MQTT_API_UPDATE

#define MQTT_API_UPDATE   "/update"

Job API identifier.

◆ MQTT_API_STREAMS

#define MQTT_API_STREAMS   "/streams/"

Stream API identifier.

◆ MQTT_API_DATA_CBOR

#define MQTT_API_DATA_CBOR   "/data/cbor"

Stream API suffix.

◆ MQTT_API_GET_CBOR

#define MQTT_API_GET_CBOR   "/get/cbor"

Stream API suffix.

◆ JOBS_API_STATUS_IN_PROGRESS

#define JOBS_API_STATUS_IN_PROGRESS   "IN_PROGRESS"

We map all of the above status cases to one of these status strings. These are the only strings that are supported by the Job Service. You shall not change them to arbitrary strings or the job will not change states. The job document has be received on the device and update is in progress.

◆ JOBS_API_STATUS_FAILED

#define JOBS_API_STATUS_FAILED   "FAILED"

OTA update failed due to an error.

◆ JOBS_API_STATUS_SUCCEEDED

#define JOBS_API_STATUS_SUCCEEDED   "SUCCEEDED"

OTA update succeeded.

◆ JOBS_API_STATUS_REJECTED

#define JOBS_API_STATUS_REJECTED   "REJECTED"

The job was rejected due to invalid parameters.

◆ U32_MAX_LEN

#define U32_MAX_LEN   10U

Maximum number of output digits of an unsigned long value.

◆ JOB_NAME_MAX_LEN

#define JOB_NAME_MAX_LEN   128U

Maximum length of the name of job documents received from the server.

◆ STREAM_NAME_MAX_LEN

#define STREAM_NAME_MAX_LEN   44U

Maximum length for the name of MQTT streams.

◆ NULL_CHAR_LEN

#define NULL_CHAR_LEN   1U

Size of a single null character used to terminate topics and messages.

◆ TOPIC_PLUS_THINGNAME_LEN

#define TOPIC_PLUS_THINGNAME_LEN (   topic)    ( CONST_STRLEN( topic ) + otaconfigMAX_THINGNAME_LEN + NULL_CHAR_LEN )

Calculate max buffer size based on topic template and thing name length.

◆ TOPIC_GET_NEXT_BUFFER_SIZE

#define TOPIC_GET_NEXT_BUFFER_SIZE   ( TOPIC_PLUS_THINGNAME_LEN( pOtaJobsGetNextTopicTemplate ) )

Max buffer size for jobs/$next/get topic.

◆ TOPIC_NOTIFY_NEXT_BUFFER_SIZE

#define TOPIC_NOTIFY_NEXT_BUFFER_SIZE   ( TOPIC_PLUS_THINGNAME_LEN( pOtaJobsNotifyNextTopicTemplate ) )

Max buffer size for jobs/notify-next topic.

◆ TOPIC_JOB_STATUS_BUFFER_SIZE

#define TOPIC_JOB_STATUS_BUFFER_SIZE   ( TOPIC_PLUS_THINGNAME_LEN( pOtaJobStatusTopicTemplate ) + JOB_NAME_MAX_LEN )

Max buffer size for jobs/<job_name>/update topic.

◆ TOPIC_STREAM_DATA_BUFFER_SIZE

#define TOPIC_STREAM_DATA_BUFFER_SIZE   ( TOPIC_PLUS_THINGNAME_LEN( pOtaStreamDataTopicTemplate ) + STREAM_NAME_MAX_LEN )

Max buffer size for streams/<stream_name>/data/cbor topic.

◆ TOPIC_GET_STREAM_BUFFER_SIZE

#define TOPIC_GET_STREAM_BUFFER_SIZE   ( TOPIC_PLUS_THINGNAME_LEN( pOtaGetStreamTopicTemplate ) + STREAM_NAME_MAX_LEN )

Max buffer size for streams/<stream_name>/get/cbor topic.

◆ MSG_GET_NEXT_BUFFER_SIZE

#define MSG_GET_NEXT_BUFFER_SIZE   ( TOPIC_PLUS_THINGNAME_LEN( pOtaGetNextJobMsgTemplate ) + U32_MAX_LEN )

Max buffer size for message of jobs/$next/get topic.

Function Documentation

◆ subscribeToJobNotificationTopics()

static OtaMqttStatus_t subscribeToJobNotificationTopics ( const OtaAgentContext_t pAgentCtx)
static

Subscribe to the jobs notification topic (i.e. New file version available).

Parameters
[in]pAgentCtxAgent context which stores the thing details and mqtt interface.
Returns
OtaMqttStatus_t Result of the subscribe operation, OtaMqttSuccess if the operation is successful

◆ unsubscribeFromDataStream()

static OtaMqttStatus_t unsubscribeFromDataStream ( const OtaAgentContext_t pAgentCtx)
static

UnSubscribe from the firmware update receive topic.

Parameters
[in]pAgentCtxAgent context which stores the thing details and mqtt interface.
Returns
OtaMqttStatus_t Result of the unsubscribe operation, OtaMqttSuccess if the operation is successful.

◆ unsubscribeFromJobNotificationTopic()

static OtaMqttStatus_t unsubscribeFromJobNotificationTopic ( const OtaAgentContext_t pAgentCtx)
static

UnSubscribe from the jobs notification topic.

Parameters
[in]pAgentCtxAgent context which stores the thing details and mqtt interface.
Returns
OtaMqttStatus_t Result of the unsubscribe operation, OtaMqttSuccess if the operation is successful.

◆ publishStatusMessage()

static OtaMqttStatus_t publishStatusMessage ( const OtaAgentContext_t pAgentCtx,
const char *  pMsg,
uint32_t  msgSize,
uint8_t  qos 
)
static

Publish a message to the job status topic.

Parameters
[in]pAgentCtxAgent context which provides the details for the thing, job and mqtt interface.
[in]pMsgMessage to publish.
[in]msgSizeSize of message to send.
[in]qosQuality of service level for mqtt.
Returns
OtaMqttStatus_t OtaMqttSuccess if the message is publish is successful.

◆ buildStatusMessageReceiving()

static uint32_t buildStatusMessageReceiving ( char *  pMsgBuffer,
size_t  msgBufferSize,
OtaJobStatus_t  status,
const OtaFileContext_t pOTAFileCtx 
)
static

Populate the message buffer with the job status message.

Parameters
[in]pMsgBufferBuffer to populate.
[in]msgBufferSizeSize of the message.
[in]statusStatus of the operation.
[in]pOTAFileCtxFile context stores the information about the downloaded blocks and required size.
Returns
uint32_t Size of the message built.

◆ prvBuildStatusMessageSelfTest()

static uint32_t prvBuildStatusMessageSelfTest ( char *  pMsgBuffer,
size_t  msgBufferSize,
OtaJobStatus_t  status,
int32_t  reason 
)
static

Populate the message buffer with the message to indicate device in self-test.

Parameters
[in]pMsgBufferBuffer to populate.
[in]msgBufferSizeSize of the message.
[in]statusStatus of the operation.
[in]reasonReason for job failure (if any).
Returns
uint32_t Size of the message.

◆ prvBuildStatusMessageFinish()

static uint32_t prvBuildStatusMessageFinish ( char *  pMsgBuffer,
size_t  msgBufferSize,
OtaJobStatus_t  status,
int32_t  reason,
int32_t  subReason,
uint32_t  previousVersion 
)
static

Populate the response message with the status of the job.

Parameters
[in]pMsgBufferBuffer to populate.
[in]msgBufferSizeSize of the message.
[in]statusStatus of the operation.
[in]reasonReason for failure or the new firmware version.
[in]subReasonError code due to which the operation failed.
[in]previousVersionVersion from which the new version was updated.
Returns
uint32_t Size of the message.

◆ stringBuilder()

static size_t stringBuilder ( char *  pBuffer,
size_t  bufferSizeBytes,
const char *const  strings[] 
)
static

Build a string from a set of strings.

Parameters
[in]pBufferBuffer to place the output string in.
[in]bufferSizeBytesSize of the buffer pointed to by pBuffer.
[in]stringsNULL-terminated array of string pointers.
Returns
size_t Length of the output string, not including the terminator.

◆ stringBuilderUInt32Decimal()

static size_t stringBuilderUInt32Decimal ( char *  pBuffer,
size_t  bufferSizeBytes,
uint32_t  value 
)
static

Build a string with the decimal representation of a uint32_t value.

Parameters
[in]pBufferBuffer to place the output string in.
[in]bufferSizeBytesSize of the buffer pointed to by pBuffer.
[in]valueThe uint32_t value to convert.
Returns
size_t Length of the output string, not including the terminator.

◆ stringBuilderUInt32Hex()

static size_t stringBuilderUInt32Hex ( char *  pBuffer,
size_t  bufferSizeBytes,
uint32_t  value 
)
static

Build a string with the hex representation of a uint32_t value.

Parameters
[in]pBufferBuffer to place the output string in.
[in]bufferSizeBytesSize of the buffer pointed to by pBuffer.
[in]valueThe uint32_t value to convert.
Returns
size_t Length of the output string, not including the terminator.

◆ requestJob_Mqtt()

OtaErr_t requestJob_Mqtt ( const OtaAgentContext_t pAgentCtx)

Check for available OTA job over MQTT.

This function Request for the next available OTA job from the job service by publishing a "get next job" message to the job service.

Parameters
[in]pAgentCtxThe OTA agent context.
Returns
The OTA error code. See OTA Agent error codes information in ota.h.

◆ updateJobStatus_Mqtt()

OtaErr_t updateJobStatus_Mqtt ( const OtaAgentContext_t pAgentCtx,
OtaJobStatus_t  status,
int32_t  reason,
int32_t  subReason 
)

Update job status over MQTT.

This function updates the OTA job status over MQTT with information like in progress, completion or failure.

Parameters
[in]pAgentCtxThe OTA agent context.
[in]statusThe OTA job status which should be updated.
See also
OtaJobStatus_t.
Parameters
[in]reasonThe major reason for the status update.
[in]subReasonThe platform specific reason.
Returns
The OTA error code. See OTA Agent error codes information in ota.h.

◆ initFileTransfer_Mqtt()

OtaErr_t initFileTransfer_Mqtt ( const OtaAgentContext_t pAgentCtx)

Initialize file transfer over MQTT.

This function initializes the file transfer after the OTA job is parsed and accepted by subscribing to the data streaming topics.

Parameters
[in]pAgentCtxThe OTA agent context.
Returns
The OTA error code. See OTA Agent error codes information in ota.h.

< Buffer to store the topic generated for requesting data stream.

◆ requestFileBlock_Mqtt()

OtaErr_t requestFileBlock_Mqtt ( OtaAgentContext_t pAgentCtx)

Request File block over MQTT.

This function is used for requesting a file block over MQTT using the file context.

Parameters
[in]pAgentCtxThe OTA agent context.
Returns
The OTA PAL layer error code combined with the MCU specific error code. See OTA Agent error codes information in ota.h.

◆ decodeFileBlock_Mqtt()

OtaErr_t decodeFileBlock_Mqtt ( const uint8_t *  pMessageBuffer,
size_t  messageSize,
int32_t *  pFileId,
int32_t *  pBlockId,
int32_t *  pBlockSize,
uint8_t *const *  pPayload,
size_t *  pPayloadSize 
)

Decode a cbor encoded fileblock.

This function is used for decoding a file block received over MQTT & encoded in cbor.

Parameters
[in]pMessageBufferThe message to be decoded.
[in]messageSizeThe size of the message in bytes.
[out]pFileIdThe server file ID.
[out]pBlockIdThe file block ID.
[out]pBlockSizeThe file block size.
[out]pPayloadThe payload.
[out]pPayloadSizeThe payload size.
Returns
The OTA PAL layer error code combined with the MCU specific error code. See OTA Agent error codes information in ota.h.

◆ cleanupControl_Mqtt()

OtaErr_t cleanupControl_Mqtt ( const OtaAgentContext_t pAgentCtx)

Cleanup related to OTA control plane over MQTT.

This function cleanup by unsubscribing from any topics that were subscribed for performing OTA over MQTT.

Parameters
[in]pAgentCtxThe OTA agent context.
Returns
The OTA error code. See OTA Agent error codes information in ota.h.

◆ cleanupData_Mqtt()

OtaErr_t cleanupData_Mqtt ( const OtaAgentContext_t pAgentCtx)

Cleanup related to OTA data plane over MQTT.

This function performs cleanup by unsubscribing from any topics that were subscribed for performing OTA data over MQTT.

Parameters
[in]pAgentCtxThe OTA agent context.
Returns
The OTA error code. See OTA Agent error codes information in ota.h.

◆ OTA_MQTT_strerror()

const char * OTA_MQTT_strerror ( OtaMqttStatus_t  status)

Status to string conversion for OTA MQTT interface status.

Parameters
[in]statusThe status to convert to a string.
Returns
The string representation of the status.

Variable Documentation

◆ pOtaJobsGetNextTopicTemplate

const char pOtaJobsGetNextTopicTemplate[] = MQTT_API_THINGS "%s"MQTT_API_JOBS_NEXT_GET
static

Topic template to request next job.

◆ pOtaJobsNotifyNextTopicTemplate

const char pOtaJobsNotifyNextTopicTemplate[] = MQTT_API_THINGS "%s"MQTT_API_JOBS_NOTIFY_NEXT
static

Topic template to notify next .

◆ pOtaJobStatusTopicTemplate

const char pOtaJobStatusTopicTemplate[] = MQTT_API_THINGS "%s"MQTT_API_JOBS "%s"MQTT_API_UPDATE
static

Topic template to update the current job.

◆ pOtaStreamDataTopicTemplate

const char pOtaStreamDataTopicTemplate[] = MQTT_API_THINGS "%s"MQTT_API_STREAMS "%s"MQTT_API_DATA_CBOR
static

Topic template to receive data over a stream.

◆ pOtaGetStreamTopicTemplate

const char pOtaGetStreamTopicTemplate[] = MQTT_API_THINGS "%s"MQTT_API_STREAMS "%s"MQTT_API_GET_CBOR
static

Topic template to request next data over a stream.

◆ pOtaGetNextJobMsgTemplate

const char pOtaGetNextJobMsgTemplate[] = "{\"clientToken\":\"%u:%s\"}"
static

Used to specify client token id to authenticate job.

◆ pOtaStringReceive

const char pOtaStringReceive[] = "\"receive\""
static

Used to build the job receive template.

◆ pOtaJobStatusStrings

const char* pOtaJobStatusStrings[NumJobStatusMappings]
static
Initial value:
=
{
"{\"status\":\""JOBS_API_STATUS_IN_PROGRESS "\",\"statusDetails\":{",
"{\"status\":\""JOBS_API_STATUS_FAILED "\",\"statusDetails\":{",
"{\"status\":\""JOBS_API_STATUS_SUCCEEDED "\",\"statusDetails\":{",
"{\"status\":\""JOBS_API_STATUS_REJECTED "\",\"statusDetails\":{",
"{\"status\":\""JOBS_API_STATUS_FAILED "\",\"statusDetails\":{",
}
#define JOBS_API_STATUS_IN_PROGRESS
Definition: ota_mqtt.c:84
#define JOBS_API_STATUS_SUCCEEDED
Definition: ota_mqtt.c:86
#define JOBS_API_STATUS_FAILED
Definition: ota_mqtt.c:85
#define JOBS_API_STATUS_REJECTED
Definition: ota_mqtt.c:87

List of all the status cases a job can be in.

◆ asciiDigits

const char asciiDigits[]
static
Initial value:
=
{
'0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f',
}

These are used for both decimal and hex string conversions.