this is fork and i will modify for STM32

Fork of AWS-test by Pierre-Marie Ancèle

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers aws_iot_shadow_records.cpp Source File

aws_iot_shadow_records.cpp

00001 /*
00002  * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License").
00005  * You may not use this file except in compliance with the License.
00006  * A copy of the License is located at
00007  *
00008  *  http://aws.amazon.com/apache2.0
00009  *
00010  * or in the "license" file accompanying this file. This file is distributed
00011  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
00012  * express or implied. See the License for the specific language governing
00013  * permissions and limitations under the License.
00014  */
00015 
00016 /**
00017  * @file aws_iot_mqtt_client_subscribe.c
00018  * @brief MQTT client subscribe API definitions
00019  */
00020 
00021 #ifdef __cplusplus
00022 extern "C" {
00023 #endif
00024 
00025 #include "aws_iot_shadow_records.h"
00026 
00027 #include <string.h>
00028 #include <stdio.h>
00029 
00030 #include "timer_interface.h"
00031 #include "aws_iot_json_utils.h"
00032 #include "aws_iot_log.h"
00033 #include "aws_iot_shadow_json.h"
00034 #include "aws_iot_config.h"
00035 
00036 typedef struct {
00037     char clientTokenID[MAX_SIZE_CLIENT_ID_WITH_SEQUENCE];
00038     char thingName[MAX_SIZE_OF_THING_NAME];
00039     ShadowActions_t action;
00040     fpActionCallback_t callback;
00041     void *pCallbackContext;
00042     bool isFree;
00043     TimerAWS timer;
00044 } ToBeReceivedAckRecord_t;
00045 
00046 typedef struct {
00047     const char *pKey;
00048     void *pStruct;
00049     jsonStructCallback_t callback;
00050     bool isFree;
00051 } JsonTokenTable_t;
00052 
00053 typedef struct {
00054     char Topic[MAX_SHADOW_TOPIC_LENGTH_BYTES];
00055     uint8_t count;
00056     bool isFree;
00057     bool isSticky;
00058 } SubscriptionRecord_t;
00059 
00060 typedef enum {
00061     SHADOW_ACCEPTED, SHADOW_REJECTED, SHADOW_ACTION
00062 } ShadowAckTopicTypes_t;
00063 
00064 ToBeReceivedAckRecord_t AckWaitList[MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME];
00065 
00066 AWS_IoT_Client *pMqttClient;
00067 
00068 char myThingName[MAX_SIZE_OF_THING_NAME];
00069 char mqttClientID[MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES];
00070 
00071 char shadowDeltaTopic[MAX_SHADOW_TOPIC_LENGTH_BYTES];
00072 
00073 #define MAX_TOPICS_AT_ANY_GIVEN_TIME 2*MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME
00074 SubscriptionRecord_t SubscriptionList[MAX_TOPICS_AT_ANY_GIVEN_TIME];
00075 
00076 #define SUBSCRIBE_SETTLING_TIME 2
00077 char shadowRxBuf[SHADOW_MAX_SIZE_OF_RX_BUFFER];
00078 
00079 static JsonTokenTable_t tokenTable[MAX_JSON_TOKEN_EXPECTED];
00080 static uint32_t tokenTableIndex = 0;
00081 static bool deltaTopicSubscribedFlag = false;
00082 uint32_t shadowJsonVersionNum = 0;
00083 bool shadowDiscardOldDeltaFlag = true;
00084 
00085 // local helper functions
00086 static void AckStatusCallback(AWS_IoT_Client *pClient, char *topicName,
00087                               uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData);
00088 
00089 static void shadow_delta_callback(AWS_IoT_Client *pClient, char *topicName,
00090                                   uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData);
00091 
00092 static void topicNameFromThingAndAction(char *pTopic, const char *pThingName, ShadowActions_t action,
00093                                         ShadowAckTopicTypes_t ackType);
00094 
00095 static int16_t getNextFreeIndexOfSubscriptionList(void);
00096 
00097 static void unsubscribeFromAcceptedAndRejected(uint8_t index);
00098 
00099 void initDeltaTokens(void) {
00100     uint32_t i;
00101     for(i = 0; i < MAX_JSON_TOKEN_EXPECTED; i++) {
00102         tokenTable[i].isFree = true;
00103     }
00104     tokenTableIndex = 0;
00105     deltaTopicSubscribedFlag = false;
00106 }
00107 
00108 IoT_Error_t registerJsonTokenOnDelta(jsonStruct_t *pStruct) {
00109 
00110     IoT_Error_t rc = IOT_SUCCESS;
00111 
00112     if(!deltaTopicSubscribedFlag) {
00113         snprintf(shadowDeltaTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/update/delta", myThingName);
00114         rc = aws_iot_mqtt_subscribe(pMqttClient, shadowDeltaTopic, (uint16_t) strlen(shadowDeltaTopic), QOS0,
00115                                     shadow_delta_callback, NULL);
00116         deltaTopicSubscribedFlag = true;
00117     }
00118 
00119     if(tokenTableIndex >= MAX_JSON_TOKEN_EXPECTED) {
00120         return IOT_FAILURE;
00121     }
00122 
00123     tokenTable[tokenTableIndex].pKey = pStruct->pKey;
00124     tokenTable[tokenTableIndex].callback = pStruct->cb;
00125     tokenTable[tokenTableIndex].pStruct = pStruct;
00126     tokenTable[tokenTableIndex].isFree = false;
00127     tokenTableIndex++;
00128 
00129     return rc;
00130 }
00131 
00132 static int16_t getNextFreeIndexOfSubscriptionList(void) {
00133     uint8_t i;
00134     for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) {
00135         if(SubscriptionList[i].isFree) {
00136             SubscriptionList[i].isFree = false;
00137             return i;
00138         }
00139     }
00140     return -1;
00141 }
00142 
00143 static void topicNameFromThingAndAction(char *pTopic, const char *pThingName, ShadowActions_t action,
00144                                         ShadowAckTopicTypes_t ackType) {
00145 
00146     char actionBuf[10];
00147     char ackTypeBuf[10];
00148 
00149     if(SHADOW_GET == action) {
00150         strncpy(actionBuf, "get", 10);
00151     } else if(SHADOW_UPDATE == action) {
00152         strncpy(actionBuf, "update", 10);
00153     } else if(SHADOW_DELETE == action) {
00154         strncpy(actionBuf, "delete", 10);
00155     }
00156 
00157     if(SHADOW_ACCEPTED == ackType) {
00158         strncpy(ackTypeBuf, "accepted", 10);
00159     } else if(SHADOW_REJECTED == ackType) {
00160         strncpy(ackTypeBuf, "rejected", 10);
00161     }
00162 
00163     if(SHADOW_ACTION == ackType) {
00164         snprintf(pTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/%s", pThingName, actionBuf);
00165     } else {
00166         snprintf(pTopic, MAX_SHADOW_TOPIC_LENGTH_BYTES, "$aws/things/%s/shadow/%s/%s", pThingName, actionBuf,
00167                  ackTypeBuf);
00168     }
00169 }
00170 
00171 static bool isAckForMyThingName(const char *pTopicName) {
00172     if(strstr(pTopicName, myThingName) != NULL &&
00173        ((strstr(pTopicName, "get/accepted") != NULL) || (strstr(pTopicName, "update/accepted") != NULL) ||
00174         (strstr(pTopicName, "delta") != NULL))) {
00175         return true;
00176     }
00177     return false;
00178 }
00179 
00180 static void AckStatusCallback(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
00181                               IoT_Publish_Message_Params *params, void *pData) {
00182     int32_t tokenCount;
00183     uint8_t i;
00184     void *pJsonHandler = NULL;
00185     char temporaryClientToken[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE];
00186 
00187     IOT_UNUSED(pClient);
00188     IOT_UNUSED(topicNameLen);
00189     IOT_UNUSED(pData);
00190 
00191     if(params->payloadLen > SHADOW_MAX_SIZE_OF_RX_BUFFER) {
00192         IOT_WARN("Payload larger than RX Buffer");
00193         return;
00194     }
00195 
00196     memcpy(shadowRxBuf, params->payload, params->payloadLen);
00197     shadowRxBuf[params->payloadLen] = '\0';    // jsmn_parse relies on a string
00198 
00199     if(!isJsonValidAndParse(shadowRxBuf, pJsonHandler, &tokenCount)) {
00200         IOT_WARN("Received JSON is not valid");
00201         return;
00202     }
00203 
00204     if(isAckForMyThingName(topicName)) {
00205         uint32_t tempVersionNumber = 0;
00206         if(extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) {
00207             if(tempVersionNumber > shadowJsonVersionNum) {
00208                 shadowJsonVersionNum = tempVersionNumber;
00209             }
00210         }
00211     }
00212 
00213     if(extractClientToken(shadowRxBuf, temporaryClientToken)) {
00214         for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) {
00215             if(!AckWaitList[i].isFree) {
00216                 if(strcmp(AckWaitList[i].clientTokenID, temporaryClientToken) == 0) {
00217                     Shadow_Ack_Status_t status;
00218                     if(strstr(topicName, "accepted") != NULL) {
00219                         status = SHADOW_ACK_ACCEPTED;
00220                     } else if(strstr(topicName, "rejected") != NULL) {
00221                         status = SHADOW_ACK_REJECTED;
00222                     }
00223                     if(status == SHADOW_ACK_ACCEPTED || status == SHADOW_ACK_REJECTED) {
00224                         if(AckWaitList[i].callback != NULL) {
00225                             AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, status,
00226                                                     shadowRxBuf, AckWaitList[i].pCallbackContext);
00227                         }
00228                         unsubscribeFromAcceptedAndRejected(i);
00229                         AckWaitList[i].isFree = true;
00230                         return;
00231                     }
00232                 }
00233             }
00234         }
00235     }
00236 }
00237 
00238 static int16_t findIndexOfSubscriptionList(const char *pTopic) {
00239     uint8_t i;
00240     for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) {
00241         if(!SubscriptionList[i].isFree) {
00242             if((strcmp(pTopic, SubscriptionList[i].Topic) == 0)) {
00243                 return i;
00244             }
00245         }
00246     }
00247     return -1;
00248 }
00249 
00250 static void unsubscribeFromAcceptedAndRejected(uint8_t index) {
00251 
00252     char TemporaryTopicNameAccepted[MAX_SHADOW_TOPIC_LENGTH_BYTES];
00253     char TemporaryTopicNameRejected[MAX_SHADOW_TOPIC_LENGTH_BYTES];
00254     IoT_Error_t ret_val = IOT_SUCCESS;
00255 
00256     int16_t indexSubList;
00257 
00258     topicNameFromThingAndAction(TemporaryTopicNameAccepted, AckWaitList[index].thingName, AckWaitList[index].action,
00259                                 SHADOW_ACCEPTED);
00260     topicNameFromThingAndAction(TemporaryTopicNameRejected, AckWaitList[index].thingName, AckWaitList[index].action,
00261                                 SHADOW_REJECTED);
00262 
00263     indexSubList = findIndexOfSubscriptionList(TemporaryTopicNameAccepted);
00264     if((indexSubList >= 0)) {
00265         if(!SubscriptionList[indexSubList].isSticky && (SubscriptionList[indexSubList].count == 1)) {
00266             ret_val = aws_iot_mqtt_unsubscribe(pMqttClient, TemporaryTopicNameAccepted,
00267                                                (uint16_t) strlen(TemporaryTopicNameAccepted));
00268             if(ret_val == IOT_SUCCESS) {
00269                 SubscriptionList[indexSubList].isFree = true;
00270             }
00271         } else if(SubscriptionList[indexSubList].count > 1) {
00272             SubscriptionList[indexSubList].count--;
00273         }
00274     }
00275 
00276     indexSubList = findIndexOfSubscriptionList(TemporaryTopicNameRejected);
00277     if((indexSubList >= 0)) {
00278         if(!SubscriptionList[indexSubList].isSticky && (SubscriptionList[indexSubList].count == 1)) {
00279             ret_val = aws_iot_mqtt_unsubscribe(pMqttClient, TemporaryTopicNameRejected,
00280                                                (uint16_t) strlen(TemporaryTopicNameRejected));
00281             if(ret_val == IOT_SUCCESS) {
00282                 SubscriptionList[indexSubList].isFree = true;
00283             }
00284         } else if(SubscriptionList[indexSubList].count > 1) {
00285             SubscriptionList[indexSubList].count--;
00286         }
00287     }
00288 }
00289 
00290 void initializeRecords(AWS_IoT_Client *pClient) {
00291     uint8_t i;
00292     for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) {
00293         AckWaitList[i].isFree = true;
00294     }
00295     for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) {
00296         SubscriptionList[i].isFree = true;
00297         SubscriptionList[i].count = 0;
00298         SubscriptionList[i].isSticky = false;
00299     }
00300 
00301     pMqttClient = pClient;
00302 }
00303 
00304 bool isSubscriptionPresent(const char *pThingName, ShadowActions_t action) {
00305 
00306     uint8_t i = 0;
00307     bool isAcceptedPresent = false;
00308     bool isRejectedPresent = false;
00309     char TemporaryTopicNameAccepted[MAX_SHADOW_TOPIC_LENGTH_BYTES];
00310     char TemporaryTopicNameRejected[MAX_SHADOW_TOPIC_LENGTH_BYTES];
00311 
00312     topicNameFromThingAndAction(TemporaryTopicNameAccepted, pThingName, action, SHADOW_ACCEPTED);
00313     topicNameFromThingAndAction(TemporaryTopicNameRejected, pThingName, action, SHADOW_REJECTED);
00314 
00315     for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) {
00316         if(!SubscriptionList[i].isFree) {
00317             if((strcmp(TemporaryTopicNameAccepted, SubscriptionList[i].Topic) == 0)) {
00318                 isAcceptedPresent = true;
00319             } else if((strcmp(TemporaryTopicNameRejected, SubscriptionList[i].Topic) == 0)) {
00320                 isRejectedPresent = true;
00321             }
00322         }
00323     }
00324 
00325     if(isRejectedPresent && isAcceptedPresent) {
00326         return true;
00327     }
00328 
00329     return false;
00330 }
00331 
00332 IoT_Error_t subscribeToShadowActionAcks(const char *pThingName, ShadowActions_t action, bool isSticky) {
00333     IoT_Error_t ret_val = IOT_SUCCESS;
00334 
00335     bool clearBothEntriesFromList = true;
00336     int16_t indexAcceptedSubList = 0;
00337     int16_t indexRejectedSubList = 0;
00338     TimerAWS subSettlingtimer;
00339     indexAcceptedSubList = getNextFreeIndexOfSubscriptionList();
00340     indexRejectedSubList = getNextFreeIndexOfSubscriptionList();
00341 
00342     if(indexAcceptedSubList >= 0 && indexRejectedSubList >= 0) {
00343         topicNameFromThingAndAction(SubscriptionList[indexAcceptedSubList].Topic, pThingName, action, SHADOW_ACCEPTED);
00344         ret_val = aws_iot_mqtt_subscribe(pMqttClient, SubscriptionList[indexAcceptedSubList].Topic,
00345                                          (uint16_t) strlen(SubscriptionList[indexAcceptedSubList].Topic), QOS0,
00346                                          AckStatusCallback, NULL);
00347         if(ret_val == IOT_SUCCESS) {
00348             SubscriptionList[indexAcceptedSubList].count = 1;
00349             SubscriptionList[indexAcceptedSubList].isSticky = isSticky;
00350             topicNameFromThingAndAction(SubscriptionList[indexRejectedSubList].Topic, pThingName, action,
00351                                         SHADOW_REJECTED);
00352             ret_val = aws_iot_mqtt_subscribe(pMqttClient, SubscriptionList[indexRejectedSubList].Topic,
00353                                              (uint16_t) strlen(SubscriptionList[indexRejectedSubList].Topic), QOS0,
00354                                              AckStatusCallback, NULL);
00355             if(ret_val == IOT_SUCCESS) {
00356                 SubscriptionList[indexRejectedSubList].count = 1;
00357                 SubscriptionList[indexRejectedSubList].isSticky = isSticky;
00358                 clearBothEntriesFromList = false;
00359 
00360                 // wait for SUBSCRIBE_SETTLING_TIME seconds to let the subscription take effect
00361                 init_timer(&subSettlingtimer);
00362                 countdown_sec(&subSettlingtimer, SUBSCRIBE_SETTLING_TIME);
00363                 while(!has_timer_expired(&subSettlingtimer));
00364 
00365             }
00366         }
00367     }
00368 
00369     if(clearBothEntriesFromList) {
00370         if(indexAcceptedSubList >= 0) {
00371             SubscriptionList[indexAcceptedSubList].isFree = true;
00372         } else if(indexRejectedSubList >= 0) {
00373             SubscriptionList[indexRejectedSubList].isFree = true;
00374         }
00375         if(SubscriptionList[indexAcceptedSubList].count == 1) {
00376             aws_iot_mqtt_unsubscribe(pMqttClient, SubscriptionList[indexAcceptedSubList].Topic,
00377                                      (uint16_t) strlen(SubscriptionList[indexAcceptedSubList].Topic));
00378         }
00379     }
00380 
00381     return ret_val;
00382 }
00383 
00384 void incrementSubscriptionCnt(const char *pThingName, ShadowActions_t action, bool isSticky) {
00385     char TemporaryTopicNameAccepted[MAX_SHADOW_TOPIC_LENGTH_BYTES];
00386     char TemporaryTopicNameRejected[MAX_SHADOW_TOPIC_LENGTH_BYTES];
00387     uint8_t i;
00388     topicNameFromThingAndAction(TemporaryTopicNameAccepted, pThingName, action, SHADOW_ACCEPTED);
00389     topicNameFromThingAndAction(TemporaryTopicNameRejected, pThingName, action, SHADOW_REJECTED);
00390 
00391     for(i = 0; i < MAX_TOPICS_AT_ANY_GIVEN_TIME; i++) {
00392         if(!SubscriptionList[i].isFree) {
00393             if((strcmp(TemporaryTopicNameAccepted, SubscriptionList[i].Topic) == 0)
00394                || (strcmp(TemporaryTopicNameRejected, SubscriptionList[i].Topic) == 0)) {
00395                 SubscriptionList[i].count++;
00396                 SubscriptionList[i].isSticky = isSticky;
00397             }
00398         }
00399     }
00400 }
00401 
00402 IoT_Error_t publishToShadowAction(const char *pThingName, ShadowActions_t action, const char *pJsonDocumentToBeSent) {
00403     IoT_Error_t ret_val = IOT_SUCCESS;
00404     char TemporaryTopicName[MAX_SHADOW_TOPIC_LENGTH_BYTES];
00405     IoT_Publish_Message_Params msgParams;
00406 
00407     if(NULL == pThingName || NULL == pJsonDocumentToBeSent) {
00408         return NULL_VALUE_ERROR;
00409     }
00410 
00411     topicNameFromThingAndAction(TemporaryTopicName, pThingName, action, SHADOW_ACTION);
00412 
00413     msgParams.qos = QOS0;
00414     msgParams.payloadLen = strlen(pJsonDocumentToBeSent);
00415     msgParams.payload = (char *) pJsonDocumentToBeSent;
00416     ret_val = aws_iot_mqtt_publish(pMqttClient, TemporaryTopicName, (uint16_t) strlen(TemporaryTopicName), &msgParams);
00417 
00418     return ret_val;
00419 }
00420 
00421 bool getNextFreeIndexOfAckWaitList(uint8_t *pIndex) {
00422     uint8_t i;
00423     bool rc = false;
00424 
00425     if(NULL == pIndex) {
00426         return false;
00427     }
00428 
00429     for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) {
00430         if(AckWaitList[i].isFree) {
00431             *pIndex = i;
00432             rc = true;
00433             break;
00434         }
00435     }
00436 
00437     return rc;
00438 }
00439 
00440 void addToAckWaitList(uint8_t indexAckWaitList, const char *pThingName, ShadowActions_t action,
00441                       const char *pExtractedClientToken, fpActionCallback_t callback, void *pCallbackContext,
00442                       uint32_t timeout_seconds) {
00443     AckWaitList[indexAckWaitList].callback = callback;
00444     strncpy(AckWaitList[indexAckWaitList].clientTokenID, pExtractedClientToken, MAX_SIZE_CLIENT_ID_WITH_SEQUENCE);
00445     strncpy(AckWaitList[indexAckWaitList].thingName, pThingName, MAX_SIZE_OF_THING_NAME);
00446     AckWaitList[indexAckWaitList].pCallbackContext = pCallbackContext;
00447     AckWaitList[indexAckWaitList].action = action;
00448     init_timer(&(AckWaitList[indexAckWaitList].timer));
00449     countdown_sec(&(AckWaitList[indexAckWaitList].timer), timeout_seconds);
00450     AckWaitList[indexAckWaitList].isFree = false;
00451 }
00452 
00453 void HandleExpiredResponseCallbacks(void) {
00454     uint8_t i;
00455     for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) {
00456         if(!AckWaitList[i].isFree) {
00457             if(has_timer_expired(&(AckWaitList[i].timer))) {
00458                 if(AckWaitList[i].callback != NULL) {
00459                     AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, SHADOW_ACK_TIMEOUT,
00460                                             shadowRxBuf, AckWaitList[i].pCallbackContext);
00461                 }
00462                 AckWaitList[i].isFree = true;
00463                 unsubscribeFromAcceptedAndRejected(i);
00464             }
00465         }
00466     }
00467 }
00468 
00469 static void shadow_delta_callback(AWS_IoT_Client *pClient, char *topicName,
00470                                   uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) {
00471     int32_t tokenCount;
00472     uint32_t i = 0;
00473     void *pJsonHandler = NULL;
00474     int32_t DataPosition;
00475     uint32_t dataLength;
00476     uint32_t tempVersionNumber = 0;
00477 
00478     FUNC_ENTRY;
00479 
00480     IOT_UNUSED(pClient);
00481     IOT_UNUSED(topicName);
00482     IOT_UNUSED(topicNameLen);
00483     IOT_UNUSED(pData);
00484 
00485     if(params->payloadLen > SHADOW_MAX_SIZE_OF_RX_BUFFER) {
00486         IOT_WARN("Payload larger than RX Buffer");
00487         return;
00488     }
00489 
00490     memcpy(shadowRxBuf, params->payload, params->payloadLen);
00491     shadowRxBuf[params->payloadLen] = '\0';    // jsmn_parse relies on a string
00492 
00493     if(!isJsonValidAndParse(shadowRxBuf, pJsonHandler, &tokenCount)) {
00494         IOT_WARN("Received JSON is not valid");
00495         return;
00496     }
00497 
00498     if(shadowDiscardOldDeltaFlag) {
00499         if(extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) {
00500             if(tempVersionNumber > shadowJsonVersionNum) {
00501                 shadowJsonVersionNum = tempVersionNumber;
00502             } else {
00503                 IOT_WARN("Old Delta Message received - Ignoring rx: %d local: %d", tempVersionNumber,
00504                          shadowJsonVersionNum);
00505                 return;
00506             }
00507         }
00508     }
00509 
00510     for(i = 0; i < tokenTableIndex; i++) {
00511         if(!tokenTable[i].isFree) {
00512             if(isJsonKeyMatchingAndUpdateValue(shadowRxBuf, pJsonHandler, tokenCount,
00513                                                (jsonStruct_t *) tokenTable[i].pStruct, &dataLength, &DataPosition)) {
00514                 if(tokenTable[i].callback != NULL) {
00515                     tokenTable[i].callback(shadowRxBuf + DataPosition, dataLength,
00516                                            (jsonStruct_t *) tokenTable[i].pStruct);
00517                 }
00518             }
00519         }
00520     }
00521 }
00522 
00523 #ifdef __cplusplus
00524 }
00525 #endif