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:
parent
73a637eda0
commit
60d9948b67
5 changed files with 112 additions and 14 deletions
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__);
|
||||
|
@ -81,8 +118,8 @@ static bool encode_repeated_record_union(zcbor_state_t *state, const struct reco
|
|||
? (((zcbor_uint32_put(state,
|
||||
(8)))) &&
|
||||
(zcbor_bstr_encode(
|
||||
state,
|
||||
(&(*input)._union_vd))))
|
||||
state,
|
||||
(&(*input)._union_vd))))
|
||||
: false)))))));
|
||||
|
||||
if (!tmp_result) {
|
||||
|
@ -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();
|
||||
|
@ -207,7 +249,7 @@ static bool encode_lwm2m_senml(zcbor_state_t *state, const struct lwm2m_senml *i
|
|||
}
|
||||
|
||||
int cbor_encode_lwm2m_senml(uint8_t *payload, size_t payload_len, const struct lwm2m_senml *input,
|
||||
size_t *payload_len_out)
|
||||
size_t *payload_len_out)
|
||||
{
|
||||
zcbor_state_t states[5];
|
||||
|
||||
|
|
|
@ -20,6 +20,6 @@
|
|||
#include "lwm2m_senml_cbor_types.h"
|
||||
|
||||
int cbor_encode_lwm2m_senml(uint8_t *payload, size_t payload_len, const struct lwm2m_senml *input,
|
||||
size_t *payload_len_out);
|
||||
size_t *payload_len_out);
|
||||
|
||||
#endif /* LWM2M_SENML_CBOR_ENCODE_H__ */
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue