net: lwm2m: Add proper resource-level discovery attribute handling

In case an individual resource is being discovered, the LwM2M client
should not only fill the attributes assinged at the resource level, but
also the ones inherited from the object and object instance levels.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2022-02-03 16:58:28 +01:00 committed by Marti Bolivar
commit 9ac83be650
2 changed files with 110 additions and 38 deletions

View file

@ -142,49 +142,112 @@ static int put_corelink_dimension(struct lwm2m_output_context *out,
return len; return len;
} }
static int put_attribute(struct lwm2m_output_context *out,
struct lwm2m_attr *attr, uint8_t *buf,
uint16_t buflen)
{
int used, ret;
const char *name = lwm2m_engine_get_attr_name(attr);
if (name == NULL) {
/* Invalid attribute, ignore. */
return 0;
}
if (attr->type <= LWM2M_ATTR_PMAX) {
used = snprintk(buf, buflen, ";%s=%d", name, attr->int_val);
} else {
uint8_t float_buf[32];
used = lwm2m_ftoa(&attr->float_val, float_buf,
sizeof(float_buf), 4);
if (used < 0 || used >= sizeof(float_buf)) {
return -ENOMEM;
}
used = snprintk(buf, buflen, ";%s=%s", name, float_buf);
}
if (used < 0 || used >= buflen) {
return -ENOMEM;
}
ret = buf_append(CPKT_BUF_WRITE(out->out_cpkt), buf, used);
if (ret < 0) {
return ret;
}
return used;
}
static int put_attributes(struct lwm2m_output_context *out,
struct lwm2m_attr **attrs, uint8_t *buf,
uint16_t buflen)
{
int ret;
int len = 0;
for (int i = 0; i < NR_LWM2M_ATTR; i++) {
if (attrs[i] == NULL) {
continue;
}
ret = put_attribute(out, attrs[i], buf, buflen);
if (ret < 0) {
return ret;
}
len += ret;
}
return len;
}
static void get_attributes(const void *ref, struct lwm2m_attr **attrs)
{
struct lwm2m_attr *attr = NULL;
while ((attr = lwm2m_engine_get_next_attr(ref, attr)) != NULL) {
if (attr->type >= NR_LWM2M_ATTR) {
continue;
}
attrs[attr->type] = attr;
}
}
static int put_corelink_attributes(struct lwm2m_output_context *out, static int put_corelink_attributes(struct lwm2m_output_context *out,
const void *ref, uint8_t *buf, const void *ref, uint8_t *buf,
uint16_t buflen) uint16_t buflen)
{ {
struct lwm2m_attr *attr = NULL; struct lwm2m_attr *attrs[NR_LWM2M_ATTR] = { 0 };
int used, ret;
int len = 0;
while ((attr = lwm2m_engine_get_next_attr(ref, attr)) != NULL) { get_attributes(ref, attrs);
const char *name = lwm2m_engine_get_attr_name(attr);
if (name == NULL) { return put_attributes(out, attrs, buf, buflen);
/* Invalid attribute, ignore. */ }
continue;
}
if (attr->type <= LWM2M_ATTR_PMAX) { /* Resource-level attribute request - should propagate attributes from Object
used = snprintk(buf, buflen, ";%s=%d", name, attr->int_val); * and Object Instance.
} else { */
uint8_t float_buf[32]; static int put_corelink_attributes_resource(struct lwm2m_output_context *out,
const struct lwm2m_obj_path *path,
uint8_t *buf, uint16_t buflen)
{
struct lwm2m_attr *attrs[NR_LWM2M_ATTR] = { 0 };
struct lwm2m_engine_obj *obj = lwm2m_engine_get_obj(path);
struct lwm2m_engine_obj_inst *obj_inst = lwm2m_engine_get_obj_inst(path);
struct lwm2m_engine_res *res = lwm2m_engine_get_res(path);
used = lwm2m_ftoa(&attr->float_val, float_buf, if (obj == NULL || obj_inst == NULL || res == NULL) {
sizeof(float_buf), 4); return -ENOENT;
if (used < 0 || used >= sizeof(float_buf)) {
return -ENOMEM;
}
used = snprintk(buf, buflen, ";%s=%s", name, float_buf);
}
if (used < 0 || used >= buflen) {
return -ENOMEM;
}
len += used;
ret = buf_append(CPKT_BUF_WRITE(out->out_cpkt), buf, used);
if (ret < 0) {
return ret;
}
} }
return len; get_attributes(obj, attrs);
get_attributes(obj_inst, attrs);
get_attributes(res, attrs);
return put_attributes(out, attrs, buf, buflen);
} }
static int put_corelink_ssid(struct lwm2m_output_context *out, static int put_corelink_ssid(struct lwm2m_output_context *out,
@ -424,10 +487,18 @@ static int put_res_corelink(struct lwm2m_output_context *out,
len += ret; len += ret;
ret = put_corelink_attributes(out, res, obj_buf, if (fd->request_level == LWM2M_PATH_LEVEL_RESOURCE) {
sizeof(obj_buf)); ret = put_corelink_attributes_resource(
if (ret < 0) { out, path, obj_buf, sizeof(obj_buf));
return ret; if (ret < 0) {
return ret;
}
} else {
ret = put_corelink_attributes(
out, res, obj_buf, sizeof(obj_buf));
if (ret < 0) {
return ret;
}
} }
len += ret; len += ret;

View file

@ -218,7 +218,8 @@ static void test_put_corelink_discovery(void)
{ {
.request_level = LWM2M_PATH_LEVEL_RESOURCE, .request_level = LWM2M_PATH_LEVEL_RESOURCE,
.path_level = LWM2M_PATH_LEVEL_RESOURCE, .path_level = LWM2M_PATH_LEVEL_RESOURCE,
.expected_payload = "</65535/0/0>;pmax=" STRINGIFY(TEST_PMAX) .expected_payload = "</65535/0/0>;pmin=" STRINGIFY(TEST_PMIN)
";pmax=" STRINGIFY(TEST_PMAX)
}, },
}; };