├── LICENSE ├── README.md ├── json-analyze ├── CMakeLists.txt ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c ├── json-array-in-array ├── CMakeLists.txt ├── Makefile ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c ├── json-array-in-object ├── CMakeLists.txt ├── Makefile ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c ├── json-basic-array ├── CMakeLists.txt ├── Makefile ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c ├── json-basic-object ├── CMakeLists.txt ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c ├── json-check ├── CMakeLists.txt ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c ├── json-create-array ├── CMakeLists.txt ├── Makefile ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c ├── json-directory-tree ├── CMakeLists.txt ├── README.md ├── fatfs_image │ ├── CMakeLists.txt │ ├── libs │ │ ├── lib001 │ │ │ └── lib001.a │ │ └── lib002 │ │ │ └── lib002.a │ ├── obj │ │ ├── main.o │ │ └── sub.o │ ├── sdkconfig │ └── src │ │ ├── main.c │ │ └── sub.c ├── main │ ├── CMakeLists.txt │ └── main.c ├── partitions_example.csv └── sdkconfig.defaults ├── json-generator ├── CMakeLists.txt ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ ├── idf_component.yml │ └── main.c ├── json-http-client1 ├── CMakeLists.txt ├── README.md ├── db.json └── main │ ├── CMakeLists.txt │ ├── Kconfig.projbuild │ ├── component.mk │ └── main.c ├── json-http-client2 ├── CMakeLists.txt ├── README.md ├── getpem.sh └── main │ ├── CMakeLists.txt │ ├── Kconfig.projbuild │ ├── component.mk │ ├── main.c │ └── server_root_cert.pem ├── json-http-client3 ├── CMakeLists.txt ├── README.md ├── db.json ├── html │ ├── error.html │ ├── favicon.ico │ ├── jsonTreeViewer.js │ ├── libs │ │ ├── app │ │ │ ├── App.js │ │ │ ├── README.md │ │ │ ├── app.css │ │ │ ├── docs │ │ │ │ ├── index.htm │ │ │ │ └── main.css │ │ │ └── reset.css │ │ └── jsonTree │ │ │ ├── icons.svg │ │ │ ├── jsonTree.css │ │ │ └── jsonTree.js │ ├── main.css │ ├── main.js │ └── root.html └── main │ ├── CMakeLists.txt │ ├── Kconfig.projbuild │ ├── component.mk │ ├── http_get_notify.c │ ├── idf_component.yml │ ├── main.c │ ├── web_client.c │ └── web_server.c ├── json-http-client4 ├── CMakeLists.txt ├── README.md ├── db.json ├── html │ ├── error.html │ ├── favicon.ico │ ├── jsonTreeViewer.js │ ├── main.css │ ├── main.js │ └── root.html └── main │ ├── CMakeLists.txt │ ├── Kconfig.projbuild │ ├── component.mk │ ├── http_get_notify.c │ ├── idf_component.yml │ ├── main.c │ ├── web_client.c │ └── web_server.c ├── json-make-tree ├── CMakeLists.txt ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c ├── json-object-in-array ├── CMakeLists.txt ├── Makefile ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c ├── json-object-in-object ├── CMakeLists.txt ├── Makefile ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c ├── json-record-in-array ├── CMakeLists.txt ├── Makefile ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c ├── json-record-in-object ├── CMakeLists.txt ├── Makefile ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c ├── json-replace-array ├── CMakeLists.txt ├── Makefile ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c ├── json-replace-object ├── CMakeLists.txt ├── Makefile ├── README.md └── main │ ├── CMakeLists.txt │ ├── component.mk │ └── main.c └── json-subarrays ├── CMakeLists.txt ├── Makefile ├── README.md └── main ├── CMakeLists.txt ├── component.mk └── main.c /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 nopnop2002 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # esp-idf-json 2 | Example of JSON Serialize and Deserialize with ESP-IDF. 3 | 4 | 5 | ESP-IDF includes [this](https://github.com/DaveGamble/cJSON) cJSON library. 6 | You can use JSON components as standard. 7 | But the documentation is very poor. 8 | The official documentation for the JSON component is [here](https://github.com/espressif/esp-idf/tree/master/components/json/README). 9 | 10 | [Here](https://github.com/DaveGamble/cJSON/blob/master/tests/readme_examples.c) is a example by Dave Gamble. 11 | 12 | # How to use 13 | ``` 14 | git clone https://github.com/nopnop2002/esp-idf-json 15 | cd esp-idf-json/json-basic-object 16 | idf.py flash monitor 17 | ``` 18 | 19 | # About cJSON_Print 20 | From print_value() function, the pointer returned is allocated by cJSON_strdup() and it is returned to the caller. 21 | Buffers returned by cJSON_Print must be freed by the caller. 22 | Please use the proper API (cJSON_free) rather than directly calling stdlib free. 23 | 24 | ``` 25 | char *my_json_string = cJSON_Print(root); 26 | ESP_LOGI(TAG, "my_json_string\n%s",my_json_string); 27 | cJSON_Delete(root); 28 | cJSON_free(my_json_string); 29 | ``` 30 | 31 | 32 | # Basic Structure 33 | - Array 34 | Array, like this, have no name. 35 | Array starts with [ and ends with ]. 36 | root is defined by cJSON_CreateArray. 37 | element is added by cJSON_AddItemToArray. 38 | ``` 39 | ["abc", 123, true, false, null] 40 | ``` 41 | 42 | - Object 43 | Object, like this, have name. 44 | Object starts with { and ends with }. 45 | root is defined by cJSON_CreateObject. 46 | element is added by cJSON_AddItemToObject. 47 | ``` 48 | { 49 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 50 | "cores": 2, 51 | } 52 | ``` 53 | 54 | # Complex structure 55 | 56 | - Object in Array 57 | ``` 58 | ["abc", 123, true, false, null, { 59 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 60 | "cores": 2 61 | }] 62 | ``` 63 | 64 | ``` 65 | [{ 66 | "id": 0, 67 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 68 | "cores": 2 69 | }, { 70 | "id": 1, 71 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 72 | "cores": 2 73 | }] 74 | ``` 75 | 76 | - Array in Array 77 | ``` 78 | [["abc", 120], ["abc", 121], ["abc", 122], ["abc", 123], ["abc", 124], ["abc", 125], ["abc", 126], ["abc", 127], ["abc", 128], ["abc", 129]] 79 | ``` 80 | 81 | 82 | 83 | - Object in Object 84 | ``` 85 | { 86 | "name": "Jack (\"Bee\") Nimble", 87 | "format": { 88 | "type": "rect", 89 | "width": 1920, 90 | "height": 1080, 91 | "interlace": false, 92 | "frame rate": 24 93 | } 94 | } 95 | ``` 96 | 97 | - Array in Object 98 | ``` 99 | { 100 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 101 | "cores": 2, 102 | "array": ["abc", 123, true, false, null] 103 | } 104 | ``` 105 | 106 | # More Complex structure 107 | 108 | - Object in Array in Object 109 | ``` 110 | { 111 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 112 | "cores": 2, 113 | "array": [{ 114 | "width": 1280, 115 | "height": 720 116 | }, { 117 | "width": 1920, 118 | "height": 1080 119 | }, { 120 | "width": 3840, 121 | "height": 2160 122 | }] 123 | } 124 | ``` 125 | 126 | - Array in Object in Array 127 | ``` 128 | [{ 129 | "id": 0, 130 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 131 | "cores": 2, 132 | "array": ["abc", 123, true, false, null] 133 | }, { 134 | "id": 1, 135 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 136 | "cores": 2, 137 | "array": ["abc", 123, true, false, null] 138 | }] 139 | ``` 140 | 141 | # How to Serialize 142 | Serialization starts from the lowest level. 143 | No matter how complex the structure, there are only objects and arrays. 144 | 145 | - Target structure 146 | ``` 147 | { 148 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 149 | "cores": 2, 150 | "array": [{ 151 | "width": 1280, 152 | "height": 720 153 | }, { 154 | "width": 1920, 155 | "height": 1080 156 | }, { 157 | "width": 3840, 158 | "height": 2160 159 | }] 160 | } 161 | ``` 162 | 163 | 164 | - Create 3 objects 165 | This is simple object. 166 | ``` 167 | { 168 | "width": 1280, 169 | "height": 720 170 | } 171 | ``` 172 | ``` 173 | { 174 | "width": 1920, 175 | "height": 1080 176 | } 177 | ``` 178 | ``` 179 | { 180 | "width": 3840, 181 | "height": 2160 182 | } 183 | 184 | ``` 185 | 186 | - Create array 187 | This is object in array. 188 | ``` 189 | [{ 190 | "width": 1280, 191 | "height": 720 192 | }, { 193 | "width": 1920, 194 | "height": 1080 195 | }, { 196 | "width": 3840, 197 | "height": 2160 198 | }] 199 | ``` 200 | 201 | - Create object as root 202 | This is array in object. 203 | ``` 204 | { 205 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 206 | "cores": 2, 207 | "array": [{ 208 | "width": 1280, 209 | "height": 720 210 | }, { 211 | "width": 1920, 212 | "height": 1080 213 | }, { 214 | "width": 3840, 215 | "height": 2160 216 | }] 217 | } 218 | ``` 219 | 220 | 221 | - Target structure 222 | ``` 223 | [{ 224 | "id": 0, 225 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 226 | "cores": 2, 227 | "array": ["abc", 123, true, false, null] 228 | }, { 229 | "id": 1, 230 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 231 | "cores": 2, 232 | "array": ["abc", 123, true, false, null] 233 | }] 234 | ``` 235 | 236 | 237 | - Create 2 arrays 238 | This is simple array. 239 | ``` 240 | ["abc", 123, true, false, null] 241 | ``` 242 | ``` 243 | ["abc", 123, true, false, null] 244 | ``` 245 | 246 | - Create 2 objects 247 | This is array in object. 248 | ``` 249 | { 250 | "id": 1, 251 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 252 | "cores": 2, 253 | "array": ["abc", 123, true, false, null] 254 | } 255 | ``` 256 | 257 | ``` 258 | { 259 | "id": 0, 260 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 261 | "cores": 2, 262 | "array": ["abc", 123, true, false, null] 263 | } 264 | ``` 265 | 266 | - Create array as root 267 | This is object in array. 268 | ``` 269 | [{ 270 | "id": 0, 271 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 272 | "cores": 2, 273 | "array": ["abc", 123, true, false, null] 274 | }, { 275 | "id": 1, 276 | "version": "v5.0-dev-3202-ga2d5041492-dirty", 277 | "cores": 2, 278 | "array": ["abc", 123, true, false, null] 279 | }] 280 | ``` 281 | 282 | 283 | 284 | # JSON Data Set Sample 285 | This is a sample JSON data set. 286 | https://opensource.adobe.com/Spry/samples/data_region/JSONDataSetSample.html 287 | -------------------------------------------------------------------------------- /json-analyze/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | -------------------------------------------------------------------------------- /json-analyze/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | 3 | ## Serialize 4 | ``` 5 | { 6 | "version": "v5.1.2-dirty", 7 | "cores": 2, 8 | "wifi": true, 9 | "ethernet": false, 10 | "bool": false, 11 | "null": null, 12 | "screen": { 13 | "type": "rect", 14 | "width": 1920, 15 | "height": 1080, 16 | "interlace": false, 17 | "luster": true 18 | }, 19 | "screen": ["rect", 1920, 1080, false, true] 20 | } 21 | ``` 22 | 23 | ## DeSerialize 24 | ``` 25 | I (381) JSON: Deserialize..... 26 | I (381) JSON: [version] 27 | I (391) JSON: v5.1.2-dirty 28 | I (391) JSON: [cores] 29 | I (391) JSON: int=2 double=2.000000 30 | I (401) JSON: [wifi] 31 | I (401) JSON: True 32 | I (401) JSON: [ethernet] 33 | I (411) JSON: False 34 | I (411) JSON: [bool] 35 | I (411) JSON: False 36 | I (411) JSON: [null] 37 | I (421) JSON: Null 38 | I (421) JSON: [screen] 39 | I (421) JSON: [type] 40 | I (431) JSON: rect 41 | I (431) JSON: [width] 42 | I (431) JSON: int=1920 double=1920.000000 43 | I (441) JSON: [height] 44 | I (441) JSON: int=1080 double=1080.000000 45 | I (441) JSON: [interlace] 46 | I (451) JSON: False 47 | I (451) JSON: [luster] 48 | I (451) JSON: True 49 | I (461) JSON: [screen] 50 | I (461) JSON: rect 51 | I (461) JSON: int=1920 double=1920.000000 52 | I (471) JSON: int=1080 double=1080.000000 53 | I (471) JSON: False 54 | I (471) JSON: True 55 | ``` 56 | 57 | ## Analysis 58 | ``` 59 | elementsLength=18 60 | element[0] cJSON_String [version] [v5.1.2-dirty] 61 | element[1] cJSON_Number [cores] int=2 double=2.000000 62 | element[2] cJSON_True [wifi] 63 | element[3] cJSON_False [ethernet] 64 | element[4] cJSON_False [bool] 65 | element[5] cJSON_NULL [null] 66 | element[6] cJSON_Object [screen] 67 | element[7] cJSON_String [type] [rect] 68 | element[8] cJSON_Number [width] int=1920 double=1920.000000 69 | element[9] cJSON_Number [height] int=1080 double=1080.000000 70 | element[10] cJSON_False [interlace] 71 | element[11] cJSON_True [luster] 72 | element[12] cJSON_Array [screen] 73 | element[13] cJSON_String [array item] [rect] 74 | element[14] cJSON_Number [array item] int=1920 double=1920.000000 75 | element[15] cJSON_Number [array item] int=1080 double=1080.000000 76 | element[16] cJSON_False [array item] 77 | element[17] cJSON_True [array item] 78 | ``` 79 | -------------------------------------------------------------------------------- /json-analyze/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "main.c") 2 | set(COMPONENT_ADD_INCLUDEDIRS "") 3 | 4 | register_component() 5 | -------------------------------------------------------------------------------- /json-analyze/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | -------------------------------------------------------------------------------- /json-analyze/main/main.c: -------------------------------------------------------------------------------- 1 | /* The example of ESP-IDF 2 | * 3 | * This sample code is in the public domain. 4 | */ 5 | 6 | #include 7 | #include 8 | #include "freertos/FreeRTOS.h" 9 | #include "freertos/task.h" 10 | #include "esp_log.h" 11 | #include "esp_chip_info.h" 12 | #include "cJSON.h" 13 | 14 | static const char *TAG = "JSON"; 15 | 16 | typedef struct { 17 | int type; 18 | char name[32]; 19 | int valueint; 20 | double valuedouble; 21 | char valuestring[32]; 22 | } JSON_t; 23 | 24 | char *JSON_Types(int type) { 25 | if (type == cJSON_Invalid) return ("cJSON_Invalid"); 26 | if (type == cJSON_False) return ("cJSON_False"); 27 | if (type == cJSON_True) return ("cJSON_True"); 28 | if (type == cJSON_NULL) return ("cJSON_NULL"); 29 | if (type == cJSON_Number) return ("cJSON_Number"); 30 | if (type == cJSON_String) return ("cJSON_String"); 31 | if (type == cJSON_Array) return ("cJSON_Array"); 32 | if (type == cJSON_Object) return ("cJSON_Object"); 33 | if (type == cJSON_Raw) return ("cJSON_Raw"); 34 | return NULL; 35 | } 36 | 37 | 38 | esp_err_t JSON_Analyze(const cJSON * const root, JSON_t **elements, size_t *elementsLength) { 39 | //ESP_LOGI(TAG, "root->type=%s", JSON_Types(root->type)); 40 | cJSON *current_element = NULL; 41 | //ESP_LOGI(TAG, "roo->child=%p", root->child); 42 | //ESP_LOGI(TAG, "roo->next =%p", root->next); 43 | cJSON_ArrayForEach(current_element, root) { 44 | //ESP_LOGI(TAG, "type=%s", JSON_Types(current_element->type)); 45 | //ESP_LOGI(TAG, "current_element->string=%p", current_element->string); 46 | 47 | if (*elements == NULL) { 48 | (*elementsLength)++; 49 | *elements = (JSON_t *)malloc(sizeof(JSON_t)); 50 | } else { 51 | (*elementsLength)++; 52 | *elements = (JSON_t *)realloc(*elements, *elementsLength * sizeof(JSON_t)); 53 | } 54 | if (*elements == NULL) { 55 | ESP_LOGE(TAG, "Error allocating memory for elements"); 56 | return ESP_ERR_NO_MEM; 57 | } 58 | 59 | if (current_element->string) { 60 | const char* name = current_element->string; 61 | ESP_LOGI(TAG, "[%s]", name); 62 | strncpy((*elements+(*elementsLength)-1)->name, name, 31); 63 | } else { 64 | strcpy((*elements+(*elementsLength)-1)->name, "array item"); 65 | } 66 | if (cJSON_IsInvalid(current_element)) { 67 | ESP_LOGI(TAG, "Invalid"); 68 | (*elements+(*elementsLength)-1)->type = cJSON_Invalid; 69 | } else if (cJSON_IsFalse(current_element)) { 70 | ESP_LOGI(TAG, "False"); 71 | (*elements+(*elementsLength)-1)->type = cJSON_False; 72 | } else if (cJSON_IsTrue(current_element)) { 73 | ESP_LOGI(TAG, "True"); 74 | (*elements+(*elementsLength)-1)->type = cJSON_True; 75 | } else if (cJSON_IsNull(current_element)) { 76 | ESP_LOGI(TAG, "Null"); 77 | (*elements+(*elementsLength)-1)->type = cJSON_NULL; 78 | } else if (cJSON_IsNumber(current_element)) { 79 | int valueint = current_element->valueint; 80 | double valuedouble = current_element->valuedouble; 81 | ESP_LOGI(TAG, "int=%d double=%f", valueint, valuedouble); 82 | (*elements+(*elementsLength)-1)->type = cJSON_Number; 83 | (*elements+(*elementsLength)-1)->valueint = valueint; 84 | (*elements+(*elementsLength)-1)->valuedouble = valuedouble; 85 | } else if (cJSON_IsString(current_element)) { 86 | const char* valuestring = current_element->valuestring; 87 | ESP_LOGI(TAG, "%s", valuestring); 88 | (*elements+(*elementsLength)-1)->type = cJSON_String; 89 | strncpy((*elements+(*elementsLength)-1)->valuestring, valuestring, 31); 90 | } else if (cJSON_IsArray(current_element)) { 91 | ESP_LOGD(TAG, "Array"); 92 | (*elements+(*elementsLength)-1)->type = cJSON_Array; 93 | JSON_Analyze(current_element, elements, elementsLength); 94 | } else if (cJSON_IsObject(current_element)) { 95 | ESP_LOGD(TAG, "Object"); 96 | (*elements+(*elementsLength)-1)->type = cJSON_Object; 97 | JSON_Analyze(current_element, elements, elementsLength); 98 | } else if (cJSON_IsRaw(current_element)) { 99 | ESP_LOGI(TAG, "Raw(Not support)"); 100 | } 101 | } 102 | return ESP_OK; 103 | } 104 | 105 | 106 | void app_main() 107 | { 108 | ESP_LOGI(TAG, "Serialize....."); 109 | cJSON *root; 110 | root = cJSON_CreateObject(); 111 | esp_chip_info_t chip_info; 112 | esp_chip_info(&chip_info); 113 | cJSON_AddStringToObject(root, "version", IDF_VER); 114 | cJSON_AddNumberToObject(root, "cores", chip_info.cores); 115 | cJSON_AddTrueToObject(root, "wifi"); 116 | cJSON_AddFalseToObject(root, "ethernet"); 117 | cJSON_AddBoolToObject(root, "bool", 0); 118 | cJSON_AddNullToObject(root, "null"); 119 | 120 | // Create object 121 | cJSON *object; 122 | cJSON_AddItemToObject(root, "screen", object=cJSON_CreateObject()); 123 | cJSON_AddStringToObject(object,"type", "rect"); 124 | cJSON_AddNumberToObject(object,"width", 1920); 125 | cJSON_AddNumberToObject(object,"height", 1080); 126 | cJSON_AddFalseToObject (object,"interlace"); 127 | cJSON_AddTrueToObject(object,"luster"); 128 | 129 | // Create array 130 | cJSON *array; 131 | array = cJSON_AddArrayToObject(root, "screen"); 132 | cJSON *array_element[5]; 133 | array_element[0] = cJSON_CreateString("rect"); 134 | cJSON_AddItemToArray(array, array_element[0]); 135 | array_element[1] = cJSON_CreateNumber(1920); 136 | cJSON_AddItemToArray(array, array_element[1]); 137 | array_element[2] = cJSON_CreateNumber(1080); 138 | cJSON_AddItemToArray(array, array_element[2]); 139 | array_element[3] = cJSON_CreateFalse(); 140 | cJSON_AddItemToArray(array, array_element[3]); 141 | array_element[4] = cJSON_CreateTrue(); 142 | cJSON_AddItemToArray(array, array_element[4]); 143 | 144 | //const char *my_json_string = cJSON_Print(root); 145 | char *my_json_string = cJSON_Print(root); 146 | ESP_LOGI(TAG, "my_json_string\n%s",my_json_string); 147 | cJSON_Delete(root); 148 | 149 | ESP_LOGI(TAG, "Deserialize....."); 150 | JSON_t *elements = NULL; 151 | size_t elementsLength = 0; 152 | cJSON *root2 = cJSON_Parse(my_json_string); 153 | JSON_Analyze(root2, &elements, &elementsLength); 154 | cJSON_Delete(root2); 155 | 156 | // Buffers returned by cJSON_Print must be freed by the caller. 157 | // Please use the proper API (cJSON_free) rather than directly calling stdlib free. 158 | cJSON_free(my_json_string); 159 | 160 | printf("elementsLength=%d\n", elementsLength); 161 | for (int i=0;itype == cJSON_Invalid) { 164 | printf(" cJSON_Invalid"); 165 | } else if ((elements+i)->type == cJSON_False) { 166 | printf(" cJSON_False"); 167 | printf(" [%s]", (elements+i)->name); 168 | } else if ((elements+i)->type == cJSON_True) { 169 | printf(" cJSON_True"); 170 | printf(" [%s]", (elements+i)->name); 171 | } else if ((elements+i)->type == cJSON_NULL) { 172 | printf(" cJSON_NULL"); 173 | printf(" [%s]", (elements+i)->name); 174 | } else if ((elements+i)->type == cJSON_Number) { 175 | printf(" cJSON_Number"); 176 | printf(" [%s]", (elements+i)->name); 177 | printf(" int=%d", (elements+i)->valueint); 178 | printf(" double=%lf", (elements+i)->valuedouble); 179 | } else if ((elements+i)->type == cJSON_String) { 180 | printf(" cJSON_String"); 181 | printf(" [%s]", (elements+i)->name); 182 | printf(" [%s]", (elements+i)->valuestring); 183 | } else if ((elements+i)->type == cJSON_Array) { 184 | printf(" cJSON_Array"); 185 | printf(" [%s]", (elements+i)->name); 186 | } else if ((elements+i)->type == cJSON_Object) { 187 | printf(" cJSON_Object"); 188 | printf(" [%s]", (elements+i)->name); 189 | } 190 | printf("\n"); 191 | } 192 | 193 | free(elements); 194 | } 195 | -------------------------------------------------------------------------------- /json-array-in-array/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | -------------------------------------------------------------------------------- /json-array-in-array/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := json-example 7 | 8 | include $(IDF_PATH)/make/project.mk 9 | 10 | -------------------------------------------------------------------------------- /json-array-in-array/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | 3 | ## Serialize 4 | ``` 5 | [["abc", 120], ["abc", 121], ["abc", 122], ["abc", 123], ["abc", 124], ["abc", 125], ["abc", 126], ["abc", 127], ["abc", 128], ["abc", 129]] 6 | ``` 7 | 8 | ## DeSerialize 9 | ``` 10 | I (365) JSON: cJSON_Array 11 | I (365) JSON: cJSON_String string=abc 12 | I (365) JSON: cJSON_Number int=120 double=120.000000 13 | I (375) JSON: cJSON_Array 14 | I (375) JSON: cJSON_String string=abc 15 | I (385) JSON: cJSON_Number int=121 double=121.000000 16 | I (385) JSON: cJSON_Array 17 | I (395) JSON: cJSON_String string=abc 18 | I (395) JSON: cJSON_Number int=122 double=122.000000 19 | I (405) JSON: cJSON_Array 20 | I (405) JSON: cJSON_String string=abc 21 | I (405) JSON: cJSON_Number int=123 double=123.000000 22 | I (415) JSON: cJSON_Array 23 | I (415) JSON: cJSON_String string=abc 24 | I (425) JSON: cJSON_Number int=124 double=124.000000 25 | I (425) JSON: cJSON_Array 26 | I (435) JSON: cJSON_String string=abc 27 | I (435) JSON: cJSON_Number int=125 double=125.000000 28 | I (445) JSON: cJSON_Array 29 | I (445) JSON: cJSON_String string=abc 30 | I (445) JSON: cJSON_Number int=126 double=126.000000 31 | I (455) JSON: cJSON_Array 32 | I (455) JSON: cJSON_String string=abc 33 | I (465) JSON: cJSON_Number int=127 double=127.000000 34 | I (465) JSON: cJSON_Array 35 | I (475) JSON: cJSON_String string=abc 36 | I (475) JSON: cJSON_Number int=128 double=128.000000 37 | I (485) JSON: cJSON_Array 38 | I (485) JSON: cJSON_String string=abc 39 | I (485) JSON: cJSON_Number int=129 double=129.000000 40 | ``` 41 | -------------------------------------------------------------------------------- /json-array-in-array/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "main.c") 2 | set(COMPONENT_ADD_INCLUDEDIRS "") 3 | 4 | register_component() 5 | -------------------------------------------------------------------------------- /json-array-in-array/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | -------------------------------------------------------------------------------- /json-array-in-array/main/main.c: -------------------------------------------------------------------------------- 1 | /* The example of ESP-IDF 2 | * 3 | * This sample code is in the public domain. 4 | */ 5 | #include "freertos/FreeRTOS.h" 6 | #include "freertos/task.h" 7 | #include "esp_log.h" 8 | #include "esp_chip_info.h" 9 | #include "cJSON.h" 10 | 11 | static const char *TAG = "JSON"; 12 | 13 | void JSON_Print(cJSON *element) { 14 | if (element->type == cJSON_Invalid) ESP_LOGI(TAG, "cJSON_Invalid"); 15 | if (element->type == cJSON_False) ESP_LOGI(TAG, "cJSON_False"); 16 | if (element->type == cJSON_True) ESP_LOGI(TAG, "cJSON_True"); 17 | if (element->type == cJSON_NULL) ESP_LOGI(TAG, "cJSON_NULL"); 18 | if (element->type == cJSON_Number) ESP_LOGI(TAG, "cJSON_Number int=%d double=%f", element->valueint, element->valuedouble); 19 | if (element->type == cJSON_String) ESP_LOGI(TAG, "cJSON_String string=%s", element->valuestring); 20 | if (element->type == cJSON_Array) { 21 | ESP_LOGI(TAG, "cJSON_Array"); 22 | cJSON *child_element = NULL; 23 | cJSON_ArrayForEach(child_element, element) { 24 | JSON_Print(child_element); 25 | } 26 | } 27 | if (element->type == cJSON_Object) { 28 | ESP_LOGI(TAG, "cJSON_Object"); 29 | cJSON *child_element = NULL; 30 | cJSON_ArrayForEach(child_element, element) { 31 | JSON_Print(child_element); 32 | } 33 | } 34 | if (element->type == cJSON_Raw) ESP_LOGI(TAG, "cJSON_Raw"); 35 | } 36 | 37 | 38 | void app_main() 39 | { 40 | ESP_LOGI(TAG, "Serialize....."); 41 | cJSON *root; 42 | root = cJSON_CreateArray(); 43 | 44 | int array_num = 10; 45 | cJSON *array[array_num]; 46 | cJSON *element[array_num*2]; 47 | 48 | for (int i=0;itype == cJSON_Invalid) ESP_LOGI(TAG, "cJSON_Invalid"); 15 | if (element->type == cJSON_False) ESP_LOGI(TAG, "cJSON_False"); 16 | if (element->type == cJSON_True) ESP_LOGI(TAG, "cJSON_True"); 17 | if (element->type == cJSON_NULL) ESP_LOGI(TAG, "cJSON_NULL"); 18 | if (element->type == cJSON_Number) ESP_LOGI(TAG, "cJSON_Number int=%d double=%f", element->valueint, element->valuedouble); 19 | if (element->type == cJSON_String) ESP_LOGI(TAG, "cJSON_String string=%s", element->valuestring); 20 | if (element->type == cJSON_Array) ESP_LOGI(TAG, "cJSON_Array"); 21 | if (element->type == cJSON_Object) { 22 | ESP_LOGI(TAG, "cJSON_Object"); 23 | cJSON *child_element = NULL; 24 | cJSON_ArrayForEach(child_element, element) { 25 | JSON_Print(child_element); 26 | } 27 | } 28 | if (element->type == cJSON_Raw) ESP_LOGI(TAG, "cJSON_Raw"); 29 | } 30 | 31 | 32 | void app_main() 33 | { 34 | ESP_LOGI(TAG, "Serialize....."); 35 | cJSON *root; 36 | root = cJSON_CreateObject(); 37 | esp_chip_info_t chip_info; 38 | esp_chip_info(&chip_info); 39 | cJSON_AddStringToObject(root, "version", IDF_VER); 40 | cJSON_AddNumberToObject(root, "cores", chip_info.cores); 41 | 42 | // Add simple element 43 | cJSON *array; 44 | array = cJSON_AddArrayToObject(root, "array"); 45 | //array = cJSON_CreateArray(); 46 | cJSON *element; 47 | element = cJSON_CreateString("abc"); 48 | cJSON_AddItemToArray(array, element); 49 | element = cJSON_CreateNumber(123); 50 | cJSON_AddItemToArray(array, element); 51 | element = cJSON_CreateTrue(); 52 | cJSON_AddItemToArray(array, element); 53 | element = cJSON_CreateFalse(); 54 | cJSON_AddItemToArray(array, element); 55 | element = cJSON_CreateNull(); 56 | cJSON_AddItemToArray(array, element); 57 | 58 | char *my_json_string = cJSON_Print(root); 59 | ESP_LOGI(TAG, "my_json_string\n%s",my_json_string); 60 | cJSON_Delete(root); 61 | 62 | 63 | ESP_LOGI(TAG, "Deserialize....."); 64 | cJSON *root2 = cJSON_Parse(my_json_string); 65 | char *version = cJSON_GetObjectItem(root2,"version")->valuestring; 66 | ESP_LOGI(TAG, "version=%s",version); 67 | int cores = cJSON_GetObjectItem(root2,"cores")->valueint; 68 | ESP_LOGI(TAG, "cores=%d",cores); 69 | cJSON *array2 = cJSON_GetObjectItem(root2,"array"); 70 | int array2_size = cJSON_GetArraySize(array2); 71 | ESP_LOGI(TAG, "array2_size=%d", array2_size); 72 | for (int i=0;itype == cJSON_Invalid) ESP_LOGI(TAG, "cJSON_Invalid"); 14 | if (element->type == cJSON_False) ESP_LOGI(TAG, "cJSON_False"); 15 | if (element->type == cJSON_True) ESP_LOGI(TAG, "cJSON_True"); 16 | if (element->type == cJSON_NULL) ESP_LOGI(TAG, "cJSON_NULL"); 17 | if (element->type == cJSON_Number) ESP_LOGI(TAG, "cJSON_Number int=%d double=%f", element->valueint, element->valuedouble); 18 | if (element->type == cJSON_String) ESP_LOGI(TAG, "cJSON_String string=%s", element->valuestring); 19 | if (element->type == cJSON_Array) ESP_LOGI(TAG, "cJSON_Array"); 20 | if (element->type == cJSON_Object) ESP_LOGI(TAG, "cJSON_Object"); 21 | if (element->type == cJSON_Raw) ESP_LOGI(TAG, "cJSON_Raw"); 22 | } 23 | 24 | 25 | void app_main() 26 | { 27 | ESP_LOGI(TAG, "Serialize....."); 28 | cJSON *root; 29 | root = cJSON_CreateArray(); 30 | 31 | // Add simple element 32 | cJSON *element[5]; 33 | element[0] = cJSON_CreateString("abc"); 34 | cJSON_AddItemToArray(root, element[0]); 35 | element[1] = cJSON_CreateNumber(123); 36 | cJSON_AddItemToArray(root, element[1]); 37 | element[2] = cJSON_CreateTrue(); 38 | cJSON_AddItemToArray(root, element[2]); 39 | element[3] = cJSON_CreateFalse(); 40 | cJSON_AddItemToArray(root, element[3]); 41 | element[4] = cJSON_CreateNull(); 42 | cJSON_AddItemToArray(root, element[4]); 43 | 44 | char *my_json_string = cJSON_Print(root); 45 | ESP_LOGI(TAG, "my_json_string\n%s",my_json_string); 46 | cJSON_Delete(root); 47 | 48 | 49 | ESP_LOGI(TAG, "Deserialize....."); 50 | cJSON *root2 = cJSON_Parse(my_json_string); 51 | int root2_array_size = cJSON_GetArraySize(root2); 52 | ESP_LOGI(TAG, "root2_array_size=%d", root2_array_size); 53 | for (int i=0;ivaluestring; 34 | ESP_LOGI(TAG, "idf=%s",idf); 35 | } 36 | if (cJSON_GetObjectItem(root2, "json")) { 37 | char *json = cJSON_GetObjectItem(root2,"json")->valuestring; 38 | ESP_LOGI(TAG, "json=%s",json); 39 | } 40 | if (cJSON_GetObjectItem(root2, "cores")) { 41 | int cores = cJSON_GetObjectItem(root2,"cores")->valueint; 42 | ESP_LOGI(TAG, "cores=%d",cores); 43 | } 44 | if (cJSON_GetObjectItem(root2, "flag_true")) { 45 | bool flag_true = cJSON_GetObjectItem(root2,"flag_true")->valueint; 46 | ESP_LOGI(TAG, "flag_true=%d",flag_true); 47 | } 48 | if (cJSON_GetObjectItem(root2, "flag_false")) { 49 | bool flag_false = cJSON_GetObjectItem(root2,"flag_false")->valueint; 50 | ESP_LOGI(TAG, "flag_false=%d",flag_false); 51 | } 52 | cJSON_Delete(root2); 53 | 54 | // Buffers returned by cJSON_Print must be freed by the caller. 55 | // Please use the proper API (cJSON_free) rather than directly calling stdlib free. 56 | cJSON_free(my_json_string); 57 | } 58 | -------------------------------------------------------------------------------- /json-check/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | -------------------------------------------------------------------------------- /json-check/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | 3 | ``` 4 | I (336) JSON: my_json_string 5 | {"roll": 57} 6 | I (346) JSON: This is json format 7 | 8 | I (346) JSON: my_json_string2 9 | {"roll"}: 10 | E (356) JSON: This is NOT json format 11 | 12 | I (356) JSON: my_json_string3 13 | {"roll"} 14 | E (356) JSON: This is NOT json format 15 | ``` 16 | -------------------------------------------------------------------------------- /json-check/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "main.c") 2 | set(COMPONENT_ADD_INCLUDEDIRS "") 3 | 4 | register_component() 5 | -------------------------------------------------------------------------------- /json-check/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | -------------------------------------------------------------------------------- /json-check/main/main.c: -------------------------------------------------------------------------------- 1 | /* The example of ESP-IDF 2 | * 3 | * This sample code is in the public domain. 4 | */ 5 | 6 | #include 7 | #include 8 | #include "freertos/FreeRTOS.h" 9 | #include "freertos/task.h" 10 | #include "esp_log.h" 11 | #include "esp_chip_info.h" 12 | #include "cJSON.h" 13 | 14 | static const char *TAG = "JSON"; 15 | 16 | typedef struct { 17 | int type; 18 | char name[32]; 19 | int valueint; 20 | double valuedouble; 21 | char valuestring[32]; 22 | } JSON_t; 23 | 24 | char *JSON_Types(int type) { 25 | if (type == cJSON_Invalid) return ("cJSON_Invalid"); 26 | if (type == cJSON_False) return ("cJSON_False"); 27 | if (type == cJSON_True) return ("cJSON_True"); 28 | if (type == cJSON_NULL) return ("cJSON_NULL"); 29 | if (type == cJSON_Number) return ("cJSON_Number"); 30 | if (type == cJSON_String) return ("cJSON_String"); 31 | if (type == cJSON_Array) return ("cJSON_Array"); 32 | if (type == cJSON_Object) return ("cJSON_Object"); 33 | if (type == cJSON_Raw) return ("cJSON_Raw"); 34 | return NULL; 35 | } 36 | 37 | 38 | esp_err_t JSON_Analyze(const cJSON * const root, JSON_t **elements, size_t *elementsLength) { 39 | //ESP_LOGI(TAG, "root->type=%s", JSON_Types(root->type)); 40 | cJSON *current_element = NULL; 41 | //ESP_LOGI(TAG, "roo->child=%p", root->child); 42 | //ESP_LOGI(TAG, "roo->next =%p", root->next); 43 | cJSON_ArrayForEach(current_element, root) { 44 | //ESP_LOGI(TAG, "type=%s", JSON_Types(current_element->type)); 45 | //ESP_LOGI(TAG, "current_element->string=%p", current_element->string); 46 | 47 | if (*elements == NULL) { 48 | (*elementsLength)++; 49 | *elements = (JSON_t *)malloc(sizeof(JSON_t)); 50 | } else { 51 | (*elementsLength)++; 52 | *elements = (JSON_t *)realloc(*elements, *elementsLength * sizeof(JSON_t)); 53 | } 54 | if (*elements == NULL) { 55 | ESP_LOGE(TAG, "Error allocating memory for elements"); 56 | return ESP_ERR_NO_MEM; 57 | } 58 | 59 | if (current_element->string) { 60 | const char* name = current_element->string; 61 | ESP_LOGI(TAG, "[%s]", name); 62 | strncpy((*elements+(*elementsLength)-1)->name, name, 31); 63 | } else { 64 | strcpy((*elements+(*elementsLength)-1)->name, "array item"); 65 | } 66 | if (cJSON_IsInvalid(current_element)) { 67 | ESP_LOGI(TAG, "Invalid"); 68 | (*elements+(*elementsLength)-1)->type = cJSON_Invalid; 69 | } else if (cJSON_IsFalse(current_element)) { 70 | ESP_LOGI(TAG, "False"); 71 | (*elements+(*elementsLength)-1)->type = cJSON_False; 72 | } else if (cJSON_IsTrue(current_element)) { 73 | ESP_LOGI(TAG, "True"); 74 | (*elements+(*elementsLength)-1)->type = cJSON_True; 75 | } else if (cJSON_IsNull(current_element)) { 76 | ESP_LOGI(TAG, "Null"); 77 | (*elements+(*elementsLength)-1)->type = cJSON_NULL; 78 | } else if (cJSON_IsNumber(current_element)) { 79 | int valueint = current_element->valueint; 80 | double valuedouble = current_element->valuedouble; 81 | ESP_LOGI(TAG, "int=%d double=%f", valueint, valuedouble); 82 | (*elements+(*elementsLength)-1)->type = cJSON_Number; 83 | (*elements+(*elementsLength)-1)->valueint = valueint; 84 | (*elements+(*elementsLength)-1)->valuedouble = valuedouble; 85 | } else if (cJSON_IsString(current_element)) { 86 | const char* valuestring = current_element->valuestring; 87 | ESP_LOGI(TAG, "%s", valuestring); 88 | (*elements+(*elementsLength)-1)->type = cJSON_String; 89 | strncpy((*elements+(*elementsLength)-1)->valuestring, valuestring, 31); 90 | } else if (cJSON_IsArray(current_element)) { 91 | ESP_LOGD(TAG, "Array"); 92 | (*elements+(*elementsLength)-1)->type = cJSON_Array; 93 | JSON_Analyze(current_element, elements, elementsLength); 94 | } else if (cJSON_IsObject(current_element)) { 95 | ESP_LOGD(TAG, "Object"); 96 | (*elements+(*elementsLength)-1)->type = cJSON_Object; 97 | JSON_Analyze(current_element, elements, elementsLength); 98 | } else if (cJSON_IsRaw(current_element)) { 99 | ESP_LOGI(TAG, "Raw(Not support)"); 100 | } 101 | } 102 | return ESP_OK; 103 | } 104 | 105 | 106 | void app_main() 107 | { 108 | ESP_LOGI(TAG, "Initialize....."); 109 | char *my_json_string = "{\"roll\": 57}"; 110 | ESP_LOGI(TAG, "my_json_string\n%s",my_json_string); 111 | cJSON *root = cJSON_Parse(my_json_string); 112 | if (root == NULL) { 113 | ESP_LOGE(TAG, "This is NOT json format"); 114 | } else { 115 | ESP_LOGI(TAG, "This is json format"); 116 | } 117 | cJSON_Delete(root); 118 | 119 | char *my_json_string2 = "{\"roll\"}:"; 120 | ESP_LOGI(TAG, "my_json_string2\n%s",my_json_string2); 121 | cJSON *root2 = cJSON_Parse(my_json_string2); 122 | if (root2 == NULL) { 123 | ESP_LOGE(TAG, "This is NOT json format"); 124 | } else { 125 | ESP_LOGI(TAG, "This is json format"); 126 | } 127 | cJSON_Delete(root2); 128 | 129 | char *my_json_string3 = "{\"roll\"}"; 130 | ESP_LOGI(TAG, "my_json_string3\n%s",my_json_string3); 131 | cJSON *root3 = cJSON_Parse(my_json_string2); 132 | if (root3 == NULL) { 133 | ESP_LOGE(TAG, "This is NOT json format"); 134 | } else { 135 | ESP_LOGI(TAG, "This is json format"); 136 | } 137 | cJSON_Delete(root3); 138 | } 139 | -------------------------------------------------------------------------------- /json-create-array/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | -------------------------------------------------------------------------------- /json-create-array/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := json-example 7 | 8 | include $(IDF_PATH)/make/project.mk 9 | 10 | -------------------------------------------------------------------------------- /json-create-array/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | These utilities create an Array of count items. 3 | The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds. 4 | 5 | ``` 6 | CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); 7 | CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); 8 | CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); 9 | CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count); 10 | ``` 11 | 12 | 13 | ## Serialize 14 | ``` 15 | { 16 | "name": "CreateArray", 17 | "intArray": [1, 11, 111], 18 | "floatArray": [1.1000000238418579, 22.200000762939453, 333.29998779296875, 4444.39990234375], 19 | "doubleArray": [1.2, 12.3, 123.4, 1234.5, 12345.6], 20 | "stringArray": ["Rena", "Yuki", "Mimi"] 21 | } 22 | ``` 23 | 24 | ## DeSerialize 25 | ``` 26 | I (343) JSON: name=CreateArray 27 | I (353) JSON: valueint[0]=1 valuedouble[0]=1.000000 28 | I (353) JSON: valueint[1]=11 valuedouble[1]=11.000000 29 | I (363) JSON: valueint[2]=111 valuedouble[2]=111.000000 30 | I (363) JSON: valueint[0]=1 valuedouble[0]=1.100000 31 | I (373) JSON: valueint[1]=22 valuedouble[1]=22.200001 32 | I (373) JSON: valueint[2]=333 valuedouble[2]=333.299988 33 | I (383) JSON: valueint[3]=4444 valuedouble[3]=4444.399902 34 | I (393) JSON: valueint[0]=1 valuedouble[0]=1.200000 35 | I (393) JSON: valueint[1]=12 valuedouble[1]=12.300000 36 | I (403) JSON: valueint[2]=123 valuedouble[2]=123.400000 37 | I (403) JSON: valueint[3]=1234 valuedouble[3]=1234.500000 38 | I (413) JSON: valueint[4]=12345 valuedouble[4]=12345.600000 39 | I (423) JSON: string[0]=Rena 40 | I (423) JSON: string[1]=Yuki 41 | I (423) JSON: string[2]=Mimi 42 | ``` 43 | 44 | __JSON library does not distinguish Interger, Float, Double.__ 45 | __These are all parsed as numbers and stored in both Interger and Double.__ 46 | 47 | ## Problems with the cJSON library version 1.7.14 48 | In Version 1.7.14, cJSON_CreateIntArray(i_numbers, 0) causes a panic. 49 | You need to update to version 1.7.15. 50 | ``` 51 | #include "freertos/FreeRTOS.h" 52 | #include "freertos/task.h" 53 | #include "esp_log.h" 54 | #include "cJSON.h" 55 | 56 | static const char *TAG = "JSON"; 57 | 58 | void app_main() 59 | { 60 | ESP_LOGI(TAG, "Serialize....."); 61 | cJSON *root; 62 | root = cJSON_CreateObject(); 63 | 64 | int i_numbers[3]; 65 | i_numbers[0] = 1; 66 | i_numbers[1] = 11; 67 | i_numbers[2] = 111; 68 | cJSON *intArray; 69 | intArray = cJSON_CreateIntArray(i_numbers, 3); 70 | cJSON_AddItemToObject(root, "intArray", intArray); 71 | 72 | char *my_json_string = cJSON_Print(root); 73 | ESP_LOGI(TAG, "my_json_string\n%s",my_json_string); 74 | cJSON_Delete(root); 75 | 76 | // Buffers returned by cJSON_Print must be freed by the caller. 77 | // Please use the proper API (cJSON_free) rather than directly calling stdlib free. 78 | cJSON_free(my_json_string); 79 | 80 | cJSON *root2; 81 | root2 = cJSON_CreateObject(); 82 | intArray = cJSON_CreateIntArray(i_numbers, 0); 83 | cJSON_AddItemToObject(root2, "intArray", intArray); 84 | 85 | char *my_json_string2 = cJSON_Print(root2); 86 | ESP_LOGI(TAG, "my_json_string\n%s",my_json_string2); 87 | cJSON_Delete(root2); 88 | 89 | // Buffers returned by cJSON_Print must be freed by the caller. 90 | // Please use the proper API (cJSON_free) rather than directly calling stdlib free. 91 | cJSON_free(my_json_string2); 92 | } 93 | ``` 94 | 95 | It works fine in version 1.7.15. 96 | Version 1.7.15 is Included in ESP-IDF version v4.4-dev-2825-gb63ec47238 or later. 97 | ``` 98 | I (0) cpu_start: Starting scheduler on APP CPU. 99 | I (326) JSON: Serialize..... 100 | I (336) JSON: my_json_string 101 | { 102 | "intArray": [1, 11, 111] 103 | } 104 | I (336) JSON: my_json_string 105 | { 106 | "intArray": [] 107 | } 108 | ``` 109 | -------------------------------------------------------------------------------- /json-create-array/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "main.c") 2 | set(COMPONENT_ADD_INCLUDEDIRS "") 3 | 4 | register_component() 5 | -------------------------------------------------------------------------------- /json-create-array/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | -------------------------------------------------------------------------------- /json-create-array/main/main.c: -------------------------------------------------------------------------------- 1 | /* The example of ESP-IDF 2 | * 3 | * This sample code is in the public domain. 4 | * 5 | */ 6 | #include "freertos/FreeRTOS.h" 7 | #include "freertos/task.h" 8 | #include "esp_log.h" 9 | #include "cJSON.h" 10 | 11 | static const char *TAG = "JSON"; 12 | 13 | char *JSON_Types(int type) { 14 | if (type == cJSON_Invalid) return ("cJSON_Invalid"); 15 | if (type == cJSON_False) return ("cJSON_False"); 16 | if (type == cJSON_True) return ("cJSON_True"); 17 | if (type == cJSON_NULL) return ("cJSON_NULL"); 18 | if (type == cJSON_Number) return ("cJSON_Number"); 19 | if (type == cJSON_String) return ("cJSON_String"); 20 | if (type == cJSON_Array) return ("cJSON_Array"); 21 | if (type == cJSON_Object) return ("cJSON_Object"); 22 | if (type == cJSON_Raw) return ("cJSON_Raw"); 23 | return NULL; 24 | } 25 | 26 | int JSON_Array(const cJSON * const item) { 27 | if (cJSON_IsArray(item)) { 28 | cJSON *current_element = NULL; 29 | int itemNumber = 0; 30 | cJSON_ArrayForEach(current_element, item) { 31 | //ESP_LOGI(TAG, "current_element->type=%s", JSON_Types(current_element->type)); 32 | if (cJSON_IsNumber(current_element)) { 33 | int valueint = current_element->valueint; 34 | double valuedouble = current_element->valuedouble; 35 | ESP_LOGI(TAG, "valueint[%d]=%d valuedouble[%d]=%f",itemNumber, valueint, itemNumber, valuedouble); 36 | } 37 | if (cJSON_IsString(current_element)) { 38 | const char* string = current_element->valuestring; 39 | ESP_LOGI(TAG, "string[%d]=%s",itemNumber, string); 40 | } 41 | itemNumber++; 42 | } 43 | return cJSON_GetArraySize(item); 44 | } else { 45 | return 0; 46 | } 47 | } 48 | 49 | void app_main() 50 | { 51 | ESP_LOGI(TAG, "Serialize....."); 52 | cJSON *root; 53 | root = cJSON_CreateObject(); 54 | cJSON_AddStringToObject(root, "name", "CreateArray"); 55 | 56 | int i_numbers[3]; 57 | i_numbers[0] = 1; 58 | i_numbers[1] = 11; 59 | i_numbers[2] = 111; 60 | cJSON *intArray; 61 | intArray = cJSON_CreateIntArray(i_numbers, 3); 62 | cJSON_AddItemToObject(root, "intArray", intArray); 63 | 64 | float f_numbers[4]; 65 | f_numbers[0] = 1.1; 66 | f_numbers[1] = 22.2; 67 | f_numbers[2] = 333.3; 68 | f_numbers[3] = 4444.4; 69 | cJSON *floatArray; 70 | floatArray = cJSON_CreateFloatArray(f_numbers, 4); 71 | cJSON_AddItemToObject(root, "floatArray", floatArray); 72 | 73 | double d_numbers[5]; 74 | d_numbers[0] = 1.2; 75 | d_numbers[1] = 12.3; 76 | d_numbers[2] = 123.4; 77 | d_numbers[3] = 1234.5; 78 | d_numbers[4] = 12345.6; 79 | cJSON *doubleArray; 80 | doubleArray = cJSON_CreateDoubleArray(d_numbers, 5); 81 | cJSON_AddItemToObject(root, "doubleArray", doubleArray); 82 | 83 | char str[3][5] = { "Rena" , "Yuki" , "Mimi" }; 84 | const char *ptr[3]; 85 | ptr[0] = str[0]; 86 | ptr[1] = str[1]; 87 | ptr[2] = str[2]; 88 | cJSON *stringArray; 89 | stringArray = cJSON_CreateStringArray(ptr, 3); 90 | cJSON_AddItemToObject(root, "stringArray", stringArray); 91 | 92 | //const char *my_json_string = cJSON_Print(root); 93 | char *my_json_string = cJSON_Print(root); 94 | ESP_LOGI(TAG, "my_json_string\n%s",my_json_string); 95 | cJSON_Delete(root); 96 | 97 | ESP_LOGI(TAG, "Deserialize....."); 98 | cJSON *root2 = cJSON_Parse(my_json_string); 99 | char *name = cJSON_GetObjectItem(root2,"name")->valuestring; 100 | ESP_LOGI(TAG, "name=%s",name); 101 | 102 | cJSON *intArray2 = cJSON_GetObjectItem(root2,"intArray"); 103 | //ESP_LOGI(TAG, "intArray2->type=%s", JSON_Types(intArray2->type)); 104 | JSON_Array(intArray2); 105 | 106 | cJSON *floatArray2 = cJSON_GetObjectItem(root2,"floatArray"); 107 | //ESP_LOGI(TAG, "floatArray2->type=%s", JSON_Types(floatArray2->type)); 108 | JSON_Array(floatArray2); 109 | 110 | cJSON *doubleArray2 = cJSON_GetObjectItem(root2,"doubleArray"); 111 | //ESP_LOGI(TAG, "doubleArray2->type=%s", JSON_Types(doubleArray2->type)); 112 | JSON_Array(doubleArray2); 113 | 114 | cJSON *stringArray2 = cJSON_GetObjectItem(root2,"stringArray"); 115 | JSON_Array(stringArray2); 116 | 117 | cJSON_Delete(root2); 118 | 119 | // Buffers returned by cJSON_Print must be freed by the caller. 120 | // Please use the proper API (cJSON_free) rather than directly calling stdlib free. 121 | cJSON_free(my_json_string); 122 | } 123 | -------------------------------------------------------------------------------- /json-directory-tree/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's CMakeLists 2 | # in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.16) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | 8 | # Create a FATFS image from the contents of the 'fatfs_image' directory 9 | # that fits the partition named 'storage'. FLASH_IN_PROJECT indicates that 10 | # the generated image should be flashed when the entire project is flashed to 11 | # the target with 'idf.py -p PORT flash'. 12 | # If read-only mode is set (CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY) 13 | # the generated image will be raw without wear levelling support. 14 | # Otherwise it will support wear levelling and thus enable read-write mounting of the image in the device. 15 | set(image fatfs_image) 16 | fatfs_create_rawflash_image(storage ${image} FLASH_IN_PROJECT PRESERVE_TIME) 17 | #fatfs_create_spiflash_image(storage ${image} FLASH_IN_PROJECT PRESERVE_TIME) 18 | -------------------------------------------------------------------------------- /json-directory-tree/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | Converts a directory structure into a nested JSON string. 3 | This is a complex structure of objects and arrays. 4 | You need to serialize from the lowest level up. 5 | 6 | # Directory structure 7 | ``` 8 | $ ls -lR fatfs_image 9 | fatfs_image: 10 | total 20 11 | -rw-rw-r-- 1 nop nop 11 Apr 6 05:37 CMakeLists.txt 12 | drwxrwxr-x 4 nop nop 4096 Apr 6 05:37 libs 13 | drwxrwxr-x 2 nop nop 4096 Apr 6 05:37 obj 14 | -rw-rw-r-- 1 nop nop 22 Apr 6 05:37 sdkconfig 15 | drwxrwxr-x 2 nop nop 4096 Apr 6 05:37 src 16 | 17 | fatfs_image/libs: 18 | total 8 19 | drwxrwxr-x 2 nop nop 4096 Apr 6 05:37 lib001 20 | drwxrwxr-x 2 nop nop 4096 Apr 6 05:37 lib002 21 | 22 | fatfs_image/libs/lib001: 23 | total 4 24 | -rw-rw-r-- 1 nop nop 33 Apr 6 05:37 lib001.a 25 | 26 | fatfs_image/libs/lib002: 27 | total 4 28 | -rw-rw-r-- 1 nop nop 55 Apr 6 05:37 lib002.a 29 | 30 | fatfs_image/obj: 31 | total 8 32 | -rw-rw-r-- 1 nop nop 22 Apr 6 05:37 main.o 33 | -rw-rw-r-- 1 nop nop 11 Apr 6 05:37 sub.o 34 | 35 | fatfs_image/src: 36 | total 8 37 | -rw-rw-r-- 1 nop nop 44 Apr 6 05:37 main.c 38 | -rw-rw-r-- 1 nop nop 11 Apr 6 05:37 sub.c 39 | ``` 40 | 41 | ## Serialize 42 | ``` 43 | { 44 | "level": 1, 45 | "self": "/root", 46 | "cmakelists.txt": { 47 | "size": 11, 48 | "mtime": "2025-04-06 05:37:38" 49 | }, 50 | "sdkconfig": { 51 | "size": 22, 52 | "mtime": "2025-04-06 05:37:38" 53 | }, 54 | "child": [{ 55 | "level": 2, 56 | "self": "/root/libs", 57 | "child": [{ 58 | "level": 3, 59 | "self": "/root/libs/lib001", 60 | "lib001.a": { 61 | "size": 33, 62 | "mtime": "2025-04-06 05:37:38" 63 | } 64 | }, { 65 | "level": 3, 66 | "self": "/root/libs/lib002", 67 | "lib002.a": { 68 | "size": 55, 69 | "mtime": "2025-04-06 05:37:38" 70 | } 71 | }] 72 | }, { 73 | "level": 2, 74 | "self": "/root/obj", 75 | "main.o": { 76 | "size": 22, 77 | "mtime": "2025-04-06 05:37:38" 78 | }, 79 | "sub.o": { 80 | "size": 11, 81 | "mtime": "2025-04-06 05:37:38" 82 | } 83 | }, { 84 | "level": 2, 85 | "self": "/root/src", 86 | "main.c": { 87 | "size": 44, 88 | "mtime": "2025-04-06 05:37:38" 89 | }, 90 | "sub.c": { 91 | "size": 11, 92 | "mtime": "2025-04-06 05:37:38" 93 | } 94 | }] 95 | } 96 | ``` 97 | -------------------------------------------------------------------------------- /json-directory-tree/fatfs_image/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 1111111111 2 | -------------------------------------------------------------------------------- /json-directory-tree/fatfs_image/libs/lib001/lib001.a: -------------------------------------------------------------------------------- 1 | 1111111111 2 | 2222222222 3 | 3333333333 4 | -------------------------------------------------------------------------------- /json-directory-tree/fatfs_image/libs/lib002/lib002.a: -------------------------------------------------------------------------------- 1 | 1111111111 2 | 1111111111 3 | 1111111111 4 | 1111111111 5 | 1111111111 6 | -------------------------------------------------------------------------------- /json-directory-tree/fatfs_image/obj/main.o: -------------------------------------------------------------------------------- 1 | 1111111111 2 | 1111111111 3 | -------------------------------------------------------------------------------- /json-directory-tree/fatfs_image/obj/sub.o: -------------------------------------------------------------------------------- 1 | 1111111111 2 | -------------------------------------------------------------------------------- /json-directory-tree/fatfs_image/sdkconfig: -------------------------------------------------------------------------------- 1 | 1111111111 2 | 2222222222 3 | -------------------------------------------------------------------------------- /json-directory-tree/fatfs_image/src/main.c: -------------------------------------------------------------------------------- 1 | 1111111111 2 | 1111111111 3 | 1111111111 4 | 1111111111 5 | -------------------------------------------------------------------------------- /json-directory-tree/fatfs_image/src/sub.c: -------------------------------------------------------------------------------- 1 | 1111111111 2 | -------------------------------------------------------------------------------- /json-directory-tree/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "main.c" INCLUDE_DIRS ".") 2 | 3 | -------------------------------------------------------------------------------- /json-directory-tree/main/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Unlicense OR CC0-1.0 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include "freertos/FreeRTOS.h" 11 | #include "freertos/task.h" 12 | #include "esp_vfs.h" 13 | #include "esp_vfs_fat.h" 14 | #include "sdkconfig.h" 15 | #include "cJSON.h" 16 | 17 | static const char *TAG = "MAIN"; 18 | 19 | // Mount path for the partition 20 | //const char *base_path = "/root"; 21 | char *base_path = "/root"; 22 | 23 | #define STR_SIZE 64 24 | typedef struct { 25 | uint8_t level; 26 | char self[STR_SIZE+1]; 27 | char parent[STR_SIZE+1]; 28 | cJSON *json; 29 | } DIRS_t; 30 | 31 | typedef struct { 32 | char file[STR_SIZE+1]; 33 | struct stat info; 34 | } FILES_t; 35 | 36 | #define MAX_DIRS 10 37 | #define MAX_FILES 10 38 | 39 | #if 0 40 | static void printDirectory(char * path) { 41 | DIR* dir = opendir(path); 42 | assert(dir != NULL); 43 | while (true) { 44 | struct dirent *pe = readdir(dir); 45 | if (!pe) break; 46 | ESP_LOGI(__FUNCTION__,"%s d_name=%s d_ino=%d d_type=%x", path, pe->d_name, pe->d_ino, pe->d_type); 47 | if (pe->d_type == 1) { 48 | char fullPath[STR_SIZE+1]; 49 | strcpy(fullPath, path); 50 | strcat(fullPath, "/"); 51 | strcat(fullPath, pe->d_name); 52 | struct stat st; 53 | if (stat(fullPath, &st) == 0) { 54 | ESP_LOGI(__FUNCTION__,"fileSize=%d", (int)st.st_size); 55 | } 56 | } 57 | 58 | if (pe->d_type == 2) { 59 | char subDir[STR_SIZE+1]; 60 | strcpy(subDir, path); 61 | strcat(subDir, "/"); 62 | strcat(subDir, pe->d_name); 63 | ESP_LOGI(__FUNCTION__, "subDir=[%s]", subDir); 64 | printDirectory(subDir); 65 | } 66 | } 67 | closedir(dir); 68 | } 69 | #endif 70 | 71 | static void saveFiles(char * path, FILES_t *files, int filesSize, int * count) { 72 | ESP_LOGI(__FUNCTION__,"path=[%s]", path); 73 | DIR* dir = opendir(path); 74 | assert(dir != NULL); 75 | while (true) { 76 | struct dirent *pe = readdir(dir); 77 | if (!pe) break; 78 | ESP_LOGD(__FUNCTION__,"%s d_name=%s d_ino=%d d_type=%x", path, pe->d_name, pe->d_ino, pe->d_type); 79 | if (pe->d_type == 1) { 80 | int _count = *count; 81 | strcpy(files[_count].file, pe->d_name); 82 | char fullPath[STR_SIZE+1]; 83 | strcpy(fullPath, path); 84 | strcat(fullPath, "/"); 85 | strcat(fullPath, pe->d_name); 86 | stat(fullPath, &files[_count].info); 87 | if ((*count) == (filesSize-1)) return; 88 | (*count)++; 89 | } 90 | #if 0 91 | if (pe->d_type == 2) { 92 | char subDir[STR_SIZE+1]; 93 | sprintf(subDir,"%s/%.64s", path, pe->d_name); 94 | ESP_LOGI(__FUNCTION__, "subDir=[%s]", subDir); 95 | printDirectory(subDir); 96 | } 97 | #endif 98 | } 99 | closedir(dir); 100 | } 101 | 102 | static void saveDirectorys(char * path, DIRS_t *dirs, int dirsSize, int * count) { 103 | int level = 0; 104 | for (int i=0;id_name, pe->d_ino, pe->d_type); 122 | #if 0 123 | if (pe->d_type == 1) { 124 | char fullPath[STR_SIZE+1]; 125 | strcpy(fullPath, path); 126 | strcat(fullPath, "/"); 127 | strcat(fullPath, pe->d_name); 128 | int fileSize = getFileSize(fullPath); 129 | ESP_LOGI(__FUNCTION__,"fileSize=%d", fileSize); 130 | } 131 | #endif 132 | if (pe->d_type == 2) { 133 | char subDir[STR_SIZE+1]; 134 | strcpy(subDir, path); 135 | strcat(subDir, "/"); 136 | strcat(subDir, pe->d_name); 137 | ESP_LOGI(__FUNCTION__, "level=%d subDir=[%s]", level, subDir); 138 | int _count = *count; 139 | dirs[_count].level = (level+1); 140 | strcpy(dirs[_count].self, subDir); 141 | strcpy(dirs[_count].parent, path); 142 | if ((*count) == (dirsSize-1)) return; 143 | (*count)++; 144 | saveDirectorys(subDir, dirs, dirsSize, count); 145 | 146 | } 147 | } 148 | 149 | closedir(dir); 150 | } 151 | 152 | void app_main(void) 153 | { 154 | ESP_LOGI(TAG, "Mounting FAT filesystem"); 155 | // To mount device we need name of device partition, define base_path 156 | // and allow format partition in case if it is new one and was not formatted before 157 | const esp_vfs_fat_mount_config_t mount_config = { 158 | .max_files = 4, 159 | .format_if_mount_failed = false, 160 | .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, 161 | .use_one_fat = false, 162 | }; 163 | 164 | //esp_err_t err; 165 | esp_err_t err = esp_vfs_fat_spiflash_mount_ro(base_path, "storage", &mount_config); 166 | if (err != ESP_OK) { 167 | ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err)); 168 | return; 169 | } 170 | 171 | //printDirectory(base_path); 172 | 173 | //DIRS_t dirs[MAX_DIRS]; 174 | DIRS_t *dirs; 175 | dirs = malloc (sizeof(DIRS_t) * MAX_DIRS); 176 | if (dirs == NULL) { 177 | ESP_LOGE(TAG, "dirs malloc fail"); 178 | return; 179 | } 180 | 181 | //FILES_t files[MAX_FILES]; 182 | FILES_t *files; 183 | files = malloc (sizeof(FILES_t) * MAX_FILES); 184 | if (files == NULL) { 185 | ESP_LOGE(TAG, "files malloc fail"); 186 | return; 187 | } 188 | 189 | // Collect directory 190 | int dirCount = 0; 191 | saveDirectorys(base_path, dirs, MAX_DIRS, &dirCount); 192 | ESP_LOGI(TAG, "dirCount=%d", dirCount); 193 | for (int i=0;i=0;target_level--) { 200 | for (int i=0;i 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | typedef struct { 22 | char buf[256]; 23 | size_t offset; 24 | } json_gen_test_result_t; 25 | 26 | static void flush_str(char *buf, void *priv) 27 | { 28 | printf("flush_str buf=[%s]\r\n", buf); 29 | json_gen_test_result_t *result = (json_gen_test_result_t *)priv; 30 | if (result) { 31 | if (strlen(buf) > sizeof(result->buf) - result->offset) { 32 | printf("Result Buffer too small\r\n"); 33 | return; 34 | } 35 | memcpy(result->buf + result->offset, buf, strlen(buf)); 36 | result->offset += strlen(buf); 37 | } 38 | } 39 | /* Creating JSON 40 | { 41 | "first_bool": true, 42 | "first_int": 30, 43 | "float_val": 54.1643, 44 | "my_str": "new_name", 45 | "null_obj": null, 46 | "arr": [ 47 | ["arr_string", false, 45.2, null, 25, { 48 | "arr_obj_str": "sample" 49 | }] 50 | ], 51 | "my_obj": { 52 | "only_val": 5 53 | } 54 | } 55 | */ 56 | 57 | void app_main() 58 | { 59 | json_gen_test_result_t result; 60 | char buf[20]; 61 | memset(&result, 0, sizeof(json_gen_test_result_t)); 62 | json_gen_str_t jstr; 63 | json_gen_str_start(&jstr, buf, sizeof(buf), flush_str, &result); 64 | json_gen_start_object(&jstr); 65 | json_gen_obj_set_bool(&jstr, "first_bool", true); 66 | json_gen_obj_set_int(&jstr, "first_int", 30); 67 | json_gen_obj_set_float(&jstr, "float_val", 54.1643); 68 | json_gen_obj_set_string(&jstr, "my_str", "new_name"); 69 | json_gen_obj_set_null(&jstr, "null_obj"); 70 | json_gen_push_array(&jstr, "arr"); 71 | json_gen_start_array(&jstr); 72 | json_gen_arr_set_string(&jstr, "arr_string"); 73 | json_gen_arr_set_bool(&jstr, false); 74 | json_gen_arr_set_float(&jstr, 45.12); 75 | json_gen_arr_set_null(&jstr); 76 | json_gen_arr_set_int(&jstr, 25); 77 | json_gen_start_object(&jstr); 78 | json_gen_obj_set_string(&jstr, "arr_obj_str", "sample"); 79 | json_gen_end_object(&jstr); 80 | json_gen_end_array(&jstr); 81 | json_gen_pop_array(&jstr); 82 | json_gen_push_object(&jstr, "my_obj"); 83 | json_gen_obj_set_int(&jstr, "only_val", 5); 84 | json_gen_pop_object(&jstr); 85 | json_gen_end_object(&jstr); 86 | json_gen_str_end(&jstr); 87 | printf("Generated: %s\r\n", result.buf); 88 | } 89 | -------------------------------------------------------------------------------- /json-http-client1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | -------------------------------------------------------------------------------- /json-http-client1/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | 3 | DeSerialize JOSN message received by HTTP. 4 | This project gets JSON data from Fake REST Server. 5 | 6 | 7 | # Install json-server (Fake REST Server) stable version on your host 8 | ``` 9 | sudo apt install npm 10 | sudo npm install -g json-server@0.17.4 11 | 12 | ``` 13 | 14 | # Start json-server (Fake REST Server) 15 | If the host parameter is not specified, it can only be accessed from local host. 16 | When accessing from ESP32, host parameter is required. 17 | ``` 18 | cd esp-idf-json/json-http-client1 19 | json-server --watch --host {My_IP_Address} ./db.json 20 | ``` 21 | 22 | ![JSON_Server](https://user-images.githubusercontent.com/6020549/71557207-3320e700-2a86-11ea-9761-823007c4b370.jpg) 23 | 24 | 25 | # Installation 26 | ``` 27 | git clone https://github.com/nopnop2002/esp-idf-json 28 | cd esp-idf-json/json-http-client1 29 | idf.py menuconfig 30 | idf.py flash monitor 31 | ``` 32 | 33 | # Configuration 34 | ![config-top-http-client1](https://user-images.githubusercontent.com/6020549/167752001-36383f6a-17cd-44e1-9550-49883fc1d408.jpg) 35 | 36 | The IP address in the URL of REST Server is the IP address of the host where you installed json-server. 37 | The IP address of the REST server needs to be changed according to your environment. 38 | ![config-app-http-client1](https://user-images.githubusercontent.com/6020549/167751997-071eec15-36c6-4159-bcd1-850a605277fb.jpg) 39 | 40 | 41 | # Console output 42 | ``` 43 | [ 44 | { 45 | "id": 1, 46 | "title": "Hello World!", 47 | "time": 1351824120, 48 | "data": [ 49 | 1, 50 | 2, 51 | 3 52 | ] 53 | }, 54 | { 55 | "id": 2, 56 | "title": "Hello Japan!", 57 | "time": 1351824240, 58 | "data": [ 59 | 1.11, 60 | 2.22 61 | ] 62 | } 63 | ] 64 | I (5263) JSON: Deserialize..... 65 | I (5273) JSON: [id] 66 | I (5273) JSON: int=1 double=1.000000 67 | I (5283) JSON: [title] 68 | I (5283) JSON: Hello World! 69 | I (5283) JSON: [time] 70 | I (5283) JSON: int=1351824120 double=1351824120.000000 71 | I (5293) JSON: [data] 72 | I (5293) JSON: int=1 double=1.000000 73 | I (5303) JSON: int=2 double=2.000000 74 | I (5303) JSON: int=3 double=3.000000 75 | I (5313) JSON: [id] 76 | I (5313) JSON: int=2 double=2.000000 77 | I (5313) JSON: [title] 78 | I (5323) JSON: Hello Japan! 79 | I (5323) JSON: [time] 80 | I (5323) JSON: int=1351824240 double=1351824240.000000 81 | I (5333) JSON: [data] 82 | I (5333) JSON: int=1 double=1.110000 83 | I (5343) JSON: int=2 double=2.220000 84 | 85 | 86 | 87 | { 88 | "id": 2, 89 | "title": "Hello Japan!", 90 | "time": 1351824240, 91 | "data": [ 92 | 1.11, 93 | 2.22 94 | ] 95 | } 96 | I (6487) JSON: Deserialize..... 97 | I (6497) JSON: [id] 98 | I (6497) JSON: int=2 double=2.000000 99 | I (6497) JSON: [title] 100 | I (6497) JSON: Hello Japan! 101 | I (6507) JSON: [time] 102 | I (6507) JSON: int=1351824240 double=1351824240.000000 103 | I (6517) JSON: [data] 104 | I (6517) JSON: int=1 double=1.110000 105 | I (6517) JSON: int=2 double=2.220000 106 | 107 | ``` 108 | 109 | # Modify JSON data 110 | Modify the db.json file. 111 | The changes will be reflected immediately. 112 | There is no need to restart json-server (Fake REST Server). 113 | ``` 114 | $ cat db.json 115 | { 116 | "todos": [ 117 | { 118 | "id": 1, 119 | "title": "Hello World!", 120 | "time":1351824120, 121 | "data":[1.00, 2.00, 3.00] 122 | }, 123 | { 124 | "id": 2, 125 | "title": "Hello Japan!", 126 | "time":1351824240, 127 | "data":[1.11, 2.22] 128 | } 129 | ] 130 | } 131 | ``` 132 | -------------------------------------------------------------------------------- /json-http-client1/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "todos": [ 3 | { 4 | "id": 1, 5 | "title": "Hello World!", 6 | "time":1351824120, 7 | "data":[1.00, 2.00, 3.00] 8 | }, 9 | { 10 | "id": 2, 11 | "title": "Hello Japan!", 12 | "time":1351824240, 13 | "data":[1.11, 2.22] 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /json-http-client1/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "main.c") 2 | set(COMPONENT_ADD_INCLUDEDIRS "") 3 | 4 | register_component() 5 | -------------------------------------------------------------------------------- /json-http-client1/main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "Application Configuration" 2 | 3 | config ESP_WIFI_SSID 4 | string "WiFi SSID" 5 | default "myssid" 6 | help 7 | SSID (network name) for the example to connect to. 8 | 9 | config ESP_WIFI_PASSWORD 10 | string "WiFi Password" 11 | default "mypassword" 12 | help 13 | WiFi password (WPA or WPA2) for the example to use. 14 | 15 | config ESP_MAXIMUM_RETRY 16 | int "Maximum retry" 17 | default 5 18 | help 19 | Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent. 20 | 21 | config ESP_REST_URL 22 | string "URL of REST Server" 23 | default "http://192.168.10.43:3000/todos" 24 | help 25 | URL of REST Server. 26 | 27 | endmenu 28 | -------------------------------------------------------------------------------- /json-http-client1/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | -------------------------------------------------------------------------------- /json-http-client2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | -------------------------------------------------------------------------------- /json-http-client2/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | 3 | DeSerialize JOSN message received by HTTPS. 4 | This project gets JSON data from https://www.howsmyssl.com/a/check 5 | 6 | # Installation 7 | 8 | ``` 9 | git clone https://github.com/nopnop2002/esp-idf-json 10 | cd esp-idf-json/json-http-client2 11 | chmod 777 getpem.sh 12 | ./getpem.sh 13 | idf.py menuconfig 14 | idf.py flash monitor 15 | ``` 16 | 17 | # Configuration 18 | ![config-top-http-client2](https://github.com/nopnop2002/esp-idf-json/assets/6020549/cfa5b64c-1b02-4161-a32f-0502f6fc0bb6) 19 | ![config-app-http-client2](https://github.com/nopnop2002/esp-idf-json/assets/6020549/b5498612-afc9-4350-ba52-eb6d272cdac5) 20 | 21 | # Console output 22 | ``` 23 | I (12837) JSON: Deserialize..... 24 | I (12847) JSON: [given_cipher_suites] 25 | I (12847) JSON: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 26 | I (12857) JSON: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 27 | I (12857) JSON: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 28 | I (12867) JSON: TLS_ECDHE_ECDSA_WITH_AES_256_CCM 29 | I (12867) JSON: TLS_DHE_RSA_WITH_AES_256_CCM 30 | I (12877) JSON: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 31 | I (12887) JSON: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 32 | I (12887) JSON: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 33 | I (12897) JSON: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 34 | I (12897) JSON: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 35 | I (12907) JSON: TLS_DHE_RSA_WITH_AES_256_CBC_SHA 36 | I (12907) JSON: TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 37 | I (12917) JSON: TLS_DHE_RSA_WITH_AES_256_CCM_8 38 | I (12917) JSON: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 39 | I (12927) JSON: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 40 | I (12937) JSON: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 41 | I (12937) JSON: TLS_ECDHE_ECDSA_WITH_AES_128_CCM 42 | I (12947) JSON: TLS_DHE_RSA_WITH_AES_128_CCM 43 | I (12947) JSON: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 44 | I (12957) JSON: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 45 | I (12957) JSON: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 46 | I (12967) JSON: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 47 | I (12967) JSON: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 48 | I (12977) JSON: TLS_DHE_RSA_WITH_AES_128_CBC_SHA 49 | I (12977) JSON: TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 50 | I (12987) JSON: TLS_DHE_RSA_WITH_AES_128_CCM_8 51 | I (12997) JSON: TLS_RSA_WITH_AES_256_GCM_SHA384 52 | I (12997) JSON: TLS_RSA_WITH_AES_256_CCM 53 | I (13007) JSON: TLS_RSA_WITH_AES_256_CBC_SHA256 54 | I (13007) JSON: TLS_RSA_WITH_AES_256_CBC_SHA 55 | I (13017) JSON: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 56 | I (13017) JSON: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 57 | I (13027) JSON: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 58 | I (13027) JSON: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 59 | I (13037) JSON: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 60 | I (13037) JSON: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 61 | I (13047) JSON: TLS_RSA_WITH_AES_256_CCM_8 62 | I (13047) JSON: TLS_RSA_WITH_AES_128_GCM_SHA256 63 | I (13057) JSON: TLS_RSA_WITH_AES_128_CCM 64 | I (13057) JSON: TLS_RSA_WITH_AES_128_CBC_SHA256 65 | I (13067) JSON: TLS_RSA_WITH_AES_128_CBC_SHA 66 | I (13067) JSON: TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 67 | I (13077) JSON: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 68 | I (13087) JSON: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 69 | I (13087) JSON: TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 70 | I (13097) JSON: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 71 | I (13097) JSON: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 72 | I (13107) JSON: TLS_RSA_WITH_AES_128_CCM_8 73 | I (13107) JSON: TLS_EMPTY_RENEGOTIATION_INFO_SCSV 74 | I (13117) JSON: [ephemeral_keys_supported] 75 | I (13117) JSON: True 76 | I (13127) JSON: [session_ticket_supported] 77 | I (13127) JSON: True 78 | I (13127) JSON: [tls_compression_supported] 79 | I (13137) JSON: False 80 | I (13137) JSON: [unknown_cipher_suite_supported] 81 | I (13147) JSON: False 82 | I (13147) JSON: [beast_vuln] 83 | I (13147) JSON: False 84 | I (13157) JSON: [able_to_detect_n_minus_one_splitting] 85 | I (13157) JSON: False 86 | I (13157) JSON: [insecure_cipher_suites] 87 | I (13167) JSON: [tls_version] 88 | I (13167) JSON: TLS 1.2 89 | I (13177) JSON: [rating] 90 | I (13177) JSON: Probably Okay 91 | ``` 92 | 93 | # Using a public JSON server 94 | This project gets JSON data from [here](https://www.howsmyssl.com/a/check). 95 | If you get the JSON data from a other public JSON server, you need to extract the root certificate. 96 | You can use ```getpem.sh``` script to extract the server's root certificate. 97 | ``` 98 | $ edit getpem.sh 99 | 100 | HOST="your public server" 101 | 102 | $ chmod 777 getpem.sh 103 | 104 | $ ./getpem.sh 105 | ``` 106 | -------------------------------------------------------------------------------- /json-http-client2/getpem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Extract the root certificate from www.metaweather.com. 4 | 5 | #set -x 6 | 7 | HOST="www.howsmyssl.com" 8 | 9 | openssl s_client -showcerts -connect ${HOST}:443 hoge 10 | #openssl s_client -showcerts -connect www.howsmyssl.com:443 hoge 11 | 12 | start=`grep -e "-----BEGIN CERTIFICATE-----" -n hoge | sed -e 's/:.*//g' | tail -n 1` 13 | 14 | last=`grep -e "-----END CERTIFICATE-----" -n hoge | sed -e 's/:.*//g' | tail -n 1` 15 | 16 | sed -n ${start},${last}p hoge > main/server_root_cert.pem 17 | 18 | rm hoge 19 | -------------------------------------------------------------------------------- /json-http-client2/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(srcs "main.c") 2 | 3 | idf_component_register(SRCS ${srcs} 4 | INCLUDE_DIRS "." 5 | EMBED_TXTFILES server_root_cert.pem) 6 | -------------------------------------------------------------------------------- /json-http-client2/main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "Application Configuration" 2 | 3 | config ESP_WIFI_SSID 4 | string "WiFi SSID" 5 | default "myssid" 6 | help 7 | SSID (network name) for the example to connect to. 8 | 9 | config ESP_WIFI_PASSWORD 10 | string "WiFi Password" 11 | default "mypassword" 12 | help 13 | WiFi password (WPA or WPA2) for the example to use. 14 | 15 | config ESP_MAXIMUM_RETRY 16 | int "Maximum retry" 17 | default 5 18 | help 19 | Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent. 20 | 21 | endmenu 22 | -------------------------------------------------------------------------------- /json-http-client2/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | -------------------------------------------------------------------------------- /json-http-client2/main/server_root_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/ 3 | MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT 4 | DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow 5 | TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh 6 | cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB 7 | AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC 8 | ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL 9 | wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D 10 | LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK 11 | 4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5 12 | bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y 13 | sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ 14 | Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4 15 | FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc 16 | SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql 17 | PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND 18 | TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw 19 | SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1 20 | c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx 21 | +tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB 22 | ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu 23 | b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E 24 | U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu 25 | MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC 26 | 5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW 27 | 9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG 28 | WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O 29 | he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC 30 | Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /json-http-client3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following five lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | -------------------------------------------------------------------------------- /json-http-client3/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | Demonstration of displaying a JSON message in tree format. 3 | Nested JSON messages lend themselves to a Tree representation. 4 | I used [this](https://github.com/summerstyle/jsonTreeViewer) library. 5 | This project gets JSON data from Fake REST Server. 6 | ![Image](https://github.com/user-attachments/assets/a23bdbe5-1e35-4706-892a-4bb9c2e8df5d) 7 | 8 | # Install json-server (Fake REST Server) stable version on your host 9 | ``` 10 | sudo apt install npm 11 | sudo npm install -g json-server@0.17.4 12 | 13 | ``` 14 | 15 | # Start json-server (Fake REST Server) 16 | If the host parameter is not specified, it can only be accessed from local host. 17 | When accessing from ESP32, host parameter is required. 18 | ``` 19 | cd esp-idf-json/json-http-client3 20 | json-server --watch --host {My_IP_Address} ./db.json 21 | ``` 22 | ![Image](https://github.com/user-attachments/assets/fc181d30-2b98-4199-8983-4359bf14239e) 23 | 24 | 25 | # Installation 26 | ``` 27 | git clone https://github.com/nopnop2002/esp-idf-json 28 | cd esp-idf-json/json-http-client3 29 | idf.py menuconfig 30 | idf.py flash monitor 31 | ``` 32 | 33 | # Configuration 34 | ![Image](https://github.com/user-attachments/assets/069b30d7-a27c-4a22-a2c6-29d6d37ff1d3) 35 | 36 | The IP address in the URL of REST Server is the IP address of the host where you installed json-server. 37 | The IP address of the REST server needs to be changed according to your environment. 38 | ![Image](https://github.com/user-attachments/assets/743c0249-a3d2-4fb5-84a1-6506db84c0af) 39 | 40 | 41 | # How to use 42 | Open a browser and enter the IP address of the esp32 in the browser's address bar. 43 | The ESP32 retrieves data from the Fake REST Server and displays it in tree format. 44 | ![Image](https://github.com/user-attachments/assets/562a3c75-8297-413b-8b07-58749c950af2) 45 | 46 | Instead of IP addresses, you can use mDNS hostnames. 47 | ![Image](https://github.com/user-attachments/assets/22396443-a204-4733-a979-ae154623f7da) 48 | 49 | # Modify JSON data 50 | Modify the db.json file. 51 | The changes will be reflected immediately. 52 | There is no need to restart json-server (Fake REST Server). 53 | ``` 54 | $ cat db.json 55 | { 56 | "tree": { 57 | "firstName": "John", 58 | "lastName": "Smith", 59 | "isAlive": true, 60 | "age": 25, 61 | "company": null, 62 | "height_cm": 167.64, 63 | "address": { 64 | "streetAddress": "21 2nd Street", 65 | "city": "New York", 66 | "state": "NY", 67 | "postalCode": "10021-3100" 68 | }, 69 | "phoneNumbers": [ 70 | { 71 | "type": "home", 72 | "number": "212 555-1234" 73 | }, 74 | { 75 | "type": "fax", 76 | "number": "646 555-4567" 77 | } 78 | ] 79 | } 80 | 81 | } 82 | ``` 83 | -------------------------------------------------------------------------------- /json-http-client3/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "tree": { 3 | "firstName": "John", 4 | "lastName": "Smith", 5 | "isAlive": true, 6 | "age": 25, 7 | "company": null, 8 | "height_cm": 167.64, 9 | "address": { 10 | "streetAddress": "21 2nd Street", 11 | "city": "New York", 12 | "state": "NY", 13 | "postalCode": "10021-3100" 14 | }, 15 | "phoneNumbers": [ 16 | { 17 | "type": "home", 18 | "number": "212 555-1234" 19 | }, 20 | { 21 | "type": "fax", 22 | "number": "646 555-4567" 23 | } 24 | ] 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /json-http-client3/html/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ESP32 Error 404 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Error 404

12 |

Unknown page. Return home.

13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /json-http-client3/html/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nopnop2002/esp-idf-json/840bfc69e73516f0b43c52584d394f6b03ff5eb8/json-http-client3/html/favicon.ico -------------------------------------------------------------------------------- /json-http-client3/html/jsonTreeViewer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JSON Tree Viewer 3 | * http://github.com/summerstyle/jsonTreeViewer 4 | * 5 | * Copyright 2017 Vera Lobacheva (http://iamvera.com) 6 | * Released under the MIT license (LICENSE.txt) 7 | */ 8 | 9 | 'use strict'; 10 | 11 | var jsonTreeViewer = (function() { 12 | 13 | /* Utilities */ 14 | var utils = App.utils; 15 | 16 | var treeWrapper = document.getElementById("tree"); 17 | var tree = jsonTree.create({}, treeWrapper); 18 | 19 | // Menu 20 | var menu = new App.Menu(utils.dom.id('nav'), { 21 | 'load' : function() { 22 | load_json_form.show(); 23 | }, 24 | 'expand' : function() { 25 | tree.expand(); 26 | }, 27 | 'collapse' : function() { 28 | tree.collapse(); 29 | }, 30 | 'source' : function() { 31 | source_json_window.print( 32 | tree.toSourceJSON('isPrettyPrinted') 33 | ); 34 | }, 35 | 'find_and_mark' : function() { 36 | find_nodes_form.show(); 37 | }, 38 | 'unmark_all' : function() { 39 | tree.unmarkAll(); 40 | }, 41 | 'help' : function() { 42 | help.show(); 43 | } 44 | }); 45 | 46 | 47 | /* Load json form */ 48 | var load_json_form = new App.Window({ 49 | content_el : utils.dom.id('load_json_form'), 50 | overlay : true, 51 | js_module : function(self) { 52 | var form = self.content_el, 53 | code_input = document.getElementById('code_input'), 54 | load_button = document.getElementById('load_code_button'); 55 | 56 | function load(e) { 57 | jsonTreeViewer.parse(code_input.value); 58 | self.hide(); 59 | code_input.value = ''; 60 | 61 | e.preventDefault(); 62 | } 63 | 64 | load_button.addEventListener('click', load, false); 65 | } 66 | }); 67 | 68 | 69 | /* Help block */ 70 | var help = new App.Window({ 71 | content_el : document.getElementById('help'), 72 | overlay : true 73 | }); 74 | 75 | /* Block for source JSON */ 76 | var source_json_window = new App.Window({ 77 | content_el : utils.dom.id('source_json'), 78 | overlay : true, 79 | js_module : function(self) { 80 | return { 81 | print: function(str) { 82 | self.content_el.innerHTML = str; 83 | self.show(); 84 | } 85 | }; 86 | } 87 | }); 88 | 89 | /* Find nodes form */ 90 | var find_nodes_form = new App.Window({ 91 | content_el : utils.dom.id('find_nodes_form'), 92 | overlay : true, 93 | js_module : function(self) { 94 | var form = self.content_el, 95 | search_type_radio = { 96 | label_name : document.getElementById('nodes_search_by_label'), 97 | node_type : document.getElementById('nodes_search_by_type') 98 | }, 99 | label_name_input = document.getElementById('search_by_label_name'), 100 | node_types_checkboxes = document.getElementsByName('nodes_type'), 101 | find_button = document.getElementById('find_button'), 102 | MATCHERS = { 103 | BY_LABEL_NAME : function(labelName, node) { 104 | return node.label === labelName; 105 | }, 106 | BY_NODE_TYPE : function(nodeTypesArray, node) { 107 | return nodeTypesArray.indexOf(node.type) >= 0; 108 | } 109 | }; 110 | 111 | function find(e) { 112 | var matcher; 113 | 114 | e.preventDefault(); 115 | 116 | if (search_type_radio.label_name.checked) { 117 | var label_name_value = label_name_input.value.trim(); 118 | 119 | if (!label_name_value) { 120 | return; 121 | } 122 | matcher = MATCHERS.BY_LABEL_NAME.bind(null, label_name_value); 123 | } else if (search_type_radio.node_type.checked) { 124 | var node_type_values = []; 125 | 126 | for (var i = 0, c = node_types_checkboxes.length; i < c; i++) { 127 | if (node_types_checkboxes[i].checked) { 128 | node_type_values.push(node_types_checkboxes[i].value); 129 | } 130 | } 131 | 132 | if (!node_type_values.length) { 133 | return; 134 | } 135 | 136 | matcher = MATCHERS.BY_NODE_TYPE.bind(null, node_type_values); 137 | } 138 | 139 | if (!matcher) { 140 | return; 141 | } 142 | 143 | tree.findAndHandle(matcher, function(node) { 144 | node.mark(); 145 | node.expandParent('isRecursive'); 146 | }); 147 | 148 | self.hide(); 149 | } 150 | 151 | find_button.addEventListener('click', find, false); 152 | } 153 | }); 154 | 155 | load_json_form.show(); 156 | 157 | return { 158 | parse : function(json_str) { 159 | var temp; 160 | 161 | try { 162 | temp = JSON.parse(json_str); 163 | } catch(e) { 164 | alert(e); 165 | } 166 | 167 | tree.loadData(temp); 168 | } 169 | }; 170 | })(); 171 | -------------------------------------------------------------------------------- /json-http-client3/html/libs/app/README.md: -------------------------------------------------------------------------------- 1 | # App.js 2 | 3 | A simple javascript-framework for building desktop-like applications. 4 | 5 | [http://github.com/summerstyle/app.js](http://github.com/summerstyle/app.js) 6 | 7 | Released under the MIT License 8 | 9 | ## Components 10 | 11 | ### constructor `App.Window` 12 | 13 | Move a block content to window and apply javascript-module for it. 14 | 15 | ```javascript 16 | var code = new App.Window({ 17 | content_el : utils.dom.id('code'), 18 | overlay : true, 19 | js_module : function(self) { 20 | return { 21 | print: function() { 22 | self.el.innerHTML = selected_keys.generate_config(); 23 | self.show(); 24 | } 25 | }; 26 | } 27 | }); 28 | ``` 29 | Parameters: 30 | 31 | * content_el* – a dom-element for including in window, 32 | * overlay – a window with overlay, 33 | * closable – a window can be closed, 34 | * layout – a style of window, 35 | * js_module – a function returns an object with methods, which are mixed in a standard window methods. 36 | 37 | The window interface: 38 | 39 | * show() — show window, 40 | * hide() — hide window. 41 | 42 | ### constructor `App.Menu` 43 | 44 | This conctructor creates multilevel menu. 45 | 46 | The menu constructor called with two arguments: dom-element with link lists and an object with name-action mapping. 47 | 48 | ```html 49 | 65 | ``` 66 | 67 | ```javascript 68 | var menu = new App.Menu(utils.dom.id('nav'), { 69 | 'clear' : function() { 70 | // Deselect all keys 71 | if (confirm('Clear all?')) { 72 | selected_keys.clear(); 73 | code.hide(); 74 | }; 75 | }, 76 | 'get_config' : function() { 77 | code.print(); 78 | }, 79 | 'show_help' : function() { 80 | help.show(); 81 | }, 82 | 'settings' : function() { 83 | settings_form.show(); 84 | } 85 | }); 86 | ``` 87 | -------------------------------------------------------------------------------- /json-http-client3/html/libs/app/app.css: -------------------------------------------------------------------------------- 1 | /* 2 | * JSON Tree Viewer 3 | * http://github.com/summerstyle/jsonTreeViewer 4 | * 5 | * Copyright 2015 Vera Lobacheva (summerstyle.ru) 6 | * Released under the GPL3 (GPL3.txt) 7 | * 8 | * Sun 27 2014 20:15:00 GMT+0400 9 | */ 10 | 11 | .global-error { 12 | position: fixed; 13 | top: 0; 14 | left: 0; 15 | width: 100%; 16 | z-index: 10000; 17 | text-align: center; 18 | font-size: 20px; 19 | padding: 5px 0; 20 | background: #F00; 21 | } 22 | #header { 23 | background: #F5F5F5; 24 | position: fixed; 25 | z-index: 1; 26 | width: 100%; 27 | box-shadow: rgba(0,0,0,0.2) 0 0 3px 2px; 28 | top: 0; 29 | left: 0; 30 | } 31 | #logo { 32 | margin-left: 20px; 33 | margin-right: 10px; 34 | margin-top: 7px; 35 | float: left; 36 | } 37 | #logo a:link, #logo a:visited { 38 | color: #32c832; 39 | transition: 2s color; 40 | } 41 | #logo a:hover { 42 | color: #000; 43 | } 44 | #logo img { 45 | display: block; 46 | } 47 | 48 | .hidden { 49 | display: none; 50 | } 51 | 52 | .menu { 53 | float: left; 54 | font-size: 13px; 55 | } 56 | .menu__item { 57 | float: left; 58 | text-transform: capitalize; 59 | position: relative; 60 | } 61 | .menu__item a::first-letter { 62 | border-bottom: 1px solid #BCBCBC; 63 | } 64 | 65 | .menu__item-name { 66 | padding: 7px 10px; 67 | display: block; 68 | color: #777; 69 | text-shadow: rgba(255, 255, 255, 0.4) 0 -1px 0; 70 | cursor: pointer; 71 | } 72 | .menu__item-name a:hover { 73 | color: #000; 74 | } 75 | 76 | .menu__item:hover { 77 | background: #FFF; 78 | } 79 | .menu__item:hover .menu { 80 | display: block; 81 | } 82 | .menu_level1 > .menu__item:hover { 83 | box-shadow: 0 0 4px rgba(0,0,0,0.3); 84 | } 85 | 86 | .menu_level2 { 87 | display: none; 88 | position: absolute; 89 | left: 0; 90 | top: 100%; 91 | background: #FFF; 92 | box-shadow: 0 0 4px rgba(0,0,0,0.3); 93 | font-size: 12px; 94 | } 95 | .menu_level2 .menu__item { 96 | min-width: 150px; 97 | max-width: 250px; 98 | line-height: 1.2; 99 | } 100 | .menu_level2 .menu__item-name:hover { 101 | background: #32c832; 102 | color: #FFF; 103 | text-shadow: none; 104 | } 105 | 106 | .txt { 107 | line-height: 1.4; 108 | } 109 | .txt section { 110 | margin-bottom: 15px; 111 | } 112 | .txt p { 113 | margin-bottom: 20px; 114 | } 115 | .txt h1 { 116 | font-size: 25px; 117 | margin-bottom: 10px; 118 | } 119 | .txt h2 { 120 | font-size: 20px; 121 | margin-bottom: 10px; 122 | } 123 | .txt h3 { 124 | font-size: 18px; 125 | margin-bottom: 7px; 126 | } 127 | .txt h4 { 128 | font-size: 16px; 129 | margin-bottom: 7px; 130 | } 131 | .txt h5 { 132 | font-size: 14px; 133 | margin-bottom: 5px; 134 | } 135 | .txt h6 { 136 | font-size: 12px; 137 | margin-bottom: 5px; 138 | } 139 | .txt footer { 140 | color: #999; 141 | font-size: 10px; 142 | margin: 20px 0 -5px; 143 | line-height: 1.3; 144 | } 145 | .txt footer a { 146 | color: #777; 147 | text-decoration: none; 148 | border-bottom: 1px solid #BBB; 149 | } 150 | .txt ul { 151 | list-style: disc; 152 | margin-bottom: 20px; 153 | margin-left: 35px; 154 | } 155 | 156 | .pseudo_link { 157 | border-bottom: 1px #000 dashed; 158 | cursor: pointer; 159 | } 160 | 161 | .code { 162 | font-family: 'PT Mono', monospace; 163 | font-size: 14px; 164 | line-height: 1.5; 165 | color: #555; 166 | border: 2px dashed #EEE; 167 | background: #F9F9F9; 168 | padding: 10px; 169 | margin-bottom: 20px; 170 | } 171 | .code_inline { 172 | padding: 3px 5px; 173 | font-weight: normal; 174 | } 175 | 176 | #debug { 177 | color: #EEE; 178 | position: absolute; 179 | top: 10px; 180 | right: 100px; 181 | z-index: 1001; 182 | font-size: 11px; 183 | } 184 | 185 | #wrapper { 186 | position: relative; 187 | padding: 70px 20px 0; 188 | } 189 | 190 | .overlay { 191 | position: fixed; 192 | top: 0; 193 | left: 0; 194 | width: 100%; 195 | height: 100%; 196 | z-index: 1002; 197 | background: #000; 198 | opacity: 0.5; 199 | display: none; 200 | } 201 | 202 | .window { 203 | width: 400px; 204 | border-radius: 10px; 205 | background: #FFF; 206 | position: absolute; 207 | top: 50px; 208 | left: 50%; 209 | margin-left: -200px; 210 | z-index: 1003; 211 | box-shadow: rgba(0,0,0,0.2) 0 0 2px 2px; 212 | padding: 20px; 213 | display: none; 214 | } 215 | .window__header { 216 | padding: 10px 20px; 217 | font-size: 15px; 218 | font-weight: bold; 219 | background: #FAFAFA; 220 | border-bottom: 1px solid #EEE; 221 | border-top-left-radius: 5px; 222 | border-top-right-radius: 5px; 223 | margin: -20px -20px 20px; 224 | } 225 | .window_movable .window__header { 226 | cursor: move; 227 | } 228 | 229 | .window__close-button { 230 | display: inline-block; 231 | background: #BBB; 232 | color: #555; 233 | box-shadow: 0 0 1px #EEE inset; 234 | border-radius: 10px; 235 | position: absolute; 236 | font-weight: bold; 237 | top: 10px; 238 | right: 10px; 239 | height: 20px; 240 | width: 20px; 241 | line-height: 16px; 242 | text-align: center; 243 | cursor: pointer; 244 | } 245 | .window__close-button:before { 246 | content: '✕'; 247 | font-family: sans-serif; 248 | font-size: 10px; 249 | } 250 | .window__close-button:hover { 251 | background: #32c832; 252 | color: #FFF; 253 | } 254 | 255 | .app-example { 256 | box-sizing: border-box; 257 | border: 3px dashed #EEE; 258 | padding: 20px; 259 | color: #AAA; 260 | } 261 | 262 | .form h5 { 263 | margin-bottom: 20px; 264 | } 265 | .form p { 266 | margin-bottom: 10px; 267 | } 268 | .form section { 269 | margin-bottom: 20px; 270 | } 271 | .form .checkboxes { 272 | margin-top: 10px; 273 | } 274 | .form .checkboxes > li { 275 | margin-bottom: 5px; 276 | } 277 | .form textarea { 278 | width: 100%; 279 | display: inline-block; 280 | border-radius: 3px; 281 | padding: 2px 7px; 282 | border: 1px solid #E1E1E1; 283 | height: 70px; 284 | box-sizing: border-box; 285 | } 286 | .form input[type=text] { 287 | width: 100%; 288 | display: inline-block; 289 | border-radius: 3px; 290 | padding: 2px 7px; 291 | border: 1px solid #E1E1E1; 292 | box-sizing: border-box; 293 | } 294 | .form button { 295 | border: 0; 296 | background: #E1E1E1; 297 | color: #555; 298 | box-shadow: 0 0 1px #eee inset; 299 | padding: 5px 20px; 300 | font-family: 'Trebuchet MS', Arial, sans-serif; 301 | border-radius: 3px; 302 | cursor: pointer; 303 | } 304 | .form button:hover { 305 | background: #32c832; 306 | color: #FFF; 307 | } 308 | 309 | ::selection { 310 | background: #EEE; 311 | color: #000; 312 | } 313 | ::-moz-selection { 314 | background: #EEE; 315 | color: #000; 316 | } 317 | -------------------------------------------------------------------------------- /json-http-client3/html/libs/app/docs/main.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, applet, object, 2 | h1, h2, h3, h4, h5, h6, p, a, em, img, 3 | strong, ol, ul, li, dl, dd, dt, 4 | form, label, input, 5 | article, aside, canvas, details, 6 | embed, figure, figcaption, footer, 7 | header, hgroup, menu, nav, output, 8 | ruby, section, summary, time, mark, 9 | audio, video { 10 | margin: 0; 11 | padding: 0; 12 | border: 0; 13 | outline: 0; 14 | font-style: inherit; 15 | font-size: 100%; 16 | font-family: inherit; 17 | vertical-align: baseline; 18 | background: transparent; 19 | } 20 | :focus { 21 | outline: 0; 22 | } 23 | ul, ol { 24 | list-style: none; 25 | } 26 | html { 27 | height: 100%; 28 | } 29 | body { 30 | padding: 0; 31 | margin: 0; 32 | font-family: 'PT Serif', 'Trebuchet MS', Arial, sans-serif; 33 | font-size: 16px; 34 | color: #000; 35 | height: 100%; 36 | min-height: 100%; 37 | background: #FFF; 38 | line-height: 1; 39 | overflow-y: scroll; 40 | } 41 | img { 42 | border: 0; 43 | } 44 | a:link, a:visited { 45 | outline: none; 46 | text-decoration: none; 47 | color: #32c832; 48 | border-bottom: 1px solid #BEEABE; 49 | } 50 | .clear { 51 | clear: both; 52 | } 53 | .clearfix:after { 54 | content: "."; 55 | display: block; 56 | clear: both; 57 | visibility: hidden; 58 | line-height: 0; 59 | height: 0; 60 | } 61 | 62 | #container { 63 | width: 800px; 64 | margin: 0 auto; 65 | padding: 20px 0; 66 | } 67 | 68 | header { 69 | border-bottom: 1px solid #CCC; 70 | margin-bottom: 30px; 71 | } 72 | 73 | .links { 74 | margin: 0 0 10px !important; 75 | } 76 | .links li { 77 | display: inline-block; 78 | list-style-type: none; 79 | margin-right: 10px; 80 | background: #F5F5F5; 81 | padding: 5px 10px; 82 | } 83 | .links a { 84 | border-bottom: 0; 85 | color: #000; 86 | } 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /json-http-client3/html/libs/app/reset.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, applet, object, 2 | h1, h2, h3, h4, h5, h6, p, a, em, img, 3 | strong, ol, ul, li, dl, dd, dt, 4 | form, label, input, 5 | article, aside, canvas, details, 6 | embed, figure, figcaption, footer, 7 | header, hgroup, menu, nav, output, 8 | ruby, section, summary, time, mark, 9 | audio, video { 10 | margin: 0; 11 | padding: 0; 12 | border: 0; 13 | outline: 0; 14 | font-style: inherit; 15 | font-size: 100%; 16 | font-family: inherit; 17 | vertical-align: baseline; 18 | background: transparent; 19 | } 20 | :focus { 21 | outline: 0; 22 | } 23 | ul, ol { 24 | list-style: none; 25 | } 26 | html { 27 | height: 100%; 28 | } 29 | body { 30 | padding: 0; 31 | margin: 0; 32 | font-family: 'Trebuchet MS', Arial, sans-serif; 33 | font-size: 14px; 34 | color: #000; 35 | height: 100%; 36 | min-height: 100%; 37 | background: #FFF; 38 | line-height: 1; 39 | overflow-y: scroll; 40 | } 41 | img { 42 | border: 0; 43 | } 44 | a:link, a:visited { 45 | outline: none; 46 | text-decoration: none; 47 | color: #000; 48 | } 49 | .clear { 50 | clear: both; 51 | } 52 | .clearfix:after { 53 | content: "."; 54 | display: block; 55 | clear: both; 56 | visibility: hidden; 57 | line-height: 0; 58 | height: 0; 59 | } -------------------------------------------------------------------------------- /json-http-client3/html/libs/jsonTree/icons.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /json-http-client3/html/libs/jsonTree/jsonTree.css: -------------------------------------------------------------------------------- 1 | /* 2 | * JSON Tree Viewer 3 | * http://github.com/summerstyle/jsonTreeViewer 4 | * 5 | * Copyright 2017 Vera Lobacheva (http://iamvera.com) 6 | * Released under the MIT license (LICENSE.txt) 7 | */ 8 | 9 | /* Background for the tree. May use for element */ 10 | .jsontree_bg { 11 | background: #FFF; 12 | } 13 | 14 | /* Styles for the container of the tree (e.g. fonts, margins etc.) */ 15 | .jsontree_tree { 16 | margin-left: 30px; 17 | font-family: 'PT Mono', monospace; 18 | font-size: 14px; 19 | } 20 | 21 | /* Styles for a list of child nodes */ 22 | .jsontree_child-nodes { 23 | display: none; 24 | margin-left: 35px; 25 | margin-bottom: 5px; 26 | line-height: 2; 27 | } 28 | .jsontree_node_expanded > .jsontree_value-wrapper > .jsontree_value > .jsontree_child-nodes { 29 | display: block; 30 | } 31 | 32 | /* Styles for labels */ 33 | .jsontree_label-wrapper { 34 | float: left; 35 | margin-right: 8px; 36 | } 37 | .jsontree_label { 38 | font-weight: normal; 39 | vertical-align: top; 40 | color: #000; 41 | position: relative; 42 | padding: 1px; 43 | border-radius: 4px; 44 | cursor: default; 45 | } 46 | .jsontree_node_marked > .jsontree_label-wrapper > .jsontree_label { 47 | background: #fff2aa; 48 | } 49 | 50 | /* Styles for values */ 51 | .jsontree_value-wrapper { 52 | display: block; 53 | overflow: hidden; 54 | } 55 | .jsontree_node_complex > .jsontree_value-wrapper { 56 | overflow: inherit; 57 | } 58 | .jsontree_value { 59 | vertical-align: top; 60 | display: inline; 61 | } 62 | .jsontree_value_null { 63 | color: #777; 64 | font-weight: bold; 65 | } 66 | .jsontree_value_string { 67 | color: #025900; 68 | font-weight: bold; 69 | } 70 | .jsontree_value_number { 71 | color: #000E59; 72 | font-weight: bold; 73 | } 74 | .jsontree_value_boolean { 75 | color: #600100; 76 | font-weight: bold; 77 | } 78 | 79 | /* Styles for active elements */ 80 | .jsontree_expand-button { 81 | position: absolute; 82 | top: 3px; 83 | left: -15px; 84 | display: block; 85 | width: 11px; 86 | height: 11px; 87 | background-image: url('icons.svg'); 88 | } 89 | .jsontree_node_expanded > .jsontree_label-wrapper > .jsontree_label > .jsontree_expand-button { 90 | background-position: 0 -11px; 91 | } 92 | .jsontree_show-more { 93 | cursor: pointer; 94 | } 95 | .jsontree_node_expanded > .jsontree_value-wrapper > .jsontree_value > .jsontree_show-more { 96 | display: none; 97 | } 98 | .jsontree_node_empty > .jsontree_label-wrapper > .jsontree_label > .jsontree_expand-button, 99 | .jsontree_node_empty > .jsontree_value-wrapper > .jsontree_value > .jsontree_show-more { 100 | display: none !important; 101 | } 102 | .jsontree_node_complex > .jsontree_label-wrapper > .jsontree_label { 103 | cursor: pointer; 104 | } 105 | .jsontree_node_empty > .jsontree_label-wrapper > .jsontree_label { 106 | cursor: default !important; 107 | } 108 | -------------------------------------------------------------------------------- /json-http-client3/html/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | Your favorite style is defined here. 3 | */ 4 | -------------------------------------------------------------------------------- /json-http-client3/html/main.js: -------------------------------------------------------------------------------- 1 | //document.getElementById("datetime").innerHTML = "WebSocket is not connected"; 2 | 3 | var websocket = new WebSocket('ws://'+location.hostname+'/'); 4 | 5 | // Initialize tree. Displays an empty tree. 6 | var treeWrapper = document.getElementById("tree"); 7 | var tree = jsonTree.create({}, treeWrapper); 8 | 9 | // Expands all tree nodes (objects or arrays) recursively 10 | function expand_all() { 11 | tree.expand(); 12 | } 13 | 14 | // Collapses all tree nodes (objects or arrays) recursively 15 | function collapse_all() { 16 | tree.collapse(); 17 | } 18 | 19 | function sendText(name) { 20 | console.log('sendText'); 21 | var data = {}; 22 | data["id"] = name; 23 | console.log('data=', data); 24 | json_data = JSON.stringify(data); 25 | console.log('json_data=' + json_data); 26 | websocket.send(json_data); 27 | } 28 | 29 | websocket.onopen = function(evt) { 30 | console.log('WebSocket connection opened'); 31 | var data = {}; 32 | data["id"] = "init"; 33 | console.log('data=', data); 34 | json_data = JSON.stringify(data); 35 | console.log('json_data=' + json_data); 36 | websocket.send(json_data); 37 | //document.getElementById("datetime").innerHTML = "WebSocket is connected!"; 38 | } 39 | 40 | websocket.onmessage = function(evt) { 41 | var msg = evt.data; 42 | console.log("msg=" + msg); 43 | var values = msg.split('\4'); // \4 is EOT 44 | //console.log("values=" + values); 45 | switch(values[0]) { 46 | case 'HEADER': 47 | /* 48 | console.log("HEAD values[1]=" + values[1]); 49 | var h1 = document.getElementById( 'header' ); 50 | h1.textContent = values[1]; 51 | */ 52 | break; 53 | 54 | case 'TREE': 55 | console.log("TREE values[1]=" + values[1]); 56 | // Convert string to JSON 57 | var data = JSON.parse(values[1]); 58 | // Update tree 59 | tree.loadData(data); 60 | break; 61 | 62 | case 'ELASPED': 63 | console.log("ELASPED values[1]=" + values[1]); 64 | 65 | // Get element object 66 | var elasped = document.getElementById("elasped"); 67 | // Clear object 68 | elasped.textContent = ""; 69 | // Convert string to JSON 70 | var data = JSON.parse(values[1]); 71 | // Create json-tree 72 | jsonTree.create(data, elasped); 73 | break; 74 | 75 | default: 76 | break; 77 | } 78 | } 79 | 80 | websocket.onclose = function(evt) { 81 | console.log('Websocket connection closed'); 82 | //document.getElementById("datetime").innerHTML = "WebSocket closed"; 83 | } 84 | 85 | websocket.onerror = function(evt) { 86 | console.log('Websocket error: ' + evt); 87 | //document.getElementById("datetime").innerHTML = "WebSocket error????!!!1!!"; 88 | } 89 | -------------------------------------------------------------------------------- /json-http-client3/html/root.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 18 | Json Tree View 19 | 20 | 21 | 22 | 23 | 64 | 65 | 66 |
67 |
68 |
69 | 70 |
71 |
72 |
73 | 74 | 75 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /json-http-client3/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "main.c" "web_server.c" "web_client.c" "http_get_notify.c" 2 | INCLUDE_DIRS "." 3 | EMBED_FILES "../html/error.html" 4 | "../html/favicon.ico" 5 | "../html/main.js" 6 | "../html/root.html" 7 | "../html/main.css" 8 | "../html/libs/app/reset.css" 9 | "../html/libs/app/app.css" 10 | "../html/libs/jsonTree/jsonTree.css" 11 | "../html/libs/jsonTree/jsonTree.js" 12 | "../html/libs/jsonTree/icons.svg") 13 | -------------------------------------------------------------------------------- /json-http-client3/main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "Application configuration" 2 | 3 | config ESP_WIFI_SSID 4 | string "WiFi SSID" 5 | default "myssid" 6 | help 7 | SSID (network name) to connect to. 8 | 9 | config ESP_WIFI_PASSWORD 10 | string "WiFi Password" 11 | default "mypassword" 12 | help 13 | WiFi password (WPA or WPA2) to connect to. 14 | 15 | config ESP_MAXIMUM_RETRY 16 | int "Maximum retry" 17 | default 5 18 | help 19 | Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent. 20 | 21 | config MDNS_HOSTNAME 22 | string "mDNS Hostname" 23 | default "esp32-server" 24 | help 25 | The mDNS host name used by the ESP32. 26 | 27 | config ESP_REST_URL 28 | string "URL of REST Server" 29 | default "http://192.168.10.43:3000/tree" 30 | help 31 | URL of REST Server. 32 | 33 | endmenu 34 | 35 | -------------------------------------------------------------------------------- /json-http-client3/main/component.mk: -------------------------------------------------------------------------------- 1 | COMPONENT_EMBED_FILES := ../html/error.html 2 | COMPONENT_EMBED_FILES += ../html/favicon.ico 3 | COMPONENT_EMBED_FILES += ../html/main.js 4 | COMPONENT_EMBED_FILES += ../html/root.html 5 | COMPONENT_EMBED_FILES += ../html/bulma.css 6 | COMPONENT_EMBED_FILES += ../html/main.css 7 | -------------------------------------------------------------------------------- /json-http-client3/main/http_get_notify.c: -------------------------------------------------------------------------------- 1 | /* The example of ESP-IDF 2 | * 3 | * This sample code is in the public domain. 4 | */ 5 | 6 | #include 7 | #include 8 | #include "freertos/FreeRTOS.h" 9 | #include "freertos/task.h" 10 | #include "esp_log.h" 11 | 12 | #include "esp_http_client.h" 13 | #include "esp_tls.h" 14 | #include "cJSON.h" 15 | 16 | extern MessageBufferHandle_t xMessageBufferToClient; 17 | 18 | static const char *TAG = "HTTP_GET"; 19 | 20 | esp_err_t _http_event_handler(esp_http_client_event_t *evt) 21 | { 22 | static int output_len; // Stores number of bytes read 23 | switch(evt->event_id) { 24 | case HTTP_EVENT_ERROR: 25 | ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); 26 | break; 27 | case HTTP_EVENT_ON_CONNECTED: 28 | ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); 29 | break; 30 | case HTTP_EVENT_HEADER_SENT: 31 | ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); 32 | break; 33 | case HTTP_EVENT_ON_HEADER: 34 | ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); 35 | break; 36 | case HTTP_EVENT_ON_DATA: 37 | ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); 38 | //ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, content_length=%d", esp_http_client_get_content_length(evt->client)); 39 | ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, output_len=%d", output_len); 40 | // If user_data buffer is configured, copy the response into the buffer 41 | if (evt->user_data) { 42 | memcpy(evt->user_data + output_len, evt->data, evt->data_len); 43 | } 44 | output_len += evt->data_len; 45 | break; 46 | case HTTP_EVENT_ON_FINISH: 47 | ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); 48 | output_len = 0; 49 | break; 50 | case HTTP_EVENT_DISCONNECTED: 51 | ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED"); 52 | int mbedtls_err = 0; 53 | esp_err_t err = esp_tls_get_and_clear_last_error(evt->data, &mbedtls_err, NULL); 54 | if (err != 0) { 55 | output_len = 0; 56 | ESP_LOGE(TAG, "Last esp error code: 0x%x", err); 57 | ESP_LOGE(TAG, "Last mbedtls failure: 0x%x", mbedtls_err); 58 | } 59 | break; 60 | #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) 61 | case HTTP_EVENT_REDIRECT: 62 | ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT"); 63 | break; 64 | #endif 65 | } 66 | return ESP_OK; 67 | } 68 | 69 | char *JSON_Types(int type) { 70 | if (type == cJSON_Invalid) return ("cJSON_Invalid"); 71 | if (type == cJSON_False) return ("cJSON_False"); 72 | if (type == cJSON_True) return ("cJSON_True"); 73 | if (type == cJSON_NULL) return ("cJSON_NULL"); 74 | if (type == cJSON_Number) return ("cJSON_Number"); 75 | if (type == cJSON_String) return ("cJSON_String"); 76 | if (type == cJSON_Array) return ("cJSON_Array"); 77 | if (type == cJSON_Object) return ("cJSON_Object"); 78 | if (type == cJSON_Raw) return ("cJSON_Raw"); 79 | return NULL; 80 | } 81 | 82 | void JSON_Parse(const cJSON * const root) { 83 | //ESP_LOGI(TAG, "root->type=%s", JSON_Types(root->type)); 84 | cJSON *current_element = NULL; 85 | //ESP_LOGI(TAG, "roo->child=%p", root->child); 86 | //ESP_LOGI(TAG, "roo->next =%p", root->next); 87 | cJSON_ArrayForEach(current_element, root) { 88 | //ESP_LOGI(TAG, "type=%s", JSON_Types(current_element->type)); 89 | //ESP_LOGI(TAG, "current_element->string=%p", current_element->string); 90 | if (current_element->string) { 91 | const char* string = current_element->string; 92 | ESP_LOGI(TAG, "[%s]", string); 93 | } 94 | if (cJSON_IsInvalid(current_element)) { 95 | ESP_LOGI(TAG, "Invalid"); 96 | } else if (cJSON_IsFalse(current_element)) { 97 | ESP_LOGI(TAG, "False"); 98 | } else if (cJSON_IsTrue(current_element)) { 99 | ESP_LOGI(TAG, "True"); 100 | } else if (cJSON_IsNull(current_element)) { 101 | ESP_LOGI(TAG, "Null"); 102 | } else if (cJSON_IsNumber(current_element)) { 103 | int valueint = current_element->valueint; 104 | double valuedouble = current_element->valuedouble; 105 | ESP_LOGI(TAG, "int=%d double=%f", valueint, valuedouble); 106 | } else if (cJSON_IsString(current_element)) { 107 | const char* valuestring = current_element->valuestring; 108 | ESP_LOGI(TAG, "%s", valuestring); 109 | } else if (cJSON_IsArray(current_element)) { 110 | //ESP_LOGI(TAG, "Array"); 111 | JSON_Parse(current_element); 112 | } else if (cJSON_IsObject(current_element)) { 113 | //ESP_LOGI(TAG, "Object"); 114 | JSON_Parse(current_element); 115 | } else if (cJSON_IsRaw(current_element)) { 116 | ESP_LOGI(TAG, "Raw(Not support)"); 117 | } 118 | } 119 | } 120 | 121 | size_t http_client_content_length(char * url, char * cert_pem) 122 | { 123 | ESP_LOGI(TAG, "http_client_content_length url=%s",url); 124 | size_t content_length; 125 | 126 | esp_http_client_config_t config = { 127 | .url = url, 128 | .event_handler = _http_event_handler, 129 | .user_data = NULL, 130 | //.user_data = local_response_buffer, // Pass address of local buffer to get response 131 | .cert_pem = cert_pem, 132 | }; 133 | esp_http_client_handle_t client = esp_http_client_init(&config); 134 | 135 | // GET 136 | esp_err_t err = esp_http_client_perform(client); 137 | if (err == ESP_OK) { 138 | ESP_LOGD(TAG, "HTTP GET Status = %d, content_length = %"PRId64, 139 | esp_http_client_get_status_code(client), 140 | esp_http_client_get_content_length(client)); 141 | content_length = esp_http_client_get_content_length(client); 142 | 143 | } else { 144 | ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err)); 145 | content_length = 0; 146 | } 147 | esp_http_client_cleanup(client); 148 | return content_length; 149 | } 150 | 151 | esp_err_t http_client_content_get(char * url, char * cert_pem, char * response_buffer) 152 | { 153 | ESP_LOGI(TAG, "http_client_content_get url=%s",url); 154 | 155 | esp_http_client_config_t config = { 156 | .url = url, 157 | .event_handler = _http_event_handler, 158 | .user_data = response_buffer, // Pass address of local buffer to get response 159 | .cert_pem = cert_pem, 160 | }; 161 | esp_http_client_handle_t client = esp_http_client_init(&config); 162 | 163 | // GET 164 | esp_err_t err = esp_http_client_perform(client); 165 | if (err == ESP_OK) { 166 | ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %"PRId64, 167 | esp_http_client_get_status_code(client), 168 | esp_http_client_get_content_length(client)); 169 | ESP_LOGD(TAG, "\n%s", response_buffer); 170 | } else { 171 | ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err)); 172 | } 173 | esp_http_client_cleanup(client); 174 | return err; 175 | } 176 | 177 | void http_get_task(void* pvParameters) 178 | { 179 | TaskHandle_t MyTaskHandle = xTaskGetCurrentTaskHandle(); 180 | ESP_LOGI(TAG, "START MyTaskHandle=%"PRIx32, (uint32_t)MyTaskHandle); 181 | while(1) { 182 | uint32_t value = ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); 183 | ESP_LOGI(TAG, "ulTaskNotifyTake value=0x%"PRIx32, value); 184 | 185 | // Get content length 186 | size_t content_length; 187 | for (int retry=0;retry<10;retry++) { 188 | content_length = http_client_content_length(CONFIG_ESP_REST_URL, NULL); 189 | ESP_LOGI(TAG, "content_length=%d", content_length); 190 | if (content_length > 0) break; 191 | vTaskDelay(100); 192 | } 193 | 194 | if (content_length == 0) { 195 | ESP_LOGE(TAG, "[%s] server does not respond", CONFIG_ESP_REST_URL); 196 | while(1) { 197 | vTaskDelay(100); 198 | } 199 | } 200 | 201 | char *response_buffer; // Buffer to store response of http request from event handler 202 | response_buffer = (char *) malloc(content_length+1); 203 | if (response_buffer == NULL) { 204 | ESP_LOGE(TAG, "Failed to allocate memory for output buffer"); 205 | while(1) { 206 | vTaskDelay(1); 207 | } 208 | } 209 | bzero(response_buffer, content_length+1); 210 | 211 | // Get content 212 | while(1) { 213 | esp_err_t err = http_client_content_get(CONFIG_ESP_REST_URL, NULL, response_buffer); 214 | if (err == ESP_OK) break; 215 | vTaskDelay(100); 216 | } 217 | ESP_LOGI(TAG, "content_length=%d", content_length); 218 | ESP_LOGI(TAG, "\n[%s]", response_buffer); 219 | 220 | #if 0 221 | ESP_LOGI(TAG, "Deserialize....."); 222 | cJSON *root = cJSON_Parse(response_buffer); 223 | JSON_Parse(root); 224 | cJSON_Delete(root); 225 | #endif 226 | 227 | cJSON *root = cJSON_CreateObject(); 228 | cJSON_AddStringToObject(root, "id", "json-request"); 229 | cJSON_AddStringToObject(root, "json", response_buffer); 230 | char *my_json_string = cJSON_Print(root); 231 | ESP_LOGI(TAG, "my_json_string=%d bytes", strlen(my_json_string)); 232 | ESP_LOGD(TAG, "\n[%s]",my_json_string); 233 | size_t xBytesSent = xMessageBufferSend(xMessageBufferToClient, my_json_string, strlen(my_json_string), portMAX_DELAY); 234 | if (xBytesSent != strlen(my_json_string)) { 235 | ESP_LOGE(TAG, "xMessageBufferSend fail"); 236 | } 237 | cJSON_free(my_json_string); 238 | free(response_buffer); 239 | } 240 | 241 | vTaskDelete(NULL); 242 | } 243 | -------------------------------------------------------------------------------- /json-http-client3/main/idf_component.yml: -------------------------------------------------------------------------------- 1 | ## IDF Component Manager Manifest File 2 | dependencies: 3 | Molorius/esp32-websocket: 4 | git: https://github.com/Molorius/esp32-websocket 5 | espressif/mdns: 6 | version: "^1.0.3" 7 | rules: 8 | - if: "idf_version >=5.0" 9 | -------------------------------------------------------------------------------- /json-http-client3/main/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | Example using WEB Socket. 3 | This example code is in the Public Domain (or CC0 licensed, at your option.) 4 | Unless required by applicable law or agreed to in writing, this 5 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 6 | CONDITIONS OF ANY KIND, either express or implied. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "freertos/FreeRTOS.h" 13 | #include "freertos/task.h" 14 | #include "freertos/queue.h" 15 | #include "freertos/event_groups.h" 16 | #include "freertos/message_buffer.h" 17 | 18 | #include "esp_wifi.h" 19 | #include "esp_log.h" 20 | #include "nvs_flash.h" 21 | #include "mdns.h" 22 | 23 | #include "websocket_server.h" 24 | 25 | MessageBufferHandle_t xMessageBufferToClient; 26 | 27 | /* FreeRTOS event group to signal when we are connected*/ 28 | static EventGroupHandle_t s_wifi_event_group; 29 | 30 | /* The event group allows multiple bits for each event, but we only care about two events: 31 | * - we are connected to the AP with an IP 32 | * - we failed to connect after the maximum amount of retries */ 33 | #define WIFI_CONNECTED_BIT BIT0 34 | #define WIFI_FAIL_BIT BIT1 35 | 36 | static const char *TAG = "main"; 37 | 38 | static int s_retry_num = 0; 39 | 40 | static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) 41 | { 42 | if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { 43 | esp_wifi_connect(); 44 | } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { 45 | if (s_retry_num < CONFIG_ESP_MAXIMUM_RETRY) { 46 | esp_wifi_connect(); 47 | s_retry_num++; 48 | ESP_LOGI(TAG, "retry to connect to the AP"); 49 | } else { 50 | xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); 51 | } 52 | ESP_LOGI(TAG,"connect to the AP fail"); 53 | } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { 54 | ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; 55 | ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); 56 | s_retry_num = 0; 57 | xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); 58 | } 59 | } 60 | 61 | void wifi_init_sta(void) 62 | { 63 | s_wifi_event_group = xEventGroupCreate(); 64 | 65 | ESP_ERROR_CHECK(esp_netif_init()); 66 | 67 | ESP_ERROR_CHECK(esp_event_loop_create_default()); 68 | esp_netif_create_default_wifi_sta(); 69 | 70 | wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); 71 | ESP_ERROR_CHECK(esp_wifi_init(&cfg)); 72 | 73 | esp_event_handler_instance_t instance_any_id; 74 | esp_event_handler_instance_t instance_got_ip; 75 | ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, 76 | ESP_EVENT_ANY_ID, 77 | &event_handler, 78 | NULL, 79 | &instance_any_id)); 80 | ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, 81 | IP_EVENT_STA_GOT_IP, 82 | &event_handler, 83 | NULL, 84 | &instance_got_ip)); 85 | 86 | wifi_config_t wifi_config = { 87 | .sta = { 88 | .ssid = CONFIG_ESP_WIFI_SSID, 89 | .password = CONFIG_ESP_WIFI_PASSWORD, 90 | /* Setting a password implies station will connect to all security modes including WEP/WPA. 91 | * However these modes are deprecated and not advisable to be used. Incase your Access point 92 | * doesn't support WPA2, these mode can be enabled by commenting below line */ 93 | .threshold.authmode = WIFI_AUTH_WPA2_PSK, 94 | 95 | .pmf_cfg = { 96 | .capable = true, 97 | .required = false 98 | }, 99 | }, 100 | }; 101 | ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); 102 | ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); 103 | ESP_ERROR_CHECK(esp_wifi_start() ); 104 | 105 | ESP_LOGI(TAG, "wifi_init_sta finished."); 106 | 107 | /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum 108 | * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */ 109 | EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, 110 | WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, 111 | pdFALSE, 112 | pdFALSE, 113 | portMAX_DELAY); 114 | 115 | /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually 116 | * happened. */ 117 | if (bits & WIFI_CONNECTED_BIT) { 118 | ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD); 119 | } else if (bits & WIFI_FAIL_BIT) { 120 | ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD); 121 | } else { 122 | ESP_LOGE(TAG, "UNEXPECTED EVENT"); 123 | } 124 | 125 | /* The event will not be processed after unregister */ 126 | ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip)); 127 | ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id)); 128 | vEventGroupDelete(s_wifi_event_group); 129 | } 130 | 131 | void initialise_mdns(void) 132 | { 133 | //initialize mDNS 134 | ESP_ERROR_CHECK( mdns_init() ); 135 | //set mDNS hostname (required if you want to advertise services) 136 | ESP_ERROR_CHECK( mdns_hostname_set(CONFIG_MDNS_HOSTNAME) ); 137 | ESP_LOGI(TAG, "mdns hostname set to: [%s]", CONFIG_MDNS_HOSTNAME); 138 | 139 | //initialize service 140 | ESP_ERROR_CHECK( mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0) ); 141 | 142 | #if 0 143 | //set default mDNS instance name 144 | ESP_ERROR_CHECK( mdns_instance_name_set("ESP32 with mDNS") ); 145 | #endif 146 | } 147 | 148 | void http_get_task(void* pvParameters); 149 | void client_task(void* pvParameters); 150 | void server_task(void* pvParameters); 151 | 152 | void app_main() { 153 | // Initialize NVS 154 | esp_err_t ret = nvs_flash_init(); 155 | if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { 156 | ESP_ERROR_CHECK(nvs_flash_erase()); 157 | ret = nvs_flash_init(); 158 | } 159 | ESP_ERROR_CHECK(ret); 160 | 161 | // Initialize WiFi 162 | wifi_init_sta(); 163 | 164 | // Initialize mDNS 165 | initialise_mdns(); 166 | 167 | // Create Message Buffer 168 | xMessageBufferToClient = xMessageBufferCreate(1024); 169 | configASSERT( xMessageBufferToClient ); 170 | 171 | // Get the local IP address 172 | esp_netif_ip_info_t ip_info; 173 | ESP_ERROR_CHECK(esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &ip_info)); 174 | char cparam0[64]; 175 | sprintf(cparam0, IPSTR, IP2STR(&ip_info.ip)); 176 | 177 | // Start http client 178 | TaskHandle_t pxCreatedTask; 179 | xTaskCreate(&http_get_task, "http_client", 1024*4, NULL, 5, &pxCreatedTask); 180 | ESP_LOGI(TAG, "pxCreatedTask1=%"PRIx32, (uint32_t)pxCreatedTask); 181 | 182 | // Start web socket server 183 | ws_server_start(); 184 | 185 | // Start web server 186 | xTaskCreate(&server_task, "server_task", 1024*4, (void *)cparam0, 5, NULL); 187 | 188 | // Start web client 189 | xTaskCreate(&client_task, "client_task", 1024*6, (void *)pxCreatedTask, 5, NULL); 190 | 191 | while(1) { 192 | vTaskDelay(100); 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /json-http-client3/main/web_client.c: -------------------------------------------------------------------------------- 1 | /* 2 | Example using WEB Socket. 3 | This example code is in the Public Domain (or CC0 licensed, at your option.) 4 | Unless required by applicable law or agreed to in writing, this 5 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 6 | CONDITIONS OF ANY KIND, either express or implied. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "freertos/FreeRTOS.h" 13 | #include "freertos/task.h" 14 | #include "freertos/queue.h" 15 | #include "freertos/event_groups.h" 16 | #include "freertos/message_buffer.h" 17 | #include "esp_log.h" 18 | #include "cJSON.h" 19 | 20 | static const char *TAG = "web_client"; 21 | 22 | #include "websocket_server.h" 23 | 24 | extern MessageBufferHandle_t xMessageBufferToClient; 25 | 26 | // Timer callback 27 | static void timer_cb(TimerHandle_t xTimer) 28 | { 29 | TickType_t nowTick; 30 | nowTick = xTaskGetTickCount(); 31 | ESP_LOGD(TAG, "timer is called, now=%"PRIu32, nowTick); 32 | 33 | cJSON *request; 34 | request = cJSON_CreateObject(); 35 | cJSON_AddStringToObject(request, "id", "timer-request"); 36 | //char *my_json_string = cJSON_Print(request); 37 | char *my_json_string = cJSON_PrintUnformatted(request); 38 | ESP_LOGD(TAG, "my_json_string\n%s",my_json_string); 39 | size_t xBytesSent = xMessageBufferSendFromISR(xMessageBufferToClient, my_json_string, strlen(my_json_string), NULL); 40 | if (xBytesSent != strlen(my_json_string)) { 41 | ESP_LOGE(TAG, "xMessageBufferSend fail"); 42 | } 43 | cJSON_Delete(request); 44 | cJSON_free(my_json_string); 45 | } 46 | 47 | void client_task(void* pvParameters) { 48 | TaskHandle_t NotifyTaskHandle = (TaskHandle_t)pvParameters; 49 | ESP_LOGI(TAG, "Start NotifyTaskHandle=%"PRIx32, (uint32_t)NotifyTaskHandle); 50 | 51 | // Create Timer (Trigger a measurement every second) 52 | TimerHandle_t timerHandle = xTimerCreate("MY Trigger", 500, pdTRUE, NULL, timer_cb); 53 | if (timerHandle != NULL) { 54 | if (xTimerStart(timerHandle, 0) != pdPASS) { 55 | ESP_LOGE(TAG, "Unable to start Timer"); 56 | vTaskDelete(NULL); 57 | } else { 58 | ESP_LOGI(TAG, "Success to start Timer"); 59 | } 60 | } else { 61 | ESP_LOGE(TAG, "Unable to create Timer"); 62 | vTaskDelete(NULL); 63 | } 64 | 65 | char inBuffer[1024]; 66 | char DEL = 0x04; 67 | char outBuffer[1024]; 68 | 69 | while (1) { 70 | size_t readBytes = xMessageBufferReceive(xMessageBufferToClient, inBuffer, sizeof(inBuffer), portMAX_DELAY ); 71 | ESP_LOGI(TAG, "readBytes=%d", readBytes); 72 | ESP_LOGI(TAG, "inBuffer=[%.*s]", readBytes, inBuffer); 73 | cJSON *root = cJSON_Parse(inBuffer); 74 | if (cJSON_GetObjectItem(root, "id")) { 75 | char *id = cJSON_GetObjectItem(root,"id")->valuestring; 76 | ESP_LOGI(TAG, "id=[%s]",id); 77 | 78 | if ( strcmp (id, "init") == 0) { 79 | #if 0 80 | sprintf(outBuffer,"HEADER%cJSON Tree View", DEL); 81 | ESP_LOGD(TAG, "outBuffer=[%s]", outBuffer); 82 | ws_server_send_text_all(outBuffer,strlen(outBuffer)); 83 | #endif 84 | 85 | // Notify http client task 86 | // The http client task reads data from the server 87 | // The http client task return the response as a json-request 88 | xTaskNotifyGive( NotifyTaskHandle ); 89 | } // end init 90 | 91 | if ( strcmp (id, "json-request") == 0) { 92 | char *json = cJSON_GetObjectItem(root,"json")->valuestring; 93 | ESP_LOGI(TAG, "json=[%s]",json); 94 | sprintf(outBuffer,"TREE%c%s",DEL, json); 95 | ESP_LOGD(TAG, "outBuffer=[%s]", outBuffer); 96 | ws_server_send_text_all(outBuffer,strlen(outBuffer)); 97 | } // end json-request 98 | 99 | if ( strcmp (id, "timer-request") == 0) { 100 | TickType_t nowTick = xTaskGetTickCount(); 101 | char wk[64]; 102 | cJSON *root2 = cJSON_CreateObject(); 103 | sprintf(wk, "%"PRIi32, nowTick); 104 | cJSON_AddStringToObject(root2, "elasped", wk); 105 | sprintf(wk, "%"PRIu32, esp_get_free_heap_size()); 106 | cJSON_AddStringToObject(root2, "freeHeep", wk); 107 | //char *json = cJSON_Print(root2); 108 | char *json = cJSON_PrintUnformatted(root2); 109 | ESP_LOGI(TAG, "json=[%s]",json); 110 | sprintf(outBuffer,"ELASPED%c%s",DEL, json); 111 | ESP_LOGD(TAG, "outBuffer=[%s]", outBuffer); 112 | ws_server_send_text_all(outBuffer,strlen(outBuffer)); 113 | cJSON_Delete(root2); 114 | cJSON_free(json); 115 | } // end timer-request 116 | 117 | } // end if 118 | 119 | // Delete a cJSON structure 120 | cJSON_Delete(root); 121 | 122 | } // end while 123 | 124 | // Never reach here 125 | vTaskDelete(NULL); 126 | } 127 | -------------------------------------------------------------------------------- /json-http-client4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following five lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | -------------------------------------------------------------------------------- /json-http-client4/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | Demonstration of displaying a JSON message in table format. 3 | An array JSON message is well suited for table representation. 4 | This project gets JSON data from Fake REST Server. 5 | ![Image](https://github.com/user-attachments/assets/7d1a49f3-8643-4420-85a6-1fcbf39119db) 6 | 7 | # Install json-server (Fake REST Server) stable version on your host 8 | ``` 9 | sudo apt install npm 10 | sudo npm install -g json-server@0.17.4 11 | 12 | ``` 13 | 14 | # Start json-server (Fake REST Server) 15 | If the host parameter is not specified, it can only be accessed from local host. 16 | When accessing from ESP32, host parameter is required. 17 | ``` 18 | cd esp-idf-json/json-http-client4 19 | json-server --watch --host {My_IP_Address} ./db.json 20 | ``` 21 | ![Image](https://github.com/user-attachments/assets/583585a4-d810-4a51-9602-f08af65d9399) 22 | 23 | 24 | # Installation 25 | ``` 26 | git clone https://github.com/nopnop2002/esp-idf-json 27 | cd esp-idf-json/json-http-client4 28 | idf.py menuconfig 29 | idf.py flash monitor 30 | ``` 31 | 32 | # Configuration 33 | ![Image](https://github.com/user-attachments/assets/d2c27b89-e715-4750-913c-2161ae0a4531) 34 | 35 | The IP address in the URL of REST Server is the IP address of the host where you installed json-server. 36 | The IP address of the REST server needs to be changed according to your environment. 37 | ![Image](https://github.com/user-attachments/assets/5490ff79-4517-491f-8ffe-513c9017b703) 38 | 39 | # How to use 40 | Open a browser and enter the IP address of the esp32 in the browser's address bar. 41 | The ESP32 retrieves data from the Fake REST Server and displays it in table format. 42 | ![Image](https://github.com/user-attachments/assets/7d1a49f3-8643-4420-85a6-1fcbf39119db) 43 | 44 | Instead of IP addresses, you can use mDNS hostnames. 45 | ![Image](https://github.com/user-attachments/assets/c6033956-9cd8-4054-83ce-861aa3542779) 46 | 47 | # Modify JSON data 48 | Modify the db.json file. 49 | The changes will be reflected immediately. 50 | There is no need to restart json-server (Fake REST Server). 51 | ``` 52 | $ cat db.json 53 | { 54 | "array": [ 55 | ["id","type","name","batter"], 56 | ["0001","donut","Cake","Regulard"], 57 | ["0001","donut","Cake","Chocolate"], 58 | ["0001","donut","Cake","Blueberry"], 59 | ["0001","donut","Cake","Devil's Food"], 60 | ["0002","donut","Raised","Regular"], 61 | ["0003","donut","Old Fashioned","Regular"], 62 | ["0003","donut","Old Fashioned","Chocolate"], 63 | ["0004","bar","Bar","Regular"], 64 | ["0005","twist","Twist","Regular"], 65 | ["0006","filled","Filled","Regular"] 66 | ] 67 | 68 | } 69 | ``` 70 | -------------------------------------------------------------------------------- /json-http-client4/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "array": [ 3 | ["id","type","name","batter"], 4 | ["0001","donut","Cake","Regulard"], 5 | ["0001","donut","Cake","Chocolate"], 6 | ["0001","donut","Cake","Blueberry"], 7 | ["0001","donut","Cake","Devil's Food"], 8 | ["0002","donut","Raised","Regular"], 9 | ["0003","donut","Old Fashioned","Regular"], 10 | ["0003","donut","Old Fashioned","Chocolate"], 11 | ["0004","bar","Bar","Regular"], 12 | ["0005","twist","Twist","Regular"], 13 | ["0006","filled","Filled","Regular"] 14 | ] 15 | 16 | } 17 | -------------------------------------------------------------------------------- /json-http-client4/html/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ESP32 Error 404 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Error 404

