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:
parent
9a034c611d
commit
bd7d6926c4
7 changed files with 187 additions and 6 deletions
|
@ -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``
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue