Pierre-Marie Ancèle
/
AWS-test
test
Embed:
(wiki syntax)
Show/hide line numbers
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 = 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 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 = 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 == 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 == 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 = 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 == 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 == 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 = 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
Generated on Tue Jul 12 2022 20:38:50 by 1.7.2