]> granicus.if.org Git - esp-idf/commitdiff
cbor: add tinycbor library and example
authorsuda-morris <362953310@qq.com>
Mon, 12 Aug 2019 14:07:47 +0000 (22:07 +0800)
committersuda-morris <362953310@qq.com>
Thu, 22 Aug 2019 09:44:29 +0000 (17:44 +0800)
13 files changed:
.gitmodules
components/cbor/CMakeLists.txt [new file with mode: 0644]
components/cbor/component.mk [new file with mode: 0644]
components/cbor/port/include/cbor.h [new file with mode: 0644]
components/cbor/tinycbor [new submodule]
examples/protocols/cbor/CMakeLists.txt [new file with mode: 0644]
examples/protocols/cbor/Makefile [new file with mode: 0644]
examples/protocols/cbor/README.md [new file with mode: 0644]
examples/protocols/cbor/main/CMakeLists.txt [new file with mode: 0644]
examples/protocols/cbor/main/cbor_example_main.c [new file with mode: 0644]
examples/protocols/cbor/main/component.mk [new file with mode: 0644]
tools/ci/build_examples.sh
tools/ci/build_examples_cmake.sh

index 70bd0c478e386c42fe091d8ee99deab13b3db30c..8366568747bfb7d7c0ad3f33585152a5514b3000 100644 (file)
@@ -74,3 +74,7 @@
 [submodule "components/bt/host/nimble/nimble"]
        path = components/bt/host/nimble/nimble
        url = ../../espressif/esp-nimble.git
