utility/msgpack/read_write_buffer.c

/*******************************************************************************
* # License
* Copyright 2019 Silicon Laboratories Inc. www.silabs.com
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
#include "common.h"
#define BUFFER_LENGTH (2048)
#define ADC_READINGS (5)
/*************************************************************************************************
* This demonstrates how to serialize/de-serialize a MessagePack buffer located in RAM.
*
* The format of the data this example uses is as follows:
* (Note: While described in JSON format, the data is actually MessagePack formatted)
*
* {
* "time-ms" : <uint64:time in ms>,
* "time-utc" : "<string: time as UTC string>",
* "tick" : <uint32: RTOS tick count>,
* "mac" : "<binary string: MAC address as binary string>",
* "gpio-list": [ <array:bool: gpio values> ],
* "adc-readings" : {
* "adc-X" :
* {
* "format" : "<string:mV/raw>",
* "value" : <uint32:value>
* }
* ...
* }
* }
*/
gos_result_t read_write_buffer(void)
{
gos_result_t result;
uint8_t buffer[BUFFER_LENGTH];
uint32_t serialized_data_length = 0;
GOS_LOG("\r\n\r\nSerialize/deserialize local buffer ...");
if (GOS_FAILED(result, serialize_data(buffer, BUFFER_LENGTH, &serialized_data_length)))
{
GOS_LOG("Failed to serialize data. Err code: %d", result);
}
else if (GOS_FAILED(result, deserialize_and_print_data(buffer, serialized_data_length)))
{
GOS_LOG("Failed to deserialize data. Err code: %d", result);
}
return result;
}
/*************************************************************************************************
* Serial data using MessagePack format
*/
static gos_result_t serialize_data(uint8_t *buffer, uint32_t buffer_max_length, uint32_t *buffer_length_ptr)
{
MSGPACK_INIT_WITH_BUFFER(serialize_context, buffer, buffer_max_length);
// The root dictionary has 6 key/value pairs
GOS_VERIFY(gos_msgpack_write_dict_marker(&serialize_context, 6));
// Write the current time
{
gos_utc_ms_t current_time_ms;
gos_time_get_current_utc_ms(&current_time_ms, false);
// Note: 'long' = 64bit
GOS_VERIFY(gos_msgpack_write_dict_ulong(&serialize_context, "time-ms", current_time_ms));
}
// Write UTC time
{
gos_iso8601_str_t current_time_utc;
gos_time_get_current_utc_as_iso8601_str(&current_time_utc, false);
GOS_VERIFY(gos_msgpack_write_dict_str(&serialize_context, "time-utc", (const char*)&current_time_utc));
}
// Write current RTOS tick
{
const uint32_t now = gos_rtos_get_time();
// Note: 'int' = 32bit
GOS_VERIFY(gos_msgpack_write_dict_uint(&serialize_context, "tick", now));
}
// Write MAC address as binary string
{
char mac_str[24];
gos_mac_t mac_address;
str_to_mac(mac_str, &mac_address);
GOS_VERIFY(gos_msgpack_write_dict_bin(&serialize_context, "mac", mac_address.octet, sizeof(mac_address.octet)));
}
// Write the current value of all GPIOs as an array
{
// Write the array marker
GOS_VERIFY(gos_msgpack_write_dict_array(&serialize_context, "gpio-list", GOS_GPIO_MAX));
// Write the array entries
for (gos_gpio_t gpio = 0; gpio < GOS_GPIO_MAX; ++gpio)
{
GOS_VERIFY(gos_msgpack_write_bool(&serialize_context, gos_gpio_get(gpio)));
}
}
// Write the ADCs object entries
{
// The sub-dictionary will have ADC_READINGS key/value pairs
GOS_VERIFY(gos_msgpack_write_dict_dict(&serialize_context, "adc-readings", ADC_READINGS));
for (int adc_reading_num = 0; adc_reading_num < ADC_READINGS; ++adc_reading_num)
{
uint16_t reading_value = 0;
char key_str[16];
//gos_adc_sample_type_t sample_type = ((adc_reading_num & 0x1) == 0) ? GOS_ADC_SAMPLE_TYPE_RAW : GOS_ADC_SAMPLE_TYPE_VOLTAGE;
const char *sample_type_str = ((adc_reading_num & 0x1) == 0) ? "raw" : "mV";
// Get the current value of the ADC
//gos_adc_sample(PLATFORM_STD_ADC, &reading_value, sample_type);
// Generate the entry key string
sprintf(key_str, "adc-%d", adc_reading_num);
// Write the adc sub-sub-dictionary which contains 2 entries
GOS_VERIFY(gos_msgpack_write_dict_dict(&serialize_context, key_str, 2));
// Write the 'format' entry
GOS_VERIFY(gos_msgpack_write_dict_str(&serialize_context, "format", sample_type_str));
// Write the value entry
GOS_VERIFY(gos_msgpack_write_dict_uint(&serialize_context, "value", reading_value));
}
}
// Return the total length of the serialized buffer
*buffer_length_ptr = MSGPACK_BUFFER_USED(&serialize_context);
return GOS_SUCCESS;
}
/*************************************************************************************************
* Deserialize the msgpack formatted buffer and print the contents
*/
static gos_result_t deserialize_and_print_data(uint8_t *buffer, uint32_t length)
{
gos_result_t result;
// Dump the 'packed' binary data
gos_dump_buffer(buffer, length, "'Packed' binary dump:", GOS_DUMP_FLAGS(16, 1, LITTLE, ADD_SPACE, PRINT_ADDRESSES, PRINT_ASCII));
if (GOS_FAILED(result, gos_msgpack_deserialize_with_buffer(&root_ptr, buffer, length, 0)))
{
GOS_LOG("Failed to deserialize msgpack buffer. Err code: %d", result);
return result;
}
// Retrieve and print the 'time-ms' entry
{
const gos_msgpack_object_t *obj = MSGPACK_DICT_GET_OBJECT(root_ptr, "time-ms");
if (obj == NULL)
{
GOS_LOG("WARN: 'time-ms' entry not found");
}
else
{
char str_buffer[32];
uint64_t time_ms;
MSGPACK_ULONG(obj, &time_ms);
GOS_LOG("'time-ms' : %s", uint64_to_str(time_ms, str_buffer));
}
}
// Retrieve and print the 'time-utc' entry
{
const gos_msgpack_object_t *obj = MSGPACK_DICT_GET_OBJECT(root_ptr, "time-utc");
if (obj == NULL)
{
GOS_LOG("WARN: 'time-utc' entry not found");
}
else if (MSGPACK_IS_STR(obj) == 0)
{
GOS_LOG("WARN: 'time-utc' entry is NOT a string object");
}
else
{
char str_buffer[32];
GOS_LOG("'time-utc' : %s", MSGPACK_STR(obj, str_buffer, sizeof(str_buffer)));
}
}
// Retrieve and print the 'tick' entry
{
const gos_msgpack_object_t *obj = MSGPACK_DICT_GET_OBJECT(root_ptr, "tick");
if (obj == NULL)
{
GOS_LOG("WARN: 'tick' entry not found");
}
else
{
GOS_LOG("'tick' : %u", MSGPACK_UINT(obj));
}
}
// Retrieve and print the 'mac' entry
{
const gos_msgpack_object_t *obj = MSGPACK_DICT_GET_OBJECT(root_ptr, "mac");
if (obj == NULL)
{
GOS_LOG("WARN: 'mac' entry not found");
}
else if (MSGPACK_IS_BIN(obj) == 0)
{
GOS_LOG("WARN: 'mac' entry is NOT a binary string object");
}
else
{
gos_mac_t mac_address;
char mac_str[20];
memcpy(mac_address.octet, MSGPACK_BIN_VALUE(obj), MSGPACK_BIN_LENGTH(obj));
GOS_LOG("'mac' : %s", mac_to_str(&mac_address, mac_str));
}
}
// Retrieve and print the 'gpio-list' entry
{
const gos_msgpack_object_t *obj = MSGPACK_DICT_GET_OBJECT(root_ptr, "gpio-list");
if (obj == NULL)
{
GOS_LOG("WARN: 'gpio-list' entry not found");
}
else if (MSGPACK_IS_ARRAY(obj) == 0)
{
GOS_LOG("WARN: 'gpio-list' entry is NOT an array object");
}
else
{
for (gos_gpio_t gpio = 0; gpio < array_obj->count; ++gpio)
{
const gos_msgpack_object_t *entry = MSGPACK_ARRAY_GET_OBJECT(array_obj, gpio);
if (entry == NULL)
{
GOS_LOG("WARN: 'gpio-list' entry not found");
}
else if (MSGPACK_IS_BOOL(entry) == 0)
{
GOS_LOG("WARN: 'gpio-list' entry is NOT a boolean object");
}
else
{
GOS_LOG("GPIO-%d : %d", gpio, MSGPACK_BOOL(entry));
}
}
}
}
// Retrieve and print the 'adc-readings' entry
{
const gos_msgpack_object_t *obj = MSGPACK_DICT_GET_OBJECT(root_ptr, "adc-readings");
if (obj == NULL)
{
GOS_LOG("WARN: 'adc-readings' entry not found");
}
else if (MSGPACK_IS_DICT(obj) == 0)
{
GOS_LOG("WARN: 'adc-readings' entry is NOT a dict object");
}
else
{
for (gos_gpio_t reading_num = 0; reading_num < dict_obj->count; ++reading_num)
{
char key_str[16];
sprintf(key_str, "adc-%d", reading_num);
const gos_msgpack_object_t *entry = MSGPACK_DICT_GET_OBJECT(dict_obj, key_str);
if (entry == NULL)
{
GOS_LOG("WARN: 'adc-readings' entry not found");
}
else if (MSGPACK_IS_DICT(entry) == 0)
{
GOS_LOG("WARN: 'adc-readings' entry is NOT a dict object");
}
else
{
char format_str[8];
const gos_msgpack_object_t *format_entry = MSGPACK_DICT_GET_OBJECT(entry, "format");
const gos_msgpack_object_t *value_entry = MSGPACK_DICT_GET_OBJECT(entry, "value");
GOS_LOG("%s : %u (%s)", key_str, MSGPACK_UINT(value_entry), MSGPACK_STR(format_entry, format_str, sizeof(format_str)));
}
}
}
}
return GOS_SUCCESS;
}