12 |

Unknown page. Return home.

13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /json-http-client4/html/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nopnop2002/esp-idf-json/840bfc69e73516f0b43c52584d394f6b03ff5eb8/json-http-client4/html/favicon.ico -------------------------------------------------------------------------------- /json-http-client4/html/jsonTreeViewer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JSON Tree Viewer 3 | * http://github.com/summerstyle/jsonTreeViewer 4 | * 5 | * Copyright 2017 Vera Lobacheva (http://iamvera.com) 6 | * Released under the MIT license (LICENSE.txt) 7 | */ 8 | 9 | 'use strict'; 10 | 11 | var jsonTreeViewer = (function() { 12 | 13 | /* Utilities */ 14 | var utils = App.utils; 15 | 16 | var treeWrapper = document.getElementById("tree"); 17 | var tree = jsonTree.create({}, treeWrapper); 18 | 19 | // Menu 20 | var menu = new App.Menu(utils.dom.id('nav'), { 21 | 'load' : function() { 22 | load_json_form.show(); 23 | }, 24 | 'expand' : function() { 25 | tree.expand(); 26 | }, 27 | 'collapse' : function() { 28 | tree.collapse(); 29 | }, 30 | 'source' : function() { 31 | source_json_window.print( 32 | tree.toSourceJSON('isPrettyPrinted') 33 | ); 34 | }, 35 | 'find_and_mark' : function() { 36 | find_nodes_form.show(); 37 | }, 38 | 'unmark_all' : function() { 39 | tree.unmarkAll(); 40 | }, 41 | 'help' : function() { 42 | help.show(); 43 | } 44 | }); 45 | 46 | 47 | /* Load json form */ 48 | var load_json_form = new App.Window({ 49 | content_el : utils.dom.id('load_json_form'), 50 | overlay : true, 51 | js_module : function(self) { 52 | var form = self.content_el, 53 | code_input = document.getElementById('code_input'), 54 | load_button = document.getElementById('load_code_button'); 55 | 56 | function load(e) { 57 | jsonTreeViewer.parse(code_input.value); 58 | self.hide(); 59 | code_input.value = ''; 60 | 61 | e.preventDefault(); 62 | } 63 | 64 | load_button.addEventListener('click', load, false); 65 | } 66 | }); 67 | 68 | 69 | /* Help block */ 70 | var help = new App.Window({ 71 | content_el : document.getElementById('help'), 72 | overlay : true 73 | }); 74 | 75 | /* Block for source JSON */ 76 | var source_json_window = new App.Window({ 77 | content_el : utils.dom.id('source_json'), 78 | overlay : true, 79 | js_module : function(self) { 80 | return { 81 | print: function(str) { 82 | self.content_el.innerHTML = str; 83 | self.show(); 84 | } 85 | }; 86 | } 87 | }); 88 | 89 | /* Find nodes form */ 90 | var find_nodes_form = new App.Window({ 91 | content_el : utils.dom.id('find_nodes_form'), 92 | overlay : true, 93 | js_module : function(self) { 94 | var form = self.content_el, 95 | search_type_radio = { 96 | label_name : document.getElementById('nodes_search_by_label'), 97 | node_type : document.getElementById('nodes_search_by_type') 98 | }, 99 | label_name_input = document.getElementById('search_by_label_name'), 100 | node_types_checkboxes = document.getElementsByName('nodes_type'), 101 | find_button = document.getElementById('find_button'), 102 | MATCHERS = { 103 | BY_LABEL_NAME : function(labelName, node) { 104 | return node.label === labelName; 105 | }, 106 | BY_NODE_TYPE : function(nodeTypesArray, node) { 107 | return nodeTypesArray.indexOf(node.type) >= 0; 108 | } 109 | }; 110 | 111 | function find(e) { 112 | var matcher; 113 | 114 | e.preventDefault(); 115 | 116 | if (search_type_radio.label_name.checked) { 117 | var label_name_value = label_name_input.value.trim(); 118 | 119 | if (!label_name_value) { 120 | return; 121 | } 122 | matcher = MATCHERS.BY_LABEL_NAME.bind(null, label_name_value); 123 | } else if (search_type_radio.node_type.checked) { 124 | var node_type_values = []; 125 | 126 | for (var i = 0, c = node_types_checkboxes.length; i < c; i++) { 127 | if (node_types_checkboxes[i].checked) { 128 | node_type_values.push(node_types_checkboxes[i].value); 129 | } 130 | } 131 | 132 | if (!node_type_values.length) { 133 | return; 134 | } 135 | 136 | matcher = MATCHERS.BY_NODE_TYPE.bind(null, node_type_values); 137 | } 138 | 139 | if (!matcher) { 140 | return; 141 | } 142 | 143 | tree.findAndHandle(matcher, function(node) { 144 | node.mark(); 145 | node.expandParent('isRecursive'); 146 | }); 147 | 148 | self.hide(); 149 | } 150 | 151 | find_button.addEventListener('click', find, false); 152 | } 153 | }); 154 | 155 | load_json_form.show(); 156 | 157 | return { 158 | parse : function(json_str) { 159 | var temp; 160 | 161 | try { 162 | temp = JSON.parse(json_str); 163 | } catch(e) { 164 | alert(e); 165 | } 166 | 167 | tree.loadData(temp); 168 | } 169 | }; 170 | })(); 171 | -------------------------------------------------------------------------------- /json-http-client4/html/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | Your favorite style is defined here. 3 | */ 4 | th,td { 5 | border: solid 1px; /* Frame line specification */ 6 | } 7 | 8 | table { 9 | border-collapse: collapse; /* Overlap cell lines */ 10 | } 11 | 12 | th { 13 | background-color: #00e2cf; /* Background color */ 14 | } 15 | 16 | td { 17 | background-color: #bde9ba; /* Background color */ 18 | } 19 | -------------------------------------------------------------------------------- /json-http-client4/html/main.js: -------------------------------------------------------------------------------- 1 | //document.getElementById("datetime").innerHTML = "WebSocket is not connected"; 2 | 3 | var websocket = new WebSocket('ws://'+location.hostname+'/'); 4 | 5 | // https://gist.github.com/pistatium/5963229 6 | var tableBuilder = function(header, data) { 7 | var html = ''; 8 | //console.log('header=', header); 9 | for (var key in header) { 10 | //console.log('key=', key); 11 | html += ''; 12 | } 13 | html += ''; 14 | for (var i in data) { 15 | //console.log('i=', i); 16 | var d = data[i]; 17 | html += ''; 18 | for (var key in header) { 19 | //console.log('key=', key); 20 | //console.log('d[key]=', d[key]); 21 | if(d[key]) { 22 | html += ''; 23 | } else { 24 | // 対応するキーがない場合 25 | html += ''; 26 | } 27 | } 28 | html += ''; 29 | } 30 | html += '
' + header[key] + '
' + d[key] + '--
'; 31 | return html; 32 | } 33 | 34 | function sendText(name) { 35 | console.log('sendText'); 36 | var data = {}; 37 | data["id"] = name; 38 | console.log('data=', data); 39 | json_data = JSON.stringify(data); 40 | console.log('json_data=' + json_data); 41 | websocket.send(json_data); 42 | } 43 | 44 | websocket.onopen = function(evt) { 45 | console.log('WebSocket connection opened'); 46 | var data = {}; 47 | data["id"] = "init"; 48 | console.log('data=', data); 49 | json_data = JSON.stringify(data); 50 | console.log('json_data=' + json_data); 51 | websocket.send(json_data); 52 | //document.getElementById("datetime").innerHTML = "WebSocket is connected!"; 53 | } 54 | 55 | websocket.onmessage = function(evt) { 56 | var msg = evt.data; 57 | console.log("msg=" + msg); 58 | var values = msg.split('\4'); // \4 is EOT 59 | //console.log("values=" + values); 60 | switch(values[0]) { 61 | case 'HEADER': 62 | console.log("HEAD values[1]=" + values[1]); 63 | var h1 = document.getElementById( 'header' ); 64 | h1.textContent = values[1]; 65 | break; 66 | 67 | case 'TABLE1': 68 | console.log("TABLE1 values[1]=" + values[1]); 69 | console.log("TABLE1 values[2]=" + values[2]); 70 | // Convert string to JSON 71 | var table_header = JSON.parse(values[1]); 72 | var table_data = JSON.parse(values[2]); 73 | 74 | // Test data 75 | // Define table header 76 | var table_header_test = { 77 | 'id' : '#', 78 | 'title' : 'タイトル', 79 | 'updated_at' : '更新日', 80 | }; 81 | 82 | // Data to display in table 83 | var table_data_test = [ 84 | {'id':1, 'created_at':'2013/05/01', 'updated_at':'2013/07/01','title':'記事1'}, 85 | {'id':2, 'created_at':'2013/06/01', 'updated_at':'2013/07/02','title':'記事2'}, 86 | {'id':3, 'created_at':'2013/07/01','title':'記事3'}, 87 | ]; 88 | 89 | //var html = tableBuilder(table_header_test, table_data_test); 90 | var html = tableBuilder(table_header, table_data); 91 | console.log("TABLE1 html=" + html); 92 | var table1 = document.getElementById("table1"); 93 | table1.innerHTML = html; 94 | break; 95 | 96 | case 'TABLE2': 97 | console.log("TABLE2 values[1]=" + values[1]); 98 | console.log("TABLE2 values[2]=" + values[2]); 99 | // Convert string to JSON 100 | var table_header = JSON.parse(values[1]); 101 | var table_data = JSON.parse(values[2]); 102 | 103 | var html = tableBuilder(table_header, table_data); 104 | console.log("TABLE2 html=" + html); 105 | var table2 = document.getElementById("table2"); 106 | table2.innerHTML = html; 107 | break; 108 | 109 | default: 110 | break; 111 | } 112 | } 113 | 114 | websocket.onclose = function(evt) { 115 | console.log('Websocket connection closed'); 116 | //document.getElementById("datetime").innerHTML = "WebSocket closed"; 117 | } 118 | 119 | websocket.onerror = function(evt) { 120 | console.log('Websocket error: ' + evt); 121 | //document.getElementById("datetime").innerHTML = "WebSocket error????!!!1!!"; 122 | } 123 | -------------------------------------------------------------------------------- /json-http-client4/html/root.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Json Table View 7 | 8 | 9 | 10 | 11 |

