1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/senml/saul.c
Silke Hofstra 9d61bdbb06 sys/senml: add SenML modules
Add a basic SenML module and submodules with support for:

- Encoding SenML values as CBOR using NanoCBOR.
- Converting from Phydat to SenML.
- Reading and encoding SAUL sensors.
2022-02-11 12:38:21 +01:00

100 lines
2.8 KiB
C

/*
* Copyright (C) 2021 Silke Hofstra
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include "nanocbor/nanocbor.h"
#include "saul_reg.h"
#include "senml.h"
#include "senml/cbor.h"
#include "senml/phydat.h"
#include "senml/saul.h"
static inline void senml_encode_phydat_bool(nanocbor_encoder_t *enc,
const saul_reg_t *dev,
const phydat_t *data,
const uint8_t dim)
{
senml_bool_value_t val = { .attr = { .name = dev->name } };
phydat_to_senml_bool(&val, data, dim);
senml_encode_bool_cbor(enc, &val);
}
static inline uint8_t senml_fix_unit(const saul_reg_t *dev, const uint8_t unit)
{
/* Fix the unit for relative humidity. */
if (dev->driver->type == SAUL_SENSE_HUM &&
unit == SENML_UNIT_PERCENT) {
return SENML_UNIT_RELATIVE_HUMIDITY_PERCENT;
}
return unit;
}
static void senml_encode_phydat_float(nanocbor_encoder_t *enc,
const saul_reg_t *dev,
const phydat_t *data, const uint8_t dim)
{
senml_value_t val = { .attr = { .name = dev->name } };
phydat_to_senml_float(&val, data, dim);
val.attr.unit = senml_fix_unit(dev, val.attr.unit);
senml_encode_value_cbor(enc, &val);
}
static void senml_encode_phydat_decimal(nanocbor_encoder_t *enc,
const saul_reg_t *dev,
const phydat_t *data, const uint8_t dim)
{
senml_value_t val = { .attr = { .name = dev->name } };
phydat_to_senml_decimal(&val, data, dim);
val.attr.unit = senml_fix_unit(dev, val.attr.unit);
senml_encode_value_cbor(enc, &val);
}
int senml_saul_reg_encode_cbor(nanocbor_encoder_t *enc, saul_reg_t *dev)
{
phydat_t data;
int dim = saul_reg_read(dev, &data);
if (dim <= 0) {
return dim;
}
for (uint8_t i = 0; i < dim; i++) {
if (data.unit == UNIT_BOOL) {
senml_encode_phydat_bool(enc, dev, &data, i);
}
else if (CONFIG_SENML_SAUL_USE_FLOATS) {
senml_encode_phydat_float(enc, dev, &data, i);
}
else {
senml_encode_phydat_decimal(enc, dev, &data, i);
}
}
return dim;
}
size_t senml_saul_encode_cbor(uint8_t *buf, size_t len, saul_reg_t *dev)
{
nanocbor_encoder_t enc;
nanocbor_encoder_init(&enc, buf, len);
nanocbor_fmt_array_indefinite(&enc);
while (dev) {
if (senml_saul_reg_encode_cbor(&enc, dev) <= 0) {
return 0;
}
dev = dev->next;
}
nanocbor_fmt_end_indefinite(&enc);
return nanocbor_encoded_len(&enc);
}