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:
parent
2ef96e2f66
commit
0562de9fbe
12 changed files with 1563 additions and 3 deletions
|
@ -59,6 +59,12 @@ zephyr_library_sources_ifdef(CONFIG_LWM2M_RW_SENML_JSON_SUPPORT
|
||||||
zephyr_library_sources_ifdef(CONFIG_LWM2M_RW_CBOR_SUPPORT
|
zephyr_library_sources_ifdef(CONFIG_LWM2M_RW_CBOR_SUPPORT
|
||||||
lwm2m_rw_cbor.c
|
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
|
# IPSO Objects
|
||||||
zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_TEMP_SENSOR
|
zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_TEMP_SENSOR
|
||||||
|
|
|
@ -447,6 +447,21 @@ config LWM2M_RW_CBOR_SUPPORT
|
||||||
help
|
help
|
||||||
Include support for writing CBOR data
|
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
|
config LWM2M_DEVICE_PWRSRC_MAX
|
||||||
int "Maximum # of device power source records"
|
int "Maximum # of device power source records"
|
||||||
default 5
|
default 5
|
||||||
|
|
|
@ -54,6 +54,9 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
||||||
#ifdef CONFIG_LWM2M_RW_CBOR_SUPPORT
|
#ifdef CONFIG_LWM2M_RW_CBOR_SUPPORT
|
||||||
#include "lwm2m_rw_cbor.h"
|
#include "lwm2m_rw_cbor.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT
|
||||||
|
#include "lwm2m_rw_senml_cbor.h"
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_LWM2M_RD_CLIENT_SUPPORT
|
#ifdef CONFIG_LWM2M_RD_CLIENT_SUPPORT
|
||||||
#include "lwm2m_rd_client.h"
|
#include "lwm2m_rd_client.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1685,6 +1688,12 @@ static int select_writer(struct lwm2m_output_context *out, uint16_t accept)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT
|
||||||
|
case LWM2M_FORMAT_APP_SENML_CBOR:
|
||||||
|
out->writer = &senml_cbor_writer;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_WRN("Unknown content type %u", accept);
|
LOG_WRN("Unknown content type %u", accept);
|
||||||
return -ENOMSG;
|
return -ENOMSG;
|
||||||
|
@ -1730,6 +1739,13 @@ static int select_reader(struct lwm2m_input_context *in, uint16_t format)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT
|
||||||
|
case LWM2M_FORMAT_APP_SENML_CBOR:
|
||||||
|
in->reader = &senml_cbor_reader;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_WRN("Unknown content type %u", format);
|
LOG_WRN("Unknown content type %u", format);
|
||||||
return -ENOMSG;
|
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);
|
return do_read_op_cbor(msg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT)
|
||||||
|
case LWM2M_FORMAT_APP_SENML_CBOR:
|
||||||
|
return do_read_op_senml_cbor(msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_ERR("Unsupported content-format: %u", content_format);
|
LOG_ERR("Unsupported content-format: %u", content_format);
|
||||||
return -ENOMSG;
|
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);
|
return do_composite_read_op_senml_json(msg);
|
||||||
#endif
|
#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:
|
default:
|
||||||
LOG_ERR("Unsupported content-format: %u", content_format);
|
LOG_ERR("Unsupported content-format: %u", content_format);
|
||||||
return -ENOMSG;
|
return -ENOMSG;
|
||||||
|
@ -3833,6 +3859,12 @@ static int do_composite_observe_read_path_op(struct lwm2m_message *msg, uint16_t
|
||||||
lwm2m_path_free_list);
|
lwm2m_path_free_list);
|
||||||
#endif
|
#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:
|
default:
|
||||||
LOG_ERR("Unsupported content-format: %u", content_format);
|
LOG_ERR("Unsupported content-format: %u", content_format);
|
||||||
return -ENOMSG;
|
return -ENOMSG;
|
||||||
|
@ -4350,6 +4382,11 @@ static int do_write_op(struct lwm2m_message *msg,
|
||||||
return do_write_op_cbor(msg);
|
return do_write_op_cbor(msg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT
|
||||||
|
case LWM2M_FORMAT_APP_SENML_CBOR:
|
||||||
|
return do_write_op_senml_cbor(msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_ERR("Unsupported format: %u", format);
|
LOG_ERR("Unsupported format: %u", format);
|
||||||
return -ENOMSG;
|
return -ENOMSG;
|
||||||
|
@ -4366,6 +4403,11 @@ static int do_composite_write_op(struct lwm2m_message *msg,
|
||||||
return do_write_op_senml_json(msg);
|
return do_write_op_senml_json(msg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT)
|
||||||
|
case LWM2M_FORMAT_APP_SENML_CBOR:
|
||||||
|
return do_write_op_senml_cbor(msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_ERR("Unsupported format: %u", format);
|
LOG_ERR("Unsupported format: %u", format);
|
||||||
return -ENOMSG;
|
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)) {
|
if (IS_ENABLED(CONFIG_LWM2M_VERSION_1_1)) {
|
||||||
/* Select content format use SenML CBOR when it possible */
|
/* 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.");
|
LOG_DBG("No accept option given. Assume SenML Json.");
|
||||||
*accept_format = LWM2M_FORMAT_APP_SEML_JSON;
|
*accept_format = LWM2M_FORMAT_APP_SEML_JSON;
|
||||||
} else if (IS_ENABLED(CONFIG_LWM2M_RW_CBOR_SUPPORT)) {
|
} 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);
|
return do_send_op_senml_json(msg, lwm2m_path_list);
|
||||||
#endif
|
#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:
|
default:
|
||||||
LOG_ERR("Unsupported content-format for /dp: %u", content_format);
|
LOG_ERR("Unsupported content-format for /dp: %u", content_format);
|
||||||
return -ENOMSG;
|
return -ENOMSG;
|
||||||
|
@ -6404,8 +6454,9 @@ int lwm2m_engine_send(struct lwm2m_ctx *ctx, char const *path_list[], uint8_t pa
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Select content format use CBOR when it possible */
|
if (IS_ENABLED(CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT)) {
|
||||||
if (IS_ENABLED(CONFIG_LWM2M_RW_SENML_JSON_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;
|
content_format = LWM2M_FORMAT_APP_SEML_JSON;
|
||||||
} else {
|
} else {
|
||||||
LOG_WRN("SenML CBOR or JSON is not supported");
|
LOG_WRN("SenML CBOR or JSON is not supported");
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#define LWM2M_FORMAT_APP_JSON 50
|
#define LWM2M_FORMAT_APP_JSON 50
|
||||||
#define LWM2M_FORMAT_APP_CBOR 60
|
#define LWM2M_FORMAT_APP_CBOR 60
|
||||||
#define LWM2M_FORMAT_APP_SEML_JSON 110
|
#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_PLAIN_TEXT 1541
|
||||||
#define LWM2M_FORMAT_OMA_OLD_TLV 1542
|
#define LWM2M_FORMAT_OMA_OLD_TLV 1542
|
||||||
#define LWM2M_FORMAT_OMA_OLD_JSON 1543
|
#define LWM2M_FORMAT_OMA_OLD_JSON 1543
|
||||||
|
|
|
@ -428,7 +428,9 @@ struct lwm2m_senml_json_context senml_json_ctx;
|
||||||
uint8_t token[8];
|
uint8_t token[8];
|
||||||
uint8_t tkl;
|
uint8_t tkl;
|
||||||
bool last_block : 1;
|
bool last_block : 1;
|
||||||
|
uint8_t level; /* 3/4 (4 = resource instance) */
|
||||||
uint16_t res_id;
|
uint16_t res_id;
|
||||||
|
uint16_t res_inst_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lwm2m_output_context {
|
struct lwm2m_output_context {
|
||||||
|
|
898
subsys/net/lib/lwm2m/lwm2m_rw_senml_cbor.c
Normal file
898
subsys/net/lib/lwm2m/lwm2m_rw_senml_cbor.c
Normal 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;
|
||||||
|
}
|
25
subsys/net/lib/lwm2m/lwm2m_rw_senml_cbor.h
Normal file
25
subsys/net/lib/lwm2m/lwm2m_rw_senml_cbor.h
Normal 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_ */
|
207
subsys/net/lib/lwm2m/lwm2m_senml_cbor_decode.c
Normal file
207
subsys/net/lib/lwm2m/lwm2m_senml_cbor_decode.c
Normal 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;
|
||||||
|
}
|
24
subsys/net/lib/lwm2m/lwm2m_senml_cbor_decode.h
Normal file
24
subsys/net/lib/lwm2m/lwm2m_senml_cbor_decode.h
Normal 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__ */
|
203
subsys/net/lib/lwm2m/lwm2m_senml_cbor_encode.c
Normal file
203
subsys/net/lib/lwm2m/lwm2m_senml_cbor_encode.c
Normal 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;
|
||||||
|
}
|
24
subsys/net/lib/lwm2m/lwm2m_senml_cbor_encode.h
Normal file
24
subsys/net/lib/lwm2m/lwm2m_senml_cbor_encode.h
Normal 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__ */
|
104
subsys/net/lib/lwm2m/lwm2m_senml_cbor_types.h
Normal file
104
subsys/net/lib/lwm2m/lwm2m_senml_cbor_types.h
Normal 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__ */
|
Loading…
Add table
Add a link
Reference in a new issue