+
+[submodule "components/cbor/tinycbor"]
+       path = components/cbor/tinycbor
+       url = ../../intel/tinycbor.git
diff --git a/components/cbor/CMakeLists.txt b/components/cbor/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5aaaaf8
--- /dev/null
@@ -0,0 +1,21 @@
+idf_component_register(SRCS "tinycbor/src/cborencoder_close_container_checked.c"
+                            "tinycbor/src/cborencoder.c"
+                            "tinycbor/src/cborerrorstrings.c"
+                            "tinycbor/src/cborparser_dup_string.c"
+                            "tinycbor/src/cborparser.c"
+                            "tinycbor/src/cborpretty_stdio.c"
+                            "tinycbor/src/cborpretty.c"
+                            "tinycbor/src/cbortojson.c"
+                            "tinycbor/src/cborvalidation.c"
+                            "tinycbor/src/open_memstream.c"
+                    INCLUDE_DIRS "port/include"
+                    PRIV_INCLUDE_DIRS "tinycbor/src")
+
+# for open_memstream.c
+target_compile_definitions(${COMPONENT_LIB} PRIVATE "__GLIBC__")
+
+# cbortojson.c:378:17: assignment discards 'const' qualifier from pointer target type
+target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-discarded-qualifiers")
+
+# cborvalidation.c:429:22: 'valf' may be used uninitialized
+target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-maybe-uninitialized")
diff --git a/components/cbor/component.mk b/components/cbor/component.mk
new file mode 100644 (file)
index 0000000..9f9d37c
--- /dev/null
@@ -0,0 +1,8 @@
+COMPONENT_SUBMODULES += tinycbor
+COMPONENT_ADD_INCLUDEDIRS := port/include
+COMPONENT_SRCDIRS :=  tinycbor/src
+COMPONENT_PRIV_INCLUDEDIRS := tinycbor/src
+
+tinycbor/src/open_memstream.o: CFLAGS += -D__GLIBC__
+tinycbor/src/cbortojson.o: CFLAGS += -Wno-discarded-qualifiers
+tinycbor/src/cborvalidation.o: CFLAGS += -Wno-maybe-uninitialized
diff --git a/components/cbor/port/include/cbor.h b/components/cbor/port/include/cbor.h
new file mode 100644 (file)
index 0000000..c8e6ccf
--- /dev/null
@@ -0,0 +1,2 @@
+#include "../../tinycbor/src/cbor.h"
+#include "../../tinycbor/src/cborjson.h"
diff --git a/components/cbor/tinycbor b/components/cbor/tinycbor
new file mode 160000 (submodule)
index 0000000..d2dd95c
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit d2dd95cb8841d88d5a801e3ef9c328fd6200e7bd
diff --git a/examples/protocols/cbor/CMakeLists.txt b/examples/protocols/cbor/CMakeLists.txt
new file mode 100644 (file)
index 0000000..8b524ec
--- /dev/null
@@ -0,0 +1,6 @@
+# The following lines of boilerplate have to be in your project's
+# CMakeLists in this exact order for cmake to work correctly
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(cbor)
diff --git a/examples/protocols/cbor/Makefile b/examples/protocols/cbor/Makefile
new file mode 100644 (file)
index 0000000..7b39413
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# This is a project Makefile. It is assumed the directory this Makefile resides in is a
+# project subdirectory.
+#
+
+PROJECT_NAME := cbor
+
+include $(IDF_PATH)/make/project.mk
+
diff --git a/examples/protocols/cbor/README.md b/examples/protocols/cbor/README.md
new file mode 100644 (file)
index 0000000..3b6f81a
--- /dev/null
@@ -0,0 +1,56 @@
+# CBOR Example
+(See the README.md file in the upper level 'examples' directory for more information about examples.)
+
+## Overview
+
+The [CBOR](https://en.wikipedia.org/wiki/CBOR)(Concise Binary Object Representation) is a binary data serialization format which is similar to JSON but with smaller footprint. This example will illustrate how to encode and decode CBOR data using the APIs provided by [tinycbor](https://github.com/intel/tinycbor).
+
+For detailed information about how CBOR encoding and decoding works, please refer to [REF7049](https://tools.ietf.org/html/rfc7049) or [cbor.io](http://cbor.io/);
+
+## How to use example
+
+### Hardware Required
+
+This example should be able to run on any commonly available ESP32 development board.
+
+### Build and Flash
+
+Run `idf.py -p PORT flash monitor` to build and flash the project.
+
+(To exit the serial monitor, type ``Ctrl-]``.)
+
+See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
+
+## Example Output
+
+```bash
+I (320) example: encoded buffer size 67
+I (320) example: convert CBOR to JSON
+[{"chip":"esp32","unicore":false,"ip":[192,168,1,100]},3.1400001049041748,"simple(99)","2019-07-10 09:00:00+0000","undefined"]
+I (340) example: decode CBOR manually
+Array[
+  Map{
+    chip
+    esp32
+    unicore
+    false
+    ip
+    Array[
+      192
+      168
+      1
+      100
+    ]
+  }
+  3.14
+  simple(99)
+  2019-07-10 09:00:00+0000
+  undefined
+]
+```
+
+## Troubleshooting
+
+For more API usage, please refer to [tinycbor API](https://intel.github.io/tinycbor/current/).
+
+(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.)
diff --git a/examples/protocols/cbor/main/CMakeLists.txt b/examples/protocols/cbor/main/CMakeLists.txt
new file mode 100644 (file)
index 0000000..31dfa61
--- /dev/null
@@ -0,0 +1,2 @@
+idf_component_register(SRCS "cbor_example_main.c"
+                       INCLUDE_DIRS "")
diff --git a/examples/protocols/cbor/main/cbor_example_main.c b/examples/protocols/cbor/main/cbor_example_main.c
new file mode 100644 (file)
index 0000000..3807ce0
--- /dev/null
@@ -0,0 +1,226 @@
+/* CBOR Example
+
+   This example code is in the Public Domain (or CC0 licensed, at your option.)
+
+   Unless required by applicable law or agreed to in writing, this
+   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+   CONDITIONS OF ANY KIND, either express or implied.
+*/
+#include <stdio.h>
+#include "esp_log.h"
+#include "cbor.h"
+
+static const char *TAG = "example";
+
+#define CBOR_CHECK(a, str, goto_tag, ret_value, ...)                              \
+    do                                                                            \
+    {                                                                             \
+        if ((a) != CborNoError)                                                   \
+        {                                                                         \
+            ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+            ret = ret_value;                                                      \
+            goto goto_tag;                                                        \
+        }                                                                         \
+    } while (0)
+
+static void indent(int nestingLevel)
+{
+    while (nestingLevel--) {
+        printf("  ");
+    }
+}
+
+static void dumpbytes(const uint8_t *buf, size_t len)
+{
+    while (len--) {
+        printf("%02X ", *buf++);
+    }
+}
+
+/**
+ * Decode CBOR data manuallly
+ */
+static CborError example_dump_cbor_buffer(CborValue *it, int nestingLevel)
+{
+    CborError ret = CborNoError;
+    while (!cbor_value_at_end(it)) {
+        CborType type = cbor_value_get_type(it);
+
+        indent(nestingLevel);
+        switch (type) {
+        case CborArrayType: {
+            CborValue recursed;
+            assert(cbor_value_is_container(it));
+            puts("Array[");
+            ret = cbor_value_enter_container(it, &recursed);
+            CBOR_CHECK(ret, "enter container failed", err, ret);
+            ret = example_dump_cbor_buffer(&recursed, nestingLevel + 1);
+            CBOR_CHECK(ret, "recursive dump failed", err, ret);
+            ret = cbor_value_leave_container(it, &recursed);
+            CBOR_CHECK(ret, "leave container failed", err, ret);
+            indent(nestingLevel);
+            puts("]");
+            continue;
+        }
+        case CborMapType: {
+            CborValue recursed;
+            assert(cbor_value_is_container(it));
+            puts("Map{");
+            ret = cbor_value_enter_container(it, &recursed);
+            CBOR_CHECK(ret, "enter container failed", err, ret);
+            ret = example_dump_cbor_buffer(&recursed, nestingLevel + 1);
+            CBOR_CHECK(ret, "recursive dump failed", err, ret);
+            ret = cbor_value_leave_container(it, &recursed);
+            CBOR_CHECK(ret, "leave container failed", err, ret);
+            indent(nestingLevel);
+            puts("}");
+            continue;
+        }
+        case CborIntegerType: {
+            int64_t val;
+            ret = cbor_value_get_int64(it, &val);
+            CBOR_CHECK(ret, "parse int64 failed", err, ret);
+            printf("%lld\n", (long long)val);
+            break;
+        }
+        case CborByteStringType: {
+            uint8_t *buf;
+            size_t n;
+            ret = cbor_value_dup_byte_string(it, &buf, &n, it);
+            CBOR_CHECK(ret, "parse byte string failed", err, ret);
+            dumpbytes(buf, n);
+            puts("");
+            free(buf);
+            continue;
+        }
+        case CborTextStringType: {
+            char *buf;
+            size_t n;
+            ret = cbor_value_dup_text_string(it, &buf, &n, it);
+            CBOR_CHECK(ret, "parse text string failed", err, ret);
+            puts(buf);
+            free(buf);
+            continue;
+        }
+        case CborTagType: {
+            CborTag tag;
+            ret = cbor_value_get_tag(it, &tag);
+            CBOR_CHECK(ret, "parse tag failed", err, ret);
+            printf("Tag(%lld)\n", (long long)tag);
+            break;
+        }
+        case CborSimpleType: {
+            uint8_t type;
+            ret = cbor_value_get_simple_type(it, &type);
+            CBOR_CHECK(ret, "parse simple type failed", err, ret);
+            printf("simple(%u)\n", type);
+            break;
+        }
+        case CborNullType:
+            puts("null");
+            break;
+        case CborUndefinedType:
+            puts("undefined");
+            break;
+        case CborBooleanType: {
+            bool val;
+            ret = cbor_value_get_boolean(it, &val);
+            CBOR_CHECK(ret, "parse boolean type failed", err, ret);
+            puts(val ? "true" : "false");
+            break;
+        }
+        case CborHalfFloatType: {
+            uint16_t val;
+            ret = cbor_value_get_half_float(it, &val);
+            CBOR_CHECK(ret, "parse half float type failed", err, ret);
+            printf("__f16(%04x)\n", val);
+            break;
+        }
+        case CborFloatType: {
+            float val;
+            ret = cbor_value_get_float(it, &val);
+            CBOR_CHECK(ret, "parse float type failed", err, ret);
+            printf("%g\n", val);
+            break;
+        }
+        case CborDoubleType: {
+            double val;
+            ret = cbor_value_get_double(it, &val);
+            CBOR_CHECK(ret, "parse double float type failed", err, ret);
+            printf("%g\n", val);
+            break;
+        }
+        case CborInvalidType: {
+            ret = CborErrorUnknownType;
+            CBOR_CHECK(ret, "unknown cbor type", err, ret);
+            break;
+        }
+        }
+
+        ret = cbor_value_advance_fixed(it);
+        CBOR_CHECK(ret, "fix value failed", err, ret);
+    }
+    return CborNoError;
+err:
+    return ret;
+}
+
+
+void app_main(void)
+{
+    CborEncoder root_encoder;
+    CborParser root_parser;
+    CborValue it;
+    uint8_t buf[100];
+
+    // Initialize the outermost cbor encoder
+    cbor_encoder_init(&root_encoder, buf, sizeof(buf), 0);
+
+    // Create an array containing several items
+    CborEncoder array_encoder;
+    CborEncoder map_encoder;
+    cbor_encoder_create_array(&root_encoder, &array_encoder, 5); // [
+    // 1. Create a map containing several pairs
+    cbor_encoder_create_map(&array_encoder, &map_encoder, 3); // {
+    // chip:esp32
+    cbor_encode_text_stringz(&map_encoder, "chip");
+    cbor_encode_text_stringz(&map_encoder, "esp32");
+    // unicore:false
+    cbor_encode_text_stringz(&map_encoder, "unicore");
+    cbor_encode_boolean(&map_encoder, false);
+    // ip:[192,168,1,100]
+    cbor_encode_text_stringz(&map_encoder, "ip");
+    CborEncoder array2;
+    cbor_encoder_create_array(&map_encoder, &array2, 4); // [
+    // Encode several numbers
+    cbor_encode_uint(&array2, 192);
+    cbor_encode_uint(&array2, 168);
+    cbor_encode_uint(&array2, 1);
+    cbor_encode_uint(&array2, 100);
+    cbor_encoder_close_container(&map_encoder, &array2);        // ]
+    cbor_encoder_close_container(&array_encoder, &map_encoder); // }
+    // 2. Encode float number
+    cbor_encode_float(&array_encoder, 3.14);
+    // 3. Encode simple value
+    cbor_encode_simple_value(&array_encoder, 99);
+    // 4. Encode a string
+    cbor_encode_text_stringz(&array_encoder, "2019-07-10 09:00:00+0000");
+    // 5. Encode a undefined value
+    cbor_encode_undefined(&array_encoder);
+    cbor_encoder_close_container(&root_encoder, &array_encoder); // ]
+
+    // If error happend when encoding, then this value should be meaningless
+    ESP_LOGI(TAG, "encoded buffer size %d", cbor_encoder_get_buffer_size(&root_encoder, buf));
+
+    // Initialize the cbor parser and the value iterator
+    cbor_parser_init(buf, sizeof(buf), 0, &root_parser, &it);
+
+    ESP_LOGI(TAG, "convert CBOR to JSON");
+    // Dump the values in JSON format
+    cbor_value_to_json(stdout, &it, 0);
+    puts("");
+
+    ESP_LOGI(TAG, "decode CBOR manually");
+    // Decode CBOR data manully
+    example_dump_cbor_buffer(&it, 0);
+}
diff --git a/examples/protocols/cbor/main/component.mk b/examples/protocols/cbor/main/component.mk
new file mode 100644 (file)
index 0000000..0b9d758
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# "main" pseudo-component makefile.
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
+
index 9be1525b3f61cad1f0693b4fd7cabab8e3d4933d..9dc831d43c09470182572f2d6e5b1e295b1cd9e3 100755 (executable)
@@ -99,7 +99,7 @@ build_example () {
 
     local EXAMPLE_DIR=$(dirname "${MAKE_FILE}")
     local EXAMPLE_NAME=$(basename "${EXAMPLE_DIR}")
-    
+
     # Check if the example needs a different base directory.
     # Path of the Makefile relative to $IDF_PATH
     local MAKE_FILE_REL=${MAKE_FILE#"${IDF_PATH}/"}
@@ -182,7 +182,8 @@ echo -e "\nFound issues:"
 IGNORE_WARNS="\
 library/error\.o\
 \|\ -Werror\
-\|error\.d\
+\|.*error.*\.o\
+\|.*error.*\.d\
 \|reassigning to symbol\
 \|changes choice state\
 \|Compiler version is not supported\
index cc5f3adc00eb2a0077b96f98c381b0dd6a0f7508..9a8751ae261d78fa5f7adb6fe14f34c7ea5df80b 100755 (executable)
@@ -145,7 +145,7 @@ build_example () {
         cat ${BUILDLOG}
     popd
 
-    grep -i "error\|warning" "${BUILDLOG}" 2>&1 | grep -v "error.c.obj" >> "${LOG_SUSPECTED}" || :
+    grep -i "error\|warning" "${BUILDLOG}" 2>&1 >> "${LOG_SUSPECTED}" || :
 }
 
 EXAMPLE_NUM=0
@@ -175,6 +175,7 @@ echo -e "\nFound issues:"
 # 'Compiler and toochain versions is not supported' from crosstool_version_check.cmake
 IGNORE_WARNS="\
 library/error\.o\
+\|.*error.*\.c\.obj\
 \|\ -Werror\
 \|error\.d\
 \|reassigning to symbol\