net: lwm2m: Add ObjLnk resource type support

Implement LWM2M ObjLnk resource type and plaintext, TLV and JSON
readers/writers.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2020-05-19 12:37:02 +02:00 committed by Jukka Rissanen
commit bd7d6926c4
7 changed files with 187 additions and 6 deletions

View file

@ -216,7 +216,7 @@ Example LwM2M object and resources: Device
- R
- Multiple
- Optional
- ObjLink
- ObjLnk
The server could query the ``Manufacturer`` resource for ``Device`` object
instance 0 (the default and only instance) by sending a ``READ 3/0/0``

View file

@ -341,6 +341,19 @@ typedef struct float64_value {
int64_t val2;
} float64_value_t;
/**
* @brief Maximum value for ObjLnk resource fields
*/
#define LWM2M_OBJLNK_MAX_ID USHRT_MAX
/**
* @brief LWM2M ObjLnk resource type structure
*/
struct lwm2m_objlnk {
uint16_t obj_id;
uint16_t obj_inst;
};
/**
* @brief Create an LwM2M object instance.
*
@ -485,6 +498,16 @@ int lwm2m_engine_set_float32(char *pathstr, float32_value_t *value);
*/
int lwm2m_engine_set_float64(char *pathstr, float64_value_t *value);
/**
* @brief Set resource (instance) value (ObjLnk)
*
* @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
* @param[in] value pointer to the lwm2m_objlnk structure
*
* @return 0 for success or negative in case of error.
*/
int lwm2m_engine_set_objlnk(char *pathstr, struct lwm2m_objlnk *value);
/**
* @brief Get resource (instance) value (opaque buffer)
*
@ -617,6 +640,17 @@ int lwm2m_engine_get_float32(char *pathstr, float32_value_t *buf);
*/
int lwm2m_engine_get_float64(char *pathstr, float64_value_t *buf);
/**
* @brief Get resource (instance) value (ObjLnk)
*
* @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
* @param[out] buf lwm2m_objlnk buffer to copy data into
*
* @return 0 for success or negative in case of error.
*/
int lwm2m_engine_get_objlnk(char *pathstr, struct lwm2m_objlnk *buf);
/**
* @brief Set resource (instance) read callback
*

View file

@ -12,11 +12,6 @@
* Joel Hoglund <joel@sics.se>
*/
/*
* TODO:
* - Handle Resource ObjLink type
*/
#define LOG_MODULE_NAME net_lwm2m_engine
#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
@ -1501,6 +1496,11 @@ static int lwm2m_engine_set(char *pathstr, void *value, uint16_t len)
((float64_value_t *)value)->val2;
break;
case LWM2M_RES_TYPE_OBJLNK:
*((struct lwm2m_objlnk *)data_ptr) =
*(struct lwm2m_objlnk *)value;
break;
default:
LOG_ERR("unknown obj data_type %d", obj_field->data_type);
return -EINVAL;
@ -1587,6 +1587,11 @@ int lwm2m_engine_set_float64(char *pathstr, float64_value_t *value)
return lwm2m_engine_set(pathstr, value, sizeof(float64_value_t));
}
int lwm2m_engine_set_objlnk(char *pathstr, struct lwm2m_objlnk *value)
{
return lwm2m_engine_set(pathstr, value, sizeof(struct lwm2m_objlnk));
}
/* user data getter functions */
int lwm2m_engine_get_res_data(char *pathstr, void **data_ptr, uint16_t *data_len,
@ -1739,6 +1744,11 @@ static int lwm2m_engine_get(char *pathstr, void *buf, uint16_t buflen)
((float64_value_t *)data_ptr)->val2;
break;
case LWM2M_RES_TYPE_OBJLNK:
*(struct lwm2m_objlnk *)buf =
*(struct lwm2m_objlnk *)data_ptr;
break;
default:
LOG_ERR("unknown obj data_type %d",
obj_field->data_type);
@ -1823,6 +1833,11 @@ int lwm2m_engine_get_float64(char *pathstr, float64_value_t *buf)
return lwm2m_engine_get(pathstr, buf, sizeof(float64_value_t));
}
int lwm2m_engine_get_objlnk(char *pathstr, struct lwm2m_objlnk *buf)
{
return lwm2m_engine_get(pathstr, buf, sizeof(struct lwm2m_objlnk));
}
int lwm2m_engine_get_resource(char *pathstr, struct lwm2m_engine_res **res)
{
int ret;
@ -2159,6 +2174,11 @@ static int lwm2m_read_handler(struct lwm2m_engine_obj_inst *obj_inst,
(float64_value_t *)data_ptr);
break;
case LWM2M_RES_TYPE_OBJLNK:
engine_put_objlnk(&msg->out, &msg->path,
(struct lwm2m_objlnk *)data_ptr);
break;
default:
LOG_ERR("unknown obj data_type %d",
obj_field->data_type);
@ -2386,6 +2406,12 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst,
len = sizeof(float64_value_t);
break;
case LWM2M_RES_TYPE_OBJLNK:
engine_get_objlnk(&msg->in,
(struct lwm2m_objlnk *)data_ptr);
len = sizeof(struct lwm2m_objlnk);
break;
default:
LOG_ERR("unknown obj data_type %d",
obj_field->data_type);

View file

@ -124,6 +124,7 @@
#define LWM2M_RES_TYPE_TIME 12
#define LWM2M_RES_TYPE_FLOAT32 13
#define LWM2M_RES_TYPE_FLOAT64 14
#define LWM2M_RES_TYPE_OBJLNK 15
/* remember that we have already output a value - can be between two block's */
#define WRITER_OUTPUT_VALUE 1
@ -470,6 +471,9 @@ struct lwm2m_writer {
size_t (*put_opaque)(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path,
char *buf, size_t buflen);
size_t (*put_objlnk)(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path,
struct lwm2m_objlnk *value);
};
struct lwm2m_reader {
@ -487,6 +491,8 @@ struct lwm2m_reader {
bool *value);
size_t (*get_opaque)(struct lwm2m_input_context *in,
uint8_t *buf, size_t buflen, bool *last_block);
size_t (*get_objlnk)(struct lwm2m_input_context *in,
struct lwm2m_objlnk *value);
};
/* output user_data management functions */
@ -674,6 +680,13 @@ static inline size_t engine_put_opaque(struct lwm2m_output_context *out,
return 0;
}
static inline size_t engine_put_objlnk(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path,
struct lwm2m_objlnk *value)
{
return out->writer->put_objlnk(out, path, value);
}
static inline size_t engine_get_s32(struct lwm2m_input_context *in,
int32_t *value)
{
@ -721,4 +734,10 @@ static inline size_t engine_get_opaque(struct lwm2m_input_context *in,
return 0;
}
static inline size_t engine_get_objlnk(struct lwm2m_input_context *in,
struct lwm2m_objlnk *value)
{
return in->reader->get_objlnk(in, value);
}
#endif /* LWM2M_OBJECT_H_ */

View file

@ -526,6 +526,20 @@ static size_t put_bool(struct lwm2m_output_context *out,
return (size_t)len;
}
static size_t put_objlnk(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path,
struct lwm2m_objlnk *value)
{
size_t len;
len = put_json_prefix(out, path, "\"ov\"");
len += plain_text_put_format(out, "\"%u:%u\"", value->obj_id,
value->obj_inst);
len += put_json_postfix(out);
return len;
}
static size_t read_number(struct lwm2m_input_context *in,
int64_t *value1, int64_t *value2,
bool accept_sign, bool accept_dot)
@ -676,6 +690,37 @@ static size_t get_opaque(struct lwm2m_input_context *in,
return 0;
}
static size_t get_objlnk(struct lwm2m_input_context *in,
struct lwm2m_objlnk *value)
{
int64_t tmp;
size_t len;
uint16_t value_offset;
struct json_in_formatter_data *fd;
fd = engine_get_in_user_data(in);
if (!fd) {
return 0;
}
/* Store the original value offset. */
value_offset = fd->value_offset;
len = read_number(in, &tmp, NULL, false, false);
value->obj_id = (uint16_t)tmp;
len++; /* +1 for ':' delimeter. */
fd->value_offset += len;
len += read_number(in, &tmp, NULL, false, false);
value->obj_inst = (uint16_t)tmp;
/* Restore the original value offset. */
fd->value_offset = value_offset;
return len;
}
const struct lwm2m_writer json_writer = {
.put_begin = put_begin,
.put_end = put_end,
@ -689,6 +734,7 @@ const struct lwm2m_writer json_writer = {
.put_float32fix = put_float32fix,
.put_float64fix = put_float64fix,
.put_bool = put_bool,
.put_objlnk = put_objlnk,
};
const struct lwm2m_reader json_reader = {
@ -699,6 +745,7 @@ const struct lwm2m_reader json_reader = {
.get_float64fix = get_float64fix,
.get_bool = get_bool,
.get_opaque = get_opaque,
.get_objlnk = get_objlnk,
};
int do_read_op_json(struct lwm2m_message *msg, int content_format)

View file

@ -566,6 +566,15 @@ static size_t put_opaque(struct lwm2m_output_context *out,
return put_string(out, path, buf, buflen);
}
static size_t 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 size_t get_number(struct lwm2m_input_context *in, int64_t *value,
uint8_t max_len)
{
@ -758,6 +767,20 @@ static size_t get_opaque(struct lwm2m_input_context *in,
return lwm2m_engine_get_opaque_more(in, value, buflen, last_block);
}
static size_t get_objlnk(struct lwm2m_input_context *in,
struct lwm2m_objlnk *value)
{
int32_t value_s32;
size_t size;
size = get_s32(in, &value_s32);
value->obj_id = (value_s32 >> 16) & 0xFFFF;
value->obj_inst = value_s32 && 0xFFFF;
return size;
}
const struct lwm2m_writer oma_tlv_writer = {
.put_begin_oi = put_begin_oi,
.put_end_oi = put_end_oi,
@ -772,6 +795,7 @@ const struct lwm2m_writer oma_tlv_writer = {
.put_float64fix = put_float64fix,
.put_bool = put_bool,
.put_opaque = put_opaque,
.put_objlnk = put_objlnk,
};
const struct lwm2m_reader oma_tlv_reader = {
@ -782,6 +806,7 @@ const struct lwm2m_reader oma_tlv_reader = {
.get_float64fix = get_float64fix,
.get_bool = get_bool,
.get_opaque = get_opaque,
.get_objlnk = get_objlnk,
};
int do_read_op_tlv(struct lwm2m_message *msg, int content_format)

View file

@ -194,6 +194,14 @@ static size_t put_bool(struct lwm2m_output_context *out,
}
}
static size_t put_objlnk(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path,
struct lwm2m_objlnk *value)
{
return plain_text_put_format(out, "%u:%u", value->obj_id,
value->obj_inst);
}
static int get_length_left(struct lwm2m_input_context *in)
{
return in->in_cpkt->offset - in->offset;
@ -330,6 +338,26 @@ static size_t get_opaque(struct lwm2m_input_context *in,
return lwm2m_engine_get_opaque_more(in, value, buflen, last_block);
}
static size_t get_objlnk(struct lwm2m_input_context *in,
struct lwm2m_objlnk *value)
{
int64_t tmp;
size_t len;
len = plain_text_read_number(in, &tmp, NULL, false, false);
value->obj_id = (uint16_t)tmp;
/* Skip ':' delimeter. */
in->offset++;
len++;
len += plain_text_read_number(in, &tmp, NULL, false, false);
value->obj_inst = (uint16_t)tmp;
return len;
}
const struct lwm2m_writer plain_text_writer = {
.put_s8 = put_s8,
.put_s16 = put_s16,
@ -339,6 +367,7 @@ const struct lwm2m_writer plain_text_writer = {
.put_float32fix = plain_text_put_float32fix,
.put_float64fix = plain_text_put_float64fix,
.put_bool = put_bool,
.put_objlnk = put_objlnk,
};
const struct lwm2m_reader plain_text_reader = {
@ -349,6 +378,7 @@ const struct lwm2m_reader plain_text_reader = {
.get_float64fix = get_float64fix,
.get_bool = get_bool,
.get_opaque = get_opaque,
.get_objlnk = get_objlnk,
};
int do_read_op_plain_text(struct lwm2m_message *msg, int content_format)