12 | 13 |
14 | 15 |
16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /json-http-client4/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "main.c" "web_server.c" "web_client.c" "http_get_notify.c" 2 | INCLUDE_DIRS "." 3 | EMBED_FILES "../html/error.html" 4 | "../html/favicon.ico" 5 | "../html/main.js" 6 | "../html/root.html" 7 | "../html/main.css") 8 | -------------------------------------------------------------------------------- /json-http-client4/main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "Application configuration" 2 | 3 | config ESP_WIFI_SSID 4 | string "WiFi SSID" 5 | default "myssid" 6 | help 7 | SSID (network name) to connect to. 8 | 9 | config ESP_WIFI_PASSWORD 10 | string "WiFi Password" 11 | default "mypassword" 12 | help 13 | WiFi password (WPA or WPA2) to connect to. 14 | 15 | config ESP_MAXIMUM_RETRY 16 | int "Maximum retry" 17 | default 5 18 | help 19 | Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent. 20 | 21 | config MDNS_HOSTNAME 22 | string "mDNS Hostname" 23 | default "esp32-server" 24 | help 25 | The mDNS host name used by the ESP32. 26 | 27 | config ESP_REST_URL 28 | string "URL of REST Server" 29 | default "http://192.168.10.43:3000/array" 30 | help 31 | URL of REST Server. 32 | 33 | endmenu 34 | 35 | -------------------------------------------------------------------------------- /json-http-client4/main/component.mk: -------------------------------------------------------------------------------- 1 | COMPONENT_EMBED_FILES := ../html/error.html 2 | COMPONENT_EMBED_FILES += ../html/favicon.ico 3 | COMPONENT_EMBED_FILES += ../html/main.js 4 | COMPONENT_EMBED_FILES += ../html/root.html 5 | COMPONENT_EMBED_FILES += ../html/bulma.css 6 | COMPONENT_EMBED_FILES += ../html/main.css 7 | -------------------------------------------------------------------------------- /json-http-client4/main/http_get_notify.c: -------------------------------------------------------------------------------- 1 | /* The example of ESP-IDF 2 | * 3 | * This sample code is in the public domain. 4 | */ 5 | 6 | #include 7 | #include 8 | #include "freertos/FreeRTOS.h" 9 | #include "freertos/task.h" 10 | #include "esp_log.h" 11 | 12 | #include "esp_http_client.h" 13 | #include "esp_tls.h" 14 | #include "cJSON.h" 15 | 16 | extern MessageBufferHandle_t xMessageBufferToClient; 17 | 18 | static const char *TAG = "HTTP_GET"; 19 | 20 | esp_err_t _http_event_handler(esp_http_client_event_t *evt) 21 | { 22 | static int output_len; // Stores number of bytes read 23 | switch(evt->event_id) { 24 | case HTTP_EVENT_ERROR: 25 | ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); 26 | break; 27 | case HTTP_EVENT_ON_CONNECTED: 28 | ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); 29 | break; 30 | case HTTP_EVENT_HEADER_SENT: 31 | ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); 32 | break; 33 | case HTTP_EVENT_ON_HEADER: 34 | ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); 35 | break; 36 | case HTTP_EVENT_ON_DATA: 37 | ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); 38 | //ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, content_length=%d", esp_http_client_get_content_length(evt->client)); 39 | ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, output_len=%d", output_len); 40 | // If user_data buffer is configured, copy the response into the buffer 41 | if (evt->user_data) { 42 | memcpy(evt->user_data + output_len, evt->data, evt->data_len); 43 | } 44 | output_len += evt->data_len; 45 | break; 46 | case HTTP_EVENT_ON_FINISH: 47 | ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); 48 | output_len = 0; 49 | break; 50 | case HTTP_EVENT_DISCONNECTED: 51 | ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED"); 52 | int mbedtls_err = 0; 53 | esp_err_t err = esp_tls_get_and_clear_last_error(evt->data, &mbedtls_err, NULL); 54 | if (err != 0) { 55 | output_len = 0; 56 | ESP_LOGE(TAG, "Last esp error code: 0x%x", err); 57 | ESP_LOGE(TAG, "Last mbedtls failure: 0x%x", mbedtls_err); 58 | } 59 | break; 60 | #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) 61 | case HTTP_EVENT_REDIRECT: 62 | ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT"); 63 | break; 64 | #endif 65 | } 66 | return ESP_OK; 67 | } 68 | 69 | char *JSON_Types(int type) { 70 | if (type == cJSON_Invalid) return ("cJSON_Invalid"); 71 | if (type == cJSON_False) return ("cJSON_False"); 72 | if (type == cJSON_True) return ("cJSON_True"); 73 | if (type == cJSON_NULL) return ("cJSON_NULL"); 74 | if (type == cJSON_Number) return ("cJSON_Number"); 75 | if (type == cJSON_String) return ("cJSON_String"); 76 | if (type == cJSON_Array) return ("cJSON_Array"); 77 | if (type == cJSON_Object) return ("cJSON_Object"); 78 | if (type == cJSON_Raw) return ("cJSON_Raw"); 79 | return NULL; 80 | } 81 | 82 | void JSON_Parse(const cJSON * const root) { 83 | //ESP_LOGI(TAG, "root->type=%s", JSON_Types(root->type)); 84 | cJSON *current_element = NULL; 85 | //ESP_LOGI(TAG, "roo->child=%p", root->child); 86 | //ESP_LOGI(TAG, "roo->next =%p", root->next); 87 | cJSON_ArrayForEach(current_element, root) { 88 | //ESP_LOGI(TAG, "type=%s", JSON_Types(current_element->type)); 89 | //ESP_LOGI(TAG, "current_element->string=%p", current_element->string); 90 | if (current_element->string) { 91 | const char* string = current_element->string; 92 | ESP_LOGI(TAG, "[%s]", string); 93 | } 94 | if (cJSON_IsInvalid(current_element)) { 95 | ESP_LOGI(TAG, "Invalid"); 96 | } else if (cJSON_IsFalse(current_element)) { 97 | ESP_LOGI(TAG, "False"); 98 | } else if (cJSON_IsTrue(current_element)) { 99 | ESP_LOGI(TAG, "True"); 100 | } else if (cJSON_IsNull(current_element)) { 101 | ESP_LOGI(TAG, "Null"); 102 | } else if (cJSON_IsNumber(current_element)) { 103 | int valueint = current_element->valueint; 104 | double valuedouble = current_element->valuedouble; 105 | ESP_LOGI(TAG, "int=%d double=%f", valueint, valuedouble); 106 | } else if (cJSON_IsString(current_element)) { 107 | const char* valuestring = current_element->valuestring; 108 | ESP_LOGI(TAG, "%s", valuestring); 109 | } else if (cJSON_IsArray(current_element)) { 110 | //ESP_LOGI(TAG, "Array"); 111 | JSON_Parse(current_element); 112 | } else if (cJSON_IsObject(current_element)) { 113 | //ESP_LOGI(TAG, "Object"); 114 | JSON_Parse(current_element); 115 | } else if (cJSON_IsRaw(current_element)) { 116 | ESP_LOGI(TAG, "Raw(Not support)"); 117 | } 118 | } 119 | } 120 | 121 | size_t http_client_content_length(char * url, char * cert_pem) 122 | { 123 | ESP_LOGI(TAG, "http_client_content_length url=%s",url); 124 | size_t content_length; 125 | 126 | esp_http_client_config_t config = { 127 | .url = url, 128 | .event_handler = _http_event_handler, 129 | .user_data = NULL, 130 | //.user_data = local_response_buffer, // Pass address of local buffer to get response 131 | .cert_pem = cert_pem, 132 | }; 133 | esp_http_client_handle_t client = esp_http_client_init(&config); 134 | 135 | // GET 136 | esp_err_t err = esp_http_client_perform(client); 137 | if (err == ESP_OK) { 138 | ESP_LOGD(TAG, "HTTP GET Status = %d, content_length = %"PRId64, 139 | esp_http_client_get_status_code(client), 140 | esp_http_client_get_content_length(client)); 141 | content_length = esp_http_client_get_content_length(client); 142 | 143 | } else { 144 | ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err)); 145 | content_length = 0; 146 | } 147 | esp_http_client_cleanup(client); 148 | return content_length; 149 | } 150 | 151 | esp_err_t http_client_content_get(char * url, char * cert_pem, char * response_buffer) 152 | { 153 | ESP_LOGI(TAG, "http_client_content_get url=%s",url); 154 | 155 | esp_http_client_config_t config = { 156 | .url = url, 157 | .event_handler = _http_event_handler, 158 | .user_data = response_buffer, // Pass address of local buffer to get response 159 | .cert_pem = cert_pem, 160 | }; 161 | esp_http_client_handle_t client = esp_http_client_init(&config); 162 | 163 | // GET 164 | esp_err_t err = esp_http_client_perform(client); 165 | if (err == ESP_OK) { 166 | ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %"PRId64, 167 | esp_http_client_get_status_code(client), 168 | esp_http_client_get_content_length(client)); 169 | ESP_LOGD(TAG, "\n%s", response_buffer); 170 | } else { 171 | ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err)); 172 | } 173 | esp_http_client_cleanup(client); 174 | return err; 175 | } 176 | 177 | void http_get_task(void* pvParameters) 178 | { 179 | TaskHandle_t MyTaskHandle = xTaskGetCurrentTaskHandle(); 180 | ESP_LOGI(TAG, "START MyTaskHandle=%"PRIx32, (uint32_t)MyTaskHandle); 181 | while(1) { 182 | uint32_t value = ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); 183 | ESP_LOGI(TAG, "ulTaskNotifyTake value=0x%"PRIx32, value); 184 | 185 | // Get content length 186 | size_t content_length; 187 | for (int retry=0;retry<10;retry++) { 188 | content_length = http_client_content_length(CONFIG_ESP_REST_URL, NULL); 189 | ESP_LOGI(TAG, "content_length=%d", content_length); 190 | if (content_length > 0) break; 191 | vTaskDelay(100); 192 | } 193 | 194 | if (content_length == 0) { 195 | ESP_LOGE(TAG, "[%s] server does not respond", CONFIG_ESP_REST_URL); 196 | while(1) { 197 | vTaskDelay(100); 198 | } 199 | } 200 | 201 | char *response_buffer; // Buffer to store response of http request from event handler 202 | response_buffer = (char *) malloc(content_length+1); 203 | if (response_buffer == NULL) { 204 | ESP_LOGE(TAG, "Failed to allocate memory for output buffer"); 205 | while(1) { 206 | vTaskDelay(1); 207 | } 208 | } 209 | bzero(response_buffer, content_length+1); 210 | 211 | // Get content 212 | while(1) { 213 | esp_err_t err = http_client_content_get(CONFIG_ESP_REST_URL, NULL, response_buffer); 214 | if (err == ESP_OK) break; 215 | vTaskDelay(100); 216 | } 217 | ESP_LOGI(TAG, "content_length=%d", content_length); 218 | ESP_LOGI(TAG, "\n[%s]", response_buffer); 219 | 220 | #if 0 221 | ESP_LOGI(TAG, "Deserialize....."); 222 | cJSON *root = cJSON_Parse(response_buffer); 223 | JSON_Parse(root); 224 | cJSON_Delete(root); 225 | #endif 226 | 227 | cJSON *root = cJSON_CreateObject(); 228 | cJSON_AddStringToObject(root, "id", "json-request"); 229 | cJSON_AddStringToObject(root, "json", response_buffer); 230 | char *my_json_string = cJSON_Print(root); 231 | ESP_LOGI(TAG, "my_json_string=%d bytes", strlen(my_json_string)); 232 | ESP_LOGD(TAG, "\n[%s]",my_json_string); 233 | size_t xBytesSent = xMessageBufferSend(xMessageBufferToClient, my_json_string, strlen(my_json_string), portMAX_DELAY); 234 | if (xBytesSent != strlen(my_json_string)) { 235 | ESP_LOGE(TAG, "xMessageBufferSend fail"); 236 | } 237 | cJSON_free(my_json_string); 238 | free(response_buffer); 239 | } 240 | 241 | vTaskDelete(NULL); 242 | } 243 | -------------------------------------------------------------------------------- /json-http-client4/main/idf_component.yml: -------------------------------------------------------------------------------- 1 | ## IDF Component Manager Manifest File 2 | dependencies: 3 | Molorius/esp32-websocket: 4 | git: https://github.com/Molorius/esp32-websocket 5 | espressif/mdns: 6 | version: "^1.0.3" 7 | rules: 8 | - if: "idf_version >=5.0" 9 | -------------------------------------------------------------------------------- /json-http-client4/main/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | Example using WEB Socket. 3 | This example code is in the Public Domain (or CC0 licensed, at your option.) 4 | Unless required by applicable law or agreed to in writing, this 5 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 6 | CONDITIONS OF ANY KIND, either express or implied. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "freertos/FreeRTOS.h" 13 | #include "freertos/task.h" 14 | #include "freertos/queue.h" 15 | #include "freertos/event_groups.h" 16 | #include "freertos/message_buffer.h" 17 | 18 | #include "esp_wifi.h" 19 | #include "esp_log.h" 20 | #include "nvs_flash.h" 21 | #include "mdns.h" 22 | 23 | #include "websocket_server.h" 24 | 25 | MessageBufferHandle_t xMessageBufferToClient; 26 | 27 | /* FreeRTOS event group to signal when we are connected*/ 28 | static EventGroupHandle_t s_wifi_event_group; 29 | 30 | /* The event group allows multiple bits for each event, but we only care about two events: 31 | * - we are connected to the AP with an IP 32 | * - we failed to connect after the maximum amount of retries */ 33 | #define WIFI_CONNECTED_BIT BIT0 34 | #define WIFI_FAIL_BIT BIT1 35 | 36 | static const char *TAG = "main"; 37 | 38 | static int s_retry_num = 0; 39 | 40 | static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) 41 | { 42 | if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { 43 | esp_wifi_connect(); 44 | } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { 45 | if (s_retry_num < CONFIG_ESP_MAXIMUM_RETRY) { 46 | esp_wifi_connect(); 47 | s_retry_num++; 48 | ESP_LOGI(TAG, "retry to connect to the AP"); 49 | } else { 50 | xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); 51 | } 52 | ESP_LOGI(TAG,"connect to the AP fail"); 53 | } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { 54 | ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; 55 | ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); 56 | s_retry_num = 0; 57 | xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); 58 | } 59 | } 60 | 61 | void wifi_init_sta(void) 62 | { 63 | s_wifi_event_group = xEventGroupCreate(); 64 | 65 | ESP_ERROR_CHECK(esp_netif_init()); 66 | 67 | ESP_ERROR_CHECK(esp_event_loop_create_default()); 68 | esp_netif_create_default_wifi_sta(); 69 | 70 | wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); 71 | ESP_ERROR_CHECK(esp_wifi_init(&cfg)); 72 | 73 | esp_event_handler_instance_t instance_any_id; 74 | esp_event_handler_instance_t instance_got_ip; 75 | ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, 76 | ESP_EVENT_ANY_ID, 77 | &event_handler, 78 | NULL, 79 | &instance_any_id)); 80 | ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, 81 | IP_EVENT_STA_GOT_IP, 82 | &event_handler, 83 | NULL, 84 | &instance_got_ip)); 85 | 86 | wifi_config_t wifi_config = { 87 | .sta = { 88 | .ssid = CONFIG_ESP_WIFI_SSID, 89 | .password = CONFIG_ESP_WIFI_PASSWORD, 90 | /* Setting a password implies station will connect to all security modes including WEP/WPA. 91 | * However these modes are deprecated and not advisable to be used. Incase your Access point 92 | * doesn't support WPA2, these mode can be enabled by commenting below line */ 93 | .threshold.authmode = WIFI_AUTH_WPA2_PSK, 94 | 95 | .pmf_cfg = { 96 | .capable = true, 97 | .required = false 98 | }, 99 | }, 100 | }; 101 | ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); 102 | ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); 103 | ESP_ERROR_CHECK(esp_wifi_start() ); 104 | 105 | ESP_LOGI(TAG, "wifi_init_sta finished."); 106 | 107 | /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum 108 | * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */ 109 | EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, 110 | WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, 111 | pdFALSE, 112 | pdFALSE, 113 | portMAX_DELAY); 114 | 115 | /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually 116 | * happened. */ 117 | if (bits & WIFI_CONNECTED_BIT) { 118 | ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD); 119 | } else if (bits & WIFI_FAIL_BIT) { 120 | ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD); 121 | } else { 122 | ESP_LOGE(TAG, "UNEXPECTED EVENT"); 123 | } 124 | 125 | /* The event will not be processed after unregister */ 126 | ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip)); 127 | ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id)); 128 | vEventGroupDelete(s_wifi_event_group); 129 | } 130 | 131 | void initialise_mdns(void) 132 | { 133 | //initialize mDNS 134 | ESP_ERROR_CHECK( mdns_init() ); 135 | //set mDNS hostname (required if you want to advertise services) 136 | ESP_ERROR_CHECK( mdns_hostname_set(CONFIG_MDNS_HOSTNAME) ); 137 | ESP_LOGI(TAG, "mdns hostname set to: [%s]", CONFIG_MDNS_HOSTNAME); 138 | 139 | //initialize service 140 | ESP_ERROR_CHECK( mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0) ); 141 | 142 | #if 0 143 | //set default mDNS instance name 144 | ESP_ERROR_CHECK( mdns_instance_name_set("ESP32 with mDNS") ); 145 | #endif 146 | } 147 | 148 | void http_get_task(void* pvParameters); 149 | void client_task(void* pvParameters); 150 | void server_task(void* pvParameters); 151 | 152 | void app_main() { 153 | // Initialize NVS 154 | esp_err_t ret = nvs_flash_init(); 155 | if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { 156 | ESP_ERROR_CHECK(nvs_flash_erase()); 157 | ret = nvs_flash_init(); 158 | } 159 | ESP_ERROR_CHECK(ret); 160 | 161 | // Initialize WiFi 162 | wifi_init_sta(); 163 | 164 | // Initialize mDNS 165 | initialise_mdns(); 166 | 167 | // Create Message Buffer 168 | xMessageBufferToClient = xMessageBufferCreate(1024); 169 | configASSERT( xMessageBufferToClient ); 170 | 171 | // Get the local IP address 172 | esp_netif_ip_info_t ip_info; 173 | ESP_ERROR_CHECK(esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &ip_info)); 174 | char cparam0[64]; 175 | sprintf(cparam0, IPSTR, IP2STR(&ip_info.ip)); 176 | 177 | // Start http client 178 | TaskHandle_t pxCreatedTask; 179 | xTaskCreate(&http_get_task, "http_client", 1024*4, NULL, 5, &pxCreatedTask); 180 | ESP_LOGI(TAG, "pxCreatedTask1=%"PRIx32, (uint32_t)pxCreatedTask); 181 | 182 | // Start web socket server 183 | ws_server_start(); 184 | 185 | // Start web server 186 | xTaskCreate(&server_task, "server_task", 1024*4, (void *)cparam0, 5, NULL); 187 | 188 | // Start web client 189 | xTaskCreate(&client_task, "client_task", 1024*6, (void *)pxCreatedTask, 5, NULL); 190 | 191 | while(1) { 192 | vTaskDelay(100); 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /json-make-tree/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | -------------------------------------------------------------------------------- /json-make-tree/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | Converts a node table into a nested JSON string. 3 | This is a complex structure of objects and arrays. 4 | You need to serialize from the lowest level up. 5 | 6 | # Node table 7 | ``` 8 | I (333) JSON: node[0] self=[0] parent=[] 9 | I (333) JSON: node[1] self=[101] parent=[0] 10 | I (333) JSON: node[2] self=[102] parent=[0] 11 | I (343) JSON: node[3] self=[103] parent=[0] 12 | I (343) JSON: node[4] self=[201] parent=[101] 13 | I (353) JSON: node[5] self=[202] parent=[102] 14 | I (353) JSON: node[6] self=[203] parent=[102] 15 | I (363) JSON: node[7] self=[301] parent=[201] 16 | I (363) JSON: node[8] self=[302] parent=[202] 17 | I (373) JSON: node[9] self=[401] parent=[301] 18 | ``` 19 | 20 | ## Serialize 21 | ``` 22 | { 23 | "level": 0, 24 | "self": "0", 25 | "child": [{ 26 | "level": 1, 27 | "self": "101", 28 | "child": [{ 29 | "level": 2, 30 | "self": "201", 31 | "child": [{ 32 | "level": 3, 33 | "self": "301", 34 | "child": [{ 35 | "level": 4, 36 | "self": "401" 37 | }] 38 | }] 39 | }] 40 | }, { 41 | "level": 1, 42 | "self": "102", 43 | "child": [{ 44 | "level": 2, 45 | "self": "202", 46 | "child": [{ 47 | "level": 3, 48 | "self": "302" 49 | }] 50 | }, { 51 | "level": 2, 52 | "self": "203" 53 | }] 54 | }, { 55 | "level": 1, 56 | "self": "103" 57 | }] 58 | } 59 | ``` 60 | -------------------------------------------------------------------------------- /json-make-tree/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "main.c") 2 | set(COMPONENT_ADD_INCLUDEDIRS "") 3 | 4 | register_component() 5 | -------------------------------------------------------------------------------- /json-make-tree/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | -------------------------------------------------------------------------------- /json-make-tree/main/main.c: -------------------------------------------------------------------------------- 1 | /* The example of ESP-IDF 2 | * 3 | * This sample code is in the public domain. 4 | */ 5 | #include 6 | #include 7 | #include "freertos/FreeRTOS.h" 8 | #include "freertos/task.h" 9 | #include "esp_log.h" 10 | #include "esp_chip_info.h" 11 | #include "cJSON.h" 12 | 13 | static const char *TAG = "JSON"; 14 | 15 | #define STR_SIZE 32 16 | typedef struct { 17 | uint8_t level; 18 | char self[STR_SIZE+1]; 19 | char parent[STR_SIZE+1]; 20 | cJSON *json; 21 | } NODE_t; 22 | 23 | #define NODE_SIZE 10 24 | 25 | void app_main() 26 | { 27 | // Initialize node table 28 | NODE_t nodes[NODE_SIZE]; 29 | 30 | // top level 31 | nodes[0].level = 0; 32 | strcpy(nodes[0].self, "0"); 33 | strcpy(nodes[0].parent, ""); 34 | 35 | // 2'nd level 36 | nodes[1].level = 1; 37 | strcpy(nodes[1].self, "101"); 38 | strcpy(nodes[1].parent, "0"); 39 | nodes[2].level = 1; 40 | strcpy(nodes[2].self, "102"); 41 | strcpy(nodes[2].parent, "0"); 42 | nodes[3].level = 1; 43 | strcpy(nodes[3].self, "103"); 44 | strcpy(nodes[3].parent, "0"); 45 | 46 | // 3'rd level 47 | nodes[4].level = 2; 48 | strcpy(nodes[4].self, "201"); 49 | strcpy(nodes[4].parent, "101"); 50 | nodes[5].level = 2; 51 | strcpy(nodes[5].self, "202"); 52 | strcpy(nodes[5].parent, "102"); 53 | nodes[6].level = 2; 54 | strcpy(nodes[6].self, "203"); 55 | strcpy(nodes[6].parent, "102"); 56 | 57 | // 4'th level 58 | nodes[7].level = 3; 59 | strcpy(nodes[7].self, "301"); 60 | strcpy(nodes[7].parent, "201"); 61 | nodes[8].level = 3; 62 | strcpy(nodes[8].self, "302"); 63 | strcpy(nodes[8].parent, "202"); 64 | 65 | // 5'th level 66 | nodes[9].level = 4; 67 | strcpy(nodes[9].self, "401"); 68 | strcpy(nodes[9].parent, "301"); 69 | 70 | // View node table 71 | for (int i=0;i=0;target_level--) { 78 | for (int i=0;itype == cJSON_Invalid) ESP_LOGI(TAG, "cJSON_Invalid"); 15 | if (element->type == cJSON_False) ESP_LOGI(TAG, "cJSON_False"); 16 | if (element->type == cJSON_True) ESP_LOGI(TAG, "cJSON_True"); 17 | if (element->type == cJSON_NULL) ESP_LOGI(TAG, "cJSON_NULL"); 18 | if (element->type == cJSON_Number) ESP_LOGI(TAG, "cJSON_Number int=%d double=%f", element->valueint, element->valuedouble); 19 | if (element->type == cJSON_String) ESP_LOGI(TAG, "cJSON_String string=%s", element->valuestring); 20 | if (element->type == cJSON_Array) ESP_LOGI(TAG, "cJSON_Array"); 21 | if (element->type == cJSON_Object) { 22 | ESP_LOGI(TAG, "cJSON_Object"); 23 | cJSON *child_element = NULL; 24 | cJSON_ArrayForEach(child_element, element) { 25 | JSON_Print(child_element); 26 | } 27 | } 28 | if (element->type == cJSON_Raw) ESP_LOGI(TAG, "cJSON_Raw"); 29 | } 30 | 31 | 32 | void app_main() 33 | { 34 | ESP_LOGI(TAG, "Serialize....."); 35 | cJSON *root; 36 | root = cJSON_CreateArray(); 37 | 38 | // Add simple element 39 | cJSON *element[5]; 40 | element[0] = cJSON_CreateString("abc"); 41 | cJSON_AddItemToArray(root, element[0]); 42 | element[1] = cJSON_CreateNumber(123); 43 | cJSON_AddItemToArray(root, element[1]); 44 | element[2] = cJSON_CreateTrue(); 45 | cJSON_AddItemToArray(root, element[2]); 46 | element[3] = cJSON_CreateFalse(); 47 | cJSON_AddItemToArray(root, element[3]); 48 | element[4] = cJSON_CreateNull(); 49 | cJSON_AddItemToArray(root, element[4]); 50 | 51 | // Add object element 52 | cJSON *object; 53 | object = cJSON_CreateObject(); 54 | esp_chip_info_t chip_info; 55 | esp_chip_info(&chip_info); 56 | cJSON_AddStringToObject(object, "version", IDF_VER); 57 | cJSON_AddNumberToObject(object, "cores", chip_info.cores); 58 | cJSON_AddItemToArray(root, object); 59 | 60 | char *my_json_string = cJSON_Print(root); 61 | ESP_LOGI(TAG, "my_json_string\n%s",my_json_string); 62 | cJSON_Delete(root); 63 | 64 | 65 | ESP_LOGI(TAG, "Deserialize....."); 66 | cJSON *root2 = cJSON_Parse(my_json_string); 67 | int root2_array_size = cJSON_GetArraySize(root2); 68 | ESP_LOGI(TAG, "root2_array_size=%d", root2_array_size); 69 | for (int i=0;ivaluestring; 33 | cJSON *format2 = cJSON_GetObjectItem(root2,"format"); 34 | char *type = cJSON_GetObjectItem(format2,"type")->valuestring; 35 | int width = cJSON_GetObjectItem(format2,"width")->valueint; 36 | int height = cJSON_GetObjectItem(format2,"height")->valueint; 37 | bool interlace = cJSON_GetObjectItem(format2,"interlace")->valueint; 38 | int frame_ratet = cJSON_GetObjectItem(format2,"frame rate")->valueint; 39 | ESP_LOGI(TAG, "name=%s",name); 40 | ESP_LOGI(TAG, "type=%s",type); 41 | ESP_LOGI(TAG, "width=%d",width); 42 | ESP_LOGI(TAG, "height=%d",height); 43 | ESP_LOGI(TAG, "interlace=%d",interlace); 44 | ESP_LOGI(TAG, "frame_ratet=%d",frame_ratet); 45 | //cJSON_Delete(format2); 46 | cJSON_Delete(root2); 47 | 48 | // Buffers returned by cJSON_Print must be freed by the caller. 49 | // Please use the proper API (cJSON_free) rather than directly calling stdlib free. 50 | cJSON_free(my_json_string); 51 | } 52 | -------------------------------------------------------------------------------- /json-record-in-array/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | -------------------------------------------------------------------------------- /json-record-in-array/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := json-example 7 | 8 | include $(IDF_PATH)/make/project.mk 9 | 10 | -------------------------------------------------------------------------------- /json-record-in-array/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | 3 | ## Serialize 4 | ``` 5 | [{ 6 | "id": 0, 7 | "version": "v4.4-dev-2825-gb63ec47238-dirty", 8 | "cores": 2, 9 | "flag": true 10 | }, { 11 | "id": 1, 12 | "version": "v4.4-dev-2825-gb63ec47238-dirty", 13 | "cores": 2, 14 | "flag": true 15 | }, { 16 | "id": 2, 17 | "version": "v4.4-dev-2825-gb63ec47238-dirty", 18 | "cores": 2, 19 | "flag": true 20 | }, { 21 | "id": 3, 22 | "version": "v4.4-dev-2825-gb63ec47238-dirty", 23 | "cores": 2, 24 | "flag": true 25 | }, { 26 | "id": 4, 27 | "version": "v4.4-dev-2825-gb63ec47238-dirty", 28 | "cores": 2, 29 | "flag": true 30 | }] 31 | ``` 32 | 33 | ## DeSerialize 34 | ``` 35 | I (385) JSON: Deserialize..... 36 | I (395) JSON: id=0 37 | I (395) JSON: version=v4.4-dev-2825-gb63ec47238-dirty 38 | I (405) JSON: cores=2 39 | I (405) JSON: flag=1 40 | I (405) JSON: id=1 41 | I (405) JSON: version=v4.4-dev-2825-gb63ec47238-dirty 42 | I (415) JSON: cores=2 43 | I (415) JSON: flag=1 44 | I (425) JSON: id=2 45 | I (425) JSON: version=v4.4-dev-2825-gb63ec47238-dirty 46 | I (425) JSON: cores=2 47 | I (435) JSON: flag=1 48 | I (435) JSON: id=3 49 | I (435) JSON: version=v4.4-dev-2825-gb63ec47238-dirty 50 | I (445) JSON: cores=2 51 | I (445) JSON: flag=1 52 | I (445) JSON: id=4 53 | I (455) JSON: version=v4.4-dev-2825-gb63ec47238-dirty 54 | I (455) JSON: cores=2 55 | I (465) JSON: flag=1 56 | ``` 57 | -------------------------------------------------------------------------------- /json-record-in-array/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "main.c") 2 | set(COMPONENT_ADD_INCLUDEDIRS "") 3 | 4 | register_component() 5 | -------------------------------------------------------------------------------- /json-record-in-array/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | -------------------------------------------------------------------------------- /json-record-in-array/main/main.c: -------------------------------------------------------------------------------- 1 | /* The example of ESP-IDF 2 | * 3 | * This sample code is in the public domain. 4 | */ 5 | #include "freertos/FreeRTOS.h" 6 | #include "freertos/task.h" 7 | #include "esp_log.h" 8 | #include "esp_chip_info.h" 9 | #include "cJSON.h" 10 | 11 | static const char *TAG = "JSON"; 12 | 13 | void JSON_Print(const cJSON * const array) { 14 | int id = cJSON_GetObjectItem(array,"id")->valueint; 15 | char *version = cJSON_GetObjectItem(array,"version")->valuestring; 16 | int cores = cJSON_GetObjectItem(array,"cores")->valueint; 17 | bool flag = cJSON_GetObjectItem(array,"flag")->valueint; 18 | ESP_LOGI(TAG, "id=%d",id); 19 | ESP_LOGI(TAG, "version=%s",version); 20 | ESP_LOGI(TAG, "cores=%d",cores); 21 | ESP_LOGI(TAG, "flag=%d",flag); 22 | } 23 | 24 | 25 | void app_main() 26 | { 27 | ESP_LOGI(TAG, "Serialize....."); 28 | cJSON *root; 29 | root = cJSON_CreateArray(); 30 | 31 | esp_chip_info_t chip_info; 32 | esp_chip_info(&chip_info); 33 | int array_num = 5; 34 | cJSON *object[array_num]; 35 | for (int i=0;itype=%s", JSON_Types(root2->type)); 52 | int root2_array_size = cJSON_GetArraySize(root2); 53 | //ESP_LOGI(TAG, "root2_array_size=%d", root2_array_size); 54 | for (int i=0;ivalueint; 15 | char *version = cJSON_GetObjectItem(array,"version")->valuestring; 16 | int cores = cJSON_GetObjectItem(array,"cores")->valueint; 17 | bool flag = cJSON_GetObjectItem(array,"flag")->valueint; 18 | ESP_LOGI(TAG, "id=%d",id); 19 | ESP_LOGI(TAG, "version=%s",version); 20 | ESP_LOGI(TAG, "cores=%d",cores); 21 | ESP_LOGI(TAG, "flag=%d",flag); 22 | } 23 | 24 | 25 | void app_main() 26 | { 27 | ESP_LOGI(TAG, "Serialize....."); 28 | cJSON *root; 29 | root = cJSON_CreateObject(); 30 | 31 | cJSON *array; 32 | array= cJSON_CreateArray(); 33 | 34 | esp_chip_info_t chip_info; 35 | esp_chip_info(&chip_info); 36 | int array_num = 5; 37 | cJSON *object[array_num]; 38 | for (int i=0;itype=%s", JSON_Types(root2->type)); 56 | cJSON *records = cJSON_GetObjectItem(root2,"records"); 57 | //ESP_LOGI(TAG, "records->type=%s", JSON_Types(records->type)); 58 | ESP_LOGI(TAG, "%s is Array", records->string); 59 | int records_array_size = cJSON_GetArraySize(records); 60 | //ESP_LOGI(TAG, "records_array_size=%d", records_array_size); 61 | for (int i=0;itype=%s", JSON_Types(array->type)); 64 | JSON_Print(array); 65 | } 66 | cJSON_Delete(root2); 67 | 68 | // Buffers returned by cJSON_Print must be freed by the caller. 69 | // Please use the proper API (cJSON_free) rather than directly calling stdlib free. 70 | cJSON_free(my_json_string); 71 | } 72 | -------------------------------------------------------------------------------- /json-replace-array/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | -------------------------------------------------------------------------------- /json-replace-array/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := json-example 7 | 8 | include $(IDF_PATH)/make/project.mk 9 | 10 | -------------------------------------------------------------------------------- /json-replace-array/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | 3 | ## Serialize 4 | ``` 5 | I (349) JSON: Serialize..... 6 | I (349) JSON: origial_json_string 7 | ["abc", 123] 8 | I (359) JSON: new_json_string 9 | ["ABC", 456] 10 | I (359) JSON: new_json_string 11 | ["XYZ", "ABC", 789, 456] 12 | I (369) JSON: new_json_string 13 | ["XYZ", 789] 14 | ``` 15 | -------------------------------------------------------------------------------- /json-replace-array/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "main.c") 2 | set(COMPONENT_ADD_INCLUDEDIRS "") 3 | 4 | register_component() 5 | -------------------------------------------------------------------------------- /json-replace-array/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | -------------------------------------------------------------------------------- /json-replace-array/main/main.c: -------------------------------------------------------------------------------- 1 | /* The example of ESP-IDF 2 | * 3 | * This sample code is in the public domain. 4 | */ 5 | #include "freertos/FreeRTOS.h" 6 | #include "freertos/task.h" 7 | #include "esp_log.h" 8 | #include "cJSON.h" 9 | 10 | static const char *TAG = "JSON"; 11 | 12 | void JSON_Print(cJSON *element) { 13 | if (element->type == cJSON_Invalid) ESP_LOGI(TAG, "cJSON_Invalid"); 14 | if (element->type == cJSON_False) ESP_LOGI(TAG, "cJSON_False"); 15 | if (element->type == cJSON_True) ESP_LOGI(TAG, "cJSON_True"); 16 | if (element->type == cJSON_NULL) ESP_LOGI(TAG, "cJSON_NULL"); 17 | if (element->type == cJSON_Number) ESP_LOGI(TAG, "cJSON_Number int=%d double=%f", element->valueint, element->valuedouble); 18 | if (element->type == cJSON_String) ESP_LOGI(TAG, "cJSON_String string=%s", element->valuestring); 19 | if (element->type == cJSON_Array) ESP_LOGI(TAG, "cJSON_Array"); 20 | if (element->type == cJSON_Object) ESP_LOGI(TAG, "cJSON_Object"); 21 | if (element->type == cJSON_Raw) ESP_LOGI(TAG, "cJSON_Raw"); 22 | } 23 | 24 | 25 | void app_main() 26 | { 27 | ESP_LOGI(TAG, "Serialize....."); 28 | cJSON *root; 29 | root = cJSON_CreateArray(); 30 | cJSON *element[2]; 31 | element[0] = cJSON_CreateString("abc"); 32 | cJSON_AddItemToArray(root, element[0]); 33 | element[1] = cJSON_CreateNumber(123); 34 | cJSON_AddItemToArray(root, element[1]); 35 | char *origial_json_string = cJSON_Print(root); 36 | ESP_LOGI(TAG, "origial_json_string\n%s",origial_json_string); 37 | 38 | cJSON *newitem[4]; 39 | newitem[0] = cJSON_CreateString("ABC"); 40 | cJSON_ReplaceItemInArray(root, 0, newitem[0]); 41 | newitem[1] = cJSON_CreateNumber(456); 42 | cJSON_ReplaceItemInArray(root, 1, newitem[1]); 43 | char *new_json_string = cJSON_Print(root); 44 | ESP_LOGI(TAG, "new_json_string\n%s",new_json_string); 45 | 46 | newitem[2] = cJSON_CreateString("XYZ"); 47 | cJSON_InsertItemInArray(root, 0, newitem[2]); 48 | newitem[3] = cJSON_CreateNumber(789); 49 | cJSON_InsertItemInArray(root, 2, newitem[3]); 50 | char *new_json_string2 = cJSON_Print(root); 51 | ESP_LOGI(TAG, "new_json_string\n%s",new_json_string2); 52 | 53 | cJSON_DeleteItemFromArray(root, 1); 54 | cJSON_DeleteItemFromArray(root, 2); 55 | char *new_json_string3 = cJSON_Print(root); 56 | ESP_LOGI(TAG, "new_json_string\n%s",new_json_string3); 57 | 58 | cJSON_Delete(root); 59 | } 60 | -------------------------------------------------------------------------------- /json-replace-object/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | -------------------------------------------------------------------------------- /json-replace-object/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := json-example 7 | 8 | include $(IDF_PATH)/make/project.mk 9 | 10 | -------------------------------------------------------------------------------- /json-replace-object/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | 3 | ## Serialize 4 | ``` 5 | I (349) JSON: Serialize..... 6 | I (349) JSON: origial_json_string 7 | { 8 | "version": "v5.1.2-dirty", 9 | "cores": 2 10 | } 11 | I (359) JSON: new_json_string 12 | { 13 | "version": "abc", 14 | "cores": 1 15 | } 16 | I (369) JSON: new_json_string 17 | { 18 | "cores": 1 19 | } 20 | ``` 21 | 22 | 23 | ## API 24 | There are cJSON_ReplaceItemInObject() and cJSON_ReplaceItemInObjectCaseSensitive(). 25 | ``` 26 | cJSON_ReplaceItemInObject(root, "cores", newitem); 27 | cJSON_ReplaceItemInObject(root, "CORES", newitem); 28 | cJSON_ReplaceItemInObjectCaseSensitive(root, "cores", newitem); 29 | cJSON_ReplaceItemInObjectCaseSensitive(root, "CORES", newitem); 30 | ``` 31 | 32 | 33 | There are cJSON_DeleteItemFromObject() and cJSON_DeleteItemFromObjectCaseSensitive(). 34 | ``` 35 | cJSON_DeleteItemFromObject(root, "version"); 36 | cJSON_DeleteItemFromObject(root, "VERSION"); 37 | cJSON_DeleteItemFromObjectCaseSensitive(root, "version"); 38 | cJSON_DeleteItemFromObjectCaseSensitive(root, "VERSION"); 39 | ``` 40 | -------------------------------------------------------------------------------- /json-replace-object/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "main.c") 2 | set(COMPONENT_ADD_INCLUDEDIRS "") 3 | 4 | register_component() 5 | -------------------------------------------------------------------------------- /json-replace-object/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | -------------------------------------------------------------------------------- /json-replace-object/main/main.c: -------------------------------------------------------------------------------- 1 | /* The example of ESP-IDF 2 | * 3 | * This sample code is in the public domain. 4 | */ 5 | #include "freertos/FreeRTOS.h" 6 | #include "freertos/task.h" 7 | #include "esp_log.h" 8 | #include "cJSON.h" 9 | 10 | static const char *TAG = "JSON"; 11 | 12 | void app_main() 13 | { 14 | ESP_LOGI(TAG, "Serialize....."); 15 | cJSON *root; 16 | root = cJSON_CreateObject(); 17 | cJSON_AddStringToObject(root, "version", IDF_VER); 18 | cJSON_AddNumberToObject(root, "cores", 2); 19 | char *origial_json_string = cJSON_Print(root); 20 | ESP_LOGI(TAG, "origial_json_string\n%s",origial_json_string); 21 | 22 | cJSON *newitem; 23 | newitem = cJSON_CreateString("abc"); 24 | cJSON_ReplaceItemInObject(root, "version", newitem); 25 | newitem = cJSON_CreateNumber(1); 26 | cJSON_ReplaceItemInObject(root, "cores", newitem); 27 | char *new_json_string = cJSON_Print(root); 28 | ESP_LOGI(TAG, "new_json_string\n%s",new_json_string); 29 | 30 | cJSON_DeleteItemFromObject(root, "version"); 31 | char *new_json_string2 = cJSON_Print(root); 32 | ESP_LOGI(TAG, "new_json_string\n%s",new_json_string2); 33 | 34 | cJSON_Delete(root); 35 | } 36 | -------------------------------------------------------------------------------- /json-subarrays/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(json-example) 7 | -------------------------------------------------------------------------------- /json-subarrays/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := json-example 7 | 8 | include $(IDF_PATH)/make/project.mk 9 | 10 | -------------------------------------------------------------------------------- /json-subarrays/README.md: -------------------------------------------------------------------------------- 1 | # JSON Example 2 | 3 | ## Serialize 4 | ``` 5 | { 6 | "name": "Awesome 4K", 7 | "resolutions": [{ 8 | "width": 1280, 9 | "height": 720 10 | }, { 11 | "width": 1920, 12 | "height": 1080 13 | }, { 14 | "width": 3840, 15 | "height": 2160 16 | }], 17 | "resolutionsWidth": [1280, 1920, 3840], 18 | "resolutionsHeight": [720, 1080, 2160] 19 | } 20 | ``` 21 | 22 | ## DeSerialize 23 | ``` 24 | I (345) JSON: name=Awesome 4K 25 | I (355) JSON: resolutions2->type=cJSON_Array 26 | I (355) JSON: resolutions2_array_size=3 27 | I (365) JSON: width=1280 28 | I (365) JSON: height=720 29 | I (365) JSON: width=1920 30 | I (375) JSON: height=1080 31 | I (375) JSON: width=3840 32 | I (375) JSON: height=2160 33 | I (385) JSON: resolutionsWidth2->type=cJSON_Array 34 | I (385) JSON: resolutionsWidth2_array_size=3 35 | I (395) JSON: resolutionsWidth[0]=1280 36 | I (395) JSON: resolutionsWidth[1]=1920 37 | I (405) JSON: resolutionsWidth[2]=3840 38 | I (405) JSON: resolutionsHeight2->type=cJSON_Array 39 | I (415) JSON: resolutionsHeight2_array_size=3 40 | I (415) JSON: resolutionsHeight[0]=720 41 | I (425) JSON: resolutionsHeight[1]=1080 42 | I (425) JSON: resolutionsHeight[2]=2160 43 | ``` 44 | -------------------------------------------------------------------------------- /json-subarrays/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "main.c") 2 | set(COMPONENT_ADD_INCLUDEDIRS "") 3 | 4 | register_component() 5 | -------------------------------------------------------------------------------- /json-subarrays/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | -------------------------------------------------------------------------------- /json-subarrays/main/main.c: -------------------------------------------------------------------------------- 1 | /* The example of ESP-IDF 2 | * 3 | * This sample code is in the public domain. 4 | * 5 | * I ported from here. 6 | * https://github.com/DaveGamble/cJSON/blob/master/tests/readme_examples.c 7 | * 8 | */ 9 | #include "freertos/FreeRTOS.h" 10 | #include "freertos/task.h" 11 | #include "esp_log.h" 12 | #include "cJSON.h" 13 | 14 | static const char *TAG = "JSON"; 15 | 16 | char *JSON_Types(int type) { 17 | if (type == cJSON_Invalid) return ("cJSON_Invalid"); 18 | if (type == cJSON_False) return ("cJSON_False"); 19 | if (type == cJSON_True) return ("cJSON_True"); 20 | if (type == cJSON_NULL) return ("cJSON_NULL"); 21 | if (type == cJSON_Number) return ("cJSON_Number"); 22 | if (type == cJSON_String) return ("cJSON_String"); 23 | if (type == cJSON_Array) return ("cJSON_Array"); 24 | if (type == cJSON_Object) return ("cJSON_Object"); 25 | if (type == cJSON_Raw) return ("cJSON_Raw"); 26 | return NULL; 27 | } 28 | 29 | void json_task(void *pvParameters) 30 | { 31 | const unsigned int resolution_numbers[3][2] = { 32 | {1280, 720}, 33 | {1920, 1080}, 34 | {3840, 2160} 35 | }; 36 | 37 | ESP_LOGI(TAG, "Serialize....."); 38 | cJSON *root; 39 | root = cJSON_CreateObject(); 40 | cJSON_AddStringToObject(root, "name", "Awesome 4K"); 41 | cJSON *resolutions; 42 | resolutions = cJSON_CreateArray(); 43 | cJSON_AddItemToObject(root, "resolutions", resolutions); 44 | 45 | int array_size = sizeof(resolution_numbers) / (2 * sizeof(int)); 46 | ESP_LOGI(TAG, "array_size=%d", array_size); 47 | cJSON *object[array_size]; 48 | cJSON *width[array_size]; 49 | cJSON *height[array_size]; 50 | for(int i=0;ivaluestring; 83 | ESP_LOGI(TAG, "name=%s",name); 84 | 85 | cJSON *resolutions2 = cJSON_GetObjectItem(root2,"resolutions"); 86 | ESP_LOGI(TAG, "resolutions2->type=%s", JSON_Types(resolutions2->type)); 87 | int resolutions2_array_size = cJSON_GetArraySize(resolutions2); 88 | ESP_LOGI(TAG, "resolutions2_array_size=%d", resolutions2_array_size); 89 | for (int i=0;itype=%s", JSON_Types(array->type)); 92 | int width = cJSON_GetObjectItem(array,"width")->valueint; 93 | int height = cJSON_GetObjectItem(array,"height")->valueint; 94 | ESP_LOGI(TAG, "width=%d",width); 95 | ESP_LOGI(TAG, "height=%d",height); 96 | } 97 | 98 | cJSON *resolutionsWidth2 = cJSON_GetObjectItem(root2,"resolutionsWidth"); 99 | ESP_LOGI(TAG, "resolutionsWidth2->type=%s", JSON_Types(resolutionsWidth2->type)); 100 | int resolutionsWidth2_array_size = cJSON_GetArraySize(resolutionsWidth2); 101 | ESP_LOGI(TAG, "resolutionsWidth2_array_size=%d", resolutionsWidth2_array_size); 102 | for (int i=0;itype=%s", JSON_Types(array->type)); 105 | int resolutionsWidth = array->valueint; 106 | ESP_LOGI(TAG, "resolutionsWidth[%d]=%d",i, resolutionsWidth); 107 | } 108 | 109 | cJSON *resolutionsHeight2 = cJSON_GetObjectItem(root2,"resolutionsHeight"); 110 | ESP_LOGI(TAG, "resolutionsHeight2->type=%s", JSON_Types(resolutionsHeight2->type)); 111 | int resolutionsHeight2_array_size = cJSON_GetArraySize(resolutionsHeight2); 112 | ESP_LOGI(TAG, "resolutionsHeight2_array_size=%d", resolutionsHeight2_array_size); 113 | for (int i=0;itype=%s", JSON_Types(array->type)); 116 | int resolutionsHeight = array->valueint; 117 | ESP_LOGI(TAG, "resolutionsHeight[%d]=%d",i, resolutionsHeight); 118 | } 119 | cJSON_Delete(root2); 120 | 121 | // Buffers returned by cJSON_Print must be freed by the caller. 122 | // Please use the proper API (cJSON_free) rather than directly calling stdlib free. 123 | cJSON_free(my_json_string); 124 | vTaskDelete(NULL); 125 | } 126 | 127 | void app_main() 128 | { 129 | xTaskCreate(json_task, "JSON", 1024*2, NULL, 2, NULL); 130 | } 131 | --------------------------------------------------------------------------------