Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of AWS-test by
aws_iot_shadow_json.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_shadow_json.c 00018 * @brief Shadow client JSON parsing API definitions 00019 */ 00020 00021 #ifdef __cplusplus 00022 extern "C" { 00023 #include <cinttypes> 00024 #else 00025 00026 #include <inttypes.h> 00027 00028 #endif 00029 00030 #include "aws_iot_shadow_json.h" 00031 00032 #include <string.h> 00033 #include <stdbool.h> 00034 00035 #include "aws_iot_json_utils.h" 00036 #include "aws_iot_log.h" 00037 #include "aws_iot_shadow_key.h" 00038 #include "aws_iot_config.h" 00039 00040 extern char mqttClientID[MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES]; 00041 00042 static uint32_t clientTokenNum = 0; 00043 00044 //helper functions 00045 static IoT_Error_t convertDataToString(char *pStringBuffer, size_t maxSizoStringBuffer, JsonPrimitiveType type, 00046 void *pData); 00047 00048 void resetClientTokenSequenceNum(void) { 00049 clientTokenNum = 0; 00050 } 00051 00052 static void emptyJsonWithClientToken(char *pJsonDocument) { 00053 sprintf(pJsonDocument, "{\"clientToken\":\""); 00054 FillWithClientToken(pJsonDocument + strlen(pJsonDocument)); 00055 sprintf(pJsonDocument + strlen(pJsonDocument), "\"}"); 00056 } 00057 00058 void aws_iot_shadow_internal_get_request_json(char *pJsonDocument) { 00059 emptyJsonWithClientToken(pJsonDocument); 00060 } 00061 00062 void aws_iot_shadow_internal_delete_request_json(char *pJsonDocument) { 00063 emptyJsonWithClientToken(pJsonDocument); 00064 } 00065 00066 static inline IoT_Error_t checkReturnValueOfSnPrintf(int32_t snPrintfReturn, size_t maxSizeOfJsonDocument) { 00067 if(snPrintfReturn < 0) { 00068 return SHADOW_JSON_ERROR; 00069 } else if((size_t) snPrintfReturn >= maxSizeOfJsonDocument) { 00070 return SHADOW_JSON_BUFFER_TRUNCATED; 00071 } 00072 return IOT_SUCCESS; 00073 } 00074 00075 IoT_Error_t aws_iot_shadow_init_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument) { 00076 00077 IoT_Error_t ret_val = IOT_SUCCESS; 00078 int32_t snPrintfReturn = 0; 00079 00080 if(pJsonDocument == NULL) { 00081 return NULL_VALUE_ERROR; 00082 } 00083 snPrintfReturn = snprintf(pJsonDocument, maxSizeOfJsonDocument, "{\"state\":{"); 00084 00085 ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, maxSizeOfJsonDocument); 00086 00087 return ret_val; 00088 00089 } 00090 00091 IoT_Error_t aws_iot_shadow_add_desired(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...) { 00092 IoT_Error_t ret_val = IOT_SUCCESS; 00093 size_t tempSize = 0; 00094 int8_t i; 00095 size_t remSizeOfJsonBuffer = maxSizeOfJsonDocument; 00096 int32_t snPrintfReturn = 0; 00097 va_list pArgs; 00098 jsonStruct_t *pTemporary = NULL; 00099 va_start(pArgs, count); 00100 00101 if(pJsonDocument == NULL) { 00102 return NULL_VALUE_ERROR; 00103 } 00104 00105 tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); 00106 if(tempSize <= 1) { 00107 return SHADOW_JSON_ERROR; 00108 } 00109 remSizeOfJsonBuffer = tempSize; 00110 00111 snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"desired\":{"); 00112 ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); 00113 00114 if(ret_val != IOT_SUCCESS) { 00115 return ret_val; 00116 } 00117 00118 for(i = 0; i < count; i++) { 00119 tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); 00120 if(tempSize <= 1) { 00121 return SHADOW_JSON_ERROR; 00122 } 00123 remSizeOfJsonBuffer = tempSize; 00124 pTemporary = va_arg (pArgs, jsonStruct_t *); 00125 if(pTemporary != NULL) { 00126 snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"%s\":", 00127 pTemporary->pKey); 00128 ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); 00129 if(ret_val != IOT_SUCCESS) { 00130 return ret_val; 00131 } 00132 if(pTemporary->pKey != NULL && pTemporary->pData != NULL) { 00133 ret_val = convertDataToString(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, 00134 pTemporary->type, pTemporary->pData); 00135 } else { 00136 return NULL_VALUE_ERROR; 00137 } 00138 if(ret_val != IOT_SUCCESS) { 00139 return ret_val; 00140 } 00141 } else { 00142 return NULL_VALUE_ERROR; 00143 } 00144 } 00145 00146 va_end(pArgs); 00147 snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument) - 1, remSizeOfJsonBuffer, "},"); 00148 ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); 00149 return ret_val; 00150 } 00151 00152 IoT_Error_t aws_iot_shadow_add_reported(char *pJsonDocument, size_t maxSizeOfJsonDocument, uint8_t count, ...) { 00153 IoT_Error_t ret_val = IOT_SUCCESS; 00154 00155 int8_t i; 00156 size_t remSizeOfJsonBuffer = maxSizeOfJsonDocument; 00157 int32_t snPrintfReturn = 0; 00158 size_t tempSize = 0; 00159 jsonStruct_t *pTemporary; 00160 va_list pArgs; 00161 va_start(pArgs, count); 00162 00163 if(pJsonDocument == NULL) { 00164 return NULL_VALUE_ERROR; 00165 } 00166 00167 00168 tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); 00169 if(tempSize <= 1) { 00170 return SHADOW_JSON_ERROR; 00171 } 00172 remSizeOfJsonBuffer = tempSize; 00173 00174 snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"reported\":{"); 00175 ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); 00176 00177 if(ret_val != IOT_SUCCESS) { 00178 return ret_val; 00179 } 00180 00181 for(i = 0; i < count; i++) { 00182 tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); 00183 if(tempSize <= 1) { 00184 return SHADOW_JSON_ERROR; 00185 } 00186 remSizeOfJsonBuffer = tempSize; 00187 00188 pTemporary = va_arg (pArgs, jsonStruct_t *); 00189 if(pTemporary != NULL) { 00190 snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"%s\":", 00191 pTemporary->pKey); 00192 ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); 00193 if(ret_val != IOT_SUCCESS) { 00194 return ret_val; 00195 } 00196 if(pTemporary->pKey != NULL && pTemporary->pData != NULL) { 00197 ret_val = convertDataToString(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, 00198 pTemporary->type, pTemporary->pData); 00199 } else { 00200 return NULL_VALUE_ERROR; 00201 } 00202 if(ret_val != IOT_SUCCESS) { 00203 return ret_val; 00204 } 00205 } else { 00206 return NULL_VALUE_ERROR; 00207 } 00208 } 00209 00210 va_end(pArgs); 00211 snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument) - 1, remSizeOfJsonBuffer, "},"); 00212 ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); 00213 return ret_val; 00214 } 00215 00216 00217 int32_t FillWithClientTokenSize(char *pBufferToBeUpdatedWithClientToken, size_t maxSizeOfJsonDocument) { 00218 int32_t snPrintfReturn; 00219 snPrintfReturn = snprintf(pBufferToBeUpdatedWithClientToken, maxSizeOfJsonDocument, "%s-%d", mqttClientID, 00220 clientTokenNum++); 00221 00222 return snPrintfReturn; 00223 } 00224 00225 IoT_Error_t aws_iot_fill_with_client_token(char *pBufferToBeUpdatedWithClientToken, size_t maxSizeOfJsonDocument) { 00226 00227 int32_t snPrintfRet = 0; 00228 snPrintfRet = FillWithClientTokenSize(pBufferToBeUpdatedWithClientToken, maxSizeOfJsonDocument); 00229 return checkReturnValueOfSnPrintf(snPrintfRet, maxSizeOfJsonDocument); 00230 00231 } 00232 00233 IoT_Error_t aws_iot_finalize_json_document(char *pJsonDocument, size_t maxSizeOfJsonDocument) { 00234 size_t remSizeOfJsonBuffer = maxSizeOfJsonDocument; 00235 int32_t snPrintfReturn = 0; 00236 size_t tempSize = 0; 00237 IoT_Error_t ret_val = IOT_SUCCESS; 00238 00239 if(pJsonDocument == NULL) { 00240 return NULL_VALUE_ERROR; 00241 } 00242 00243 tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); 00244 if(tempSize <= 1) { 00245 return SHADOW_JSON_ERROR; 00246 } 00247 remSizeOfJsonBuffer = tempSize; 00248 00249 // strlen(ShadowTxBuffer) - 1 is to ensure we remove the last ,(comma) that was added 00250 snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument) - 1, remSizeOfJsonBuffer, "}, \"%s\":\"", 00251 SHADOW_CLIENT_TOKEN_STRING); 00252 ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); 00253 00254 if(ret_val != IOT_SUCCESS) { 00255 return ret_val; 00256 } 00257 // refactor this XXX repeated code 00258 tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); 00259 if(tempSize <= 1) { 00260 return SHADOW_JSON_ERROR; 00261 } 00262 remSizeOfJsonBuffer = tempSize; 00263 00264 00265 snPrintfReturn = FillWithClientTokenSize(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer); 00266 ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); 00267 00268 if(ret_val != IOT_SUCCESS) { 00269 return ret_val; 00270 } 00271 tempSize = maxSizeOfJsonDocument - strlen(pJsonDocument); 00272 if(tempSize <= 1) { 00273 return SHADOW_JSON_ERROR; 00274 } 00275 remSizeOfJsonBuffer = tempSize; 00276 00277 00278 snPrintfReturn = snprintf(pJsonDocument + strlen(pJsonDocument), remSizeOfJsonBuffer, "\"}"); 00279 ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, remSizeOfJsonBuffer); 00280 00281 return ret_val; 00282 } 00283 00284 void FillWithClientToken(char *pBufferToBeUpdatedWithClientToken) { 00285 sprintf(pBufferToBeUpdatedWithClientToken, "%s-%d", mqttClientID, clientTokenNum++); 00286 } 00287 00288 static IoT_Error_t convertDataToString(char *pStringBuffer, size_t maxSizoStringBuffer, JsonPrimitiveType type, 00289 void *pData) { 00290 int32_t snPrintfReturn = 0; 00291 IoT_Error_t ret_val = IOT_SUCCESS; 00292 00293 if(maxSizoStringBuffer == 0) { 00294 return SHADOW_JSON_ERROR; 00295 } 00296 00297 if(type == SHADOW_JSON_INT32) { 00298 snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIi32",", *(int32_t *) (pData)); 00299 } else if(type == SHADOW_JSON_INT16) { 00300 snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIi16",", *(int16_t *) (pData)); 00301 } else if(type == SHADOW_JSON_INT8) { 00302 snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIi8",", *(int8_t *) (pData)); 00303 } else if(type == SHADOW_JSON_UINT32) { 00304 snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIu32",", *(uint32_t *) (pData)); 00305 } else if(type == SHADOW_JSON_UINT16) { 00306 snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIu16",", *(uint16_t *) (pData)); 00307 } else if(type == SHADOW_JSON_UINT8) { 00308 snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%" PRIu8",", *(uint8_t *) (pData)); 00309 } else if(type == SHADOW_JSON_DOUBLE) { 00310 snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%f,", *(double *) (pData)); 00311 } else if(type == SHADOW_JSON_FLOAT) { 00312 snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%f,", *(float *) (pData)); 00313 } else if(type == SHADOW_JSON_BOOL) { 00314 snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "%s,", *(bool *) (pData) ? "true" : "false"); 00315 } else if(type == SHADOW_JSON_STRING) { 00316 snPrintfReturn = snprintf(pStringBuffer, maxSizoStringBuffer, "\"%s\",", (char *) (pData)); 00317 } 00318 00319 ret_val = checkReturnValueOfSnPrintf(snPrintfReturn, maxSizoStringBuffer); 00320 00321 return ret_val; 00322 } 00323 00324 static jsmn_parser shadowJsonParser; 00325 static jsmntok_t jsonTokenStruct[MAX_JSON_TOKEN_EXPECTED]; 00326 00327 bool isJsonValidAndParse(const char *pJsonDocument, void *pJsonHandler, int32_t *pTokenCount) { 00328 int32_t tokenCount; 00329 00330 jsmn_init(&shadowJsonParser); 00331 00332 tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, strlen(pJsonDocument), jsonTokenStruct, 00333 sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); 00334 00335 if(tokenCount < 0) { 00336 IOT_WARN("Failed to parse JSON: %d\n", tokenCount); 00337 return false; 00338 } 00339 00340 /* Assume the top-level element is an object */ 00341 if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { 00342 IOT_WARN("Top Level is not an object\n"); 00343 return false; 00344 } 00345 00346 pJsonHandler = (void *) jsonTokenStruct; 00347 *pTokenCount = tokenCount; 00348 00349 return true; 00350 } 00351 00352 static IoT_Error_t UpdateValueIfNoObject(const char *pJsonString, jsonStruct_t *pDataStruct, jsmntok_t token) { 00353 IoT_Error_t ret_val = IOT_SUCCESS; 00354 if(pDataStruct->type == SHADOW_JSON_BOOL) { 00355 ret_val = parseBooleanValue((bool *) pDataStruct->pData, pJsonString, &token); 00356 } else if(pDataStruct->type == SHADOW_JSON_INT32) { 00357 ret_val = parseInteger32Value((int32_t *) pDataStruct->pData, pJsonString, &token); 00358 } else if(pDataStruct->type == SHADOW_JSON_INT16) { 00359 ret_val = parseInteger16Value((int16_t *) pDataStruct->pData, pJsonString, &token); 00360 } else if(pDataStruct->type == SHADOW_JSON_INT8) { 00361 ret_val = parseInteger8Value((int8_t *) pDataStruct->pData, pJsonString, &token); 00362 } else if(pDataStruct->type == SHADOW_JSON_UINT32) { 00363 ret_val = parseUnsignedInteger32Value((uint32_t *) pDataStruct->pData, pJsonString, &token); 00364 } else if(pDataStruct->type == SHADOW_JSON_UINT16) { 00365 ret_val = parseUnsignedInteger16Value((uint16_t *) pDataStruct->pData, pJsonString, &token); 00366 } else if(pDataStruct->type == SHADOW_JSON_UINT8) { 00367 ret_val = parseUnsignedInteger8Value((uint8_t *) pDataStruct->pData, pJsonString, &token); 00368 } else if(pDataStruct->type == SHADOW_JSON_FLOAT) { 00369 ret_val = parseFloatValue((float *) pDataStruct->pData, pJsonString, &token); 00370 } else if(pDataStruct->type == SHADOW_JSON_DOUBLE) { 00371 ret_val = parseDoubleValue((double *) pDataStruct->pData, pJsonString, &token); 00372 } 00373 00374 return ret_val; 00375 } 00376 00377 bool isJsonKeyMatchingAndUpdateValue(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, 00378 jsonStruct_t *pDataStruct, uint32_t *pDataLength, int32_t *pDataPosition) { 00379 int32_t i; 00380 uint32_t dataLength; 00381 jsmntok_t *pJsonTokenStruct; 00382 jsmntok_t dataToken; 00383 00384 pJsonTokenStruct = (jsmntok_t *) pJsonHandler; 00385 for(i = 1; i < tokenCount; i++) { 00386 if(jsoneq(pJsonDocument, &(jsonTokenStruct[i]), pDataStruct->pKey) == 0) { 00387 dataToken = jsonTokenStruct[i + 1]; 00388 dataLength = (uint32_t) (dataToken.end - dataToken.start); 00389 UpdateValueIfNoObject(pJsonDocument, pDataStruct, dataToken); 00390 *pDataPosition = dataToken.start; 00391 *pDataLength = dataLength; 00392 return true; 00393 } 00394 } 00395 return false; 00396 } 00397 00398 bool isReceivedJsonValid(const char *pJsonDocument) { 00399 int32_t tokenCount; 00400 00401 jsmn_init(&shadowJsonParser); 00402 00403 tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, strlen(pJsonDocument), jsonTokenStruct, 00404 sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); 00405 00406 if(tokenCount < 0) { 00407 IOT_WARN("Failed to parse JSON: %d\n", tokenCount); 00408 return false; 00409 } 00410 00411 /* Assume the top-level element is an object */ 00412 if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { 00413 return false; 00414 } 00415 00416 return true; 00417 } 00418 00419 bool extractClientToken(const char *pJsonDocument, char *pExtractedClientToken) { 00420 int32_t tokenCount, i; 00421 uint8_t length; 00422 jsmntok_t ClientJsonToken; 00423 jsmn_init(&shadowJsonParser); 00424 00425 tokenCount = jsmn_parse(&shadowJsonParser, pJsonDocument, strlen(pJsonDocument), jsonTokenStruct, 00426 sizeof(jsonTokenStruct) / sizeof(jsonTokenStruct[0])); 00427 00428 if(tokenCount < 0) { 00429 IOT_WARN("Failed to parse JSON: %d\n", tokenCount); 00430 return false; 00431 } 00432 00433 /* Assume the top-level element is an object */ 00434 if(tokenCount < 1 || jsonTokenStruct[0].type != JSMN_OBJECT) { 00435 return false; 00436 } 00437 00438 for(i = 1; i < tokenCount; i++) { 00439 if(jsoneq(pJsonDocument, &jsonTokenStruct[i], SHADOW_CLIENT_TOKEN_STRING) == 0) { 00440 ClientJsonToken = jsonTokenStruct[i + 1]; 00441 length = (uint8_t) (ClientJsonToken.end - ClientJsonToken.start); 00442 strncpy(pExtractedClientToken, pJsonDocument + ClientJsonToken.start, length); 00443 pExtractedClientToken[length] = '\0'; 00444 return true; 00445 } 00446 } 00447 00448 return false; 00449 } 00450 00451 bool extractVersionNumber(const char *pJsonDocument, void *pJsonHandler, int32_t tokenCount, uint32_t *pVersionNumber) { 00452 int32_t i; 00453 IoT_Error_t ret_val = IOT_SUCCESS; 00454 00455 IOT_UNUSED(pJsonHandler); 00456 00457 for(i = 1; i < tokenCount; i++) { 00458 if(jsoneq(pJsonDocument, &(jsonTokenStruct[i]), SHADOW_VERSION_STRING) == 0) { 00459 ret_val = parseUnsignedInteger32Value(pVersionNumber, pJsonDocument, &jsonTokenStruct[i + 1]); 00460 if(ret_val == IOT_SUCCESS) { 00461 return true; 00462 } 00463 } 00464 } 00465 return false; 00466 } 00467 00468 #ifdef __cplusplus 00469 } 00470 #endif 00471
Generated on Tue Jul 12 2022 11:16:37 by
