2 * AWS IoT Shadow V2.1.0
\r
3 * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
24 * @file aws_iot_shadow.h
\r
25 * @brief User-facing functions of the Shadow library.
\r
28 #ifndef AWS_IOT_SHADOW_H_
\r
29 #define AWS_IOT_SHADOW_H_
\r
31 /* The config header is always included first. */
\r
32 #include "iot_config.h"
\r
34 /* Shadow types include. */
\r
35 #include "types/aws_iot_shadow_types.h"
\r
37 /*------------------------ Shadow library functions -------------------------*/
\r
40 * @functionspage{shadow,Shadow library}
\r
41 * - @functionname{shadow_function_init}
\r
42 * - @functionname{shadow_function_cleanup}
\r
43 * - @functionname{shadow_function_deleteasync}
\r
44 * - @functionname{shadow_function_deletesync}
\r
45 * - @functionname{shadow_function_getasync}
\r
46 * - @functionname{shadow_function_getsync}
\r
47 * - @functionname{shadow_function_updateasync}
\r
48 * - @functionname{shadow_function_updatesync}
\r
49 * - @functionname{shadow_function_wait}
\r
50 * - @functionname{shadow_function_setdeltacallback}
\r
51 * - @functionname{shadow_function_setupdatedcallback}
\r
52 * - @functionname{shadow_function_removepersistentsubscriptions}
\r
53 * - @functionname{shadow_function_strerror}
\r
57 * @functionpage{AwsIotShadow_Init,shadow,init}
\r
58 * @functionpage{AwsIotShadow_Cleanup,shadow,cleanup}
\r
59 * @functionpage{AwsIotShadow_DeleteAsync,shadow,deleteasync}
\r
60 * @functionpage{AwsIotShadow_DeleteSync,shadow,deletesync}
\r
61 * @functionpage{AwsIotShadow_GetAsync,shadow,getasync}
\r
62 * @functionpage{AwsIotShadow_GetSync,shadow,getsync}
\r
63 * @functionpage{AwsIotShadow_UpdateAsync,shadow,updateasync}
\r
64 * @functionpage{AwsIotShadow_UpdateSync,shadow,updatesync}
\r
65 * @functionpage{AwsIotShadow_Wait,shadow,wait}
\r
66 * @functionpage{AwsIotShadow_SetDeltaCallback,shadow,setdeltacallback}
\r
67 * @functionpage{AwsIotShadow_SetUpdatedCallback,shadow,setupdatedcallback}
\r
68 * @functionpage{AwsIotShadow_RemovePersistentSubscriptions,shadow,removepersistentsubscriptions}
\r
69 * @functionpage{AwsIotShadow_strerror,shadow,strerror}
\r
73 * @brief One-time initialization function for the Shadow library.
\r
75 * This function performs internal setup of the Shadow library. <b>It must be
\r
76 * called once (and only once) before calling any other Shadow function.</b>
\r
77 * Calling this function more than once without first calling @ref
\r
78 * shadow_function_cleanup may result in a crash.
\r
80 * @param[in] mqttTimeout The amount of time (in milliseconds) that the Shadow
\r
81 * library will wait for MQTT operations. Optional; set this to `0` to use
\r
82 * @ref AWS_IOT_SHADOW_DEFAULT_MQTT_TIMEOUT_MS.
\r
84 * @return One of the following:
\r
85 * - #AWS_IOT_SHADOW_SUCCESS
\r
86 * - #AWS_IOT_SHADOW_INIT_FAILED
\r
88 * @warning No thread-safety guarantees are provided for this function.
\r
90 * @see @ref shadow_function_cleanup
\r
92 /* @[declare_shadow_init] */
\r
93 AwsIotShadowError_t AwsIotShadow_Init( uint32_t mqttTimeout );
\r
94 /* @[declare_shadow_init] */
\r
97 * @brief One-time deinitialization function for the Shadow library.
\r
99 * This function frees resources taken in @ref shadow_function_init and deletes
\r
100 * any [persistent subscriptions.](@ref AWS_IOT_SHADOW_FLAG_KEEP_SUBSCRIPTIONS)
\r
101 * It should be called to clean up the Shadow library. After this function returns,
\r
102 * @ref shadow_function_init must be called again before calling any other Shadow
\r
105 * @warning No thread-safety guarantees are provided for this function.
\r
107 * @see @ref shadow_function_init
\r
109 /* @[declare_shadow_cleanup] */
\r
110 void AwsIotShadow_Cleanup( void );
\r
111 /* @[declare_shadow_cleanup] */
\r
114 * @brief Delete a Thing Shadow and receive an asynchronous notification when
\r
115 * the Delete completes.
\r
117 * This function deletes any existing Shadow document for the given Thing Name.
\r
118 * If the given Thing has no Shadow and this function is called, the result will
\r
119 * be #AWS_IOT_SHADOW_NOT_FOUND.
\r
121 * Deleting a Shadow involves sending an MQTT message to AWS IoT and waiting on
\r
122 * a response. This message will always be sent at [MQTT QoS 0](@ref #IOT_MQTT_QOS_0).
\r
124 * @param[in] mqttConnection The MQTT connection to use for Shadow delete.
\r
125 * @param[in] pThingName The Thing Name associated with the Shadow to delete.
\r
126 * @param[in] thingNameLength The length of `pThingName`.
\r
127 * @param[in] flags Flags which modify the behavior of this function. See @ref shadow_constants_flags.
\r
128 * @param[in] pCallbackInfo Asynchronous notification of this function's completion.
\r
129 * @param[out] pDeleteOperation Set to a handle by which this operation may be referenced
\r
130 * after this function returns. This reference is invalidated once the Shadow delete
\r
133 * @return This function will return #AWS_IOT_SHADOW_STATUS_PENDING upon successfully
\r
134 * queuing a Shadow delete.
\r
135 * @return If this function fails before queuing a Shadow delete, it will return one of:
\r
136 * - #AWS_IOT_SHADOW_NOT_INITIALIZED
\r
137 * - #AWS_IOT_SHADOW_BAD_PARAMETER
\r
138 * - #AWS_IOT_SHADOW_NO_MEMORY
\r
139 * @return Upon successful completion of the Shadow delete (either through an #AwsIotShadowCallbackInfo_t
\r
140 * or #AwsIotShadow_Wait), the status will be #AWS_IOT_SHADOW_SUCCESS.
\r
141 * @return Should the Shadow delete fail, the status will be one of:
\r
142 * - #AWS_IOT_SHADOW_MQTT_ERROR
\r
143 * - #AWS_IOT_SHADOW_BAD_RESPONSE
\r
144 * - A Shadow service rejection reason between 400 (#AWS_IOT_SHADOW_BAD_REQUEST)
\r
145 * and 500 (#AWS_IOT_SHADOW_SERVER_ERROR)
\r
147 * @see @ref shadow_function_deletesync for a blocking variant of this function.
\r
151 * #define THING_NAME "Test_device"
\r
152 * #define THING_NAME_LENGTH ( sizeof( THING_NAME ) - 1 )
\r
154 * // Shadow operation handle.
\r
155 * AwsIotShadowOperation_t deleteOperation = AWS_IOT_SHADOW_OPERATION_INITIALIZER;
\r
157 * // Queue a Shadow delete.
\r
158 * AwsIotShadowError_t deleteResult = AwsIotShadow_DeleteAsync( mqttConnection,
\r
160 * THING_NAME_LENGTH,
\r
161 * AWS_IOT_SHADOW_FLAG_WAITABLE,
\r
163 * &deleteOperation );
\r
165 * // Shadow delete should return AWS_IOT_SHADOW_STATUS_PENDING upon success.
\r
166 * if( deleteResult == AWS_IOT_SHADOW_STATUS_PENDING )
\r
168 * // Wait for the Shadow delete to complete.
\r
169 * deleteResult = AwsIotShadow_Wait( deleteOperation, 5000 );
\r
171 * // Delete result should be AWS_IOT_SHADOW_SUCCESS upon successfully
\r
172 * // deleting an existing Shadow.
\r
176 /* @[declare_shadow_deleteasync] */
\r
177 AwsIotShadowError_t AwsIotShadow_DeleteAsync( IotMqttConnection_t mqttConnection,
\r
178 const char * pThingName,
\r
179 size_t thingNameLength,
\r
181 const AwsIotShadowCallbackInfo_t * pCallbackInfo,
\r
182 AwsIotShadowOperation_t * const pDeleteOperation );
\r
183 /* @[declare_shadow_deleteasync] */
\r
186 * @brief Delete a Thing Shadow with a timeout.
\r
188 * This function queues a Shadow delete, then waits for the result. Internally, this
\r
189 * function is a call to @ref shadow_function_deleteasync followed by @ref shadow_function_wait.
\r
190 * See @ref shadow_function_deleteasync for more information on the Shadow delete operation.
\r
192 * @param[in] mqttConnection The MQTT connection to use for Shadow delete.
\r
193 * @param[in] pThingName The Thing Name associated with the Shadow to delete.
\r
194 * @param[in] thingNameLength The length of `pThingName`.
\r
195 * @param[in] flags Flags which modify the behavior of this function. See @ref shadow_constants_flags.
\r
196 * @param[in] timeoutMs If the Shadow service does not respond to the Shadow delete
\r
197 * within this timeout, this function returns #AWS_IOT_SHADOW_TIMEOUT.
\r
199 * @return One of the following:
\r
200 * - #AWS_IOT_SHADOW_SUCCESS
\r
201 * - #AWS_IOT_SHADOW_NOT_INITIALIZED
\r
202 * - #AWS_IOT_SHADOW_BAD_PARAMETER
\r
203 * - #AWS_IOT_SHADOW_NO_MEMORY
\r
204 * - #AWS_IOT_SHADOW_MQTT_ERROR
\r
205 * - #AWS_IOT_SHADOW_BAD_RESPONSE
\r
206 * - #AWS_IOT_SHADOW_TIMEOUT
\r
207 * - A Shadow service rejection reason between 400 (#AWS_IOT_SHADOW_BAD_REQUEST)
\r
208 * and 500 (#AWS_IOT_SHADOW_SERVER_ERROR)
\r
210 /* @[declare_shadow_deletesync] */
\r
211 AwsIotShadowError_t AwsIotShadow_DeleteSync( IotMqttConnection_t mqttConnection,
\r
212 const char * pThingName,
\r
213 size_t thingNameLength,
\r
215 uint32_t timeoutMs );
\r
216 /* @[declare_shadow_deletesync] */
\r
219 * @brief Retrieve a Thing Shadow and receive an asynchronous notification when
\r
220 * the Shadow document is received.
\r
222 * This function retrieves the Thing Shadow document currently stored by the
\r
223 * Shadow service. If a given Thing has no Shadow and this function is called,
\r
224 * the result will be #AWS_IOT_SHADOW_NOT_FOUND.
\r
226 * Shadow documents may be large, and their size is not known beforehand.
\r
227 * Therefore, this function works best when memory is dynamically allocated.
\r
228 * Because the Shadow document is retrieved in an MQTT PUBLISH packet, the MQTT
\r
229 * library will allocate a buffer for the Shadow document using #IotMqtt_MallocMessage.
\r
231 * The MQTT library may free the buffer for a retrieved Shadow document as soon
\r
232 * as the [Shadow completion callback](@ref AwsIotShadowCallbackInfo_t) returns.
\r
233 * Therefore, any data needed later must be copied from the Shadow document.
\r
234 * Similarly, if the flag #AWS_IOT_SHADOW_FLAG_WAITABLE is given to this function
\r
235 * (which indicates that the Shadow document will be needed after the Shadow
\r
236 * operation completes), #AwsIotShadowDocumentInfo_t.mallocDocument must be
\r
237 * provided to allocate a longer-lasting buffer.
\r
239 * @note Because of the potentially large size of complete Shadow documents, it is more
\r
240 * memory-efficient for most applications to use [delta callbacks]
\r
241 * (@ref shadow_function_setdeltacallback) to retrieve Shadows from
\r
242 * the Shadow service.
\r
244 * @param[in] mqttConnection The MQTT connection to use for Shadow get.
\r
245 * @param[in] pGetInfo Shadow document parameters.
\r
246 * @param[in] flags Flags which modify the behavior of this function. See @ref shadow_constants_flags.
\r
247 * @param[in] pCallbackInfo Asynchronous notification of this function's completion.
\r
248 * @param[out] pGetOperation Set to a handle by which this operation may be referenced
\r
249 * after this function returns. This reference is invalidated once the Shadow get
\r
252 * @return This function will return #AWS_IOT_SHADOW_STATUS_PENDING upon successfully
\r
253 * queuing a Shadow get.
\r
254 * @return If this function fails before queuing a Shadow get, it will return one of:
\r
255 * - #AWS_IOT_SHADOW_NOT_INITIALIZED
\r
256 * - #AWS_IOT_SHADOW_BAD_PARAMETER
\r
257 * - #AWS_IOT_SHADOW_NO_MEMORY
\r
258 * @return Upon successful completion of the Shadow get (either through an #AwsIotShadowCallbackInfo_t
\r
259 * or #AwsIotShadow_Wait), the status will be #AWS_IOT_SHADOW_SUCCESS.
\r
260 * @return Should the Shadow get fail, the status will be one of:
\r
261 * - #AWS_IOT_SHADOW_NO_MEMORY (Memory could not be allocated for incoming document)
\r
262 * - #AWS_IOT_SHADOW_MQTT_ERROR
\r
263 * - #AWS_IOT_SHADOW_BAD_RESPONSE
\r
264 * - A Shadow service rejection reason between 400 (#AWS_IOT_SHADOW_BAD_REQUEST)
\r
265 * and 500 (#AWS_IOT_SHADOW_SERVER_ERROR)
\r
267 * @see @ref shadow_function_getsync for a blocking variant of this function.
\r
271 * // Shadow get completion callback. The retrieved document will be in
\r
272 * // pCallbackParam. Any data in the retrieved document needed after this
\r
273 * // function returns must be copied.
\r
274 * void _processRetrievedDocument( void * pCallbackContext,
\r
275 * AwsIotShadowCallbackParam_t * pCallbackParam );
\r
277 * // Parameters and return value of Shadow get.
\r
278 * AwsIotShadowError_t result = AWS_IOT_SHADOW_STATUS_PENDING;
\r
279 * AwsIotShadowDocumentInfo_t getInfo = { ... };
\r
280 * uint32_t timeout = 5000; // 5 seconds
\r
282 * // Callback for get completion.
\r
283 * AwsIotShadowCallbackInfo_t getCallback = AWS_IOT_SHADOW_CALLBACK_INFO_INITIALIZER;
\r
284 * getCallback.function = _processRetrievedDocument;
\r
286 * // Shadow get operation.
\r
287 * result = AwsIotShadow_GetAsync( mqttConnection,
\r
293 * // Get should have returned AWS_IOT_SHADOW_STATUS_PENDING. The function
\r
294 * // _processRetrievedDocument will be invoked once the Shadow get completes.
\r
297 * See @ref shadow_function_wait <b>Example 2</b> for an example of using this
\r
298 * function with #AWS_IOT_SHADOW_FLAG_WAITABLE and @ref shadow_function_wait.
\r
300 /* @[declare_shadow_getasync] */
\r
301 AwsIotShadowError_t AwsIotShadow_GetAsync( IotMqttConnection_t mqttConnection,
\r
302 const AwsIotShadowDocumentInfo_t * pGetInfo,
\r
304 const AwsIotShadowCallbackInfo_t * pCallbackInfo,
\r
305 AwsIotShadowOperation_t * const pGetOperation );
\r
306 /* @[declare_shadow_getasync] */
\r
309 * @brief Retrieve a Thing Shadow with a timeout.
\r
311 * This function queues a Shadow get, then waits for the result. Internally, this
\r
312 * function is a call to @ref shadow_function_getasync followed by @ref shadow_function_wait.
\r
313 * See @ref shadow_function_getasync for more information on the Shadow get operation.
\r
315 * @param[in] mqttConnection The MQTT connection to use for Shadow get.
\r
316 * @param[in] pGetInfo Shadow document parameters.
\r
317 * @param[in] flags Flags which modify the behavior of this function. See @ref shadow_constants_flags.
\r
318 * @param[in] timeoutMs If the Shadow service does not respond to the Shadow get
\r
319 * within this timeout, this function returns #AWS_IOT_SHADOW_TIMEOUT.
\r
320 * @param[out] pShadowDocument A pointer to a buffer containing the Shadow document
\r
321 * retrieved by a Shadow get is placed here. The buffer was allocated with the function
\r
322 * `pGetInfo->get.mallocDocument`. This output parameter is only valid if this function
\r
323 * returns #AWS_IOT_SHADOW_SUCCESS.
\r
324 * @param[out] pShadowDocumentLength The length of the Shadow document in
\r
325 * `pShadowDocument` is placed here. This output parameter is only valid if this function
\r
326 * returns #AWS_IOT_SHADOW_SUCCESS.
\r
328 * @return One of the following:
\r
329 * - #AWS_IOT_SHADOW_SUCCESS
\r
330 * - #AWS_IOT_SHADOW_NOT_INITIALIZED
\r
331 * - #AWS_IOT_SHADOW_BAD_PARAMETER
\r
332 * - #AWS_IOT_SHADOW_NO_MEMORY
\r
333 * - #AWS_IOT_SHADOW_MQTT_ERROR
\r
334 * - #AWS_IOT_SHADOW_BAD_RESPONSE
\r
335 * - #AWS_IOT_SHADOW_TIMEOUT
\r
336 * - A Shadow service rejection reason between 400 (#AWS_IOT_SHADOW_BAD_REQUEST)
\r
337 * and 500 (#AWS_IOT_SHADOW_SERVER_ERROR)
\r
339 /* @[declare_shadow_getsync] */
\r
340 AwsIotShadowError_t AwsIotShadow_GetSync( IotMqttConnection_t mqttConnection,
\r
341 const AwsIotShadowDocumentInfo_t * pGetInfo,
\r
343 uint32_t timeoutMs,
\r
344 const char ** const pShadowDocument,
\r
345 size_t * const pShadowDocumentLength );
\r
346 /* @[declare_shadow_getsync] */
\r
349 * @brief Send a Thing Shadow update and receive an asynchronous notification when
\r
350 * the Shadow Update completes.
\r
352 * This function modifies the Thing Shadow document stored by the Shadow service.
\r
353 * If a given Thing has no Shadow and this function is called, then a new Shadow
\r
356 * New JSON keys in the Shadow document will be appended. For example, if the Shadow service
\r
357 * currently has a document containing key `example1` and this function sends a document
\r
358 * only containing key `example2`, then the resulting document in the Shadow service
\r
359 * will contain both `example1` and `example2`.
\r
361 * Existing JSON keys in the Shadow document will be replaced. For example, if the Shadow
\r
362 * service currently has a document containing `"example1": [0,1,2]` and this function sends
\r
363 * a document containing key `"example1": [1,2,3]`, then the resulting document in the Shadow
\r
364 * service will contain `"example1": [1,2,3]`.
\r
366 * Successful Shadow updates will trigger the [Shadow updated callback]
\r
367 * (@ref shadow_function_setupdatedcallback). If the resulting Shadow document contains
\r
368 * different `desired` and `reported` keys, then the [Shadow delta callback]
\r
369 * (@ref shadow_function_setdeltacallback) will be triggered as well.
\r
371 * @attention All documents passed to this function must contain a `clientToken`.
\r
372 * The [client token]
\r
373 * (https://docs.aws.amazon.com/iot/latest/developerguide/device-shadow-document.html#client-token)
\r
374 * is a string used to distinguish between Shadow updates. They are limited to 64
\r
375 * characters; attempting to use a client token longer than 64 characters will
\r
376 * cause the Shadow update to fail. They must be unique at any given time, i.e.
\r
377 * they may be reused <i>as long as no two Shadow updates are using the same
\r
378 * client token at the same time</i>.
\r
380 * @param[in] mqttConnection The MQTT connection to use for Shadow update.
\r
381 * @param[in] pUpdateInfo Shadow document parameters.
\r
382 * @param[in] flags Flags which modify the behavior of this function. See @ref shadow_constants_flags.
\r
383 * @param[in] pCallbackInfo Asynchronous notification of this function's completion.
\r
384 * @param[out] pUpdateOperation Set to a handle by which this operation may be referenced
\r
385 * after this function returns. This reference is invalidated once the Shadow update
\r
388 * @return This function will return #AWS_IOT_SHADOW_STATUS_PENDING upon successfully
\r
389 * queuing a Shadow update.
\r
390 * @return If this function fails before queuing a Shadow update, it will return one of:
\r
391 * - #AWS_IOT_SHADOW_NOT_INITIALIZED
\r
392 * - #AWS_IOT_SHADOW_BAD_PARAMETER
\r
393 * - #AWS_IOT_SHADOW_NO_MEMORY
\r
394 * @return Upon successful completion of the Shadow update (either through an #AwsIotShadowCallbackInfo_t
\r
395 * or #AwsIotShadow_Wait), the status will be #AWS_IOT_SHADOW_SUCCESS.
\r
396 * @return Should the Shadow update fail, the status will be one of:
\r
397 * - #AWS_IOT_SHADOW_MQTT_ERROR
\r
398 * - #AWS_IOT_SHADOW_BAD_RESPONSE
\r
399 * - A Shadow service rejection reason between 400 (#AWS_IOT_SHADOW_BAD_REQUEST)
\r
400 * and 500 (#AWS_IOT_SHADOW_SERVER_ERROR)
\r
402 * @see @ref shadow_function_updatesync for a blocking variant of this function.
\r
406 * // Shadow update completion callback.
\r
407 * void _updateComplete( void * pCallbackContext,
\r
408 * AwsIotShadowCallbackParam_t * pCallbackParam );
\r
410 * // Parameters and return value of Shadow update.
\r
411 * AwsIotShadowError_t result = AWS_IOT_SHADOW_STATUS_PENDING;
\r
412 * AwsIotShadowDocumentInfo_t updateInfo = { ... };
\r
413 * uint32_t timeout = 5000; // 5 seconds
\r
415 * // Set Shadow document to send.
\r
416 * updateInfo.update.pUpdateDocument = "{...}"; // Must contain clientToken
\r
417 * updateInfo.update.updateDocumentLength = strlen( updateInfo.update.pUpdateDocument );
\r
419 * // Callback for update completion.
\r
420 * AwsIotShadowCallbackInfo_t updateCallback = AWS_IOT_SHADOW_CALLBACK_INFO_INITIALIZER;
\r
421 * updateCallback.function = _updateComplete;
\r
423 * // Shadow update operation.
\r
424 * result = AwsIotShadow_UpdateAsync( mqttConnection,
\r
430 * // Update should have returned AWS_IOT_SHADOW_STATUS_PENDING. The function
\r
431 * // _updateComplete will be invoked once the Shadow update completes.
\r
434 * See @ref shadow_function_wait <b>Example 1</b> for an example of using this
\r
435 * function with #AWS_IOT_SHADOW_FLAG_WAITABLE and @ref shadow_function_wait.
\r
437 /* @[declare_shadow_updateasync] */
\r
438 AwsIotShadowError_t AwsIotShadow_UpdateAsync( IotMqttConnection_t mqttConnection,
\r
439 const AwsIotShadowDocumentInfo_t * pUpdateInfo,
\r
441 const AwsIotShadowCallbackInfo_t * pCallbackInfo,
\r
442 AwsIotShadowOperation_t * const pUpdateOperation );
\r
443 /* @[declare_shadow_updateasync] */
\r
446 * @brief Send a Thing Shadow update with a timeout.
\r
448 * This function queues a Shadow update, then waits for the result. Internally, this
\r
449 * function is a call to @ref shadow_function_updateasync followed by @ref shadow_function_wait.
\r
450 * See @ref shadow_function_updateasync for more information on the Shadow update operation.
\r
452 * @param[in] mqttConnection The MQTT connection to use for Shadow update.
\r
453 * @param[in] pUpdateInfo Shadow document parameters.
\r
454 * @param[in] flags Flags which modify the behavior of this function. See @ref shadow_constants_flags.
\r
455 * @param[in] timeoutMs If the Shadow service does not respond to the Shadow update
\r
456 * within this timeout, this function returns #AWS_IOT_SHADOW_TIMEOUT.
\r
458 * @return One of the following:
\r
459 * - #AWS_IOT_SHADOW_SUCCESS
\r
460 * - #AWS_IOT_SHADOW_NOT_INITIALIZED
\r
461 * - #AWS_IOT_SHADOW_BAD_PARAMETER
\r
462 * - #AWS_IOT_SHADOW_NO_MEMORY
\r
463 * - #AWS_IOT_SHADOW_MQTT_ERROR
\r
464 * - #AWS_IOT_SHADOW_BAD_RESPONSE
\r
465 * - #AWS_IOT_SHADOW_TIMEOUT
\r
466 * - A Shadow service rejection reason between 400 (#AWS_IOT_SHADOW_BAD_REQUEST)
\r
467 * and 500 (#AWS_IOT_SHADOW_SERVER_ERROR)
\r
469 /* @[declare_shadow_updatesync] */
\r
470 AwsIotShadowError_t AwsIotShadow_UpdateSync( IotMqttConnection_t mqttConnection,
\r
471 const AwsIotShadowDocumentInfo_t * pUpdateInfo,
\r
473 uint32_t timeoutMs );
\r
474 /* @[declare_shadow_updatesync] */
\r
477 * @brief Wait for a Shadow operation to complete.
\r
479 * This function blocks to wait for a [delete](@ref shadow_function_deleteasync),
\r
480 * [get](@ref shadow_function_getasync), or [update](@ref shadow_function_updateasync) to
\r
481 * complete. These operations are by default asynchronous; the function calls
\r
482 * queue an operation for processing, and a callback is invoked once the operation
\r
485 * To use this function, the flag #AWS_IOT_SHADOW_FLAG_WAITABLE must have been
\r
486 * set in the operation's function call. Additionally, this function must always
\r
487 * be called with any waitable operation to clean up resources.
\r
489 * Regardless of its return value, this function always clean up resources used
\r
490 * by the waitable operation. This means `operation` is invalidated as soon as
\r
491 * this function returns, even if it returns #AWS_IOT_SHADOW_TIMEOUT or another
\r
494 * @param[in] operation Reference to the Shadow operation to wait for. The flag
\r
495 * #AWS_IOT_SHADOW_FLAG_WAITABLE must have been set for this operation.
\r
496 * @param[in] timeoutMs How long to wait before returning #AWS_IOT_SHADOW_TIMEOUT.
\r
497 * @param[out] pShadowDocument A pointer to a buffer containing the Shadow document
\r
498 * retrieved by a [Shadow get](@ref shadow_function_getasync) is placed here. The buffer
\r
499 * was allocated with the function #AwsIotShadowDocumentInfo_t.mallocDocument passed
\r
500 * to @ref shadow_function_getasync. This parameter is only valid for a [Shadow get]
\r
501 * (@ref shadow_function_getasync) and ignored for other Shadow operations. This output
\r
502 * parameter is only valid if this function returns #AWS_IOT_SHADOW_SUCCESS.
\r
503 * @param[out] pShadowDocumentLength The length of the Shadow document in
\r
504 * `pShadowDocument` is placed here. This parameter is only valid for a [Shadow get]
\r
505 * (@ref shadow_function_getasync) and ignored for other Shadow operations. This output
\r
506 * parameter is only valid if this function returns #AWS_IOT_SHADOW_SUCCESS.
\r
508 * @return One of the following:
\r
509 * - #AWS_IOT_SHADOW_SUCCESS
\r
510 * - #AWS_IOT_SHADOW_NOT_INITIALIZED
\r
511 * - #AWS_IOT_SHADOW_BAD_PARAMETER
\r
512 * - #AWS_IOT_SHADOW_BAD_RESPONSE
\r
513 * - #AWS_IOT_SHADOW_TIMEOUT
\r
514 * - A Shadow service rejection reason between 400 (#AWS_IOT_SHADOW_BAD_REQUEST)
\r
515 * and 500 (#AWS_IOT_SHADOW_SERVER_ERROR)
\r
517 * <b>Example 1 (Shadow Update)</b>
\r
519 * AwsIotShadowError_t result = AWS_IOT_SHADOW_STATUS_PENDING;
\r
520 * AwsIotShadowDocumentInfo_t updateInfo = { ... };
\r
522 * // Reference and timeout.
\r
523 * AwsIotShadowOperation_t updateOperation = AWS_IOT_SHADOW_OPERATION_INITIALIZER;
\r
524 * uint32_t timeout = 5000; // 5 seconds
\r
526 * // Shadow update operation.
\r
527 * result = AwsIotShadow_UpdateAsync( mqttConnection,
\r
529 * AWS_IOT_SHADOW_FLAG_WAITABLE,
\r
531 * &updateOperation );
\r
533 * // Update should have returned AWS_IOT_SHADOW_STATUS_PENDING. The call to wait
\r
534 * // returns once the result of the update is available or the timeout expires.
\r
535 * if( result == AWS_IOT_SHADOW_STATUS_PENDING )
\r
537 * // The last two parameters are ignored for a Shadow update.
\r
538 * result = AwsIotShadow_Wait( updateOperation, timeout, NULL, NULL );
\r
540 * // After the call to wait, the result of the update is known
\r
541 * // (not AWS_IOT_SHADOW_STATUS_PENDING).
\r
542 * assert( result != AWS_IOT_SHADOW_STATUS_PENDING );
\r
546 * <b>Example 2 (Shadow Get)</b>
\r
548 * AwsIotShadowError_t result = AWS_IOT_SHADOW_STATUS_PENDING;
\r
549 * AwsIotShadowDocumentInfo_t getInfo = { ... };
\r
551 * // Reference and timeout.
\r
552 * AwsIotShadowOperation_t getOperation = AWS_IOT_SHADOW_OPERATION_INITIALIZER;
\r
553 * uint32_t timeout = 5000; // 5 seconds
\r
555 * // Buffer pointer and size for retrieved Shadow document.
\r
556 * const char * pShadowDocument = NULL;
\r
557 * size_t documentLength = 0;
\r
559 * // Buffer allocation function must be set for a waitable Shadow get.
\r
560 * getInfo.get.mallocDocument = malloc;
\r
562 * // Shadow get operation.
\r
563 * result = AwsIotShadow_GetAsync( mqttConnection,
\r
565 * AWS_IOT_SHADOW_FLAG_WAITABLE,
\r
569 * // Get should have returned AWS_IOT_SHADOW_STATUS_PENDING. The call to wait
\r
570 * // returns once the result of the get is available or the timeout expires.
\r
571 * if( result == AWS_IOT_SHADOW_STATUS_PENDING )
\r
573 * // The last two parameters must be set for a Shadow get.
\r
574 * result = AwsIotShadow_Wait( getOperation, timeout, &pShadowDocument, &documentLength );
\r
576 * // After the call to wait, the result of the get is known
\r
577 * // (not AWS_IOT_SHADOW_STATUS_PENDING).
\r
578 * assert( result != AWS_IOT_SHADOW_STATUS_PENDING );
\r
580 * // The retrieved Shadow document is only valid for a successful Shadow get.
\r
581 * if( result == AWS_IOT_SHADOW_SUCCESS )
\r
583 * // Do something with the Shadow document...
\r
585 * // Free the Shadow document when finished.
\r
586 * free( pShadowDocument );
\r
591 /* @[declare_shadow_wait] */
\r
592 AwsIotShadowError_t AwsIotShadow_Wait( AwsIotShadowOperation_t operation,
\r
593 uint32_t timeoutMs,
\r
594 const char ** const pShadowDocument,
\r
595 size_t * const pShadowDocumentLength );
\r
596 /* @[declare_shadow_wait] */
\r
599 * @brief Set a callback to be invoked when the Thing Shadow `desired` and `reported`
\r
602 * A Thing Shadow contains `reported` and `desired` states, meant to represent
\r
603 * the current device status and some desired status, respectively. When the
\r
604 * `reported` and `desired` states differ, the Thing Shadow service generates a
\r
605 * <i>delta document</i> and publishes it to the topic `update/delta`. Devices
\r
606 * with a subscription for this topic will receive the delta document and may act
\r
607 * based on the different `reported` and `desired` states. See [this page]
\r
608 * (https://docs.aws.amazon.com/iot/latest/developerguide/using-device-shadows.html#delta-state)
\r
609 * for more information about using delta documents.
\r
611 * A <i>delta callback</i> may be invoked whenever a delta document is generated.
\r
612 * Each Thing may have a single delta callback set. This function modifies the delta
\r
613 * callback for a specific Thing depending on the `pDeltaCallback` parameter and
\r
614 * the presence of any existing delta callback:
\r
615 * - When no existing delta callback exists for a specific Thing, a new delta
\r
616 * callback is added.
\r
617 * - If there is an existing delta callback and `pDeltaCallback` is not `NULL`, then
\r
618 * the existing callback function and parameter are replaced with `pDeltaCallback`.
\r
619 * - If there is an existing subscription and `pDeltaCallback` is `NULL`, then the
\r
620 * delta callback is removed.
\r
622 * This function is always blocking; it may block for up to the default MQTT
\r
623 * timeout. This timeout is set as a parameter to @ref shadow_function_init,
\r
624 * and defaults to @ref AWS_IOT_SHADOW_DEFAULT_MQTT_TIMEOUT_MS if not set. If
\r
625 * this function's underlying MQTT operations fail to complete within this
\r
626 * timeout, then this function returns #AWS_IOT_SHADOW_TIMEOUT.
\r
628 * @param[in] mqttConnection The MQTT connection to use for the subscription to
\r
630 * @param[in] pThingName The subscription to `update/delta` will be added for
\r
632 * @param[in] thingNameLength The length of `pThingName`.
\r
633 * @param[in] flags This parameter is for future-compatibility. Currently, flags
\r
634 * are not supported for this function and this parameter is ignored.
\r
635 * @param[in] pDeltaCallback Callback function to invoke for incoming delta
\r
638 * @return One of the following:
\r
639 * - #AWS_IOT_SHADOW_SUCCESS
\r
640 * - #AWS_IOT_SHADOW_NOT_INITIALIZED
\r
641 * - #AWS_IOT_SHADOW_BAD_PARAMETER
\r
642 * - #AWS_IOT_SHADOW_NO_MEMORY
\r
643 * - #AWS_IOT_SHADOW_MQTT_ERROR
\r
644 * - #AWS_IOT_SHADOW_TIMEOUT
\r
646 * @return This function always returns #AWS_IOT_SHADOW_SUCCESS when replacing or
\r
647 * removing existing delta callbacks.
\r
649 * @see @ref shadow_function_setupdatedcallback for the function to register
\r
650 * callbacks for all Shadow updates.
\r
654 * #define THING_NAME "Test_device"
\r
655 * #define THING_NAME_LENGTH ( sizeof( THING_NAME ) - 1 )
\r
657 * AwsIotShadowError_t result = AWS_IOT_SHADOW_STATUS_PENDING;
\r
658 * AwsIotShadowCallbackInfo_t deltaCallback = AWS_IOT_SHADOW_CALLBACK_INFO_INITIALIZER;
\r
660 * // _deltaCallbackFunction will be invoked when a delta document is received.
\r
661 * deltaCallback.function = _deltaCallbackFunction;
\r
663 * // Set the delta callback for the Thing "Test_device".
\r
664 * result = AwsIotShadow_SetDeltaCallback( mqttConnection,
\r
666 * THING_NAME_LENGTH,
\r
668 * &deltaCallback );
\r
670 * // Check if callback was successfully set.
\r
671 * if( result == AWS_IOT_SHADOW_SUCCESS )
\r
673 * AwsIotShadowDocumentInfo_t updateInfo = AWS_IOT_SHADOW_DOCUMENT_INFO_INITIALIZER;
\r
675 * // Set the Thing Name for Shadow update.
\r
676 * updateInfo.pThingName = THING_NAME;
\r
677 * updateInfo.thingNameLength = THING_NAME_LENGTH;
\r
679 * // Set the Shadow document to send. This document has different "reported"
\r
680 * // and "desired" states. It represents a scenario where a device is currently
\r
681 * // off, but is being ordered to turn on.
\r
682 * updateInfo.update.pUpdateDocument =
\r
685 * "\"reported\": { \"deviceOn\": false },"
\r
686 * "\"desired\": { \"deviceOn\": true }"
\r
689 * updateInfo.update.updateDocumentLength = strlen( updateInfo.update.pUpdateDocument );
\r
691 * // Send the Shadow document with different "reported" and desired states.
\r
692 * result = AwsIotShadow_UpdateSync( mqttConnection,
\r
698 * // After the update is successfully sent, the function _deltaCallbackFunction
\r
699 * // will be invoked once the Shadow service generates and sends a delta document.
\r
700 * // The delta document will contain the different "deviceOn" states, as well as
\r
703 * // Once the delta callback is no longer needed, it may be removed by passing
\r
704 * // NULL as pDeltaCallback.
\r
705 * result = AwsIotShadow_SetDeltaCallback( mqttConnection,
\r
707 * THING_NAME_LENGTH,
\r
711 * // The return value from removing a delta callback should always be success.
\r
712 * assert( result == AWS_IOT_SHADOW_SUCCESS );
\r
716 /* @[declare_shadow_setdeltacallback] */
\r
717 AwsIotShadowError_t AwsIotShadow_SetDeltaCallback( IotMqttConnection_t mqttConnection,
\r
718 const char * pThingName,
\r
719 size_t thingNameLength,
\r
721 const AwsIotShadowCallbackInfo_t * pDeltaCallback );
\r
722 /* @[declare_shadow_setdeltacallback] */
\r
725 * @brief Set a callback to be invoked when a Thing Shadow changes.
\r
727 * The Shadow service publishes a state document to the `update/documents` topic
\r
728 * whenever a Thing Shadow is successfully updated. This document reports the
\r
729 * complete previous and current Shadow documents in `previous` and `current`
\r
730 * sections, respectively. Therefore, the `update/documents` topic is useful
\r
731 * for monitoring Shadow updates.
\r
733 * An <i>updated callback</i> may be invoked whenever a document is published to
\r
734 * `update/documents`. Each Thing may have a single updated callback set. This function
\r
735 * modifies the updated callback for a specific Thing depending on the `pUpdatedCallback`
\r
736 * parameter and the presence of any existing updated callback.
\r
737 * - When no existing updated callback exists for a specific Thing, a new updated
\r
738 * callback is added.
\r
739 * - If there is an existing updated callback and `pUpdatedCallback` is not `NULL`,
\r
740 * then the existing callback function and parameter are replaced with `pUpdatedCallback`.
\r
741 * - If there is an existing updated callback and `pUpdatedCallback` is `NULL`,
\r
742 * then the updated callback is removed.
\r
744 * @param[in] mqttConnection The MQTT connection to use for the subscription to `update/documents`.
\r
745 * @param[in] pThingName The subscription to `update/documents` will be added for
\r
747 * @param[in] thingNameLength The length of `pThingName`.
\r
748 * @param[in] flags This parameter is for future-compatibility. Currently, flags are
\r
749 * not supported for this function and this parameter is ignored.
\r
750 * @param[in] pUpdatedCallback Callback function to invoke for incoming updated documents.
\r
752 * @return One of the following:
\r
753 * - #AWS_IOT_SHADOW_SUCCESS
\r
754 * - #AWS_IOT_SHADOW_NOT_INITIALIZED
\r
755 * - #AWS_IOT_SHADOW_BAD_PARAMETER
\r
756 * - #AWS_IOT_SHADOW_NO_MEMORY
\r
757 * - #AWS_IOT_SHADOW_MQTT_ERROR
\r
758 * - #AWS_IOT_SHADOW_TIMEOUT
\r
760 * @note Documents published to `update/documents` will be large, as they contain 2
\r
761 * complete Shadow state documents. If an updated callback is used, ensure that the
\r
762 * device has sufficient memory for incoming documents.
\r
764 * @see @ref shadow_function_setdeltacallback for the function to register callbacks
\r
765 * for delta documents.
\r
769 * #define THING_NAME "Test_device"
\r
770 * #define THING_NAME_LENGTH ( sizeof( THING_NAME ) - 1 )
\r
772 * AwsIotShadowError_t result = AWS_IOT_SHADOW_STATUS_PENDING;
\r
773 * AwsIotShadowCallbackInfo_t updatedCallback = AWS_IOT_SHADOW_CALLBACK_INFO_INITIALIZER;
\r
775 * // _updatedCallbackFunction will be invoked when an updated document is received.
\r
776 * updatedCallback.function = _updatedCallbackFunction;
\r
778 * // Set the updated callback for the Thing "Test_device".
\r
779 * result = AwsIotShadow_SetUpdatedCallback( mqttConnection,
\r
781 * THING_NAME_LENGTH,
\r
783 * &updatedCallback );
\r
785 * // Check if the callback was successfully set.
\r
786 * if( result == AWS_IOT_SHADOW_SUCCESS )
\r
788 * AwsIotShadowDocumentInfo_t updateInfo = AWS_IOT_SHADOW_DOCUMENT_INFO_INITIALIZER;
\r
790 * // Set the Thing Name for Shadow update.
\r
791 * updateInfo.pThingName = THING_NAME;
\r
792 * updateInfo.thingNameLength = THING_NAME_LENGTH;
\r
794 * // Set the Shadow document to send. Any Shadow update will trigger the
\r
795 * // updated callback.
\r
796 * updateInfo.update.pUpdateDocument =
\r
799 * "\"reported\": { \"deviceOn\": false }"
\r
802 * updateInfo.update.updateDocumentLength = strlen( updateInfo.update.pUpdateDocument );
\r
804 * // Send the Shadow document. A successful update will trigger the updated callback.
\r
805 * result = AwsIotShadow_UpdateSync( mqttConnection,
\r
811 * // After a successful Shadow update, the updated callback will be invoked.
\r
813 * // Once the updated callback is no longer needed, it may be removed by
\r
814 * // passing NULL as pUpdatedCallback.
\r
815 * result = AwsIotShadow_SetUpdatedCallback( mqttConnection,
\r
817 * THING_NAME_LENGTH,
\r
820 * // The return value from removing an updated callback should always be
\r
822 * assert( result == AWS_IOT_SHADOW_SUCCESS );
\r
826 /* @[declare_shadow_setupdatedcallback] */
\r
827 AwsIotShadowError_t AwsIotShadow_SetUpdatedCallback( IotMqttConnection_t mqttConnection,
\r
828 const char * pThingName,
\r
829 size_t thingNameLength,
\r
831 const AwsIotShadowCallbackInfo_t * pUpdatedCallback );
\r
832 /* @[declare_shadow_setupdatedcallback] */
\r
835 * @brief Remove persistent Thing Shadow operation topic subscriptions.
\r
837 * Passing the flag @ref AWS_IOT_SHADOW_FLAG_KEEP_SUBSCRIPTIONS to @ref shadow_function_deleteasync,
\r
838 * @ref shadow_function_getasync, @ref shadow_function_updateasync, or their blocking versions.
\r
839 * causes the Shadow operation topic subscriptions to be maintained for future calls to the
\r
840 * same function. If a persistent subscription for a Shadow topic are no longer needed,
\r
841 * this function may be used to remove it.
\r
843 * @param[in] mqttConnection The MQTT connection associated with the persistent subscription.
\r
844 * @param[in] pThingName The Thing Name associated with the persistent subscription.
\r
845 * @param[in] thingNameLength The length of `pThingName`.
\r
846 * @param[in] flags Flags that determine which subscriptions to remove. Valid values are
\r
847 * the bitwise OR of the following individual flags:
\r
848 * - @ref AWS_IOT_SHADOW_FLAG_REMOVE_DELETE_SUBSCRIPTIONS
\r
849 * - @ref AWS_IOT_SHADOW_FLAG_REMOVE_GET_SUBSCRIPTIONS
\r
850 * - @ref AWS_IOT_SHADOW_FLAG_REMOVE_UPDATE_SUBSCRIPTIONS
\r
852 * @return On success:
\r
853 * - #AWS_IOT_SHADOW_SUCCESS
\r
854 * @return If an MQTT UNSUBSCRIBE packet cannot be sent, one of the following:
\r
855 * - #AWS_IOT_SHADOW_NO_MEMORY
\r
856 * - #AWS_IOT_SHADOW_MQTT_ERROR
\r
858 * @note @ref shadow_function_cleanup removes all persistent subscriptions as well.
\r
860 * @warning This function is not safe to call with any in-progress operations!
\r
861 * It also does not affect delta and updated callbacks registered with @ref
\r
862 * shadow_function_setdeltacallback and @ref shadow_function_setupdatedcallback,
\r
863 * respectively. (See documentation for those functions on how to remove their
\r
866 /* @[declare_shadow_removepersistentsubscriptions] */
\r
867 AwsIotShadowError_t AwsIotShadow_RemovePersistentSubscriptions( IotMqttConnection_t mqttConnection,
\r
868 const char * pThingName,
\r
869 size_t thingNameLength,
\r
871 /* @[declare_shadow_removepersistentsubscriptions] */
\r
873 /*------------------------- Shadow helper functions -------------------------*/
\r
876 * @brief Returns a string that describes an #AwsIotShadowError_t.
\r
878 * Like POSIX's `strerror`, this function returns a string describing a return
\r
879 * code. In this case, the return code is a Shadow library error code, `status`.
\r
881 * The string returned by this function <b>MUST</b> be treated as read-only: any
\r
882 * attempt to modify its contents may result in a crash. Therefore, this function
\r
883 * is limited to usage in logging.
\r
885 * @param[in] status The status to describe.
\r
887 * @return A read-only string that describes `status`.
\r
889 * @warning The string returned by this function must never be modified.
\r
891 /* @[declare_shadow_strerror] */
\r
892 const char * AwsIotShadow_strerror( AwsIotShadowError_t status );
\r
893 /* @[declare_shadow_strerror] */
\r
896 * @cond DOXYGEN_IGNORE
\r
897 * Doxygen should ignore this section.
\r
899 * Backwards compatibility macros for previous function names.
\r
901 #define AwsIotShadow_Delete AwsIotShadow_DeleteAsync
\r
902 #define AwsIotShadow_TimedDelete AwsIotShadow_DeleteSync
\r
903 #define AwsIotShadow_Get AwsIotShadow_GetAsync
\r
904 #define AwsIotShadow_TimedGet AwsIotShadow_GetSync
\r
905 #define AwsIotShadow_Update AwsIotShadow_UpdateAsync
\r
906 #define AwsIotShadow_TimedUpdate AwsIotShadow_UpdateSync
\r
909 #endif /* ifndef AWS_IOT_SHADOW_H_ */
\r