mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-04 06:11:06 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			227 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* 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);
 | 
						|
}
 |