[修改] 增加freeRTOS
1. 版本FreeRTOSv202212.01,命名为kernel;
This commit is contained in:
751
kernel/FreeRTOS-Plus/Source/AWS/jobs/source/include/jobs.h
Normal file
751
kernel/FreeRTOS-Plus/Source/AWS/jobs/source/include/jobs.h
Normal file
@ -0,0 +1,751 @@
|
||||
/*
|
||||
* AWS IoT Jobs v1.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 jobs.h
|
||||
* @brief Client library APIs for the AWS IoT Jobs service.
|
||||
*
|
||||
* https://docs.aws.amazon.com/iot/latest/developerguide/jobs-api.html#jobs-mqtt-api
|
||||
*/
|
||||
|
||||
#ifndef JOBS_H_
|
||||
#define JOBS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/**
|
||||
* @ingroup jobs_constants
|
||||
* @brief Maximum length of a thing name for the AWS IoT Jobs Service.
|
||||
*/
|
||||
#define JOBS_THINGNAME_MAX_LENGTH 128U /* per AWS IoT API Reference */
|
||||
|
||||
/**
|
||||
* @ingroup jobs_constants
|
||||
* @brief Maximum length of a job ID for the AWS IoT Jobs Service.
|
||||
*/
|
||||
#define JOBS_JOBID_MAX_LENGTH 64U /* per AWS IoT API Reference */
|
||||
|
||||
#ifndef THINGNAME_MAX_LENGTH
|
||||
|
||||
/**
|
||||
* @brief User defined maximum length of a thing name for the application.
|
||||
*
|
||||
* <br><b>Default value</b>: @ref JOBS_THINGNAME_MAX_LENGTH
|
||||
*/
|
||||
#define THINGNAME_MAX_LENGTH JOBS_THINGNAME_MAX_LENGTH
|
||||
#endif
|
||||
|
||||
#ifndef JOBID_MAX_LENGTH
|
||||
|
||||
/**
|
||||
* @brief User defined maximum length of a job ID for the application.
|
||||
*
|
||||
* <br><b>Default value</b>: @ref JOBS_JOBID_MAX_LENGTH
|
||||
*/
|
||||
#define JOBID_MAX_LENGTH JOBS_JOBID_MAX_LENGTH
|
||||
#endif
|
||||
|
||||
#if ( THINGNAME_MAX_LENGTH > JOBS_THINGNAME_MAX_LENGTH )
|
||||
#error "The value of THINGNAME_MAX_LENGTH exceeds the AWS IoT Jobs Service limit."
|
||||
#endif
|
||||
|
||||
#if ( JOBID_MAX_LENGTH > JOBS_JOBID_MAX_LENGTH )
|
||||
#error "The value of JOBID_MAX_LENGTH exceeds the AWS IoT Jobs Service limit."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @cond DOXYGEN_IGNORE
|
||||
* Doxygen should ignore these macros as they are private.
|
||||
*/
|
||||
|
||||
#define JOBS_API_PREFIX "$aws/things/"
|
||||
#define JOBS_API_PREFIX_LENGTH ( sizeof( JOBS_API_PREFIX ) - 1U )
|
||||
|
||||
#define JOBS_API_BRIDGE "/jobs/"
|
||||
#define JOBS_API_BRIDGE_LENGTH ( sizeof( JOBS_API_BRIDGE ) - 1U )
|
||||
|
||||
#define JOBS_API_SUCCESS "/accepted"
|
||||
#define JOBS_API_SUCCESS_LENGTH ( sizeof( JOBS_API_SUCCESS ) - 1U )
|
||||
|
||||
#define JOBS_API_FAILURE "/rejected"
|
||||
#define JOBS_API_FAILURE_LENGTH ( sizeof( JOBS_API_FAILURE ) - 1U )
|
||||
|
||||
#define JOBS_API_JOBSCHANGED "notify"
|
||||
#define JOBS_API_JOBSCHANGED_LENGTH ( sizeof( JOBS_API_JOBSCHANGED ) - 1U )
|
||||
|
||||
#define JOBS_API_NEXTJOBCHANGED "notify-next"
|
||||
#define JOBS_API_NEXTJOBCHANGED_LENGTH ( sizeof( JOBS_API_NEXTJOBCHANGED ) - 1U )
|
||||
|
||||
#define JOBS_API_GETPENDING "get"
|
||||
#define JOBS_API_GETPENDING_LENGTH ( sizeof( JOBS_API_GETPENDING ) - 1U )
|
||||
|
||||
#define JOBS_API_STARTNEXT "start-next"
|
||||
#define JOBS_API_STARTNEXT_LENGTH ( sizeof( JOBS_API_STARTNEXT ) - 1U )
|
||||
|
||||
#define JOBS_API_DESCRIBE "get"
|
||||
#define JOBS_API_DESCRIBE_LENGTH ( sizeof( JOBS_API_DESCRIBE ) - 1U )
|
||||
|
||||
#define JOBS_API_UPDATE "update"
|
||||
#define JOBS_API_UPDATE_LENGTH ( sizeof( JOBS_API_UPDATE ) - 1U )
|
||||
|
||||
#define JOBS_API_JOBID_NEXT "$next"
|
||||
#define JOBS_API_JOBID_NEXT_LENGTH ( sizeof( JOBS_API_JOBID_NEXT ) - 1U )
|
||||
|
||||
#define JOBS_API_JOBID_NULL ""
|
||||
#define JOBS_API_LEVEL_SEPARATOR "/"
|
||||
|
||||
#define JOBS_API_COMMON_LENGTH( thingNameLength ) \
|
||||
( JOBS_API_PREFIX_LENGTH + ( thingNameLength ) + JOBS_API_BRIDGE_LENGTH )
|
||||
|
||||
/** @endcond */
|
||||
|
||||
|
||||
/**
|
||||
* @cond DOXYGEN_IGNORE
|
||||
* Doxygen should ignore this macro as it is private.
|
||||
*/
|
||||
|
||||
/* AWS IoT Jobs API topics. */
|
||||
#define JOBS_TOPIC_COMMON( thingName, jobId, jobsApi ) \
|
||||
( JOBS_API_PREFIX \
|
||||
thingName \
|
||||
JOBS_API_BRIDGE \
|
||||
jobId \
|
||||
jobsApi )
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @ingroup jobs_constants
|
||||
* @brief Topic string for subscribing to the NextJobExecutionChanged API.
|
||||
*
|
||||
* This macro should be used when the thing name is known at the compile time.
|
||||
* If the thing name is not known at compile time, the #Jobs_GetTopic API
|
||||
* should be used instead.
|
||||
*
|
||||
* @param thingName The thing name as registered with AWS IoT Core.
|
||||
*/
|
||||
#define JOBS_API_SUBSCRIBE_NEXTJOBCHANGED( thingName ) \
|
||||
JOBS_TOPIC_COMMON( thingName, JOBS_API_JOBID_NULL, JOBS_API_NEXTJOBCHANGED )
|
||||
|
||||
/**
|
||||
* @ingroup jobs_constants
|
||||
* @brief Topic string for subscribing to the JobExecutionsChanged API.
|
||||
*
|
||||
* This macro should be used when the thing name is known at the compile time.
|
||||
* If the thing name is not known at compile time, the #Jobs_GetTopic API
|
||||
* should be used instead.
|
||||
*
|
||||
* @param thingName The thing name as registered with AWS IoT Core.
|
||||
*/
|
||||
#define JOBS_API_SUBSCRIBE_JOBSCHANGED( thingName ) \
|
||||
JOBS_TOPIC_COMMON( thingName, JOBS_API_JOBID_NULL, JOBS_API_JOBSCHANGED )
|
||||
|
||||
/**
|
||||
* @ingroup jobs_constants
|
||||
* @brief Topic string for publishing to the StartNextPendingJobExecution API.
|
||||
*
|
||||
* This macro should be used when the thing name is known at the compile time.
|
||||
* If the thing name is not known at compile time, the #Jobs_StartNext API
|
||||
* should be used instead.
|
||||
*
|
||||
* @param thingName The thing name as registered with AWS IoT Core.
|
||||
*/
|
||||
#define JOBS_API_PUBLISH_STARTNEXT( thingName ) \
|
||||
JOBS_TOPIC_COMMON( thingName, JOBS_API_JOBID_NULL, JOBS_API_STARTNEXT )
|
||||
|
||||
/**
|
||||
* @ingroup jobs_constants
|
||||
* @brief Topic string for publishing to the GetPendingJobExecutions API.
|
||||
*
|
||||
* This macro should be used when the thing name is known at the compile time.
|
||||
* If the thing name is not known at compile time, the #Jobs_GetPending API
|
||||
* should be used instead.
|
||||
*
|
||||
* @param thingName The thing name as registered with AWS IoT Core.
|
||||
*/
|
||||
#define JOBS_API_PUBLISH_GETPENDING( thingName ) \
|
||||
JOBS_TOPIC_COMMON( thingName, JOBS_API_JOBID_NULL, JOBS_API_GETPENDING )
|
||||
|
||||
/**
|
||||
* @ingroup jobs_constants
|
||||
* @brief Topic string for querying the next pending job from the
|
||||
* DescribeJobExecution API.
|
||||
*
|
||||
* This macro should be used when the thing name and jobID are known at the
|
||||
* compile time. If next pending job is being queried, use $next as job ID.
|
||||
* If the thing name or job ID are not known at compile time, the #Jobs_Describe API
|
||||
* should be used instead.
|
||||
*
|
||||
* @param thingName The thing name as registered with AWS IoT Core.
|
||||
*/
|
||||
#define JOBS_API_PUBLISH_DESCRIBENEXTJOB( thingName ) \
|
||||
JOBS_TOPIC_COMMON( thingName, JOBS_API_JOBID_NEXT JOBS_API_LEVEL_SEPARATOR, JOBS_API_DESCRIBE )
|
||||
|
||||
/**
|
||||
* @ingroup jobs_constants
|
||||
* @brief The size needed to hold the longest topic for a given thing name length.
|
||||
* @note This includes space for a terminating NUL character.
|
||||
*/
|
||||
#define JOBS_API_MAX_LENGTH( thingNameLength ) \
|
||||
( JOBS_API_COMMON_LENGTH( thingNameLength ) + \
|
||||
JOBID_MAX_LENGTH + sizeof( '/' ) + JOBS_API_UPDATE_LENGTH + \
|
||||
JOBS_API_SUCCESS_LENGTH + 1U )
|
||||
|
||||
/**
|
||||
* @ingroup jobs_enum_types
|
||||
* @brief Return codes from jobs functions.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JobsError = 0,
|
||||
JobsSuccess, /**< @brief The buffer was properly written or a match was found. */
|
||||
JobsNoMatch, /**< @brief The buffer does not contain a jobs topic. */
|
||||
JobsBadParameter, /**< @brief A function parameter was NULL or has an illegal value. */
|
||||
JobsBufferTooSmall /**< @brief The buffer write was truncated. */
|
||||
} JobsStatus_t;
|
||||
|
||||
/**
|
||||
* @ingroup jobs_enum_types
|
||||
* @brief Topic values for subscription requests.
|
||||
*
|
||||
* @note The enum values for valid topics must be contiguous,
|
||||
* starting with 0. The last valid topic must be followed
|
||||
* by JobsMaxTopic. This arrangement is necessary since the
|
||||
* enum values are used as indexes to arrays of topic strings
|
||||
* and lengths.
|
||||
*
|
||||
* @note The ordering is important, providing a means
|
||||
* to divide topics into those that use a job ID
|
||||
* and those that do not.
|
||||
*
|
||||
* @note These constraints are enforced by a unit test.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JobsInvalidTopic = -1,
|
||||
JobsJobsChanged,
|
||||
JobsNextJobChanged,
|
||||
JobsGetPendingSuccess,
|
||||
JobsGetPendingFailed,
|
||||
JobsStartNextSuccess,
|
||||
JobsStartNextFailed,
|
||||
/* Topics below use a job ID. */
|
||||
JobsDescribeSuccess,
|
||||
JobsDescribeFailed,
|
||||
JobsUpdateSuccess,
|
||||
JobsUpdateFailed,
|
||||
JobsMaxTopic
|
||||
} JobsTopic_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Populate a topic string for a subscription request.
|
||||
*
|
||||
* @param[in] buffer The buffer to contain the topic string.
|
||||
* @param[in] length The size of the buffer.
|
||||
* @param[in] thingName The device's thingName as registered with AWS IoT.
|
||||
* @param[in] thingNameLength The length of the thingName.
|
||||
* @param[in] api The desired Jobs API, e.g., JobsNextJobChanged.
|
||||
* @param[out] outLength The length of the topic string written to the buffer.
|
||||
*
|
||||
* @return #JobsSuccess if the topic was written to the buffer;
|
||||
* #JobsBadParameter if invalid parameters are passed;
|
||||
* #JobsBufferTooSmall if the buffer cannot hold the full topic string.
|
||||
*
|
||||
* When all parameters are valid, the topic string is written to
|
||||
* the buffer up to one less than the buffer size. The topic is
|
||||
* ended with a NUL character.
|
||||
*
|
||||
* @note The thingName parameter does not need a NUL terminator.
|
||||
*
|
||||
* @note The AWS IoT Jobs service does not require clients to subscribe
|
||||
* to the "/accepted" and "/rejected" response topics for the APIs that
|
||||
* accept requests on PUBLISH topics. The Jobs service will send responses
|
||||
* to requests from clients irrespective of whether they have subscribed to
|
||||
* response topics or not. For more information, refer to the AWS docs here:
|
||||
* https://docs.aws.amazon.com/iot/latest/developerguide/jobs-mqtt-api.html
|
||||
*
|
||||
* <b>Example</b>
|
||||
* @code{c}
|
||||
*
|
||||
* // The following example shows usage of the Jobs_GetTopic API to
|
||||
* // generate topic string for the NextJobExecutionChanged API
|
||||
* // of AWS IoT Jobs service.
|
||||
*
|
||||
* // Every device should have a unique thing name registered with AWS IoT Core.
|
||||
* // This example uses a dummy serial number for the thing name.
|
||||
* #define THING_NAME "11223445566"
|
||||
* #define THING_NAME_LENGTH ( sizeof( THING_NAME ) - 1U )
|
||||
*
|
||||
* // This example allocates a buffer of maximum length for a Jobs topic
|
||||
* // possible for the thing name using the JOBS_API_MAX_LENGTH macro.
|
||||
* char topicBuffer[ JOBS_API_MAX_LENGTH( THING_NAME_LENGTH ) ] = { 0 };
|
||||
* uint16_t topicLength = 0U;
|
||||
* JobsStatus_t status = JobsSuccess;
|
||||
* status = Jobs_GetTopic( topicBuffer,
|
||||
* sizeof( topicBuffer ),
|
||||
* THING_NAME,
|
||||
* THING_NAME_LENGTH,
|
||||
* &( topicLength ) );
|
||||
*
|
||||
* if( status == JobsSuccess )
|
||||
* {
|
||||
* // The topic string of length, topicLength, has been
|
||||
* // generated in the buffer, topicBuffer, for the NextJobExecutionChanged API.
|
||||
* // Subscribe to this topic using an MQTT client of your choice.
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
/* @[declare_jobs_gettopic] */
|
||||
JobsStatus_t Jobs_GetTopic( char * buffer,
|
||||
size_t length,
|
||||
const char * thingName,
|
||||
uint16_t thingNameLength,
|
||||
JobsTopic_t api,
|
||||
size_t * outLength );
|
||||
/* @[declare_jobs_gettopic] */
|
||||
|
||||
/**
|
||||
* @brief Output a topic value if a Jobs API topic string is present.
|
||||
* Optionally, output a pointer to a jobID within the topic and its
|
||||
* length.
|
||||
*
|
||||
* @param[in] topic The topic string to check.
|
||||
* @param[in] length The length of the topic string.
|
||||
* @param[in] thingName The device's thingName as registered with AWS IoT.
|
||||
* @param[in] thingNameLength The length of the thingName.
|
||||
* @param[out] outApi The jobs topic API value if present, e.g., JobsUpdateSuccess.
|
||||
* @param[out] outJobId The beginning of the jobID in the topic string.
|
||||
* @param[out] outJobIdLength The length of the jobID in the topic string.
|
||||
*
|
||||
* @return #JobsSuccess if a matching topic was found;
|
||||
* #JobsNoMatch if a matching topic was NOT found
|
||||
* (parameter outApi gets JobsInvalidTopic );
|
||||
* #JobsBadParameter if invalid parameters are passed.
|
||||
*
|
||||
* @note The topic and thingName parameters do not need a NUL terminator.
|
||||
*
|
||||
* @note Not all Jobs APIs have jobIDs within the topic string.
|
||||
* NULL and 0 are output when no jobID is present.
|
||||
* The parameters jobId and jobIdLength may be NULL.
|
||||
*
|
||||
* <b>Example</b>
|
||||
* @code{c}
|
||||
*
|
||||
* // The following example shows how to use the Jobs_MatchTopic API to
|
||||
* // check if an incoming MQTT publish message is from the AWS IoT Jobs
|
||||
* // service.
|
||||
*
|
||||
* // Assuming that these variables contain incoming topic data received
|
||||
* // from the MQTT client used.
|
||||
* char * pIncomingTopic;
|
||||
* size_t topicLength;
|
||||
*
|
||||
* // Every device should have a unique thing name registered with AWS IoT Core.
|
||||
* // This example uses a dummy serial number for the thing name.
|
||||
* // The Jobs_MatchTopic API will check that the incoming message topic contains
|
||||
* // this thing name.
|
||||
* #define THING_NAME "11223445566"
|
||||
* #define THING_NAME_LENGTH ( sizeof( THING_NAME ) - 1U )
|
||||
*
|
||||
* JobsTopic_t api;
|
||||
* char * pJobId = NULL;
|
||||
* uint16_t jobIdLength;
|
||||
* JobsStatus_t status = JobsSuccess;
|
||||
*
|
||||
* status = Jobs_MatchTopic( pIncomingTopic,
|
||||
* topicLength,
|
||||
* THING_NAME,
|
||||
* THING_NAME_LENGTH,
|
||||
* &api,
|
||||
* &pJobId,
|
||||
* &jobIdLength );
|
||||
*
|
||||
* if( status == JobsSuccess )
|
||||
* {
|
||||
* // The Jobs_MatchTopic API has determined that the incoming topic is from
|
||||
* // AWS IoT Jobs service for the expected thing name.
|
||||
* // If the topic contains a jobID, then the pJobId and jobIdLength parameters
|
||||
* // populated by the API.
|
||||
*
|
||||
* if( api == JobsJobsChanged )
|
||||
* { // Message from JobExecutionsChanged API.
|
||||
* }
|
||||
*
|
||||
* else if( api == JobsNextJobChanged )
|
||||
* { // Message from NextJobExecutionChanged API.
|
||||
* }
|
||||
*
|
||||
* else if( api == JobsGetPendingSuccess )
|
||||
* { // Received accepted response for request to GetPendingJobExecutions API.
|
||||
* }
|
||||
*
|
||||
* else if( api == JobsGetPendingFailed )
|
||||
* { // Received rejected response for request to GetPendingJobExecutions API.
|
||||
* }
|
||||
*
|
||||
* else if( api == JobsStartNextSuccess )
|
||||
* { // Received accepted response for request to StartNextPendingJobExecution API.
|
||||
* }
|
||||
*
|
||||
* else if( api == JobsStartNextFailed )
|
||||
* { // Received rejected response for request to StartNextPendingJobExecution API.
|
||||
* }
|
||||
*
|
||||
* else if( api == JobsDescribeSuccess )
|
||||
* { // Received accepted response for request to DescribeJobExecution API.
|
||||
* }
|
||||
*
|
||||
* else if( api == JobsDescribeFailed )
|
||||
* { // Received rejected response for request to DescribeJobExecution API.
|
||||
* }
|
||||
*
|
||||
* else if( api == JobsUpdateSuccess )
|
||||
* { // Received accepted response for request to UpdateJobExecution API.
|
||||
* }
|
||||
*
|
||||
* else if( api == JobsUpdateFailed )
|
||||
* { // Received rejected response for request to UpdateJobExecution API.
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* // Unexpected response.
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
/* @[declare_jobs_matchtopic] */
|
||||
JobsStatus_t Jobs_MatchTopic( char * topic,
|
||||
size_t length,
|
||||
const char * thingName,
|
||||
uint16_t thingNameLength,
|
||||
JobsTopic_t * outApi,
|
||||
char ** outJobId,
|
||||
uint16_t * outJobIdLength );
|
||||
/* @[declare_jobs_matchtopic] */
|
||||
|
||||
/**
|
||||
* @brief Populate a topic string for a GetPendingJobExecutions request.
|
||||
*
|
||||
* @param[in] buffer The buffer to contain the topic string.
|
||||
* @param[in] length The size of the buffer.
|
||||
* @param[in] thingName The device's thingName as registered with AWS IoT.
|
||||
* @param[in] thingNameLength The length of the thingName.
|
||||
* @param[out] outLength The length of the topic string written to the buffer.
|
||||
*
|
||||
* @return #JobsSuccess if the topic was written to the buffer;
|
||||
* #JobsBadParameter if invalid parameters are passed;
|
||||
* #JobsBufferTooSmall if the buffer cannot hold the full topic string.
|
||||
*
|
||||
* When all parameters are valid, the topic string is written to
|
||||
* the buffer up to one less than the buffer size. The topic is
|
||||
* ended with a NUL character.
|
||||
*
|
||||
* @note The thingName parameter does not need a NUL terminator.
|
||||
*
|
||||
* @note The AWS IoT Jobs service does not require clients to subscribe
|
||||
* to the "/accepted" and "/rejected" response topics of the
|
||||
* GetPendingJobExecutions API.
|
||||
* The Jobs service will send responses to requests published to the API
|
||||
* from clients irrespective of whether they have subscribed to response topics
|
||||
* or not. For more information, refer to the AWS docs here:
|
||||
* https://docs.aws.amazon.com/iot/latest/developerguide/jobs-mqtt-api.html
|
||||
*
|
||||
* <b>Example</b>
|
||||
* @code{c}
|
||||
*
|
||||
* // The following example shows usage of the Jobs_GetPending API to
|
||||
* // generate topic string for the GetPendingJobExecutions API
|
||||
* // of the AWS IoT Jobs service.
|
||||
*
|
||||
* // Every device should have a unique thing name registered with AWS IoT Core.
|
||||
* // This example uses a dummy serial number for the thing name.
|
||||
* #define THING_NAME "11223445566"
|
||||
* #define THING_NAME_LENGTH ( sizeof( THING_NAME ) - 1U )
|
||||
*
|
||||
* // This example allocates a buffer of maximum length for a Jobs topic
|
||||
* // possible for the thing name using the JOBS_API_MAX_LENGTH macro.
|
||||
* char topicBuffer[ JOBS_API_MAX_LENGTH( THING_NAME_LENGTH ) ] = { 0 };
|
||||
* uint16_t topicLength = 0U;
|
||||
* JobsStatus_t status = JobsSuccess;
|
||||
* status = Jobs_GetPending( topicBuffer,
|
||||
* sizeof( topicBuffer ),
|
||||
* THING_NAME,
|
||||
* THING_NAME_LENGTH,
|
||||
* &( topicLength ) );
|
||||
*
|
||||
* if( status == JobsSuccess )
|
||||
* {
|
||||
* // The topic string of length, topicLength, has been
|
||||
* // generated in the buffer, topicBuffer, for the GetPendingJobExecutions API.
|
||||
* // Publish to this topic using an MQTT client of your choice.
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
/* @[declare_jobs_getpending] */
|
||||
JobsStatus_t Jobs_GetPending( char * buffer,
|
||||
size_t length,
|
||||
const char * thingName,
|
||||
uint16_t thingNameLength,
|
||||
size_t * outLength );
|
||||
/* @[declare_jobs_getpending] */
|
||||
|
||||
/**
|
||||
* @brief Populate a topic string for a StartNextPendingJobExecution request.
|
||||
*
|
||||
* @param[in] buffer The buffer to contain the topic string.
|
||||
* @param[in] length The size of the buffer.
|
||||
* @param[in] thingName The device's thingName as registered with AWS IoT.
|
||||
* @param[in] thingNameLength The length of the thingName.
|
||||
* @param[out] outLength The length of the topic string written to the buffer.
|
||||
*
|
||||
* @return #JobsSuccess if the topic was written to the buffer;
|
||||
* #JobsBadParameter if invalid parameters are passed;
|
||||
* #JobsBufferTooSmall if the buffer cannot hold the full topic string.
|
||||
*
|
||||
* When all parameters are valid, the topic string is written to
|
||||
* the buffer up to one less than the buffer size. The topic is
|
||||
* ended with a NUL character.
|
||||
*
|
||||
* @note The thingName parameter does not need a NUL terminator.
|
||||
*
|
||||
* @note The AWS IoT Jobs service does not require clients to subscribe
|
||||
* to the "/accepted" and "/rejected" response topics of the
|
||||
* StartNextPendingJobExecution API.
|
||||
* The Jobs service will send responses to requests published to the API
|
||||
* from clients irrespective of whether they have subscribed to response topics
|
||||
* or not. For more information, refer to the AWS docs here:
|
||||
* https://docs.aws.amazon.com/iot/latest/developerguide/jobs-mqtt-api.html
|
||||
*
|
||||
* <b>Example</b>
|
||||
* @code{c}
|
||||
*
|
||||
* // The following example shows usage of the Jobs_StartNext API to
|
||||
* // generate topic string for the StartNextPendingJobExecution API
|
||||
* // of the AWS IoT Jobs service.
|
||||
*
|
||||
* // Every device should have a unique thing name registered with AWS IoT Core.
|
||||
* // This example uses a dummy serial number for the thing name.
|
||||
* #define THING_NAME "11223445566"
|
||||
* #define THING_NAME_LENGTH ( sizeof( THING_NAME ) - 1U )
|
||||
*
|
||||
* // This example allocates a buffer of maximum length for a Jobs topic
|
||||
* // possible for the thing name using the JOBS_API_MAX_LENGTH macro.
|
||||
* char topicBuffer[ JOBS_API_MAX_LENGTH( THING_NAME_LENGTH ) ] = { 0 };
|
||||
* uint16_t topicLength = 0U;
|
||||
* JobsStatus_t status = JobsSuccess;
|
||||
* status = Jobs_StartNext( topicBuffer,
|
||||
* sizeof( topicBuffer ),
|
||||
* THING_NAME,
|
||||
* THING_NAME_LENGTH,
|
||||
* &( topicLength ) );
|
||||
*
|
||||
* if( status == JobsSuccess )
|
||||
* {
|
||||
* // The topic string of length, topicLength, has been generated in
|
||||
* // the buffer, topicBuffer, for the StartNextPendingJobExecution API.
|
||||
* // Publish to this topic using an MQTT client of your choice.
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
/* @[declare_jobs_startnext] */
|
||||
JobsStatus_t Jobs_StartNext( char * buffer,
|
||||
size_t length,
|
||||
const char * thingName,
|
||||
uint16_t thingNameLength,
|
||||
size_t * outLength );
|
||||
/* @[declare_jobs_startnext] */
|
||||
|
||||
/**
|
||||
* @brief Populate a topic string for a DescribeJobExecution request.
|
||||
*
|
||||
* @param[in] buffer The buffer to contain the topic string.
|
||||
* @param[in] length The size of the buffer.
|
||||
* @param[in] thingName The device's thingName as registered with AWS IoT.
|
||||
* @param[in] thingNameLength The length of the thingName.
|
||||
* @param[out] jobId The ID of the job to describe.
|
||||
* @param[out] jobIdLength The length of the job ID.
|
||||
* @param[out] outLength The length of the topic string written to the buffer.
|
||||
*
|
||||
* @return #JobsSuccess if the topic was written to the buffer;
|
||||
* #JobsBadParameter if invalid parameters are passed;
|
||||
* #JobsBufferTooSmall if the buffer cannot hold the full topic string.
|
||||
*
|
||||
* When all parameters are valid, the topic string is written to
|
||||
* the buffer up to one less than the buffer size. The topic is
|
||||
* ended with a NUL character.
|
||||
*
|
||||
* @note A jobId consisting of the string, "$next", is supported to generate
|
||||
* a topic string to request the next pending job.
|
||||
*
|
||||
* @note The thingName and jobId parameters do not need a NUL terminator.
|
||||
*
|
||||
* @note The AWS IoT Jobs service does not require clients to subscribe
|
||||
* to the "/accepted" and "/rejected" response topics of the
|
||||
* DescribeJobExecution API.
|
||||
* The Jobs service will send responses to requests published to the API
|
||||
* from clients irrespective of whether they have subscribed to response topics
|
||||
* or not. For more information, refer to the AWS docs here:
|
||||
* https://docs.aws.amazon.com/iot/latest/developerguide/jobs-mqtt-api.html
|
||||
*
|
||||
* <b>Example</b>
|
||||
* @code{c}
|
||||
*
|
||||
* // The following example shows usage of the Jobs_Describe API to
|
||||
* // generate topic string for the DescribeJobExecution API
|
||||
* // of the AWS IoT Jobs service.
|
||||
*
|
||||
* // Every device should have a unique thing name registered with AWS IoT Core.
|
||||
* // This example uses a dummy serial number for the thing name.
|
||||
* #define THING_NAME "11223445566"
|
||||
* #define THING_NAME_LENGTH ( sizeof( THING_NAME ) - 1U )
|
||||
*
|
||||
* // The job ID is required to send a status update for a job to the AWS IoT
|
||||
* // Jobs service.
|
||||
* #define JOB_ID "My_Job"
|
||||
* #define JOB_ID_LENGTH ( sizeof( JOB_ID ) - 1U )
|
||||
*
|
||||
* // This example allocates a buffer of maximum length for a Jobs topic
|
||||
* // possible for the thing name using the JOBS_API_MAX_LENGTH macro.
|
||||
* char topicBuffer[ JOBS_API_MAX_LENGTH( THING_NAME_LENGTH ) ] = { 0 };
|
||||
* uint16_t topicLength = 0U;
|
||||
* JobsStatus_t status = JobsSuccess;
|
||||
* status = Jobs_Describe( topicBuffer,
|
||||
* sizeof( topicBuffer ),
|
||||
* THING_NAME,
|
||||
* THING_NAME_LENGTH,
|
||||
* JOB_ID,
|
||||
* JOB_ID_LENGTH,
|
||||
* &( topicLength ) );
|
||||
*
|
||||
* if( status == JobsSuccess )
|
||||
* {
|
||||
* // The topic string of length, topicLength, has been generated in
|
||||
* // the buffer, topicBuffer, for the DescribeJobExecution API.
|
||||
* // Publish to this topic using an MQTT client of your choice.
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
/* @[declare_jobs_describe] */
|
||||
JobsStatus_t Jobs_Describe( char * buffer,
|
||||
size_t length,
|
||||
const char * thingName,
|
||||
uint16_t thingNameLength,
|
||||
const char * jobId,
|
||||
uint16_t jobIdLength,
|
||||
size_t * outLength );
|
||||
/* @[declare_jobs_describe] */
|
||||
|
||||
/**
|
||||
* @brief Populate a topic string for an UpdateJobExecution request.
|
||||
*
|
||||
* @param[in] buffer The buffer to contain the topic string.
|
||||
* @param[in] length The size of the buffer.
|
||||
* @param[in] thingName The device's thingName as registered with AWS IoT.
|
||||
* @param[in] thingNameLength The length of the thingName.
|
||||
* @param[out] jobId The ID of the job to describe.
|
||||
* @param[out] jobIdLength The length of the job ID.
|
||||
* @param[out] outLength The length of the topic string written to the buffer.
|
||||
*
|
||||
* @return #JobsSuccess if the topic was written to the buffer;
|
||||
* #JobsBadParameter if invalid parameters are passed;
|
||||
* #JobsBufferTooSmall if the buffer cannot hold the full topic string.
|
||||
*
|
||||
* When all parameters are valid, the topic string is written to
|
||||
* the buffer up to one less than the buffer size. The topic is
|
||||
* ended with a NUL character.
|
||||
*
|
||||
* @note The thingName and jobId parameters do not need a NUL terminator.
|
||||
*
|
||||
* @note The AWS IoT Jobs service does not require clients to subscribe
|
||||
* to the "/accepted" and "/rejected" response topics of the
|
||||
* UpdateJobExecution API.
|
||||
* The Jobs service will send responses to requests published to the API
|
||||
* from clients irrespective of whether they have subscribed to response topics
|
||||
* or not. For more information, refer to the AWS docs here:
|
||||
* https://docs.aws.amazon.com/iot/latest/developerguide/jobs-mqtt-api.html
|
||||
*
|
||||
* <b>Example</b>
|
||||
* @code{c}
|
||||
*
|
||||
* // The following example shows usage of the Jobs_Update API to
|
||||
* // generate topic string for the UpdateJobExecution API
|
||||
* // of the AWS IoT Jobs service.
|
||||
*
|
||||
* // Every device should have a unique thing name registered with AWS IoT Core.
|
||||
* // This example uses a dummy serial number for the thing name.
|
||||
* #define THING_NAME "11223445566"
|
||||
* #define THING_NAME_LENGTH ( sizeof( THING_NAME ) - 1U )
|
||||
*
|
||||
* // The job ID is required to send a status update for a job to the AWS IoT
|
||||
* // Jobs service.
|
||||
* #define JOB_ID "My_Job"
|
||||
* #define JOB_ID_LENGTH ( sizeof( JOB_ID ) - 1U )
|
||||
*
|
||||
* // This example allocates a buffer of maximum length for a Jobs topic
|
||||
* // possible for the thing name using the JOBS_API_MAX_LENGTH macro.
|
||||
* char topicBuffer[ JOBS_API_MAX_LENGTH( THING_NAME_LENGTH ) ] = { 0 };
|
||||
* uint16_t topicLength = 0U;
|
||||
* JobsStatus_t status = JobsSuccess;
|
||||
* status = Jobs_Update( topicBuffer,
|
||||
* sizeof( topicBuffer ),
|
||||
* THING_NAME,
|
||||
* THING_NAME_LENGTH,
|
||||
* JOB_ID,
|
||||
* JOB_ID_LENGTH,
|
||||
* &( topicLength ) );
|
||||
*
|
||||
* if( status == JobsSuccess )
|
||||
* {
|
||||
* // The topic string of length, topicLength, has been
|
||||
* // generated in the buffer, topicBuffer, for the UpdateJobExecution API.
|
||||
* // Publish to this topic using an MQTT client of your choice.
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
/* @[declare_jobs_update] */
|
||||
JobsStatus_t Jobs_Update( char * buffer,
|
||||
size_t length,
|
||||
const char * thingName,
|
||||
uint16_t thingNameLength,
|
||||
const char * jobId,
|
||||
uint16_t jobIdLength,
|
||||
size_t * outLength );
|
||||
/* @[declare_jobs_update] */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* ifndef JOBS_H_ */
|
||||
747
kernel/FreeRTOS-Plus/Source/AWS/jobs/source/jobs.c
Normal file
747
kernel/FreeRTOS-Plus/Source/AWS/jobs/source/jobs.c
Normal file
@ -0,0 +1,747 @@
|
||||
/*
|
||||
* AWS IoT Jobs v1.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 jobs.c
|
||||
* @brief Implementation of the APIs from jobs.h.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "jobs.h"
|
||||
|
||||
/** @cond DO_NOT_DOCUMENT */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
true = 1, false = 0
|
||||
} bool_;
|
||||
|
||||
/**
|
||||
* @brief Table of topic API strings in JobsTopic_t order.
|
||||
*/
|
||||
static const char * const apiTopic[] =
|
||||
{
|
||||
JOBS_API_JOBSCHANGED,
|
||||
JOBS_API_NEXTJOBCHANGED,
|
||||
JOBS_API_GETPENDING JOBS_API_SUCCESS,
|
||||
JOBS_API_GETPENDING JOBS_API_FAILURE,
|
||||
JOBS_API_STARTNEXT JOBS_API_SUCCESS,
|
||||
JOBS_API_STARTNEXT JOBS_API_FAILURE,
|
||||
JOBS_API_DESCRIBE JOBS_API_SUCCESS,
|
||||
JOBS_API_DESCRIBE JOBS_API_FAILURE,
|
||||
JOBS_API_UPDATE JOBS_API_SUCCESS,
|
||||
JOBS_API_UPDATE JOBS_API_FAILURE,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Table of topic API string lengths in JobsTopic_t order.
|
||||
*/
|
||||
static const size_t apiTopicLength[] =
|
||||
{
|
||||
JOBS_API_JOBSCHANGED_LENGTH,
|
||||
JOBS_API_NEXTJOBCHANGED_LENGTH,
|
||||
JOBS_API_GETPENDING_LENGTH + JOBS_API_SUCCESS_LENGTH,
|
||||
JOBS_API_GETPENDING_LENGTH + JOBS_API_FAILURE_LENGTH,
|
||||
JOBS_API_STARTNEXT_LENGTH + JOBS_API_SUCCESS_LENGTH,
|
||||
JOBS_API_STARTNEXT_LENGTH + JOBS_API_FAILURE_LENGTH,
|
||||
JOBS_API_DESCRIBE_LENGTH + JOBS_API_SUCCESS_LENGTH,
|
||||
JOBS_API_DESCRIBE_LENGTH + JOBS_API_FAILURE_LENGTH,
|
||||
JOBS_API_UPDATE_LENGTH + JOBS_API_SUCCESS_LENGTH,
|
||||
JOBS_API_UPDATE_LENGTH + JOBS_API_FAILURE_LENGTH,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Predicate returns true for a valid thing name or job ID character.
|
||||
*
|
||||
* @param[in] a character to check
|
||||
* @param[in] allowColon set to true for thing names
|
||||
*
|
||||
* @return true if the character is valid;
|
||||
* false otherwise
|
||||
*/
|
||||
static bool_ isValidChar( char a,
|
||||
bool_ allowColon )
|
||||
{
|
||||
bool_ ret;
|
||||
|
||||
if( ( a == '-' ) || ( a == '_' ) )
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else if( ( a >= '0' ) && ( a <= '9' ) )
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else if( ( a >= 'A' ) && ( a <= 'Z' ) )
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else if( ( a >= 'a' ) && ( a <= 'z' ) )
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else if( a == ':' )
|
||||
{
|
||||
ret = allowColon;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Predicate returns true for a valid identifier.
|
||||
*
|
||||
* The identifier may be a thing name or a job ID.
|
||||
*
|
||||
* @param[in] id character sequence to check
|
||||
* @param[in] length length of the character sequence
|
||||
* @param[in] max maximum length of a valid identifier
|
||||
* @param[in] allowColon set to true for thing names
|
||||
*
|
||||
* @return true if the identifier is valid;
|
||||
* false otherwise
|
||||
*/
|
||||
static bool_ isValidID( const char * id,
|
||||
uint16_t length,
|
||||
uint16_t max,
|
||||
bool_ allowColon )
|
||||
{
|
||||
bool_ ret = false;
|
||||
|
||||
if( ( id != NULL ) && ( length > 0U ) &&
|
||||
( length <= max ) )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for( i = 0; i < length; i++ )
|
||||
{
|
||||
if( isValidChar( id[ i ], allowColon ) == false )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ( i == length ) ? true : false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Predicate returns true for a valid thing name string.
|
||||
*
|
||||
* @param[in] thingName character sequence to check
|
||||
* @param[in] thingNameLength length of the character sequence
|
||||
*
|
||||
* @return true if the thing name is valid;
|
||||
* false otherwise
|
||||
*/
|
||||
static bool_ isValidThingName( const char * thingName,
|
||||
uint16_t thingNameLength )
|
||||
{
|
||||
return isValidID( thingName, thingNameLength,
|
||||
THINGNAME_MAX_LENGTH, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Predicate returns true for a valid job ID string.
|
||||
*
|
||||
* @param[in] jobId character sequence to check
|
||||
* @param[in] jobIdLength length of the character sequence
|
||||
*
|
||||
* @return true if the job ID is valid;
|
||||
* false otherwise
|
||||
*/
|
||||
static bool_ isValidJobId( const char * jobId,
|
||||
uint16_t jobIdLength )
|
||||
{
|
||||
return isValidID( jobId, jobIdLength,
|
||||
JOBID_MAX_LENGTH, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A strncpy replacement based on lengths only.
|
||||
*
|
||||
* @param[in] buffer The buffer to be written.
|
||||
* @param[in,out] start The index at which to begin.
|
||||
* @param[in] max The size of the buffer.
|
||||
* @param[in] value The characters to copy.
|
||||
* @param[in] valueLength How many characters to copy.
|
||||
*
|
||||
* @return #JobsSuccess if the value was written to the buffer;
|
||||
* #JobsBufferTooSmall if the buffer cannot hold the entire value.
|
||||
*
|
||||
* @note There is no harm from calling this function when
|
||||
* start >= max. This allows for sequential calls to
|
||||
* strnAppend() where only the final call's return value
|
||||
* is needed.
|
||||
*/
|
||||
static JobsStatus_t strnAppend( char * buffer,
|
||||
size_t * start,
|
||||
size_t max,
|
||||
const char * value,
|
||||
size_t valueLength )
|
||||
{
|
||||
size_t i, j = 0;
|
||||
|
||||
assert( ( buffer != NULL ) && ( start != NULL ) && ( value != NULL ) );
|
||||
|
||||
i = *start;
|
||||
|
||||
while( ( i < max ) && ( j < valueLength ) )
|
||||
{
|
||||
buffer[ i ] = value[ j ];
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
*start = i;
|
||||
|
||||
return ( i < max ) ? JobsSuccess : JobsBufferTooSmall;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Populate the common leading portion of a topic string.
|
||||
*
|
||||
* @param[in] buffer The buffer to contain the topic string.
|
||||
* @param[in,out] start The index at which to begin.
|
||||
* @param[in] length The size of the buffer.
|
||||
* @param[in] thingName The device's thingName as registered with AWS IoT.
|
||||
* @param[in] thingNameLength The length of the thingName.
|
||||
*/
|
||||
static void writePreamble( char * buffer,
|
||||
size_t * start,
|
||||
size_t length,
|
||||
const char * thingName,
|
||||
uint16_t thingNameLength )
|
||||
{
|
||||
( void ) strnAppend( buffer, start, length,
|
||||
JOBS_API_PREFIX, JOBS_API_PREFIX_LENGTH );
|
||||
( void ) strnAppend( buffer, start, length,
|
||||
thingName, thingNameLength );
|
||||
( void ) strnAppend( buffer, start, length,
|
||||
JOBS_API_BRIDGE, JOBS_API_BRIDGE_LENGTH );
|
||||
}
|
||||
|
||||
#define checkThingParams() \
|
||||
( isValidThingName( thingName, thingNameLength ) == true )
|
||||
|
||||
#define checkCommonParams() \
|
||||
( ( buffer != NULL ) && ( length > 0U ) && checkThingParams() )
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* See jobs.h for docs.
|
||||
*
|
||||
* @brief Populate a topic string for a subscription request.
|
||||
*/
|
||||
JobsStatus_t Jobs_GetTopic( char * buffer,
|
||||
size_t length,
|
||||
const char * thingName,
|
||||
uint16_t thingNameLength,
|
||||
JobsTopic_t api,
|
||||
size_t * outLength )
|
||||
{
|
||||
JobsStatus_t ret = JobsBadParameter;
|
||||
size_t start = 0U;
|
||||
|
||||
if( checkCommonParams() &&
|
||||
( api > JobsInvalidTopic ) && ( api < JobsMaxTopic ) )
|
||||
{
|
||||
writePreamble( buffer, &start, length, thingName, thingNameLength );
|
||||
|
||||
if( api >= JobsDescribeSuccess )
|
||||
{
|
||||
( void ) strnAppend( buffer, &start, length,
|
||||
"+/", ( sizeof( "+/" ) - 1U ) );
|
||||
}
|
||||
|
||||
ret = strnAppend( buffer, &start, length,
|
||||
apiTopic[ api ], apiTopicLength[ api ] );
|
||||
|
||||
if( start == length )
|
||||
{
|
||||
start--;
|
||||
}
|
||||
|
||||
buffer[ start ] = '\0';
|
||||
|
||||
if( outLength != NULL )
|
||||
{
|
||||
*outLength = start;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @cond DO_NOT_DOCUMENT */
|
||||
|
||||
/**
|
||||
* @brief Compare the leading n bytes of two character sequences.
|
||||
*
|
||||
* @param[in] a first character sequence
|
||||
* @param[in] b second character sequence
|
||||
* @param[in] n number of bytes
|
||||
*
|
||||
* @return JobsSuccess if the sequences are the same;
|
||||
* JobsNoMatch otherwise
|
||||
*/
|
||||
static JobsStatus_t strnEq( const char * a,
|
||||
const char * b,
|
||||
size_t n )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert( ( a != NULL ) && ( b != NULL ) );
|
||||
|
||||
for( i = 0U; i < n; i++ )
|
||||
{
|
||||
if( a[ i ] != b[ i ] )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ( i == n ) ? JobsSuccess : JobsNoMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wrap strnEq() with a check to compare two lengths.
|
||||
*
|
||||
* @param[in] a first character sequence
|
||||
* @param[in] aLength Length of a
|
||||
* @param[in] b second character sequence
|
||||
* @param[in] bLength Length of b
|
||||
*
|
||||
* @return JobsSuccess if the sequences are the same;
|
||||
* JobsNoMatch otherwise
|
||||
*/
|
||||
static JobsStatus_t strnnEq( const char * a,
|
||||
size_t aLength,
|
||||
const char * b,
|
||||
size_t bLength )
|
||||
{
|
||||
JobsStatus_t ret = JobsNoMatch;
|
||||
|
||||
if( aLength == bLength )
|
||||
{
|
||||
ret = strnEq( a, b, aLength );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Predicate returns true for a match to JOBS_API_JOBID_NEXT
|
||||
*
|
||||
* @param[in] jobId character sequence to check
|
||||
* @param[in] jobIdLength length of the character sequence
|
||||
*
|
||||
* @return true if the job ID matches;
|
||||
* false otherwise
|
||||
*/
|
||||
static bool_ isNextJobId( const char * jobId,
|
||||
uint16_t jobIdLength )
|
||||
{
|
||||
bool_ ret = false;
|
||||
|
||||
if( ( jobId != NULL ) &&
|
||||
( strnnEq( JOBS_API_JOBID_NEXT, JOBS_API_JOBID_NEXT_LENGTH, jobId, jobIdLength ) == JobsSuccess ) )
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Parse a job ID and search for the API portion of a topic string in a table.
|
||||
*
|
||||
* @param[in] topic The topic string to check.
|
||||
* @param[in] topicLength The length of the topic string.
|
||||
* @param[out] outApi The jobs topic API value if present, e.g., #JobsUpdateSuccess.
|
||||
* @param[out] outJobId The beginning of the jobID in the topic string.
|
||||
* @param[out] outJobIdLength The length of the jobID in the topic string.
|
||||
*
|
||||
* @return #JobsSuccess if a matching topic was found;
|
||||
* #JobsNoMatch if a matching topic was NOT found
|
||||
* (parameter outApi gets #JobsInvalidTopic ).
|
||||
*/
|
||||
static JobsStatus_t matchIdApi( char * topic,
|
||||
size_t topicLength,
|
||||
JobsTopic_t * outApi,
|
||||
char ** outJobId,
|
||||
uint16_t * outJobIdLength )
|
||||
{
|
||||
JobsStatus_t ret = JobsNoMatch;
|
||||
size_t i;
|
||||
char * p = topic;
|
||||
size_t length = topicLength;
|
||||
char * jobId = NULL;
|
||||
uint16_t jobIdLength = 0U;
|
||||
|
||||
assert( ( topic != NULL ) && ( outApi != NULL ) &&
|
||||
( outJobId != NULL ) && ( outJobIdLength != NULL ) );
|
||||
|
||||
for( i = 0U; i < length; i++ )
|
||||
{
|
||||
if( ( i > 0U ) && ( p[ i ] == '/' ) )
|
||||
{
|
||||
/* Save the leading job ID and its length. */
|
||||
jobId = p;
|
||||
jobIdLength = ( uint16_t ) i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Advance p to after the '/' and reduce buffer length
|
||||
* for the remaining API search. */
|
||||
p = &p[ jobIdLength + 1U ];
|
||||
length = length - jobIdLength - 1U;
|
||||
|
||||
if( ( isNextJobId( jobId, jobIdLength ) == true ) ||
|
||||
( isValidJobId( jobId, jobIdLength ) == true ) )
|
||||
{
|
||||
if( JobsSuccess == strnnEq( p, length, apiTopic[ JobsDescribeSuccess ], apiTopicLength[ JobsDescribeSuccess ] ) )
|
||||
{
|
||||
ret = JobsSuccess;
|
||||
*outApi = JobsDescribeSuccess;
|
||||
}
|
||||
else if( JobsSuccess == strnnEq( p, length, apiTopic[ JobsDescribeFailed ], apiTopicLength[ JobsDescribeFailed ] ) )
|
||||
{
|
||||
ret = JobsSuccess;
|
||||
*outApi = JobsDescribeFailed;
|
||||
}
|
||||
else if( JobsSuccess == strnnEq( p, length, apiTopic[ JobsUpdateSuccess ], apiTopicLength[ JobsUpdateSuccess ] ) )
|
||||
{
|
||||
ret = JobsSuccess;
|
||||
*outApi = JobsUpdateSuccess;
|
||||
}
|
||||
else if( JobsSuccess == strnnEq( p, length, apiTopic[ JobsUpdateFailed ], apiTopicLength[ JobsUpdateFailed ] ) )
|
||||
{
|
||||
ret = JobsSuccess;
|
||||
*outApi = JobsUpdateFailed;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* MISRA Empty Body */
|
||||
}
|
||||
|
||||
if( ret == JobsSuccess )
|
||||
{
|
||||
*outJobId = jobId;
|
||||
*outJobIdLength = jobIdLength;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Search for the API portion of a topic string in a table.
|
||||
*
|
||||
* @param[in] topic The topic string to check.
|
||||
* @param[in] topicLength The length of the topic string.
|
||||
* @param[out] outApi The jobs topic API value if present, e.g., #JobsUpdateSuccess.
|
||||
* @param[out] outJobId The beginning of the jobID in the topic string.
|
||||
* @param[out] outJobIdLength The length of the jobID in the topic string.
|
||||
*
|
||||
* @return #JobsSuccess if a matching topic was found;
|
||||
* #JobsNoMatch if a matching topic was NOT found
|
||||
* (parameter outApi gets #JobsInvalidTopic ).
|
||||
*/
|
||||
static JobsStatus_t matchApi( char * topic,
|
||||
size_t topicLength,
|
||||
JobsTopic_t * outApi,
|
||||
char ** outJobId,
|
||||
uint16_t * outJobIdLength )
|
||||
{
|
||||
JobsStatus_t ret = JobsNoMatch;
|
||||
|
||||
assert( ( topic != NULL ) && ( outApi != NULL ) &&
|
||||
( outJobId != NULL ) && ( outJobIdLength != NULL ) );
|
||||
|
||||
/* The first set of APIs do not have job IDs. */
|
||||
if( JobsSuccess == strnnEq( topic, topicLength, apiTopic[ JobsJobsChanged ], apiTopicLength[ JobsJobsChanged ] ) )
|
||||
{
|
||||
ret = JobsSuccess;
|
||||
*outApi = JobsJobsChanged;
|
||||
}
|
||||
else if( JobsSuccess == strnnEq( topic, topicLength, apiTopic[ JobsNextJobChanged ], apiTopicLength[ JobsNextJobChanged ] ) )
|
||||
{
|
||||
ret = JobsSuccess;
|
||||
*outApi = JobsNextJobChanged;
|
||||
}
|
||||
else if( JobsSuccess == strnnEq( topic, topicLength, apiTopic[ JobsGetPendingSuccess ], apiTopicLength[ JobsGetPendingSuccess ] ) )
|
||||
{
|
||||
ret = JobsSuccess;
|
||||
*outApi = JobsGetPendingSuccess;
|
||||
}
|
||||
else if( JobsSuccess == strnnEq( topic, topicLength, apiTopic[ JobsGetPendingFailed ], apiTopicLength[ JobsGetPendingFailed ] ) )
|
||||
{
|
||||
ret = JobsSuccess;
|
||||
*outApi = JobsGetPendingFailed;
|
||||
}
|
||||
else if( JobsSuccess == strnnEq( topic, topicLength, apiTopic[ JobsStartNextSuccess ], apiTopicLength[ JobsStartNextSuccess ] ) )
|
||||
{
|
||||
ret = JobsSuccess;
|
||||
*outApi = JobsStartNextSuccess;
|
||||
}
|
||||
else if( JobsSuccess == strnnEq( topic, topicLength, apiTopic[ JobsStartNextFailed ], apiTopicLength[ JobsStartNextFailed ] ) )
|
||||
{
|
||||
ret = JobsSuccess;
|
||||
*outApi = JobsStartNextFailed;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* MISRA Empty Body */
|
||||
}
|
||||
|
||||
/* The remaining APIs must have a job ID. */
|
||||
if( ret == JobsNoMatch )
|
||||
{
|
||||
ret = matchIdApi( topic, topicLength, outApi, outJobId, outJobIdLength );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* See jobs.h for docs.
|
||||
*
|
||||
* @brief Output a topic value if a Jobs API topic string is present.
|
||||
*/
|
||||
JobsStatus_t Jobs_MatchTopic( char * topic,
|
||||
size_t length,
|
||||
const char * thingName,
|
||||
uint16_t thingNameLength,
|
||||
JobsTopic_t * outApi,
|
||||
char ** outJobId,
|
||||
uint16_t * outJobIdLength )
|
||||
{
|
||||
JobsStatus_t ret = JobsBadParameter;
|
||||
JobsTopic_t api = JobsInvalidTopic;
|
||||
char * jobId = NULL;
|
||||
uint16_t jobIdLength = 0U;
|
||||
|
||||
if( ( topic != NULL ) && ( outApi != NULL ) && checkThingParams() && ( length > 0U ) )
|
||||
{
|
||||
ret = JobsNoMatch;
|
||||
|
||||
if( ( length > JOBS_API_COMMON_LENGTH( thingNameLength ) ) &&
|
||||
( length < JOBS_API_MAX_LENGTH( thingNameLength ) ) )
|
||||
{
|
||||
char * prefix = topic;
|
||||
char * name = &prefix[ JOBS_API_PREFIX_LENGTH ];
|
||||
char * bridge = &name[ thingNameLength ];
|
||||
|
||||
/* check the shortest match first */
|
||||
if( ( strnEq( bridge, JOBS_API_BRIDGE, JOBS_API_BRIDGE_LENGTH ) == JobsSuccess ) &&
|
||||
( strnEq( prefix, JOBS_API_PREFIX, JOBS_API_PREFIX_LENGTH ) == JobsSuccess ) &&
|
||||
( strnEq( name, thingName, thingNameLength ) == JobsSuccess ) )
|
||||
{
|
||||
char * tail = &bridge[ JOBS_API_BRIDGE_LENGTH ];
|
||||
size_t tailLength = length - JOBS_API_COMMON_LENGTH( thingNameLength );
|
||||
|
||||
ret = matchApi( tail, tailLength, &api, &jobId, &jobIdLength );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( outApi != NULL )
|
||||
{
|
||||
*outApi = api;
|
||||
}
|
||||
|
||||
if( outJobId != NULL )
|
||||
{
|
||||
*outJobId = jobId;
|
||||
}
|
||||
|
||||
if( outJobIdLength != NULL )
|
||||
{
|
||||
*outJobIdLength = jobIdLength;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* See jobs.h for docs.
|
||||
*
|
||||
* @brief Populate a topic string for a GetPendingJobExecutions request.
|
||||
*/
|
||||
JobsStatus_t Jobs_GetPending( char * buffer,
|
||||
size_t length,
|
||||
const char * thingName,
|
||||
uint16_t thingNameLength,
|
||||
size_t * outLength )
|
||||
{
|
||||
JobsStatus_t ret = JobsBadParameter;
|
||||
size_t start = 0U;
|
||||
|
||||
if( checkCommonParams() )
|
||||
{
|
||||
writePreamble( buffer, &start, length, thingName, thingNameLength );
|
||||
|
||||
ret = strnAppend( buffer, &start, length,
|
||||
JOBS_API_GETPENDING, JOBS_API_GETPENDING_LENGTH );
|
||||
|
||||
start = ( start >= length ) ? ( length - 1U ) : start;
|
||||
buffer[ start ] = '\0';
|
||||
|
||||
if( outLength != NULL )
|
||||
{
|
||||
*outLength = start;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* See jobs.h for docs.
|
||||
*
|
||||
* @brief Populate a topic string for a StartNextPendingJobExecution request.
|
||||
*/
|
||||
JobsStatus_t Jobs_StartNext( char * buffer,
|
||||
size_t length,
|
||||
const char * thingName,
|
||||
uint16_t thingNameLength,
|
||||
size_t * outLength )
|
||||
{
|
||||
JobsStatus_t ret = JobsBadParameter;
|
||||
size_t start = 0U;
|
||||
|
||||
if( checkCommonParams() )
|
||||
{
|
||||
writePreamble( buffer, &start, length, thingName, thingNameLength );
|
||||
|
||||
ret = strnAppend( buffer, &start, length,
|
||||
JOBS_API_STARTNEXT, JOBS_API_STARTNEXT_LENGTH );
|
||||
|
||||
start = ( start >= length ) ? ( length - 1U ) : start;
|
||||
buffer[ start ] = '\0';
|
||||
|
||||
if( outLength != NULL )
|
||||
{
|
||||
*outLength = start;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See jobs.h for docs.
|
||||
*
|
||||
* @brief Populate a topic string for a DescribeJobExecution request.
|
||||
*/
|
||||
JobsStatus_t Jobs_Describe( char * buffer,
|
||||
size_t length,
|
||||
const char * thingName,
|
||||
uint16_t thingNameLength,
|
||||
const char * jobId,
|
||||
uint16_t jobIdLength,
|
||||
size_t * outLength )
|
||||
{
|
||||
JobsStatus_t ret = JobsBadParameter;
|
||||
size_t start = 0U;
|
||||
|
||||
if( checkCommonParams() &&
|
||||
( ( isNextJobId( jobId, jobIdLength ) == true ) ||
|
||||
( isValidJobId( jobId, jobIdLength ) == true ) ) )
|
||||
{
|
||||
writePreamble( buffer, &start, length, thingName, thingNameLength );
|
||||
|
||||
( void ) strnAppend( buffer, &start, length,
|
||||
jobId, jobIdLength );
|
||||
( void ) strnAppend( buffer, &start, length,
|
||||
"/", ( sizeof( "/" ) - 1U ) );
|
||||
ret = strnAppend( buffer, &start, length,
|
||||
JOBS_API_DESCRIBE, JOBS_API_DESCRIBE_LENGTH );
|
||||
|
||||
start = ( start >= length ) ? ( length - 1U ) : start;
|
||||
buffer[ start ] = '\0';
|
||||
|
||||
if( outLength != NULL )
|
||||
{
|
||||
*outLength = start;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* See jobs.h for docs.
|
||||
*
|
||||
* @brief Populate a topic string for an UpdateJobExecution request.
|
||||
*/
|
||||
JobsStatus_t Jobs_Update( char * buffer,
|
||||
size_t length,
|
||||
const char * thingName,
|
||||
uint16_t thingNameLength,
|
||||
const char * jobId,
|
||||
uint16_t jobIdLength,
|
||||
size_t * outLength )
|
||||
{
|
||||
JobsStatus_t ret = JobsBadParameter;
|
||||
size_t start = 0U;
|
||||
|
||||
if( checkCommonParams() &&
|
||||
( isValidJobId( jobId, jobIdLength ) == true ) )
|
||||
{
|
||||
writePreamble( buffer, &start, length, thingName, thingNameLength );
|
||||
|
||||
( void ) strnAppend( buffer, &start, length,
|
||||
jobId, jobIdLength );
|
||||
( void ) strnAppend( buffer, &start, length,
|
||||
"/", ( sizeof( "/" ) - 1U ) );
|
||||
ret = strnAppend( buffer, &start, length,
|
||||
JOBS_API_UPDATE, JOBS_API_UPDATE_LENGTH );
|
||||
|
||||
start = ( start >= length ) ? ( length - 1U ) : start;
|
||||
buffer[ start ] = '\0';
|
||||
|
||||
if( outLength != NULL )
|
||||
{
|
||||
*outLength = start;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user