net: lwm2m: SenML CBOR RW support

* LwM2M v1.1 SenML CBOR content format support.
* Composite operations
* SEND functionality

Signed-off-by: Veijo Pesonen <veijo.pesonen@nordicsemi.no>
This commit is contained in:
Veijo Pesonen 2022-02-16 17:09:32 +02:00 committed by Carles Cufí
commit 0562de9fbe
12 changed files with 1563 additions and 3 deletions

View file

@ -59,6 +59,12 @@ zephyr_library_sources_ifdef(CONFIG_LWM2M_RW_SENML_JSON_SUPPORT
zephyr_library_sources_ifdef(CONFIG_LWM2M_RW_CBOR_SUPPORT
lwm2m_rw_cbor.c
)
# SENML CBOR support
zephyr_library_sources_ifdef(CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT
lwm2m_rw_senml_cbor.c
lwm2m_senml_cbor_decode.c
lwm2m_senml_cbor_encode.c
)
# IPSO Objects
zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_TEMP_SENSOR

View file

@ -447,6 +447,21 @@ config LWM2M_RW_CBOR_SUPPORT
help
Include support for writing CBOR data
config LWM2M_RW_SENML_CBOR_SUPPORT
bool "support for SenML CBOR writer"
depends on ZCBOR
depends on ZCBOR_CANONICAL
help
Include support for writing SenML CBOR data
config LWM2M_RW_SENML_CBOR_RECORDS
int "Maximum # of SenML records packed into a CBOR binary"
depends on LWM2M_RW_SENML_CBOR_SUPPORT
default 30
help
The CBOR library requires you to set an upper limit for the records when encoder
and decoder do get generated.
config LWM2M_DEVICE_PWRSRC_MAX
int "Maximum # of device power source records"
default 5

View file

@ -54,6 +54,9 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#ifdef CONFIG_LWM2M_RW_CBOR_SUPPORT
#include "lwm2m_rw_cbor.h"
#endif
#ifdef CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT
#include "lwm2m_rw_senml_cbor.h"
#endif
#ifdef CONFIG_LWM2M_RD_CLIENT_SUPPORT
#include "lwm2m_rd_client.h"
#endif
@ -1685,6 +1688,12 @@ static int select_writer(struct lwm2m_output_context *out, uint16_t accept)
break;
#endif
#ifdef CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT
case LWM2M_FORMAT_APP_SENML_CBOR:
out->writer = &senml_cbor_writer;
break;
#endif
default:
LOG_WRN("Unknown content type %u", accept);
return -ENOMSG;
@ -1730,6 +1739,13 @@ static int select_reader(struct lwm2m_input_context *in, uint16_t format)
break;
#endif
#ifdef CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT
case LWM2M_FORMAT_APP_SENML_CBOR:
in->reader = &senml_cbor_reader;
break;
#endif
default:
LOG_WRN("Unknown content type %u", format);
return -ENOMSG;
@ -3799,6 +3815,11 @@ static int do_read_op(struct lwm2m_message *msg, uint16_t content_format)
return do_read_op_cbor(msg);
#endif
#if defined(CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT)
case LWM2M_FORMAT_APP_SENML_CBOR:
return do_read_op_senml_cbor(msg);
#endif
default:
LOG_ERR("Unsupported content-format: %u", content_format);
return -ENOMSG;
@ -3815,6 +3836,11 @@ static int do_composite_read_op(struct lwm2m_message *msg, uint16_t content_form
return do_composite_read_op_senml_json(msg);
#endif
#if defined(CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT)
case LWM2M_FORMAT_APP_SENML_CBOR:
return do_composite_read_op_senml_cbor(msg);
#endif
default:
LOG_ERR("Unsupported content-format: %u", content_format);
return -ENOMSG;
@ -3833,6 +3859,12 @@ static int do_composite_observe_read_path_op(struct lwm2m_message *msg, uint16_t
lwm2m_path_free_list);
#endif
#if defined(CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT)
case LWM2M_FORMAT_APP_SENML_CBOR:
return do_composite_observe_parse_path_senml_cbor(msg, lwm2m_path_list,
lwm2m_path_free_list);
#endif
default:
LOG_ERR("Unsupported content-format: %u", content_format);
return -ENOMSG;
@ -4350,6 +4382,11 @@ static int do_write_op(struct lwm2m_message *msg,
return do_write_op_cbor(msg);
#endif
#ifdef CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT
case LWM2M_FORMAT_APP_SENML_CBOR:
return do_write_op_senml_cbor(msg);
#endif
default:
LOG_ERR("Unsupported format: %u", format);
return -ENOMSG;
@ -4366,6 +4403,11 @@ static int do_composite_write_op(struct lwm2m_message *msg,
return do_write_op_senml_json(msg);
#endif
#if defined(CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT)
case LWM2M_FORMAT_APP_SENML_CBOR:
return do_write_op_senml_cbor(msg);
#endif
default:
LOG_ERR("Unsupported format: %u", format);
return -ENOMSG;
@ -4523,7 +4565,10 @@ static int lwm2m_engine_default_content_format(uint16_t *accept_format)
{
if (IS_ENABLED(CONFIG_LWM2M_VERSION_1_1)) {
/* Select content format use SenML CBOR when it possible */
if (IS_ENABLED(CONFIG_LWM2M_RW_SENML_JSON_SUPPORT)) {
if (IS_ENABLED(CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT)) {
LOG_DBG("No accept option given. Assume SenML CBOR.");
*accept_format = LWM2M_FORMAT_APP_SENML_CBOR;
} else if (IS_ENABLED(CONFIG_LWM2M_RW_SENML_JSON_SUPPORT)) {
LOG_DBG("No accept option given. Assume SenML Json.");
*accept_format = LWM2M_FORMAT_APP_SEML_JSON;
} else if (IS_ENABLED(CONFIG_LWM2M_RW_CBOR_SUPPORT)) {
@ -6341,6 +6386,11 @@ static int do_send_op(struct lwm2m_message *msg, uint16_t content_format,
return do_send_op_senml_json(msg, lwm2m_path_list);
#endif
#if defined(CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT)
case LWM2M_FORMAT_APP_SENML_CBOR:
return do_send_op_senml_cbor(msg, lwm2m_path_list);
#endif
default:
LOG_ERR("Unsupported content-format for /dp: %u", content_format);
return -ENOMSG;
@ -6404,8 +6454,9 @@ int lwm2m_engine_send(struct lwm2m_ctx *ctx, char const *path_list[], uint8_t pa
return -E2BIG;
}
/* Select content format use CBOR when it possible */
if (IS_ENABLED(CONFIG_LWM2M_RW_SENML_JSON_SUPPORT)) {
if (IS_ENABLED(CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT)) {
content_format = LWM2M_FORMAT_APP_SENML_CBOR;
} else if (IS_ENABLED(CONFIG_LWM2M_RW_SENML_JSON_SUPPORT)) {
content_format = LWM2M_FORMAT_APP_SEML_JSON;
} else {
LOG_WRN("SenML CBOR or JSON is not supported");

View file

@ -29,6 +29,7 @@
#define LWM2M_FORMAT_APP_JSON 50
#define LWM2M_FORMAT_APP_CBOR 60
#define LWM2M_FORMAT_APP_SEML_JSON 110
#define LWM2M_FORMAT_APP_SENML_CBOR 112
#define LWM2M_FORMAT_OMA_PLAIN_TEXT 1541
#define LWM2M_FORMAT_OMA_OLD_TLV 1542
#define LWM2M_FORMAT_OMA_OLD_JSON 1543

View file

@ -428,7 +428,9 @@ struct lwm2m_senml_json_context senml_json_ctx;
uint8_t token[8];
uint8_t tkl;
bool last_block : 1;
uint8_t level; /* 3/4 (4 = resource instance) */
uint16_t res_id;
uint16_t res_inst_id;
};
struct lwm2m_output_context {

View file

@ -0,0 +1,898 @@
/*
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#define LOG_MODULE_NAME net_lwm2m_senml_cbor
#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <inttypes.h>
#include <ctype.h>
#include <sys/util.h>
#include <zcbor_common.h>
#include <zcbor_decode.h>
#include <zcbor_encode.h>
#include "lwm2m_engine.h"
#include "lwm2m_object.h"
#include "lwm2m_rw_senml_cbor.h"
#include "lwm2m_senml_cbor_decode.h"
#include "lwm2m_senml_cbor_encode.h"
#include "lwm2m_senml_cbor_types.h"
#include "lwm2m_util.h"
struct cbor_out_fmt_data {
/* Data */
struct lwm2m_senml input;
/* Storage for basenames and names ~ sizeof("/65535/999/") */
struct {
char names[CONFIG_LWM2M_RW_SENML_CBOR_RECORDS][sizeof("/65535/999/")];
size_t name_sz; /* Name buff size */
uint8_t name_cnt;
};
};
struct cbor_in_fmt_data {
/* Decoded data */
struct lwm2m_senml dcd; /* Decoded data */
struct record *current;
char basename[sizeof("/65535/999/")]; /* Null terminated basename */
};
#define GET_CBOR_FD_NAME(fd) ((fd)->names[(fd)->name_cnt])
/* Get the current record */
#define GET_CBOR_FD_REC(fd) \
&((fd)->input._lwm2m_senml__record[(fd)->input._lwm2m_senml__record_count])
/* Get a record */
#define GET_IN_FD_REC_I(fd, i) &((fd)->dcd._lwm2m_senml__record[i])
/* Consume the current record */
#define CONSUME_CBOR_FD_REC(fd) \
&((fd)->input._lwm2m_senml__record[(fd)->input._lwm2m_senml__record_count++])
/* Get CBOR output formatter data */
#define LWM2M_OFD_CBOR(octx) ((struct cbor_out_fmt_data *)engine_get_out_user_data(octx))
static struct cbor_out_fmt_data *setup_out_fmt_data(struct lwm2m_message *msg)
{
struct cbor_out_fmt_data *fd = malloc(sizeof(*fd));
if (!fd) {
return NULL;
}
(void)memset(fd, 0, sizeof(*fd));
engine_set_out_user_data(&msg->out, fd);
fd->name_sz = sizeof("/65535/999/");
return fd;
}
static void clear_out_fmt_data(struct lwm2m_message *msg, struct cbor_out_fmt_data *fd)
{
free(fd);
fd = NULL;
engine_clear_out_user_data(&msg->out);
}
static struct cbor_in_fmt_data *setup_in_fmt_data(struct lwm2m_message *msg)
{
struct cbor_in_fmt_data *fd = malloc(sizeof(*fd));
if (!fd) {
return NULL;
}
(void)memset(fd, 0, sizeof(*fd));
engine_set_in_user_data(&msg->in, fd);
return fd;
}
static void clear_in_fmt_data(struct lwm2m_message *msg, struct cbor_in_fmt_data *fd)
{
free(fd);
fd = NULL;
engine_clear_in_user_data(&msg->in);
}
static int put_basename(struct lwm2m_output_context *out, struct lwm2m_obj_path *path)
{
struct cbor_out_fmt_data *fd = LWM2M_OFD_CBOR(out);
int len;
if (fd->name_cnt >= CONFIG_LWM2M_RW_SENML_CBOR_RECORDS) {
LOG_ERR("CONFIG_LWM2M_RW_SENML_CBOR_RECORDS too small");
return -ENOMEM;
}
char *basename = GET_CBOR_FD_NAME(fd);
len = lwm2m_path_to_string(basename, fd->name_sz, path, LWM2M_PATH_LEVEL_OBJECT_INST);
if (len < 0) {
return len;
}
/* Tell CBOR encoder where to find the name */
struct record *record = GET_CBOR_FD_REC(fd);
record->_record_bn._record_bn.value = basename;
record->_record_bn._record_bn.len = len;
record->_record_bn_present = 1;
if ((len < sizeof("0/0") - 1) || (len >= sizeof("65535/999"))) {
__ASSERT_NO_MSG(false);
return -EINVAL;
}
fd->name_cnt++;
return 0;
}
static int put_end(struct lwm2m_output_context *out, struct lwm2m_obj_path *path)
{
size_t len;
uint_fast8_t ret =
cbor_encode_lwm2m_senml(CPKT_BUF_W_REGION(out->out_cpkt),
(struct lwm2m_senml *)&(LWM2M_OFD_CBOR(out)->input), &len);
if (ret != ZCBOR_SUCCESS) {
LOG_ERR("unable to encode senml cbor msg");
return -E2BIG;
}
out->out_cpkt->offset += len;
return len;
}
static int put_begin_oi(struct lwm2m_output_context *out, struct lwm2m_obj_path *path)
{
int ret;
uint8_t tmp = path->level;
/* In case path level is set to 'none' or 'object' and we have only default oi */
path->level = LWM2M_PATH_LEVEL_OBJECT_INST;
ret = put_basename(out, path);
path->level = tmp;
return ret;
}
static int put_begin_r(struct lwm2m_output_context *out, struct lwm2m_obj_path *path)
{
struct cbor_out_fmt_data *fd = LWM2M_OFD_CBOR(out);
int len;
if (fd->name_cnt >= CONFIG_LWM2M_RW_SENML_CBOR_RECORDS) {
LOG_ERR("CONFIG_LWM2M_RW_SENML_CBOR_RECORDS too small");
return -ENOMEM;
}
char *name = GET_CBOR_FD_NAME(fd);
/* Write resource name */
len = snprintk(name, sizeof("65535"), "%" PRIu16 "", path->res_id);
if (len < sizeof("0") - 1) {
__ASSERT_NO_MSG(false);
return -EINVAL;
}
/* Check if we could use an already existing name
* -> latest name slot is used as a scratchpad
*/
for (int idx = 0; idx < fd->name_cnt; idx++) {
if (strncmp(name, fd->names[idx], len) == 0) {
name = fd->names[idx];
break;
}
}
/* Tell CBOR encoder where to find the name */
struct record *record = GET_CBOR_FD_REC(fd);
record->_record_n._record_n.value = name;
record->_record_n._record_n.len = len;
record->_record_n_present = 1;
/* Makes possible to use same slot for storing r/ri name combination.
* No need to increase the name count if an existing name has been used
*/
if (path->level < LWM2M_PATH_LEVEL_RESOURCE_INST && name == GET_CBOR_FD_NAME(fd)) {
fd->name_cnt++;
}
return 0;
}
static int put_begin_ri(struct lwm2m_output_context *out, struct lwm2m_obj_path *path)
{
struct cbor_out_fmt_data *fd = LWM2M_OFD_CBOR(out);
char *name = GET_CBOR_FD_NAME(fd);
struct record *record = GET_CBOR_FD_REC(fd);
if (fd->name_cnt >= CONFIG_LWM2M_RW_SENML_CBOR_RECORDS) {
LOG_ERR("CONFIG_LWM2M_RW_SENML_CBOR_RECORDS too small");
return -ENOMEM;
}
/* Forms name from resource id and resource instance id */
int len = snprintk(name, sizeof("65535/999"),
"%" PRIu16 "/%" PRIu16 "",
path->res_id, path->res_inst_id);
if (len < sizeof("0/0") - 1) {
__ASSERT_NO_MSG(false);
return -EINVAL;
}
/* Check if we could use an already existing name
* -> latest name slot is used as a scratchpad
*/
for (int idx = 0; idx < fd->name_cnt; idx++) {
if (strncmp(name, fd->names[idx], len) == 0) {
name = fd->names[idx];
break;
}
}
/* Tell CBOR encoder where to find the name */
record->_record_n._record_n.value = name;
record->_record_n._record_n.len = len;
record->_record_n_present = 1;
/* No need to increase the name count if an existing name has been used */
if (name == GET_CBOR_FD_NAME(fd)) {
fd->name_cnt++;
}
return 0;
}
static int put_name_nth_ri(struct lwm2m_output_context *out, struct lwm2m_obj_path *path)
{
int ret = 0;
/* With the first ri the resource name (and ri name) are already in place */
if (path->res_inst_id > 0) {
ret = put_begin_ri(out, path);
}
return ret;
}
static int put_value(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int64_t value)
{
int ret = put_name_nth_ri(out, path);
if (ret < 0) {
return ret;
}
struct record *record = CONSUME_CBOR_FD_REC(LWM2M_OFD_CBOR(out));
/* Write the value */
record->_record_union._record_union_choice = _union_v;
record->_record_union._union_v._numeric_choice = _numeric_int;
record->_record_union._union_v._numeric_int = value;
record->_record_union_present = 1;
return 0;
}
static int put_s8(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int8_t value)
{
return put_value(out, path, value);
}
static int put_s16(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int16_t value)
{
return put_value(out, path, value);
}
static int put_s32(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int32_t value)
{
return put_value(out, path, value);
}
static int put_s64(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int64_t value)
{
return put_value(out, path, value);
}
static int put_time(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int64_t value)
{
int ret = put_name_nth_ri(out, path);
if (ret < 0) {
return ret;
}
struct record *record = CONSUME_CBOR_FD_REC(LWM2M_OFD_CBOR(out));
/* Write the value */
record->_record_union._record_union_choice = _union_v;
record->_record_union._union_v._numeric_choice = _numeric_int;
record->_record_union._union_v._numeric_int = value;
record->_record_union_present = 1;
return 0;
}
static int put_float(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, double *value)
{
int ret = put_name_nth_ri(out, path);
if (ret < 0) {
return ret;
}
struct record *record = CONSUME_CBOR_FD_REC(LWM2M_OFD_CBOR(out));
/* Write the value */
record->_record_union._record_union_choice = _union_v;
record->_record_union._union_v._numeric_choice = _numeric_float;
record->_record_union._union_v._numeric_float = *value;
record->_record_union_present = 1;
return 0;
}
static int put_string(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, char *buf,
size_t buflen)
{
int ret = put_name_nth_ri(out, path);
if (ret < 0) {
return ret;
}
struct record *record = CONSUME_CBOR_FD_REC(LWM2M_OFD_CBOR(out));
/* Write the value */
record->_record_union._record_union_choice = _union_vs;
record->_record_union._union_vs.value = buf;
record->_record_union._union_vs.len = buflen;
record->_record_union_present = 1;
return 0;
}
static int put_bool(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, bool value)
{
int ret = put_name_nth_ri(out, path);
if (ret < 0) {
return ret;
}
struct record *record = CONSUME_CBOR_FD_REC(LWM2M_OFD_CBOR(out));
/* Write the value */
record->_record_union._record_union_choice = _union_vb;
record->_record_union._union_vb = value;
record->_record_union_present = 1;
return 0;
}
static int put_opaque(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, char *buf,
size_t buflen)
{
int ret = put_name_nth_ri(out, path);
if (ret < 0) {
return ret;
}
struct record *record = CONSUME_CBOR_FD_REC(LWM2M_OFD_CBOR(out));
/* Write the value */
record->_record_union._record_union_choice = _union_vd;
record->_record_union._union_vd.value = buf;
record->_record_union._union_vd.len = buflen;
record->_record_union_present = 1;
return 0;
}
static int put_objlnk(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
struct lwm2m_objlnk *value)
{
int32_t value_s32 = (value->obj_id << 16) | value->obj_inst;
return put_s32(out, path, value_s32);
}
static int get_opaque(struct lwm2m_input_context *in,
uint8_t *value, size_t buflen,
struct lwm2m_opaque_context *opaque,
bool *last_block)
{
struct cbor_in_fmt_data *fd;
/* Get the CBOR header only on first read. */
if (opaque->remaining == 0) {
fd = engine_get_in_user_data(in);
if (!fd || !fd->current) {
return -EINVAL;
}
/* TODO: get the opaque data and it's length -
* now plain zero
*/
opaque->len = fd->current->_record_union._union_vd.len;
opaque->remaining = fd->current->_record_union._union_vd.len;
fd->current = NULL;
goto not_supported;
}
return lwm2m_engine_get_opaque_more(in, value, buflen,
opaque, last_block);
not_supported:
return -ENOTSUP;
}
static int get_s32(struct lwm2m_input_context *in, int32_t *value)
{
struct cbor_in_fmt_data *fd;
fd = engine_get_in_user_data(in);
if (!fd || !fd->current) {
return -EINVAL;
}
*value = fd->current->_record_union._union_v._numeric_int;
fd->current = NULL;
return 0;
}
static int get_s64(struct lwm2m_input_context *in, int64_t *value)
{
struct cbor_in_fmt_data *fd;
fd = engine_get_in_user_data(in);
if (!fd || !fd->current) {
return -EINVAL;
}
*value = fd->current->_record_union._union_v._numeric_int;
fd->current = NULL;
return 0;
}
static int get_float(struct lwm2m_input_context *in, double *value)
{
struct cbor_in_fmt_data *fd;
fd = engine_get_in_user_data(in);
if (!fd || !fd->current) {
return -EINVAL;
}
*value = fd->current->_record_union._union_v._numeric_float;
fd->current = NULL;
return 0;
}
static int get_string(struct lwm2m_input_context *in, uint8_t *buf, size_t buflen)
{
struct cbor_in_fmt_data *fd;
int len;
fd = engine_get_in_user_data(in);
if (!fd || !fd->current) {
return -EINVAL;
}
len = MIN(buflen-1, fd->current->_record_union._union_vs.len);
memcpy(buf, fd->current->_record_union._union_vs.value, len);
buf[len] = '\0';
fd->current = NULL;
return 0;
}
static int get_objlnk(struct lwm2m_input_context *in,
struct lwm2m_objlnk *value)
{
char objlnk[sizeof("65535:65535")] = {0};
unsigned long id;
int ret;
ret = get_string(in, objlnk, sizeof(objlnk));
if (ret < 0) {
return ret;
}
value->obj_id = LWM2M_OBJLNK_MAX_ID;
value->obj_inst = LWM2M_OBJLNK_MAX_ID;
char *end;
char *idp = objlnk;
for (int idx = 0; idx < 2; idx++) {
errno = 0;
id = strtoul(idp, &end, 10);
idp = end;
if ((id == 0 && errno == ERANGE) || id > 65535) {
LOG_WRN("decoded id %lu out of range[0..65535]", id);
return -EBADMSG;
}
switch (idx) {
case 0:
value->obj_id = id;
continue;
case 1:
value->obj_inst = id;
continue;
}
}
if (value->obj_inst != LWM2M_OBJLNK_MAX_ID && (value->obj_id == LWM2M_OBJLNK_MAX_ID)) {
LOG_WRN("decoded obj inst id without obj id");
return -EBADMSG;
}
return ret;
}
static int get_bool(struct lwm2m_input_context *in, bool *value)
{
struct cbor_in_fmt_data *fd;
fd = engine_get_in_user_data(in);
if (!fd || !fd->current) {
return -EINVAL;
}
*value = fd->current->_record_union._union_vb;
fd->current = NULL;
return 0;
}
static int do_write_op_item(struct lwm2m_message *msg, struct record *rec)
{
struct lwm2m_engine_obj_inst *obj_inst = NULL;
struct lwm2m_engine_obj_field *obj_field;
struct lwm2m_engine_res *res = NULL;
struct lwm2m_engine_res_inst *res_inst = NULL;
int ret;
uint8_t created = 0U;
struct cbor_in_fmt_data *fd;
fd = engine_get_in_user_data(&msg->in);
if (!fd) {
return -EINVAL;
}
/* Composite op - name with basename */
if (rec->_record_n_present) {
char name[sizeof("65535/999")]; /* Null terminated name */
int len = MIN(sizeof(name) - 1, rec->_record_n._record_n.len);
char fqn[MAX_RESOURCE_LEN + 1] = {0};
snprintk(name, len + 1, "%s", rec->_record_n._record_n.value);
/* Form fully qualified path name */
snprintk(fqn, sizeof(fqn), "%s%s", fd->basename, name);
/* Set path on record basis */
ret = lwm2m_string_to_path(fqn, &msg->path, '/');
if (ret < 0) {
__ASSERT_NO_MSG(false);
return ret;
}
}
fd->current = rec;
ret = lwm2m_get_or_create_engine_obj(msg, &obj_inst, &created);
if (ret < 0) {
return ret;
}
ret = lwm2m_engine_validate_write_access(msg, obj_inst, &obj_field);
if (ret < 0) {
return ret;
}
ret = lwm2m_engine_get_create_res_inst(&msg->path, &res, &res_inst);
if (ret < 0) {
return -ENOENT;
}
return lwm2m_write_handler(obj_inst, res, res_inst, obj_field, msg);
}
const struct lwm2m_writer senml_cbor_writer = {
.put_end = put_end,
.put_begin_oi = put_begin_oi,
.put_begin_r = put_begin_r,
.put_begin_ri = put_begin_ri,
.put_s8 = put_s8,
.put_s16 = put_s16,
.put_s32 = put_s32,
.put_s64 = put_s64,
.put_time = put_time,
.put_string = put_string,
.put_float = put_float,
.put_bool = put_bool,
.put_opaque = put_opaque,
.put_objlnk = put_objlnk,
};
const struct lwm2m_reader senml_cbor_reader = {
.get_s32 = get_s32,
.get_s64 = get_s64,
.get_time = get_s64,
.get_string = get_string,
.get_float = get_float,
.get_bool = get_bool,
.get_opaque = get_opaque,
.get_objlnk = get_objlnk,
};
int do_read_op_senml_cbor(struct lwm2m_message *msg)
{
int ret;
struct cbor_out_fmt_data *fd = setup_out_fmt_data(msg);
if (!fd) {
return -ENOMEM;
}
ret = lwm2m_perform_read_op(msg, LWM2M_FORMAT_APP_SENML_CBOR);
clear_out_fmt_data(msg, fd);
return ret;
}
static uint8_t parse_composite_read_paths(struct lwm2m_message *msg,
sys_slist_t *lwm2m_path_list,
sys_slist_t *lwm2m_path_free_list)
{
char basename[MAX_RESOURCE_LEN + 1] = {0}; /* to include terminating null */
char name[MAX_RESOURCE_LEN + 1] = {0}; /* to include terminating null */
char fqn[MAX_RESOURCE_LEN + 1] = {0};
struct lwm2m_obj_path path;
struct cbor_in_fmt_data *fd;
uint8_t paths = 0;
uint32_t isize;
uint_fast8_t dret;
int len;
int ret;
fd = setup_in_fmt_data(msg);
if (!fd) {
LOG_ERR("unable to decode composite read paths, out of memory");
return -ENOMEM;
}
dret = cbor_decode_lwm2m_senml(ICTX_BUF_R_REGION(&msg->in), &fd->dcd, &isize);
if (dret != ZCBOR_SUCCESS) {
__ASSERT_NO_MSG(false);
goto out;
}
msg->in.offset += isize;
for (int idx = 0; idx < fd->dcd._lwm2m_senml__record_count; idx++) {
/* Where to find the basenames and names */
struct record *record = GET_IN_FD_REC_I(fd, idx);
/* Set null terminated effective basename */
if (record->_record_bn_present) {
len = MIN(sizeof(basename)-1, record->_record_bn._record_bn.len);
snprintk(basename, len + 1, "%s", record->_record_bn._record_bn.value);
basename[len] = '\0';
}
/* Best effort with read, skip if no proper name is available */
if (!record->_record_n_present) {
if (strcmp(basename, "") == 0) {
continue;
}
}
/* Set null terminated name */
if (record->_record_n_present) {
len = MIN(sizeof(name)-1, record->_record_n._record_n.len);
snprintk(name, len + 1, "%s", record->_record_n._record_n.value);
name[len] = '\0';
}
/* Form fully qualified path name */
snprintk(fqn, sizeof(fqn), "%s%s", basename, name);
ret = lwm2m_string_to_path(fqn, &path, '/');
/* invalid path is forgiven with read */
if (ret < 0) {
continue;
}
ret = lwm2m_engine_add_path_to_list(lwm2m_path_list, lwm2m_path_free_list, &path);
if (ret < 0) {
continue;
}
paths++;
}
out:
clear_in_fmt_data(msg, fd);
return paths;
}
int do_composite_read_op_senml_cbor(struct lwm2m_message *msg)
{
int ret;
struct cbor_out_fmt_data *fd;
struct lwm2m_obj_path_list lwm2m_path_list_buf[CONFIG_LWM2M_COMPOSITE_PATH_LIST_SIZE];
sys_slist_t lwm_path_list;
sys_slist_t lwm_path_free_list;
uint8_t len;
lwm2m_engine_path_list_init(&lwm_path_list,
&lwm_path_free_list,
lwm2m_path_list_buf,
CONFIG_LWM2M_COMPOSITE_PATH_LIST_SIZE);
/* Parse paths */
len = parse_composite_read_paths(msg, &lwm_path_list, &lwm_path_free_list);
if (len == 0) {
LOG_ERR("No Valid URL at msg");
return -ESRCH;
}
lwm2m_engine_clear_duplicate_path(&lwm_path_list, &lwm_path_free_list);
fd = setup_out_fmt_data(msg);
if (!fd) {
LOG_ERR("unable to encode composite read msg, out of memory");
return -ENOMEM;
}
ret = lwm2m_perform_composite_read_op(msg, LWM2M_FORMAT_APP_SENML_CBOR, &lwm_path_list);
clear_out_fmt_data(msg, fd);
return ret;
}
int do_write_op_senml_cbor(struct lwm2m_message *msg)
{
uint_fast8_t dret;
int ret = 0;
uint32_t decoded_sz;
struct cbor_in_fmt_data *fd;
/* With block-wise transfer consecutive blocks will not carry the content header -
* go directly to the message processing
*/
if (msg->in.block_ctx != NULL && msg->in.block_ctx->ctx.current > 0) {
msg->path.res_id = msg->in.block_ctx->res_id;
msg->path.level = msg->in.block_ctx->level;
if (msg->path.level == LWM2M_PATH_LEVEL_RESOURCE_INST) {
msg->path.res_inst_id = msg->in.block_ctx->res_inst_id;
}
return do_write_op_item(msg, NULL);
}
fd = setup_in_fmt_data(msg);
if (!fd) {
LOG_ERR("unable to decode msg, out of memory");
return -ENOMEM;
}
dret = cbor_decode_lwm2m_senml(ICTX_BUF_R_PTR(&msg->in), ICTX_BUF_R_LEFT_SZ(&msg->in),
&fd->dcd, &decoded_sz);
if (dret == ZCBOR_SUCCESS) {
msg->in.offset += decoded_sz;
for (int idx = 0; idx < fd->dcd._lwm2m_senml__record_count; idx++) {
struct record *rec = &fd->dcd._lwm2m_senml__record[idx];
/* Basename applies for current and succeeding records */
if (rec->_record_bn_present) {
int len = MIN(sizeof(fd->basename) - 1,
rec->_record_bn._record_bn.len);
snprintk(fd->basename, len + 1, "%s",
rec->_record_bn._record_bn.value);
}
ret = do_write_op_item(msg, rec);
/* Write isn't supposed to fail */
if (ret < 0) {
break;
}
}
} else {
ret = -EBADMSG;
}
clear_in_fmt_data(msg, fd);
return ret < 0 ? ret : decoded_sz;
}
int do_composite_observe_parse_path_senml_cbor(struct lwm2m_message *msg,
sys_slist_t *lwm2m_path_list,
sys_slist_t *lwm2m_path_free_list)
{
uint16_t original_offset;
uint8_t len;
original_offset = msg->in.offset;
/* Parse paths */
len = parse_composite_read_paths(msg, lwm2m_path_list, lwm2m_path_free_list);
if (len == 0) {
LOG_ERR("No Valid URL at msg");
return -ESRCH;
}
msg->in.offset = original_offset;
return 0;
}
int do_send_op_senml_cbor(struct lwm2m_message *msg, sys_slist_t *lwm2m_path_list)
{
int ret;
struct cbor_out_fmt_data *fd = setup_out_fmt_data(msg);
if (!fd) {
LOG_ERR("Unable to complete SEND op, out of memory");
return -ENOMEM;
}
ret = lwm2m_perform_composite_read_op(msg, LWM2M_FORMAT_APP_SENML_CBOR, lwm2m_path_list);
clear_out_fmt_data(msg, fd);
return ret;
}

View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef LWM2M_RW_SENML_CBOR_H_
#define LWM2M_RW_SENML_CBOR_H_
#include "lwm2m_object.h"
extern const struct lwm2m_writer senml_cbor_writer;
extern const struct lwm2m_reader senml_cbor_reader;
int do_read_op_senml_cbor(struct lwm2m_message *msg);
int do_composite_read_op_senml_cbor(struct lwm2m_message *msg);
int do_write_op_senml_cbor(struct lwm2m_message *msg);
int do_composite_observe_parse_path_senml_cbor(struct lwm2m_message *msg,
sys_slist_t *lwm2m_path_list,
sys_slist_t *lwm2m_path_free_list);
int do_send_op_senml_cbor(struct lwm2m_message *msg, sys_slist_t *lwm2m_path_list);
#endif /* LWM2M_RW_SENML_CBOR_H_ */

View file

@ -0,0 +1,207 @@
/*
* Generated using zcbor version 0.3.99
* https://github.com/zephyrproject-rtos/zcbor
* Generated with a --default-max-qty of 99
*/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "zcbor_decode.h"
#include "lwm2m_senml_cbor_decode.h"
#if DEFAULT_MAX_QTY != 99
#error "The type file was generated with a different default_max_qty than this file"
#endif
static bool decode_repeated_record_bn(zcbor_state_t *state, struct record_bn *result)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result = ((((zcbor_int32_expect(state, (-2)))) &&
(zcbor_tstr_decode(state, (&(*result)._record_bn)))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool decode_repeated_record_n(zcbor_state_t *state, struct record_n *result)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result = ((((zcbor_uint32_expect(state, (0)))) &&
(zcbor_tstr_decode(state, (&(*result)._record_n)))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool decode_numeric(zcbor_state_t *state, struct numeric_ *result)
{
zcbor_print("%s\r\n", __func__);
bool int_res;
bool tmp_result =
(((zcbor_union_start_code(state) &&
(int_res = ((((zcbor_int64_decode(state, (&(*result)._numeric_int))) &&
((((*result)._numeric_int >= -9223372036854775807LL) &&
((*result)._numeric_int <= 9223372036854775807LL)) ||
(zcbor_error(state, ZCBOR_ERR_WRONG_RANGE), false))) &&
(((*result)._numeric_choice = _numeric_int) || 1)) ||
(((zcbor_float_decode(state, (&(*result)._numeric_float)))) &&
(((*result)._numeric_choice = _numeric_float) || 1))),
zcbor_union_end_code(state), int_res))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool decode_repeated_record_union(zcbor_state_t *state, struct record_union_ *result)
{
zcbor_print("%s\r\n", __func__);
bool int_res;
bool tmp_result = (((zcbor_union_start_code(state) &&
(int_res = (((((zcbor_uint32_expect_union(state, (2)))) &&
(decode_numeric(state, (&(*result)._union_v)))) &&
(((*result)._record_union_choice = _union_v) || 1)) ||
((((zcbor_uint32_expect_union(state, (3)))) &&
(zcbor_tstr_decode(state, (&(*result)._union_vs)))) &&
(((*result)._record_union_choice = _union_vs) || 1)) ||
((((zcbor_uint32_expect_union(state, (4)))) &&
(zcbor_bool_decode(state, (&(*result)._union_vb)))) &&
(((*result)._record_union_choice = _union_vb) || 1)) ||
((((zcbor_uint32_expect_union(state, (8)))) &&
(zcbor_bstr_decode(state, (&(*result)._union_vd)))) &&
(((*result)._record_union_choice = _union_vd) || 1))),
zcbor_union_end_code(state), int_res))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool decode_value(zcbor_state_t *state, struct value_ *result)
{
zcbor_print("%s\r\n", __func__);
bool int_res;
bool tmp_result =
(((zcbor_union_start_code(state) &&
(int_res = ((((zcbor_tstr_decode(state, (&(*result)._value_tstr)))) &&
(((*result)._value_choice = _value_tstr) || 1)) ||
(((zcbor_bstr_decode(state, (&(*result)._value_bstr)))) &&
(((*result)._value_choice = _value_bstr) || 1)) ||
(zcbor_union_elem_code(state) &&
(((decode_numeric(state, (&(*result)._value__numeric)))) &&
(((*result)._value_choice = _value__numeric) || 1))) ||
(zcbor_union_elem_code(state) &&
(((zcbor_bool_decode(state, (&(*result)._value_bool)))) &&
(((*result)._value_choice = _value_bool) || 1)))),
zcbor_union_end_code(state), int_res))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool decode_key_value_pair(zcbor_state_t *state, struct key_value_pair *result)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result = ((((zcbor_int32_decode(state, (&(*result)._key_value_pair_key)))) &&
(decode_value(state, (&(*result)._key_value_pair)))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool decode_repeated_record__key_value_pair(zcbor_state_t *state,
struct record__key_value_pair *result)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result = (((decode_key_value_pair(state, (&(*result)._record__key_value_pair)))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool decode_record(zcbor_state_t *state, struct record *result)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result =
(((zcbor_map_start_decode(state) &&
((zcbor_present_decode(&((*result)._record_bn_present),
(zcbor_decoder_t *)decode_repeated_record_bn, state,
(&(*result)._record_bn)) &&
zcbor_present_decode(&((*result)._record_n_present),
(zcbor_decoder_t *)decode_repeated_record_n, state,
(&(*result)._record_n)) &&
zcbor_present_decode(&((*result)._record_union_present),
(zcbor_decoder_t *)decode_repeated_record_union, state,
(&(*result)._record_union)) &&
zcbor_multi_decode(0, 3, &(*result)._record__key_value_pair_count,
(zcbor_decoder_t *)decode_repeated_record__key_value_pair,
state, (&(*result)._record__key_value_pair),
sizeof(struct record__key_value_pair))) ||
(zcbor_list_map_end_force_decode(state), false)) &&
zcbor_map_end_decode(state))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool decode_lwm2m_senml(zcbor_state_t *state, struct lwm2m_senml *result)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result = ((
(zcbor_list_start_decode(state) &&
((zcbor_multi_decode(1, 99, &(*result)._lwm2m_senml__record_count,
(zcbor_decoder_t *)decode_record, state,
(&(*result)._lwm2m_senml__record), sizeof(struct record))) ||
(zcbor_list_map_end_force_decode(state), false)) &&
zcbor_list_end_decode(state))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
uint_fast8_t cbor_decode_lwm2m_senml(const uint8_t *payload, size_t payload_len,
struct lwm2m_senml *result, size_t *payload_len_out)
{
zcbor_state_t states[6];
zcbor_new_state(states, sizeof(states) / sizeof(zcbor_state_t), payload, payload_len, 1);
bool ret = decode_lwm2m_senml(states, result);
if (ret && (payload_len_out != NULL)) {
*payload_len_out = MIN(payload_len, (size_t)states[0].payload - (size_t)payload);
}
if (!ret) {
uint_fast8_t ret = zcbor_pop_error(states);
return (ret == ZCBOR_SUCCESS) ? ZCBOR_ERR_UNKNOWN : ret;
}
return ZCBOR_SUCCESS;
}

View file

@ -0,0 +1,24 @@
/*
* Generated using zcbor version 0.3.99
* https://github.com/zephyrproject-rtos/zcbor
* Generated with a --default-max-qty of 99
*/
#ifndef LWM2M_SENML_CBOR_DECODE_H__
#define LWM2M_SENML_CBOR_DECODE_H__
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "zcbor_decode.h"
#include "lwm2m_senml_cbor_decode_types.h"
#if DEFAULT_MAX_QTY != 99
#error "The type file was generated with a different default_max_qty than this file"
#endif
uint_fast8_t cbor_decode_lwm2m_senml(const uint8_t *payload, size_t payload_len,
struct lwm2m_senml *result, size_t *payload_len_out);
#endif /* LWM2M_SENML_CBOR_DECODE_H__ */

View file

@ -0,0 +1,203 @@
/*
* Generated using zcbor version 0.3.99
* https://github.com/zephyrproject-rtos/zcbor
* Generated with a --default-max-qty of 99
*/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "zcbor_encode.h"
#include "lwm2m_senml_cbor_encode.h"
#if DEFAULT_MAX_QTY != 99
#error "The type file was generated with a different default_max_qty than this file"
#endif
static bool encode_repeated_record_bn(zcbor_state_t *state, const struct record_bn *input)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result = ((((zcbor_int32_put(state, (-2)))) &&
(zcbor_tstr_encode(state, (&(*input)._record_bn)))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool encode_repeated_record_n(zcbor_state_t *state, const struct record_n *input)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result = ((((zcbor_uint32_put(state, (0)))) &&
(zcbor_tstr_encode(state, (&(*input)._record_n)))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool encode_numeric(zcbor_state_t *state, const struct numeric_ *input)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result =
(((((*input)._numeric_choice == _numeric_int) ?
(((((*input)._numeric_int >= -9223372036854775807LL) &&
((*input)._numeric_int <= 9223372036854775807LL)) ||
(zcbor_error(state, ZCBOR_ERR_WRONG_RANGE), false)) &&
(zcbor_int64_encode(state, (&(*input)._numeric_int)))) :
(((*input)._numeric_choice == _numeric_float) ?
((zcbor_float64_encode(state, (&(*input)._numeric_float)))) :
false))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool encode_repeated_record_union(zcbor_state_t *state, const struct record_union_ *input)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result =
(((((*input)._record_union_choice == _union_v) ?
(((zcbor_uint32_put(state, (2)))) &&
(encode_numeric(state, (&(*input)._union_v)))) :
(((*input)._record_union_choice == _union_vs) ?
(((zcbor_uint32_put(state, (3)))) &&
(zcbor_tstr_encode(state, (&(*input)._union_vs)))) :
(((*input)._record_union_choice == _union_vb) ?
(((zcbor_uint32_put(state, (4)))) &&
(zcbor_bool_encode(state, (&(*input)._union_vb)))) :
(((*input)._record_union_choice == _union_vd) ?
(((zcbor_uint32_put(state, (8)))) &&
(zcbor_bstr_encode(state,
(&(*input)._union_vd)))) :
false))))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool encode_value(zcbor_state_t *state, const struct value_ *input)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result = ((
(((*input)._value_choice == _value_tstr) ?
((zcbor_tstr_encode(state, (&(*input)._value_tstr)))) :
(((*input)._value_choice == _value_bstr) ?
((zcbor_bstr_encode(state, (&(*input)._value_bstr)))) :
(((*input)._value_choice == _value__numeric) ?
((encode_numeric(state, (&(*input)._value__numeric)))) :
(((*input)._value_choice == _value_bool) ?
((zcbor_bool_encode(state,
(&(*input)._value_bool)))) :
false))))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool encode_key_value_pair(zcbor_state_t *state, const struct key_value_pair *input)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result = ((((zcbor_int32_encode(state, (&(*input)._key_value_pair_key)))) &&
(encode_value(state, (&(*input)._key_value_pair)))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool encode_repeated_record__key_value_pair(zcbor_state_t *state,
const struct record__key_value_pair *input)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result = (((encode_key_value_pair(state, (&(*input)._record__key_value_pair)))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool encode_record(zcbor_state_t *state, const struct record *input)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result = (((zcbor_map_start_encode(state, 6) &&
((zcbor_present_encode(&((*input)._record_bn_present),
(zcbor_encoder_t *)encode_repeated_record_bn,
state, (&(*input)._record_bn)) &&
zcbor_present_encode(&((*input)._record_n_present),
(zcbor_encoder_t *)encode_repeated_record_n,
state, (&(*input)._record_n)) &&
zcbor_present_encode(&((*input)._record_union_present),
(zcbor_encoder_t *)encode_repeated_record_union,
state, (&(*input)._record_union)) &&
zcbor_multi_encode_minmax(
0, 3, &(*input)._record__key_value_pair_count,
(zcbor_encoder_t *)encode_repeated_record__key_value_pair,
state, (&(*input)._record__key_value_pair),
sizeof(struct record__key_value_pair))) ||
(zcbor_list_map_end_force_encode(state), false)) &&
zcbor_map_end_encode(state, 6))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
static bool encode_lwm2m_senml(zcbor_state_t *state, const struct lwm2m_senml *input)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result =
(((zcbor_list_start_encode(state, 99) &&
((zcbor_multi_encode_minmax(1, 99, &(*input)._lwm2m_senml__record_count,
(zcbor_encoder_t *)encode_record, state,
(&(*input)._lwm2m_senml__record),
sizeof(struct record))) ||
(zcbor_list_map_end_force_encode(state), false)) &&
zcbor_list_end_encode(state, 99))));
if (!tmp_result)
zcbor_trace();
return tmp_result;
}
uint_fast8_t cbor_encode_lwm2m_senml(uint8_t *payload, size_t payload_len,
const struct lwm2m_senml *input, size_t *payload_len_out)
{
zcbor_state_t states[6];
zcbor_new_state(states, sizeof(states) / sizeof(zcbor_state_t), payload, payload_len, 1);
bool ret = encode_lwm2m_senml(states, input);
if (ret && (payload_len_out != NULL)) {
*payload_len_out = MIN(payload_len, (size_t)states[0].payload - (size_t)payload);
}
if (!ret) {
uint_fast8_t ret = zcbor_pop_error(states);
return (ret == ZCBOR_SUCCESS) ? ZCBOR_ERR_UNKNOWN : ret;
}
return ZCBOR_SUCCESS;
}

View file

@ -0,0 +1,24 @@
/*
* Generated using zcbor version 0.3.99
* https://github.com/zephyrproject-rtos/zcbor
* Generated with a --default-max-qty of 99
*/
#ifndef LWM2M_SENML_CBOR_ENCODE_H__
#define LWM2M_SENML_CBOR_ENCODE_H__
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "zcbor_encode.h"
#include "lwm2m_senml_cbor_encode_types.h"
#if DEFAULT_MAX_QTY != 99
#error "The type file was generated with a different default_max_qty than this file"
#endif
uint_fast8_t cbor_encode_lwm2m_senml(uint8_t *payload, size_t payload_len,
const struct lwm2m_senml *input, size_t *payload_len_out);
#endif /* LWM2M_SENML_CBOR_ENCODE_H__ */

View file

@ -0,0 +1,104 @@
/*
* Generated using zcbor version 0.3.99
* https://github.com/zephyrproject-rtos/zcbor
* Generated with a --default-max-qty of 99
*/
#ifndef LWM2M_SENML_CBOR_DECODE_TYPES_H__
#define LWM2M_SENML_CBOR_DECODE_TYPES_H__
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "zcbor_decode.h"
/** Which value for --default-max-qty this file was created with.
*
* The define is used in the other generated file to do a build-time
* compatibility check.
*
* See `zcbor --help` for more information about --default-max-qty
*/
#define DEFAULT_MAX_QTY 99
struct record_bn {
struct zcbor_string _record_bn;
};
struct record_n {
struct zcbor_string _record_n;
};
struct numeric_ {
union {
int64_t _numeric_int;
double _numeric_float;
};
enum { _numeric_int,
_numeric_float,
} _numeric_choice;
};
struct record_union_ {
union {
struct {
struct numeric_ _union_v;
};
struct {
struct zcbor_string _union_vs;
};
struct {
bool _union_vb;
};
struct {
struct zcbor_string _union_vd;
};
};
enum { _union_v,
_union_vs,
_union_vb,
_union_vd,
} _record_union_choice;
};
struct value_ {
union {
struct zcbor_string _value_tstr;
struct zcbor_string _value_bstr;
struct numeric_ _value__numeric;
bool _value_bool;
};
enum { _value_tstr,
_value_bstr,
_value__numeric,
_value_bool,
} _value_choice;
};
struct key_value_pair {
int32_t _key_value_pair_key;
struct value_ _key_value_pair;
};
struct record__key_value_pair {
struct key_value_pair _record__key_value_pair;
};
struct record {
struct record_bn _record_bn;
uint_fast32_t _record_bn_present;
struct record_n _record_n;
uint_fast32_t _record_n_present;
struct record_union_ _record_union;
uint_fast32_t _record_union_present;
struct record__key_value_pair _record__key_value_pair[3];
uint_fast32_t _record__key_value_pair_count;
};
struct lwm2m_senml {
struct record _lwm2m_senml__record[99];
uint_fast32_t _lwm2m_senml__record_count;
};
#endif /* LWM2M_SENML_CBOR_DECODE_TYPES_H__ */