net: lwm2m: SenML-CBOR Encoder and CDDL update

Added support for historical data encode by adding base time (bt)
and time (t) label. New labels are needed for Encoder so Decoder
is not regenerated.

Added support for SenML-CBOR to write time series data.
Use "bt" base time and "t" timestamp labels for data cache.

Signed-off-by: Juha Heiskanen <juha.heiskanen@nordicsemi.no>
This commit is contained in:
Juha Heiskanen 2022-09-12 13:08:02 +03:00 committed by Fabio Baltieri
commit 60d9948b67
5 changed files with 112 additions and 14 deletions

View file

@ -17,6 +17,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#include <string.h>
#include <inttypes.h>
#include <ctype.h>
#include <time.h>
#include <zephyr/sys/util.h>
#include <zephyr/kernel.h>
@ -42,6 +43,9 @@ struct cbor_out_fmt_data {
size_t name_sz; /* Name buff size */
uint8_t name_cnt;
};
/* Basetime for Cached data timestamp */
time_t basetime;
};
struct cbor_in_fmt_data {
@ -83,6 +87,7 @@ static void setup_out_fmt_data(struct lwm2m_message *msg)
(void)memset(fd, 0, sizeof(*fd));
engine_set_out_user_data(&msg->out, fd);
fd->name_sz = sizeof("/65535/999/");
fd->basetime = 0;
}
static void clear_out_fmt_data(struct lwm2m_message *msg)
@ -253,6 +258,33 @@ static int put_begin_r(struct lwm2m_output_context *out, struct lwm2m_obj_path *
return 0;
}
static int put_data_timestamp(struct lwm2m_output_context *out, time_t value)
{
struct record *out_record;
struct cbor_out_fmt_data *fd = LWM2M_OFD_CBOR(out);
int ret;
ret = fmt_range_check(fd);
if (ret < 0) {
return ret;
}
/* Tell CBOR encoder where to find the name */
out_record = GET_CBOR_FD_REC(fd);
if (fd->basetime) {
out_record->_record_t._record_t = value - fd->basetime;
out_record->_record_t_present = 1;
} else {
fd->basetime = value;
out_record->_record_bt._record_bt = value;
out_record->_record_bt_present = 1;
}
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);
@ -301,10 +333,15 @@ static int put_begin_ri(struct lwm2m_output_context *out, struct lwm2m_obj_path
static int put_name_nth_ri(struct lwm2m_output_context *out, struct lwm2m_obj_path *path)
{
int ret = 0;
struct cbor_out_fmt_data *fd = LWM2M_OFD_CBOR(out);
struct record *record = GET_CBOR_FD_REC(fd);
/* With the first ri the resource name (and ri name) are already in place */
/* 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);
} else if (record && record->_record_t_present) {
/* Name need to be add for each time serialized record */
ret = put_begin_r(out, path);
}
return ret;
@ -696,6 +733,7 @@ const struct lwm2m_writer senml_cbor_writer = {
.put_bool = put_bool,
.put_opaque = put_opaque,
.put_objlnk = put_objlnk,
.put_data_timestamp = put_data_timestamp,
};
const struct lwm2m_reader senml_cbor_reader = {

View file

@ -2,13 +2,15 @@ lwm2m_senml = [1* record]
record = {
? bn => tstr, ; Base Name
? bt => int .size 8, ; Base Time
? n => tstr, ; Name
? t => int .size 8, ; Time
? ( vi => int .size 8 // ; Integer Value
vf => float // ; Float Value
vs => tstr // ; String Value
vb => bool // ; Boolean Value
vd => bstr ), ; Data Value
0*3 key-value-pair ; To handle unordered maps; length-first ordered map keys
0*5 key-value-pair ; To handle unordered maps; length-first ordered map keys
}
; now define the generic versions
@ -17,7 +19,9 @@ key-value-pair = ( int => value )
value = tstr / bstr / int .size 8 / float / bool
n = 0
t = 6
bn = -2
bt = -3
vi = 2
vf = 2
vs = 3

View file

@ -13,12 +13,15 @@
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include "zcbor_encode.h"
#include "lwm2m_senml_cbor_encode.h"
#include "lwm2m_senml_cbor_types.h"
static bool encode_repeated_record_bn(zcbor_state_t *state, const struct record_bn *input);
static bool encode_repeated_record_bt(zcbor_state_t *state, const struct record_bt *input);
static bool encode_repeated_record_n(zcbor_state_t *state, const struct record_n *input);
static bool encode_repeated_record_t(zcbor_state_t *state, const struct record_t *input);
static bool encode_repeated_record_union(zcbor_state_t *state, const struct record_union_ *input);
static bool encode_value(zcbor_state_t *state, const struct value_ *input);
static bool encode_key_value_pair(zcbor_state_t *state, const struct key_value_pair *input);
@ -41,6 +44,23 @@ static bool encode_repeated_record_bn(zcbor_state_t *state, const struct record_
return tmp_result;
}
static bool encode_repeated_record_bt(zcbor_state_t *state, const struct record_bt *input)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result = ((((zcbor_int32_put(state, (-3)))) &&
((((*input)._record_bt >= INT64_MIN) &&
((*input)._record_bt <= INT64_MAX)) ||
(zcbor_error(state, ZCBOR_ERR_WRONG_RANGE), false)) &&
(zcbor_int64_encode(state, (&(*input)._record_bt)))));
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__);
@ -55,6 +75,23 @@ static bool encode_repeated_record_n(zcbor_state_t *state, const struct record_n
return tmp_result;
}
static bool encode_repeated_record_t(zcbor_state_t *state, const struct record_t *input)
{
zcbor_print("%s\r\n", __func__);
bool tmp_result =
((((zcbor_uint32_put(state, (6)))) &&
((((*input)._record_t >= INT64_MIN) && ((*input)._record_t <= INT64_MAX)) ||
(zcbor_error(state, ZCBOR_ERR_WRONG_RANGE), false)) &&
(zcbor_int64_encode(state, (&(*input)._record_t)))));
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__);
@ -102,10 +139,8 @@ static bool encode_value(zcbor_state_t *state, const struct value_ *input)
: (((*input)._value_choice == _value_bstr)
? ((zcbor_bstr_encode(state, (&(*input)._value_bstr))))
: (((*input)._value_choice == _value_int)
? (((((*input)._value_int >=
INT64_MIN) &&
((*input)._value_int <=
INT64_MAX)) ||
? (((((*input)._value_int >= INT64_MIN) &&
((*input)._value_int <= INT64_MAX)) ||
(zcbor_error(state, ZCBOR_ERR_WRONG_RANGE),
false)) &&
(zcbor_int64_encode(state,
@ -155,19 +190,26 @@ static bool encode_repeated_record__key_value_pair(zcbor_state_t *state,
return tmp_result;
}
static bool encode_record(zcbor_state_t *state, const struct record *input)
static bool encode_record(
zcbor_state_t *state, const struct record *input)
{
zcbor_print("%s\r\n", __func__);
int max_keys = ARRAY_SIZE(input->_record__key_value_pair);
bool tmp_result = (((zcbor_map_start_encode(state, max_keys + 3) &&
bool tmp_result = (((zcbor_map_start_encode(state, max_keys + 5) &&
((zcbor_present_encode(&((*input)._record_bn_present),
(zcbor_encoder_t *)encode_repeated_record_bn,
state, (&(*input)._record_bn)) &&
zcbor_present_encode(&((*input)._record_bt_present),
(zcbor_encoder_t *)encode_repeated_record_bt,
state, (&(*input)._record_bt)) &&
zcbor_present_encode(&((*input)._record_n_present),
(zcbor_encoder_t *)encode_repeated_record_n,
state, (&(*input)._record_n)) &&
zcbor_present_encode(&((*input)._record_t_present),
(zcbor_encoder_t *)encode_repeated_record_t,
state, (&(*input)._record_t)) &&
zcbor_present_encode(&((*input)._record_union_present),
(zcbor_encoder_t *)encode_repeated_record_union,
state, (&(*input)._record_union)) &&
@ -177,7 +219,7 @@ static bool encode_record(zcbor_state_t *state, const struct record *input)
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, max_keys + 3))));
zcbor_map_end_encode(state, max_keys + 5))));
if (!tmp_result) {
zcbor_trace();

View file

@ -21,7 +21,9 @@
enum lwm2m_senml_cbor_key {
lwm2m_senml_cbor_key_bn = -2,
lwm2m_senml_cbor_key_bt = -3,
lwm2m_senml_cbor_key_n = 0,
lwm2m_senml_cbor_key_t = 6,
lwm2m_senml_cbor_key_vi = 2,
lwm2m_senml_cbor_key_vf = 2,
lwm2m_senml_cbor_key_vs = 3,
@ -42,10 +44,18 @@ struct record_bn {
struct zcbor_string _record_bn;
};
struct record_bt {
int64_t _record_bt;
};
struct record_n {
struct zcbor_string _record_n;
};
struct record_t {
int64_t _record_t;
};
struct record_union_ {
union {
struct {
@ -102,11 +112,15 @@ struct record__key_value_pair {
struct record {
struct record_bn _record_bn;
uint_fast32_t _record_bn_present;
struct record_bt _record_bt;
uint_fast32_t _record_bt_present;
struct record_n _record_n;
uint_fast32_t _record_n_present;
struct record_t _record_t;
uint_fast32_t _record_t_present;
struct record_union_ _record_union;
uint_fast32_t _record_union_present;
struct record__key_value_pair _record__key_value_pair[3];
struct record__key_value_pair _record__key_value_pair[5];
uint_fast32_t _record__key_value_pair_count;
};