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_json.cpp Source File

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