mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
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.
This commit is contained in:
parent
4fb2394f1d
commit
9d61bdbb06
3
dist/tools/codespell/ignored_words.txt
vendored
3
dist/tools/codespell/ignored_words.txt
vendored
@ -116,3 +116,6 @@ ether
|
||||
|
||||
# crate (Rust's package format) => create
|
||||
crate
|
||||
|
||||
# VAs (volt ampere second) => was
|
||||
vas
|
||||
|
23
examples/senml_saul/Makefile
Normal file
23
examples/senml_saul/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
# name of your application
|
||||
APPLICATION = senml_saul_example
|
||||
|
||||
# If no BOARD is found in the environment, use this default:
|
||||
BOARD ?= native
|
||||
|
||||
# This has to be the absolute path to the RIOT base directory:
|
||||
RIOTBASE ?= $(CURDIR)/../..
|
||||
|
||||
# we want to use SAUL and SenML
|
||||
USEMODULE += saul_default
|
||||
USEMODULE += senml_saul
|
||||
USEMODULE += fmt
|
||||
|
||||
# Comment this out to disable code in RIOT that does safety checking
|
||||
# which is not needed in a production environment but helps in the
|
||||
# development process:
|
||||
DEVELHELP ?= 1
|
||||
|
||||
# Change this to 0 show compiler invocation lines by default:
|
||||
QUIET ?= 1
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
9
examples/senml_saul/Makefile.ci
Normal file
9
examples/senml_saul/Makefile.ci
Normal file
@ -0,0 +1,9 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atmega328p-xplained-mini \
|
||||
nucleo-l011k4 \
|
||||
#
|
52
examples/senml_saul/main.c
Normal file
52
examples/senml_saul/main.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup examples
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Short SenML SAUL example
|
||||
*
|
||||
* @author Silke Hofstra <silke@slxh.eu>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "senml/saul.h"
|
||||
#include "fmt.h"
|
||||
|
||||
static uint8_t cbor_buf[1024];
|
||||
|
||||
void print_hex(uint8_t *a, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
print_byte_hex(a[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
size_t len = senml_saul_encode_cbor(cbor_buf, sizeof cbor_buf, saul_reg);
|
||||
|
||||
if (len == 0) {
|
||||
print_str("SenML/SAUL error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
print_str("CBOR (");
|
||||
print_u32_dec(len);
|
||||
print_str(" B): ");
|
||||
print_hex(cbor_buf, len);
|
||||
print_str("\n");
|
||||
|
||||
return 0;
|
||||
}
|
@ -186,6 +186,9 @@ PSEUDOMODULES += scanf_float
|
||||
PSEUDOMODULES += sched_cb
|
||||
PSEUDOMODULES += sched_runq_callback
|
||||
PSEUDOMODULES += semtech_loramac_rx
|
||||
PSEUDOMODULES += senml_cbor
|
||||
PSEUDOMODULES += senml_phydat
|
||||
PSEUDOMODULES += senml_saul
|
||||
PSEUDOMODULES += shell_hooks
|
||||
PSEUDOMODULES += slipdev_stdio
|
||||
PSEUDOMODULES += slipdev_l2addr
|
||||
|
@ -75,6 +75,7 @@ rsource "rtc_utils/Kconfig"
|
||||
rsource "saul_reg/Kconfig"
|
||||
rsource "schedstatistics/Kconfig"
|
||||
rsource "sema/Kconfig"
|
||||
rsource "senml/Kconfig"
|
||||
rsource "seq/Kconfig"
|
||||
rsource "shell/Kconfig"
|
||||
rsource "test_utils/Kconfig"
|
||||
|
@ -386,6 +386,10 @@ ifneq (,$(filter saul_default,$(USEMODULE)))
|
||||
USEMODULE += saul_reg
|
||||
endif
|
||||
|
||||
ifneq (,$(filter senml%,$(USEMODULE)))
|
||||
include $(RIOTBASE)/sys/senml/Makefile.dep
|
||||
endif
|
||||
|
||||
ifneq (,$(filter phydat,$(USEMODULE)))
|
||||
USEMODULE += fmt
|
||||
endif
|
||||
|
526
sys/include/senml.h
Normal file
526
sys/include/senml.h
Normal file
@ -0,0 +1,526 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sys_senml SenML
|
||||
* @ingroup sys
|
||||
* @brief Basic SenML types.
|
||||
*
|
||||
* The `senml` module contains the building blocks for using
|
||||
* [SenML](https://www.rfc-editor.org/rfc/rfc8428).
|
||||
* This module provides the basic types that can be used with (for example)
|
||||
* @ref sys_senml_cbor for encoding measurement data.
|
||||
*
|
||||
* Some attributes defined in SenML need to be enabled explicitly,
|
||||
* see @ref senml_attr_t for details. To enable all attributes, set:
|
||||
*
|
||||
* ```
|
||||
* CFLAGS += -DCONFIG_SENML_ATTR_SUM=1
|
||||
* CFLAGS += -DCONFIG_SENML_ATTR_VERSION=1
|
||||
* CFLAGS += -DCONFIG_SENML_ATTR_UPDATE_TIME=1
|
||||
* ```
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Basic SenML types.
|
||||
*
|
||||
* @author Silke Hofstra <silke@slxh.eu>
|
||||
*/
|
||||
|
||||
#ifndef SENML_H
|
||||
#define SENML_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "kernel_defines.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable the SenML 'sum' and 'base sum' attributes.
|
||||
*/
|
||||
#ifndef CONFIG_SENML_ATTR_SUM
|
||||
#define CONFIG_SENML_ATTR_SUM 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable the SenML 'version' and 'base version' attributes.
|
||||
*/
|
||||
#ifndef CONFIG_SENML_ATTR_VERSION
|
||||
#define CONFIG_SENML_ATTR_VERSION 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable the SenML 'update time' attribute.
|
||||
*/
|
||||
#ifndef CONFIG_SENML_ATTR_UPDATE_TIME
|
||||
#define CONFIG_SENML_ATTR_UPDATE_TIME 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SenML units and secondary units
|
||||
*
|
||||
* This list contains the SenML units and secondary units as assigned by
|
||||
* [IANA](https://www.iana.org/assignments/senml/senml.xhtml).
|
||||
* Units in italic are not recommended to be produced by new implementations.
|
||||
* Secondary units include the equivalent primary unit.
|
||||
*/
|
||||
typedef enum {
|
||||
/* SenML units from RFC8428 */
|
||||
SENML_UNIT_NONE, /**< No unit specified */
|
||||
SENML_UNIT_METER, /**< meter (m) */
|
||||
SENML_UNIT_KILOGRAM, /**< kilogram (kg) */
|
||||
SENML_UNIT_GRAM, /**< *gram* (g) */
|
||||
SENML_UNIT_SECOND, /**< second (s) */
|
||||
SENML_UNIT_AMPERE, /**< ampere (A) */
|
||||
SENML_UNIT_KELVIN, /**< kelvin (K) */
|
||||
SENML_UNIT_CANDELA, /**< candela (cd) */
|
||||
SENML_UNIT_MOLE, /**< mole (mol) */
|
||||
SENML_UNIT_HERTZ, /**< hertz (Hz) */
|
||||
SENML_UNIT_RADIAN, /**< radian (rad) */
|
||||
SENML_UNIT_STERADIAN, /**< steradian (sr) */
|
||||
SENML_UNIT_NEWTON, /**< newton (N) */
|
||||
SENML_UNIT_PASCAL, /**< pascal (Pa) */
|
||||
SENML_UNIT_JOULE, /**< joule (J) */
|
||||
SENML_UNIT_WATT, /**< watt (W) */
|
||||
SENML_UNIT_COULOMB, /**< coulomb (C) */
|
||||
SENML_UNIT_VOLT, /**< volt (V) */
|
||||
SENML_UNIT_FARAD, /**< farad (F) */
|
||||
SENML_UNIT_OHM, /**< ohm (Ohm) */
|
||||
SENML_UNIT_SIEMENS, /**< siemens (S) */
|
||||
SENML_UNIT_WEBER, /**< weber (Wb) */
|
||||
SENML_UNIT_TESLA, /**< tesla (T) */
|
||||
SENML_UNIT_HENRY, /**< henry (H) */
|
||||
SENML_UNIT_CELSIUS, /**< degrees Celsius (Cel) */
|
||||
SENML_UNIT_LUMEN, /**< lumen (lm) */
|
||||
SENML_UNIT_LUX, /**< lux (lx) */
|
||||
SENML_UNIT_BECQUEREL, /**< becquerel (Bq) */
|
||||
SENML_UNIT_GRAY, /**< gray (Gy) */
|
||||
SENML_UNIT_SIEVERT, /**< sievert (Sv) */
|
||||
SENML_UNIT_KATAL, /**< katal (kat) */
|
||||
SENML_UNIT_SQUARE_METER, /**< square meter (area) (m2) */
|
||||
SENML_UNIT_CUBIC_METER, /**< cubic meter (volume) (m3) */
|
||||
SENML_UNIT_LITER, /**< *liter (volume)* (l) */
|
||||
SENML_UNIT_METER_PER_SECOND, /**< meter per second (velocity) (m/s) */
|
||||
SENML_UNIT_METER_PER_SQUARE_SECOND, /**< meter per square second (acceleration) (m/s2) */
|
||||
SENML_UNIT_CUBIC_METER_PER_SECOND, /**< cubic meter per second (flow rate) (m3/s) */
|
||||
SENML_UNIT_LITER_PER_SECOND, /**< *liter per second (flow rate)* (l/s) */
|
||||
SENML_UNIT_WATT_PER_SQUARE_METER, /**< watt per square meter (irradiance) (W/m2) */
|
||||
SENML_UNIT_CANDELA_PER_SQUARE_METER, /**< candela per square meter (luminance) (cd/m2) */
|
||||
SENML_UNIT_BIT, /**< bit (information content) (bit) */
|
||||
SENML_UNIT_BIT_PER_SECOND, /**< bit per second (data rate) (bit/s) */
|
||||
SENML_UNIT_LATITUDE, /**< degrees latitude (lat) */
|
||||
SENML_UNIT_LONGITUDE, /**< degrees longitude (lon) */
|
||||
SENML_UNIT_PH, /**< pH value (acidity; logarithmic quantity) (pH) */
|
||||
SENML_UNIT_DECIBEL, /**< decibel (logarithmic quantity) (dB) */
|
||||
SENML_UNIT_DBW, /**< decibel relative to 1 W (power level) (dBW) */
|
||||
SENML_UNIT_BEL, /**< *bel (sound pressure level; logarithmic quantity)* (Bspl) */
|
||||
SENML_UNIT_COUNT, /**< 1 (counter value) (count) */
|
||||
SENML_UNIT_RATIO, /**< 1 (ratio e.g., value of a switch) (/) */
|
||||
SENML_UNIT_RATIO_2, /**< *1 (ratio e.g., value of a switch)* (%) */
|
||||
SENML_UNIT_RELATIVE_HUMIDITY_PERCENT, /**< Percentage (Relative Humidity) (%RH) */
|
||||
SENML_UNIT_REMAINING_BATTERY_PERCENT, /**< Percentage (remaining battery energy level) (%EL) */
|
||||
SENML_UNIT_REMAINING_BATTERY_SECONDS, /**< seconds (remaining battery energy level) (EL) */
|
||||
SENML_UNIT_RATE, /**< 1 per second (event rate) (1/s) */
|
||||
SENML_UNIT_RPM, /**< *1 per minute (event rate, "rpm")* (1/min) */
|
||||
SENML_UNIT_BEAT_PER_MINUTE, /**< *1 per minute (heart rate in beats per minute)* (beat/min)) */
|
||||
SENML_UNIT_BEATS, /**< *1 (Cumulative number of heart beats)* (beats) */
|
||||
SENML_UNIT_SIEMENS_PER_METER, /**< Siemens per meter (conductivity) (S/m) */
|
||||
|
||||
/* SenML units from RFC8798 */
|
||||
SENML_UNIT_BYTE, /**< Byte (information content) (B) */
|
||||
SENML_UNIT_VOLT_AMPERE, /**< volt-ampere (Apparent Power) (VA) */
|
||||
SENML_UNIT_VOLT_AMPERE_SECOND, /**< volt-ampere second (Apparent Energy) (VAs) */
|
||||
SENML_UNIT_VOLT_AMPERE_REACTIVE, /**< volt-ampere reactive (Reactive Power) (var) */
|
||||
SENML_UNIT_VOLT_AMPERE_REACTIVE_SECOND, /**< volt-ampere-reactive second (Reactive Energy) (vars) */
|
||||
SENML_UNIT_JOULE_PER_METER, /**< joule per meter (Energy per distance) (J/m) */
|
||||
SENML_UNIT_KILOGRAM_PER_CUBIC_METER, /**< kilogram per cubic meter (mass density, mass concentration) (kg/m3) */
|
||||
SENML_UNIT_DEGREE, /**< *degree (angle)* (deg) */
|
||||
|
||||
/* SenML units from ISO7027-1:2016 */
|
||||
SENML_UNIT_NEPHELOMETRIC_TURBIDITY_UNIT, /**< Nephelometric Turbidity Unit (NTU) */
|
||||
|
||||
/* SenML secondary units from RFC8798 */
|
||||
SENML_UNIT_MILLISECOND, /**< millisecond (ms, equivalent to 1/1000 s) */
|
||||
SENML_UNIT_MINUTE, /**< minute (min, equivalent to 60 s) */
|
||||
SENML_UNIT_HOUR, /**< hour (h, equivalent to 3600 s) */
|
||||
SENML_UNIT_MEGAHERTZ, /**< megahertz (MHz, equivalent to 1000000 Hz) */
|
||||
SENML_UNIT_KILOWATT, /**< kilowatt (kW, equivalent to 1000 W) */
|
||||
SENML_UNIT_KILOVOLT_AMPERE, /**< kilovolt-ampere (kVA, equivalent to 1000 VA) */
|
||||
SENML_UNIT_KILOVAR, /**< kilovar (kvar, equivalent to 1000 var) */
|
||||
SENML_UNIT_AMPERE_HOUR, /**< ampere-hour (Ah, equivalent to 3600 C) */
|
||||
SENML_UNIT_WATT_HOUR, /**< watt-hour (Wh, equivalent to 3600 J) */
|
||||
SENML_UNIT_KILOWATT_HOUR, /**< kilowatt-hour (kWh, equivalent to 3600000 J) */
|
||||
SENML_UNIT_VAR_HOUR, /**< var-hour (varh, equivalent to 3600 vars) */
|
||||
SENML_UNIT_KILOVAR_HOUR, /**< kilovar-hour (kvarh, equivalent to 3600000 vars) */
|
||||
SENML_UNIT_KILOVOLT_AMPERE_HOUR, /**< kilovolt-ampere-hour (kVAh, equivalent to 3600000 VAs) */
|
||||
SENML_UNIT_WATT_HOUR_PER_KILOMETER, /**< watt-hour per kilometer (Wh/km, equivalent to 3.6 J/m) */
|
||||
SENML_UNIT_KIBIBYTE, /**< kibibyte (KiB, equivalent to 1024 B) */
|
||||
SENML_UNIT_GIGABYTE, /**< gigabyte (GB, equivalent to 1e9 B) */
|
||||
SENML_UNIT_MEGABIT_PER_SECOND, /**< megabit per second (Mbit/s, equivalent to 1000000 bit/s) */
|
||||
SENML_UNIT_BYTE_PER_SECOND, /**< byte per second (B/s, equivalent to 8 bit/s) */
|
||||
SENML_UNIT_MEGABYTE_PER_SECOND, /**< megabyte per second (MB/s, equivalent to 8000000 bit/s) */
|
||||
SENML_UNIT_MILLIVOLT, /**< millivolt (mV, equivalent to 1/1000 V) */
|
||||
SENML_UNIT_MILLIAMPERE, /**< milliampere (mA, equivalent to 1/1000 A) */
|
||||
SENML_UNIT_DECIBEL_MILLIWATT, /**< decibel (milliwatt) (dBm, equivalent to -29 dBW) */
|
||||
SENML_UNIT_MICROGRAM_PER_CUBIC_METER, /**< microgram per cubic meter (ug/m3, equivalent to 1e-9 kg/m3) */
|
||||
SENML_UNIT_MILLIMETER_PER_HOUR, /**< millimeter per hour (mm/h, equivalent to 1/3600000 m/s) */
|
||||
SENML_UNIT_METER_PER_HOUR, /**< meter per hour (m/h, equivalent to 1/3600 m/s) */
|
||||
SENML_UNIT_PARTS_PER_MILLION, /**< parts per million (ppm, equivalent to 1e-6 '/') */
|
||||
SENML_UNIT_PERCENT, /**< percent (/100, equivalent to 1/100 '/') */
|
||||
SENML_UNIT_PERMILLE, /**< permille (/1000, equivalent to 1/1000 '/') */
|
||||
SENML_UNIT_HECTOPASCAL, /**< hectopascal (hPa, equivalent to 100 Pa) */
|
||||
SENML_UNIT_MILLIMETER, /**< millimeter (mm, equivalent to 1/1000 m) */
|
||||
SENML_UNIT_CENTIMETER, /**< centimeter (cm, equivalent to 1/100 m) */
|
||||
SENML_UNIT_KILOMETER, /**< kilometer (km, equivalent to 1000 m) */
|
||||
SENML_UNIT_KILOMETER_PER_HOUR, /**< kilometer per hour (km/h, equivalent to 1/3.6 m/s) */
|
||||
|
||||
/* SenML secondary units from CoRE-1 */
|
||||
SENML_UNIT_PARTS_PER_BILLION, /**< parts per billion (ppb, equivalent to 1e-9 '/') */
|
||||
SENML_UNIT_PARTS_PER_TRILLION, /**< parts per trillion (ppt, equivalent to 1e-12 '/') */
|
||||
SENML_UNIT_VOLT_AMPERE_HOUR, /**< volt-ampere-hour (VAh, equivalent to 3600 VAs) */
|
||||
SENML_UNIT_MILLIGRAM_PER_LITER, /**< milligram per liter (mg/l, equivalent to 1/1000 kg/m3) */
|
||||
SENML_UNIT_MICROGRAM_PER_LITER, /**< microgram per liter (ug/l, equivalent to 1e-6 kg/m3) */
|
||||
SENML_UNIT_GRAM_PER_LITER, /**< gram per liter (g/l, equivalent to 1 kg/m3) */
|
||||
} senml_unit_t;
|
||||
|
||||
/**
|
||||
* @brief SenML numeric value types.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SENML_TYPE_NUMERIC_UINT, /**< Unsigned integer */
|
||||
SENML_TYPE_NUMERIC_INT, /**< Integer */
|
||||
SENML_TYPE_NUMERIC_FLOAT, /**< Floating point number */
|
||||
SENML_TYPE_NUMERIC_DOUBLE, /**< Double-precision floating point number */
|
||||
SENML_TYPE_NUMERIC_DECFRAC, /**< Decimal fraction */
|
||||
} senml_value_type_t;
|
||||
|
||||
/**
|
||||
* @brief Decimal fraction containing a value in the form of m * 10^e.
|
||||
*/
|
||||
typedef struct {
|
||||
int32_t e; /**< Exponent */
|
||||
int32_t m; /**< Mantissa */
|
||||
} senml_decfrac_t;
|
||||
|
||||
/**
|
||||
* @brief SenML numeric value.
|
||||
*
|
||||
* Various SenML attributes (see @ref senml_attr_t) may contain any 'numeric'
|
||||
* types. This struct is used to contain these.
|
||||
*/
|
||||
typedef struct {
|
||||
senml_value_type_t type; /**< Type of the value */
|
||||
union {
|
||||
uint64_t u;
|
||||
int64_t i;
|
||||
float f;
|
||||
double d;
|
||||
struct { int32_t e; int32_t m; } df /** Decimal fraction */;
|
||||
} value; /**< Value data */
|
||||
} senml_numeric_t;
|
||||
|
||||
/**
|
||||
* @brief SenML common record attributes.
|
||||
* All of these values are optional: empty or 0 values will not be encoded.
|
||||
* Note that some attributes need to be enabled explicitly.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *base_name; /**< Base Name */
|
||||
senml_numeric_t base_time; /**< Base Time */
|
||||
senml_unit_t base_unit; /**< Base Unit */
|
||||
senml_numeric_t base_value; /**< Base Value */
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_SUM) || defined(DOXYGEN)
|
||||
senml_numeric_t base_sum; /**< Base Sum, set `CONFIG_SENML_ATTR_SUM` to 1 to enable */
|
||||
#endif
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_VERSION) || defined(DOXYGEN)
|
||||
uint64_t base_version; /**< Base Version, set `CONFIG_SENML_ATTR_VERSION` to 1 to enable */
|
||||
#endif
|
||||
const char *name; /**< Name of the measurement */
|
||||
senml_unit_t unit; /**< Unit */
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_SUM) || defined(DOXYGEN)
|
||||
senml_numeric_t sum; /**< Sum, set `CONFIG_SENML_ATTR_SUM` to 1 to enable */
|
||||
#endif
|
||||
senml_numeric_t time; /**< Time of the measurement (relative or Unix) in seconds */
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_UPDATE_TIME) || defined(DOXYGEN)
|
||||
senml_numeric_t update_time; /**< Maximum time before the next sensor value, set `CONFIG_SENML_ATTR_UPDATE_TIME` to 1 to enable */
|
||||
#endif
|
||||
} senml_attr_t;
|
||||
|
||||
/**
|
||||
* @brief SenML string value.
|
||||
*/
|
||||
typedef struct {
|
||||
senml_attr_t attr; /**< SenML attributes */
|
||||
senml_numeric_t value; /**< Value */
|
||||
} senml_value_t;
|
||||
|
||||
/**
|
||||
* @brief SenML string value.
|
||||
*/
|
||||
typedef struct {
|
||||
senml_attr_t attr; /**< SenML attributes */
|
||||
const char *value; /**< Value */
|
||||
size_t len; /**< Value length */
|
||||
} senml_string_value_t;
|
||||
|
||||
/**
|
||||
* @brief SenML boolean value.
|
||||
*/
|
||||
typedef struct {
|
||||
senml_attr_t attr; /**< SenML attributes */
|
||||
bool value; /**< Value */
|
||||
} senml_bool_value_t;
|
||||
|
||||
/**
|
||||
* @brief SenML data value.
|
||||
*/
|
||||
typedef struct {
|
||||
senml_attr_t attr; /**< SenML attributes */
|
||||
const uint8_t *value; /**< Value */
|
||||
size_t len; /**< Value length */
|
||||
} senml_data_value_t;
|
||||
|
||||
/**
|
||||
* @brief Create a floating point numeric value.
|
||||
*
|
||||
* @param v Value to encode.
|
||||
* @return Numeric value containing the given value.
|
||||
*/
|
||||
static inline senml_numeric_t senml_float(float v)
|
||||
{
|
||||
return (senml_numeric_t){ .type = SENML_TYPE_NUMERIC_FLOAT,
|
||||
.value = { .f = v } };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a floating point numeric value.
|
||||
*
|
||||
* @param n Numeric value to set.
|
||||
* @param v Value to encode.
|
||||
*/
|
||||
static inline void senml_set_float(senml_numeric_t *n, float v)
|
||||
{
|
||||
n->type = SENML_TYPE_NUMERIC_FLOAT;
|
||||
n->value.f = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a double precision floating point numeric value.
|
||||
*
|
||||
* @param v Value to encode.
|
||||
* @return Numeric value containing the given value.
|
||||
*/
|
||||
static inline senml_numeric_t senml_double(double v)
|
||||
{
|
||||
return (senml_numeric_t){ .type = SENML_TYPE_NUMERIC_DOUBLE,
|
||||
.value = { .d = v } };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a double precision floating point numeric value.
|
||||
*
|
||||
* @param n Numeric value to set.
|
||||
* @param v Value to encode.
|
||||
*/
|
||||
static inline void senml_set_double(senml_numeric_t *n, double v)
|
||||
{
|
||||
n->type = SENML_TYPE_NUMERIC_DOUBLE;
|
||||
n->value.d = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create an integer numeric value.
|
||||
*
|
||||
* @param v Value to encode.
|
||||
* @return Numeric value containing the given value.
|
||||
*/
|
||||
static inline senml_numeric_t senml_int(int64_t v)
|
||||
{
|
||||
return (senml_numeric_t){ .type = SENML_TYPE_NUMERIC_INT,
|
||||
.value = { .i = v } };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set an integer numeric value.
|
||||
*
|
||||
* @param n Numeric value to set.
|
||||
* @param v Value to encode.
|
||||
*/
|
||||
static inline void senml_set_int(senml_numeric_t *n, int64_t v)
|
||||
{
|
||||
n->type = SENML_TYPE_NUMERIC_INT;
|
||||
n->value.i = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create an unsigned integer numeric value.
|
||||
*
|
||||
* @param v Value to encode.
|
||||
* @return Numeric value containing the given value.
|
||||
*/
|
||||
static inline senml_numeric_t senml_uint(uint64_t v)
|
||||
{
|
||||
return (senml_numeric_t){ .type = SENML_TYPE_NUMERIC_UINT,
|
||||
.value = { .u = v } };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set an unsigned integer numeric value.
|
||||
*
|
||||
* @param n Numeric value to set.
|
||||
* @param v Value to encode.
|
||||
*/
|
||||
static inline void set_senml_uint(senml_numeric_t *n, uint64_t v)
|
||||
{
|
||||
n->type = SENML_TYPE_NUMERIC_UINT;
|
||||
n->value.u = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a decimal fraction numeric value in the form `m*10^e`.
|
||||
*
|
||||
* @param m Mantissa (value) to encode.
|
||||
* @param e Exponent (scale) to encode.
|
||||
* @return Numeric value containing the given value.
|
||||
*/
|
||||
static inline senml_numeric_t senml_decfrac(int32_t m, int32_t e)
|
||||
{
|
||||
return (senml_numeric_t){ .type = SENML_TYPE_NUMERIC_DECFRAC,
|
||||
.value = { .df = { .e = e, .m = m } } };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a decimal fraction numeric value in the form `m*10^e`.
|
||||
*
|
||||
* @param n Numeric value to set.
|
||||
* @param m Mantissa (value) to encode.
|
||||
* @param e Exponent (scale) to encode.
|
||||
*/
|
||||
static inline void senml_set_decfrac(senml_numeric_t *n, int32_t m, int32_t e)
|
||||
{
|
||||
n->type = SENML_TYPE_NUMERIC_DECFRAC;
|
||||
n->value.df.e = e;
|
||||
n->value.df.m = m;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get an integer representation of a duration in seconds.
|
||||
*
|
||||
* @param s Duration in seconds.
|
||||
* @return Numeric representation of the duration in seconds.
|
||||
*/
|
||||
static inline senml_numeric_t senml_duration_s(int64_t s)
|
||||
{
|
||||
return senml_int(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set an integer representation of a duration in seconds.
|
||||
*
|
||||
* @param n Numeric value to set.
|
||||
* @param s Duration in seconds.
|
||||
*/
|
||||
static inline void senml_set_duration_s(senml_numeric_t *n, int64_t s)
|
||||
{
|
||||
senml_set_int(n, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a @ref senml_decfrac_t representation of a duration in milliseconds.
|
||||
*
|
||||
* @param ms Duration in milliseconds.
|
||||
* @return Numeric representation of the duration.
|
||||
*/
|
||||
static inline senml_numeric_t senml_duration_ms(int32_t ms)
|
||||
{
|
||||
return senml_decfrac(ms, -3);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a @ref senml_decfrac_t representation of a duration in milliseconds.
|
||||
*
|
||||
* @param n Numeric value to set.
|
||||
* @param ms Duration in milliseconds.
|
||||
* @return Numeric representation of the duration.
|
||||
*/
|
||||
static inline void senml_set_duration_ms(senml_numeric_t *n, int32_t ms)
|
||||
{
|
||||
senml_set_decfrac(n, ms, -3);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a @ref senml_decfrac_t representation of a duration in microseconds.
|
||||
*
|
||||
* @param us Duration in microseconds.
|
||||
* @return Numeric representation of the duration.
|
||||
*/
|
||||
static inline senml_numeric_t senml_duration_us(int32_t us)
|
||||
{
|
||||
return senml_decfrac(us, -6);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a @ref senml_decfrac_t representation of a duration in microseconds.
|
||||
*
|
||||
* @param n Numeric value to set.
|
||||
* @param us Duration in microseconds.
|
||||
* @return Numeric representation of the duration.
|
||||
*/
|
||||
static inline void senml_set_duration_us(senml_numeric_t *n, int32_t us)
|
||||
{
|
||||
senml_set_decfrac(n, us, -6);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a @ref senml_decfrac_t representation of a duration in nanoseconds.
|
||||
*
|
||||
* @param ns Duration in nanoseconds.
|
||||
* @return Numeric representation of the duration.
|
||||
*/
|
||||
static inline senml_numeric_t senml_duration_ns(int32_t ns)
|
||||
{
|
||||
return senml_decfrac(ns, -9);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a @ref senml_decfrac_t representation of a duration in nanoseconds.
|
||||
*
|
||||
* @param n Numeric value to set.
|
||||
* @param ns Duration in nanoseconds.
|
||||
*/
|
||||
static inline void senml_set_duration_ns(senml_numeric_t *n, int32_t ns)
|
||||
{
|
||||
senml_set_decfrac(n, ns, -9);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a SenML unit to a string.
|
||||
*
|
||||
* See the [SenML units](https://www.iana.org/assignments/senml/senml.xhtml#senml-units) and
|
||||
* [Secondary units](https://www.iana.org/assignments/senml/senml.xhtml#secondary-units) from IANA.
|
||||
* Values not defined in @ref senml_unit_t will result in an empty string.
|
||||
*
|
||||
* @param unit Unit to convert to string.
|
||||
*
|
||||
* @return String representation of the unit.
|
||||
*/
|
||||
const char *senml_unit_to_str(senml_unit_t unit);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SENML_H */
|
||||
/** @} */
|
121
sys/include/senml/cbor.h
Normal file
121
sys/include/senml/cbor.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sys_senml_cbor SenML CBOR
|
||||
* @ingroup sys_senml
|
||||
* @brief Functionality for encoding SenML values as CBOR
|
||||
*
|
||||
* The `senml_cbor` module contains functionality for encoding @ref sys_senml
|
||||
* values to CBOR using @ref pkg_nanocbor.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Functionality for encoding SenML values as CBOR
|
||||
*
|
||||
* @author Silke Hofstra <silke@slxh.eu>
|
||||
*/
|
||||
|
||||
#ifndef SENML_CBOR_H
|
||||
#define SENML_CBOR_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "senml.h"
|
||||
#include "nanocbor/nanocbor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SenML CBOR labels
|
||||
*
|
||||
* This list contains the SenML CBOR labels as assigned by IANA.
|
||||
*/
|
||||
typedef enum {
|
||||
SENML_LABEL_BASE_VERSION = -1,
|
||||
SENML_LABEL_BASE_NAME = -2,
|
||||
SENML_LABEL_BASE_TIME = -3,
|
||||
SENML_LABEL_BASE_UNIT = -4,
|
||||
SENML_LABEL_BASE_VALUE = -5,
|
||||
SENML_LABEL_BASE_SUM = -6,
|
||||
SENML_LABEL_NAME = 0,
|
||||
SENML_LABEL_UNIT = 1,
|
||||
SENML_LABEL_VALUE = 2,
|
||||
SENML_LABEL_STRING_VALUE = 3,
|
||||
SENML_LABEL_BOOLEAN_VALUE = 4,
|
||||
SENML_LABEL_SUM = 5,
|
||||
SENML_LABEL_TIME = 6,
|
||||
SENML_LABEL_UPDATE_TIME = 7,
|
||||
SENML_LABEL_DATA_VALUE = 8,
|
||||
} senml_cbor_label_t;
|
||||
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_SUM) || defined(DOXYGEN)
|
||||
/**
|
||||
* @brief Encode @ref senml_attr_t containing `sum` as CBOR.
|
||||
*
|
||||
* Requires the `sum` attribute to be enabled by setting `CONFIG_SENML_ATTR_SUM` to 1.
|
||||
*
|
||||
* @param enc NanoCBOR encoder.
|
||||
* @param attr Attributes (including `sum`) to encode.
|
||||
*
|
||||
* @return Size of the encoded data.
|
||||
*/
|
||||
int senml_encode_sum_cbor(nanocbor_encoder_t *enc, const senml_attr_t *attr);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Encode @ref senml_bool_value_t as CBOR.
|
||||
*
|
||||
* @param enc NanoCBOR encoder.
|
||||
* @param val value to encode.
|
||||
*
|
||||
* @return Size of the encoded data.
|
||||
*/
|
||||
int senml_encode_bool_cbor(nanocbor_encoder_t *enc, const senml_bool_value_t *val);
|
||||
|
||||
/**
|
||||
* @brief Encode @ref senml_value_t as CBOR.
|
||||
*
|
||||
* @param enc NanoCBOR encoder.
|
||||
* @param val value to encode.
|
||||
*
|
||||
* @return Size of the encoded data.
|
||||
*/
|
||||
int senml_encode_value_cbor(nanocbor_encoder_t *enc, const senml_value_t *val);
|
||||
|
||||
/**
|
||||
* @brief Encode @ref senml_string_value_t as CBOR.
|
||||
*
|
||||
* @param enc NanoCBOR encoder.
|
||||
* @param val value to encode.
|
||||
*
|
||||
* @return Size of the encoded data.
|
||||
*/
|
||||
int senml_encode_string_cbor(nanocbor_encoder_t *enc, const senml_string_value_t *val);
|
||||
|
||||
/**
|
||||
* @brief Encode @ref senml_data_value_t as CBOR.
|
||||
*
|
||||
* @param enc NanoCBOR encoder.
|
||||
* @param val value to encode.
|
||||
*
|
||||
* @return Size of the encoded data.
|
||||
*/
|
||||
int senml_encode_data_cbor(nanocbor_encoder_t *enc, const senml_data_value_t *val);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SENML_CBOR_H */
|
||||
/** @} */
|
98
sys/include/senml/phydat.h
Normal file
98
sys/include/senml/phydat.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sys_senml_phydat SenML Phydat
|
||||
* @ingroup sys_senml
|
||||
* @brief Functionality for converting from @ref sys_phydat to @ref sys_senml
|
||||
*
|
||||
* The `senml_phydat` module contains various functions for converting
|
||||
* @ref sys_phydat values to @ref sys_senml.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Functionality for converting from @ref sys_phydat to @ref sys_senml
|
||||
*
|
||||
* @author Silke Hofstra <silke@slxh.eu>
|
||||
*/
|
||||
|
||||
#ifndef SENML_PHYDAT_H
|
||||
#define SENML_PHYDAT_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "senml.h"
|
||||
#include <phydat.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Create a SenML boolean value.
|
||||
*
|
||||
* Writes the value of the given @p dim of @p phydat as a boolean.
|
||||
* @p phydat is assumed to be of @ref UNIT_BOOL.
|
||||
*
|
||||
* @note `phydat->scale` must be zero.
|
||||
*
|
||||
* @param[out] senml SenML value to store value in.
|
||||
* @param[in] phydat Phydat to convert.
|
||||
* @param[in] dim Dimension of @p phydat to convert.
|
||||
*/
|
||||
void phydat_to_senml_bool(senml_bool_value_t *senml, const phydat_t *phydat, const uint8_t dim);
|
||||
|
||||
/**
|
||||
* @brief Create a SenML float value.
|
||||
*
|
||||
* Writes the value of the given @p dim of @p phydat as a float.
|
||||
* The unit of @p phydat is converted using the following rules:
|
||||
*
|
||||
* - @ref UNIT_TIME is converted to @ref SENML_UNIT_SECOND.
|
||||
* - @ref UNIT_F is converted to @ref SENML_UNIT_KELVIN.
|
||||
* - @ref UNIT_G is converted to @ref SENML_UNIT_METER_PER_SQUARE_SECOND.
|
||||
* - @ref UNIT_BAR is converted to @ref SENML_UNIT_PASCAL.
|
||||
* - @ref UNIT_GPM3 is converted to @ref SENML_UNIT_KILOGRAM_PER_CUBIC_METER.
|
||||
* - @ref UNIT_GS is converted to @ref SENML_UNIT_TESLA.
|
||||
* - Compatible units are set to their SenML equivalent.
|
||||
* - Incompatible (or unknown) units are set to @ref SENML_UNIT_NONE.
|
||||
*
|
||||
* @param[out] senml SenML value to store value in.
|
||||
* @param[in] phydat Phydat to convert.
|
||||
* @param[in] dim Dimension of @p phydat to convert.
|
||||
*/
|
||||
void phydat_to_senml_float(senml_value_t *senml, const phydat_t *phydat, const uint8_t dim);
|
||||
|
||||
/**
|
||||
* @brief Create a SenML decimal fraction value.
|
||||
*
|
||||
* Writes the value of the given @p dim of @p phydat as a decimal value.
|
||||
* The unit of @p phydat is converted using the following rules:
|
||||
*
|
||||
* - @ref UNIT_TIME is converted to @ref SENML_UNIT_SECOND.
|
||||
* - @ref UNIT_BAR is converted to @ref SENML_UNIT_PASCAL.
|
||||
* - @ref UNIT_GPM3 is converted to @ref SENML_UNIT_KILOGRAM_PER_CUBIC_METER.
|
||||
* - @ref UNIT_GS is converted to @ref SENML_UNIT_TESLA.
|
||||
* - Compatible units are set to their SenML equivalent.
|
||||
* - Incompatible (or unknown) units are set to @ref SENML_UNIT_NONE.
|
||||
*
|
||||
* @param[out] senml SenML value to store value in.
|
||||
* @param[in] phydat Phydat to convert.
|
||||
* @param[in] dim Dimension of @p phydat to convert.
|
||||
*/
|
||||
void phydat_to_senml_decimal(senml_value_t *senml, const phydat_t *phydat, const uint8_t dim);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SENML_PHYDAT_H */
|
||||
/** @} */
|
76
sys/include/senml/saul.h
Normal file
76
sys/include/senml/saul.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sys_senml_saul SenML SAUL
|
||||
* @ingroup sys_senml
|
||||
* @brief Functionality for reading @ref drivers_saul sensors as @ref sys_senml
|
||||
*
|
||||
* The `senml_saul` module contains functions for reading sensors using
|
||||
* @ref drivers_saul and converting them to @ref sys_senml_cbor.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Functionality for reading @ref drivers_saul sensors as @ref sys_senml
|
||||
*
|
||||
* @author Silke Hofstra <silke@slxh.eu>
|
||||
*/
|
||||
|
||||
#ifndef SENML_SAUL_H
|
||||
#define SENML_SAUL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nanocbor/nanocbor.h"
|
||||
#include "saul_reg.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Use floats instead of decimal types when encoding SAUL measurements.
|
||||
*
|
||||
* If this is set to `1` the @ref phydat_t values from SAUL are converted to
|
||||
* @ref senml_numeric_t using @ref phydat_to_senml_float.
|
||||
* Values are converted using @ref phydat_to_senml_decimal otherwise.
|
||||
*/
|
||||
#ifndef CONFIG_SENML_SAUL_USE_FLOATS
|
||||
#define CONFIG_SENML_SAUL_USE_FLOATS 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Encode a single @ref drivers_saul sensor as senml+cbor.
|
||||
*
|
||||
* @param enc NanoCBOR encoder.
|
||||
* @param dev SAUL sensor to encode.
|
||||
*
|
||||
* @return Number of dimensions encoded. Less or equal to 0 on error.
|
||||
*/
|
||||
int senml_saul_reg_encode_cbor(nanocbor_encoder_t *enc, saul_reg_t *dev);
|
||||
|
||||
/**
|
||||
* @brief Encode all sensors from a @ref drivers_saul registry as senml+cbor.
|
||||
*
|
||||
* This functions reads all @ref drivers_saul sensors in a registry and encodes
|
||||
* the values as SenML/CBOR.
|
||||
*
|
||||
* @param buf Buffer to store the CBOR in.
|
||||
* @param len Length of the buffer.
|
||||
* @param reg SAUL registry to encode.
|
||||
*
|
||||
* @return Size of the encoded data.
|
||||
*/
|
||||
size_t senml_saul_encode_cbor(uint8_t *buf, size_t len, saul_reg_t *reg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SENML_SAUL_H */
|
||||
/** @} */
|
38
sys/senml/Kconfig
Normal file
38
sys/senml/Kconfig
Normal file
@ -0,0 +1,38 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
config MODULE_SENML
|
||||
bool "SenML"
|
||||
depends on TEST_KCONFIG
|
||||
help
|
||||
Generic data container for physical data and utility functions.
|
||||
|
||||
config MODULE_SENML_SAUL
|
||||
bool "SenML SAUL integration"
|
||||
depends on TEST_KCONFIG
|
||||
select MODULE_SENML_PHYDAT
|
||||
select MODULE_SENML_CBOR
|
||||
depends on MODULE_SAUL
|
||||
depends on MODULE_SAUL_REG
|
||||
help
|
||||
Generic data container for physical data and utility functions.
|
||||
|
||||
config MODULE_SENML_PHYDAT
|
||||
bool "SenML Phydat support"
|
||||
depends on TEST_KCONFIG
|
||||
select MODULE_SENML
|
||||
select MODULE_PHYDAT
|
||||
help
|
||||
Utilities to convert Phydat valus to SenML
|
||||
|
||||
config MODULE_SENML_CBOR
|
||||
bool "SenML CBOR enconding"
|
||||
depends on TEST_KCONFIG
|
||||
select MODULE_SENML
|
||||
select PACKAGE_NANOCBOR
|
||||
help
|
||||
Support for CBOR encoding of SenML values
|
7
sys/senml/Makefile
Normal file
7
sys/senml/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
MODULE = senml
|
||||
|
||||
SRC = senml.c
|
||||
|
||||
SUBMODULES = 1
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
16
sys/senml/Makefile.dep
Normal file
16
sys/senml/Makefile.dep
Normal file
@ -0,0 +1,16 @@
|
||||
ifneq (,$(filter senml_saul,$(USEMODULE)))
|
||||
USEMODULE += senml
|
||||
USEMODULE += senml_cbor
|
||||
USEMODULE += senml_phydat
|
||||
USEMODULE += saul_reg
|
||||
endif
|
||||
|
||||
ifneq (,$(filter senml_cbor,$(USEMODULE)))
|
||||
USEPKG += nanocbor
|
||||
USEMODULE += senml
|
||||
endif
|
||||
|
||||
ifneq (,$(filter senml_phydat,$(USEMODULE)))
|
||||
USEMODULE += senml
|
||||
USEMODULE += phydat
|
||||
endif
|
155
sys/senml/cbor.c
Normal file
155
sys/senml/cbor.c
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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 "senml.h"
|
||||
#include "senml/cbor.h"
|
||||
#include "nanocbor/nanocbor.h"
|
||||
|
||||
static int senml_encode_numeric_cbor(nanocbor_encoder_t *enc, const senml_numeric_t *v)
|
||||
{
|
||||
switch (v->type) {
|
||||
case SENML_TYPE_NUMERIC_FLOAT:
|
||||
return nanocbor_fmt_float(enc, v->value.f);
|
||||
case SENML_TYPE_NUMERIC_DOUBLE:
|
||||
return nanocbor_fmt_double(enc, v->value.d);
|
||||
case SENML_TYPE_NUMERIC_INT:
|
||||
return nanocbor_fmt_int(enc, v->value.i);
|
||||
case SENML_TYPE_NUMERIC_UINT:
|
||||
return nanocbor_fmt_uint(enc, v->value.u);
|
||||
case SENML_TYPE_NUMERIC_DECFRAC:
|
||||
return nanocbor_fmt_decimal_frac(enc, v->value.df.e, v->value.df.m);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int senml_encode_start_cbor(nanocbor_encoder_t *enc, const senml_attr_t *attr,
|
||||
bool sum_value)
|
||||
{
|
||||
int n = nanocbor_fmt_map(enc, !sum_value
|
||||
+ (attr->base_name != NULL)
|
||||
+ (attr->base_time.value.u != 0)
|
||||
+ (attr->base_unit != SENML_UNIT_NONE)
|
||||
+ (attr->base_value.value.u != 0)
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_SUM)
|
||||
+ (attr->base_sum.value.u != 0)
|
||||
#endif
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_VERSION)
|
||||
+ (attr->base_version != 0 && attr->base_version != 10)
|
||||
#endif
|
||||
+ (attr->name != NULL)
|
||||
+ (attr->unit != SENML_UNIT_NONE)
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_SUM)
|
||||
+ (sum_value || attr->sum.value.u != 0)
|
||||
#endif
|
||||
+ (attr->time.value.u != 0)
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_UPDATE_TIME)
|
||||
+ (attr->update_time.value.u != 0)
|
||||
#endif
|
||||
);
|
||||
|
||||
if (attr->base_name != NULL) {
|
||||
n += nanocbor_fmt_int(enc, SENML_LABEL_BASE_NAME);
|
||||
n += nanocbor_put_tstr(enc, attr->base_name);
|
||||
}
|
||||
|
||||
if (attr->base_time.value.u != 0) {
|
||||
n += nanocbor_fmt_int(enc, SENML_LABEL_BASE_TIME);
|
||||
n += senml_encode_numeric_cbor(enc, &attr->base_time);
|
||||
}
|
||||
|
||||
if (attr->base_unit != SENML_UNIT_NONE) {
|
||||
n += nanocbor_fmt_int(enc, SENML_LABEL_BASE_UNIT);
|
||||
n += nanocbor_put_tstr(enc, senml_unit_to_str(attr->base_unit));
|
||||
}
|
||||
|
||||
if (attr->base_value.value.u != 0) {
|
||||
n += nanocbor_fmt_int(enc, SENML_LABEL_BASE_VALUE);
|
||||
n += senml_encode_numeric_cbor(enc, &attr->base_value);
|
||||
}
|
||||
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_SUM)
|
||||
if (attr->base_sum.value.u != 0) {
|
||||
n += nanocbor_fmt_int(enc, SENML_LABEL_BASE_SUM);
|
||||
n += senml_encode_numeric_cbor(enc, &attr->base_sum);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_VERSION)
|
||||
if (attr->base_version != 0 && attr->base_version != 10) {
|
||||
n += nanocbor_fmt_int(enc, SENML_LABEL_BASE_VERSION);
|
||||
n += nanocbor_fmt_uint(enc, attr->base_version);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (attr->name != NULL) {
|
||||
n += nanocbor_fmt_int(enc, SENML_LABEL_NAME);
|
||||
n += nanocbor_put_tstr(enc, attr->name);
|
||||
}
|
||||
|
||||
if (attr->unit != SENML_UNIT_NONE) {
|
||||
n += nanocbor_fmt_int(enc, SENML_LABEL_UNIT);
|
||||
n += nanocbor_put_tstr(enc, senml_unit_to_str(attr->unit));
|
||||
}
|
||||
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_SUM)
|
||||
if (sum_value || attr->sum.value.u != 0) {
|
||||
n += nanocbor_fmt_int(enc, SENML_LABEL_SUM);
|
||||
n += senml_encode_numeric_cbor(enc, &attr->sum);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (attr->time.value.u != 0) {
|
||||
n += nanocbor_fmt_int(enc, SENML_LABEL_TIME);
|
||||
n += senml_encode_numeric_cbor(enc, &attr->time);
|
||||
}
|
||||
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_UPDATE_TIME)
|
||||
if (attr->update_time.value.u != 0) {
|
||||
n += nanocbor_fmt_int(enc, SENML_LABEL_UPDATE_TIME);
|
||||
n += senml_encode_numeric_cbor(enc, &attr->update_time);
|
||||
}
|
||||
#endif
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
#if IS_ACTIVE(CONFIG_SENML_ATTR_SUM)
|
||||
int senml_encode_sum_cbor(nanocbor_encoder_t *enc, const senml_attr_t *attr)
|
||||
{
|
||||
return senml_encode_start_cbor(enc, attr, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
int senml_encode_bool_cbor(nanocbor_encoder_t *enc, const senml_bool_value_t *val)
|
||||
{
|
||||
return senml_encode_start_cbor(enc, &val->attr, false) +
|
||||
nanocbor_fmt_int(enc, SENML_LABEL_BOOLEAN_VALUE) +
|
||||
nanocbor_fmt_bool(enc, val->value);
|
||||
}
|
||||
|
||||
int senml_encode_value_cbor(nanocbor_encoder_t *enc, const senml_value_t *val)
|
||||
{
|
||||
return senml_encode_start_cbor(enc, &val->attr, false) +
|
||||
nanocbor_fmt_int(enc, SENML_LABEL_VALUE) +
|
||||
senml_encode_numeric_cbor(enc, &val->value);
|
||||
}
|
||||
|
||||
int senml_encode_string_cbor(nanocbor_encoder_t *enc, const senml_string_value_t *val)
|
||||
{
|
||||
return senml_encode_start_cbor(enc, &val->attr, false) +
|
||||
nanocbor_fmt_int(enc, SENML_LABEL_STRING_VALUE) +
|
||||
nanocbor_put_tstrn(enc, val->value, val->len);
|
||||
}
|
||||
|
||||
int senml_encode_data_cbor(nanocbor_encoder_t *enc, const senml_data_value_t *val)
|
||||
{
|
||||
return senml_encode_start_cbor(enc, &val->attr, false) +
|
||||
nanocbor_fmt_int(enc, SENML_LABEL_DATA_VALUE) +
|
||||
nanocbor_put_bstr(enc, val->value, val->len);
|
||||
}
|
153
sys/senml/phydat.c
Normal file
153
sys/senml/phydat.c
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
|
||||
#include "math.h"
|
||||
#include "senml.h"
|
||||
#include "senml/phydat.h"
|
||||
|
||||
|
||||
|
||||
static uint8_t phydat_unit_to_senml_unit(uint8_t unit)
|
||||
{
|
||||
switch (unit) {
|
||||
/* Compatible units */
|
||||
case UNIT_TEMP_C: return SENML_UNIT_CELSIUS;
|
||||
case UNIT_TEMP_K: return SENML_UNIT_KELVIN;
|
||||
case UNIT_LUX: return SENML_UNIT_LUX;
|
||||
case UNIT_M: return SENML_UNIT_METER;
|
||||
case UNIT_M2: return SENML_UNIT_SQUARE_METER;
|
||||
case UNIT_M3: return SENML_UNIT_CUBIC_METER;
|
||||
case UNIT_GR: return SENML_UNIT_GRAM;
|
||||
case UNIT_A: return SENML_UNIT_AMPERE;
|
||||
case UNIT_V: return SENML_UNIT_VOLT;
|
||||
case UNIT_W: return SENML_UNIT_WATT;
|
||||
case UNIT_T: return SENML_UNIT_TESLA;
|
||||
case UNIT_COULOMB: return SENML_UNIT_COULOMB;
|
||||
case UNIT_F: return SENML_UNIT_FARAD;
|
||||
case UNIT_OHM: return SENML_UNIT_OHM;
|
||||
case UNIT_PH: return SENML_UNIT_PH;
|
||||
case UNIT_PA: return SENML_UNIT_PASCAL;
|
||||
case UNIT_CD: return SENML_UNIT_CANDELA;
|
||||
|
||||
/* Compatible Secondary units */
|
||||
case UNIT_DBM: return SENML_UNIT_DECIBEL_MILLIWATT;
|
||||
case UNIT_PERCENT: return SENML_UNIT_PERCENT;
|
||||
case UNIT_PERMILL: return SENML_UNIT_PERMILLE;
|
||||
case UNIT_PPM: return SENML_UNIT_PARTS_PER_MILLION;
|
||||
case UNIT_PPB: return SENML_UNIT_PARTS_PER_BILLION;
|
||||
|
||||
/* Incompatible units */
|
||||
case UNIT_TEMP_F: return SENML_UNIT_NONE; /* use K or Cel instead */
|
||||
case UNIT_GS: return SENML_UNIT_NONE; /* use T instead */
|
||||
case UNIT_G: return SENML_UNIT_NONE; /* use m/s2 instead */
|
||||
case UNIT_BAR: return SENML_UNIT_NONE; /* use Pa or hPa instead */
|
||||
case UNIT_TIME: return SENML_UNIT_NONE; /* split into second/minute/hour */
|
||||
case UNIT_DATE: return SENML_UNIT_NONE; /* split into day/month/year */
|
||||
case UNIT_GPM3: return SENML_UNIT_NONE; /* use kg/m3 instead */
|
||||
case UNIT_DPS: return SENML_UNIT_NONE; /* no alternative */
|
||||
case UNIT_CPM3: return SENML_UNIT_NONE; /* no alternative */
|
||||
default: return SENML_UNIT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void phydat_to_senml_bool(senml_bool_value_t *senml, const phydat_t *phydat, const uint8_t dim)
|
||||
{
|
||||
senml->value = phydat->val[dim] == 1;
|
||||
senml->attr.unit = SENML_UNIT_NONE;
|
||||
}
|
||||
|
||||
void phydat_to_senml_float(senml_value_t *senml, const phydat_t *phydat, const uint8_t dim)
|
||||
{
|
||||
float value = (float)(phydat->val[dim]);
|
||||
|
||||
if (phydat->scale) {
|
||||
value *= pow(10, phydat->scale);
|
||||
}
|
||||
|
||||
switch (phydat->unit) {
|
||||
/* time conversion */
|
||||
case UNIT_TIME:
|
||||
senml->attr.unit = (dim == 0)
|
||||
? SENML_UNIT_SECOND
|
||||
: (dim == 1)
|
||||
? SENML_UNIT_MINUTE
|
||||
: SENML_UNIT_HOUR;
|
||||
break;
|
||||
|
||||
/* simple conversions */
|
||||
case UNIT_TEMP_F:
|
||||
/* convert fahrenheit to kelvin */
|
||||
value = (value + 459.67) * (5. / 9.);
|
||||
senml->attr.unit = SENML_UNIT_KELVIN;
|
||||
break;
|
||||
case UNIT_G:
|
||||
/* convert gravitational acceleration to acceleration */
|
||||
value *= 9.80665;
|
||||
senml->attr.unit = SENML_UNIT_METER_PER_SQUARE_SECOND;
|
||||
break;
|
||||
case UNIT_BAR:
|
||||
value *= 100000;
|
||||
senml->attr.unit = SENML_UNIT_PASCAL;
|
||||
break;
|
||||
case UNIT_GPM3:
|
||||
value *= 0.001;
|
||||
senml->attr.unit = SENML_UNIT_KILOGRAM_PER_CUBIC_METER;
|
||||
break;
|
||||
case UNIT_GS:
|
||||
value *= 0.0001;
|
||||
senml->attr.unit = SENML_UNIT_TESLA;
|
||||
break;
|
||||
|
||||
/* compatible (or not converted) */
|
||||
default:
|
||||
senml->attr.unit = phydat_unit_to_senml_unit(phydat->unit);
|
||||
break;
|
||||
}
|
||||
|
||||
senml->value = senml_float(value);
|
||||
}
|
||||
|
||||
void phydat_to_senml_decimal(senml_value_t *senml, const phydat_t *phydat, const uint8_t dim)
|
||||
{
|
||||
int32_t m = phydat->val[dim];
|
||||
int32_t e = phydat->scale;
|
||||
|
||||
switch (phydat->unit) {
|
||||
/* time conversion */
|
||||
case UNIT_TIME:
|
||||
senml->attr.unit = (dim == 0)
|
||||
? SENML_UNIT_SECOND
|
||||
: (dim == 1)
|
||||
? SENML_UNIT_MINUTE
|
||||
: SENML_UNIT_HOUR;
|
||||
break;
|
||||
|
||||
/* simple conversions */
|
||||
case UNIT_BAR:
|
||||
e += 5;
|
||||
senml->attr.unit = SENML_UNIT_PASCAL;
|
||||
break;
|
||||
case UNIT_GPM3:
|
||||
e -= 3;
|
||||
senml->attr.unit = SENML_UNIT_KILOGRAM_PER_CUBIC_METER;
|
||||
break;
|
||||
case UNIT_GS:
|
||||
e -= 4;
|
||||
senml->attr.unit = SENML_UNIT_TESLA;
|
||||
break;
|
||||
|
||||
/* compatible, or not converted */
|
||||
default:
|
||||
senml->attr.unit = phydat_unit_to_senml_unit(phydat->unit);
|
||||
break;
|
||||
}
|
||||
|
||||
senml->value = senml_decfrac(m, e);
|
||||
}
|
99
sys/senml/saul.c
Normal file
99
sys/senml/saul.c
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
127
sys/senml/senml.c
Normal file
127
sys/senml/senml.c
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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 "senml.h"
|
||||
|
||||
const char *senml_unit_to_str(senml_unit_t unit)
|
||||
{
|
||||
switch (unit) {
|
||||
case SENML_UNIT_NONE: return "";
|
||||
case SENML_UNIT_METER: return "m";
|
||||
case SENML_UNIT_KILOGRAM: return "kg";
|
||||
case SENML_UNIT_GRAM: return "g";
|
||||
case SENML_UNIT_SECOND: return "s";
|
||||
case SENML_UNIT_AMPERE: return "A";
|
||||
case SENML_UNIT_KELVIN: return "K";
|
||||
case SENML_UNIT_CANDELA: return "cd";
|
||||
case SENML_UNIT_MOLE: return "mol";
|
||||
case SENML_UNIT_HERTZ: return "Hz";
|
||||
case SENML_UNIT_RADIAN: return "rad";
|
||||
case SENML_UNIT_STERADIAN: return "sr";
|
||||
case SENML_UNIT_NEWTON: return "N";
|
||||
case SENML_UNIT_PASCAL: return "Pa";
|
||||
case SENML_UNIT_JOULE: return "J";
|
||||
case SENML_UNIT_WATT: return "W";
|
||||
case SENML_UNIT_COULOMB: return "C";
|
||||
case SENML_UNIT_VOLT: return "V";
|
||||
case SENML_UNIT_FARAD: return "F";
|
||||
case SENML_UNIT_OHM: return "Ohm";
|
||||
case SENML_UNIT_SIEMENS: return "S";
|
||||
case SENML_UNIT_WEBER: return "Wb";
|
||||
case SENML_UNIT_TESLA: return "T";
|
||||
case SENML_UNIT_HENRY: return "H";
|
||||
case SENML_UNIT_CELSIUS: return "Cel";
|
||||
case SENML_UNIT_LUMEN: return "lm";
|
||||
case SENML_UNIT_LUX: return "lx";
|
||||
case SENML_UNIT_BECQUEREL: return "Bq";
|
||||
case SENML_UNIT_GRAY: return "Gy";
|
||||
case SENML_UNIT_SIEVERT: return "Sv";
|
||||
case SENML_UNIT_KATAL: return "kat";
|
||||
case SENML_UNIT_SQUARE_METER: return "m2";
|
||||
case SENML_UNIT_CUBIC_METER: return "m3";
|
||||
case SENML_UNIT_LITER: return "l";
|
||||
case SENML_UNIT_METER_PER_SECOND: return "m/s";
|
||||
case SENML_UNIT_METER_PER_SQUARE_SECOND: return "m/s2";
|
||||
case SENML_UNIT_CUBIC_METER_PER_SECOND: return "m3/s";
|
||||
case SENML_UNIT_LITER_PER_SECOND: return "l/s";
|
||||
case SENML_UNIT_WATT_PER_SQUARE_METER: return "W/m2";
|
||||
case SENML_UNIT_CANDELA_PER_SQUARE_METER: return "cd/m2";
|
||||
case SENML_UNIT_BIT: return "bit";
|
||||
case SENML_UNIT_BIT_PER_SECOND: return "bit/s";
|
||||
case SENML_UNIT_LATITUDE: return "lat";
|
||||
case SENML_UNIT_LONGITUDE: return "lon";
|
||||
case SENML_UNIT_PH: return "pH";
|
||||
case SENML_UNIT_DECIBEL: return "dB";
|
||||
case SENML_UNIT_DBW: return "dBW";
|
||||
case SENML_UNIT_BEL: return "Bspl";
|
||||
case SENML_UNIT_COUNT: return "count";
|
||||
case SENML_UNIT_RATIO: return "/";
|
||||
case SENML_UNIT_RATIO_2: return "%";
|
||||
case SENML_UNIT_RELATIVE_HUMIDITY_PERCENT: return "%RH";
|
||||
case SENML_UNIT_REMAINING_BATTERY_PERCENT: return "%EL";
|
||||
case SENML_UNIT_REMAINING_BATTERY_SECONDS: return "EL";
|
||||
case SENML_UNIT_RATE: return "1/s";
|
||||
case SENML_UNIT_RPM: return "1/min";
|
||||
case SENML_UNIT_BEAT_PER_MINUTE: return "beat/min";
|
||||
case SENML_UNIT_BEATS: return "beats";
|
||||
case SENML_UNIT_SIEMENS_PER_METER: return "S/m";
|
||||
|
||||
case SENML_UNIT_BYTE: return "B";
|
||||
case SENML_UNIT_VOLT_AMPERE: return "VA";
|
||||
case SENML_UNIT_VOLT_AMPERE_SECOND: return "VAs";
|
||||
case SENML_UNIT_VOLT_AMPERE_REACTIVE: return "var";
|
||||
case SENML_UNIT_VOLT_AMPERE_REACTIVE_SECOND: return "vars";
|
||||
case SENML_UNIT_JOULE_PER_METER: return "J/m";
|
||||
case SENML_UNIT_KILOGRAM_PER_CUBIC_METER: return "kg/m3";
|
||||
case SENML_UNIT_DEGREE: return "deg";
|
||||
|
||||
case SENML_UNIT_NEPHELOMETRIC_TURBIDITY_UNIT: return "NTU";
|
||||
|
||||
case SENML_UNIT_MILLISECOND: return "ms";
|
||||
case SENML_UNIT_MINUTE: return "min";
|
||||
case SENML_UNIT_HOUR: return "h";
|
||||
case SENML_UNIT_MEGAHERTZ: return "MHz";
|
||||
case SENML_UNIT_KILOWATT: return "kW";
|
||||
case SENML_UNIT_KILOVOLT_AMPERE: return "kVA";
|
||||
case SENML_UNIT_KILOVAR: return "kvar";
|
||||
case SENML_UNIT_AMPERE_HOUR: return "Ah";
|
||||
case SENML_UNIT_WATT_HOUR: return "Wh";
|
||||
case SENML_UNIT_KILOWATT_HOUR: return "kWh";
|
||||
case SENML_UNIT_VAR_HOUR: return "varh";
|
||||
case SENML_UNIT_KILOVAR_HOUR: return "kvarh";
|
||||
case SENML_UNIT_KILOVOLT_AMPERE_HOUR: return "kVAh";
|
||||
case SENML_UNIT_WATT_HOUR_PER_KILOMETER: return "Wh/km";
|
||||
case SENML_UNIT_KIBIBYTE: return "KiB";
|
||||
case SENML_UNIT_GIGABYTE: return "GB";
|
||||
case SENML_UNIT_MEGABIT_PER_SECOND: return "MBit/s";
|
||||
case SENML_UNIT_BYTE_PER_SECOND: return "B/s";
|
||||
case SENML_UNIT_MEGABYTE_PER_SECOND: return "MB/s";
|
||||
case SENML_UNIT_MILLIVOLT: return "mV";
|
||||
case SENML_UNIT_MILLIAMPERE: return "mA";
|
||||
case SENML_UNIT_DECIBEL_MILLIWATT: return "dBm";
|
||||
case SENML_UNIT_MICROGRAM_PER_CUBIC_METER: return "ug/m3";
|
||||
case SENML_UNIT_MILLIMETER_PER_HOUR: return "mm/h";
|
||||
case SENML_UNIT_METER_PER_HOUR: return "m/h";
|
||||
case SENML_UNIT_PARTS_PER_MILLION: return "ppm";
|
||||
case SENML_UNIT_PERCENT: return "/100";
|
||||
case SENML_UNIT_PERMILLE: return "/1000";
|
||||
case SENML_UNIT_HECTOPASCAL: return "hPa";
|
||||
case SENML_UNIT_MILLIMETER: return "mm";
|
||||
case SENML_UNIT_CENTIMETER: return "cm";
|
||||
case SENML_UNIT_KILOMETER: return "km";
|
||||
case SENML_UNIT_KILOMETER_PER_HOUR: return "km/h";
|
||||
case SENML_UNIT_PARTS_PER_BILLION: return "ppb";
|
||||
case SENML_UNIT_PARTS_PER_TRILLION: return "ppt";
|
||||
case SENML_UNIT_VOLT_AMPERE_HOUR: return "VAh";
|
||||
case SENML_UNIT_MILLIGRAM_PER_LITER: return "mg/l";
|
||||
case SENML_UNIT_MICROGRAM_PER_LITER: return "ug/l";
|
||||
case SENML_UNIT_GRAM_PER_LITER: return "g/l";
|
||||
|
||||
default: return "";
|
||||
}
|
||||
}
|
16
tests/senml_cbor/Makefile
Normal file
16
tests/senml_cbor/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
USEMODULE += senml_cbor
|
||||
USEMODULE += fmt
|
||||
USEMODULE += embunit
|
||||
|
||||
CFLAGS += -DCONFIG_SENML_ATTR_SUM
|
||||
CFLAGS += -DCONFIG_SENML_ATTR_VERSION
|
||||
CFLAGS += -DCONFIG_SENML_ATTR_UPDATE_TIME
|
||||
|
||||
CFLAGS += -DTHREAD_STACKSIZE_DEFAULT=1536
|
||||
|
||||
# The following BOARDs redefine THREAD_STACKSIZE_DEFAULT
|
||||
BOARD_BLACKLIST += nucleo-l011k4 stk3200
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
10
tests/senml_cbor/Makefile.ci
Normal file
10
tests/senml_cbor/Makefile.ci
Normal file
@ -0,0 +1,10 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atmega328p-xplained-mini \
|
||||
nucleo-f031k6 \
|
||||
nucleo-l011k4 \
|
||||
#
|
3
tests/senml_cbor/app.config.test
Normal file
3
tests/senml_cbor/app.config.test
Normal file
@ -0,0 +1,3 @@
|
||||
CONFIG_MODULE_SENML_CBOR=y
|
||||
CONFIG_MODULE_FMT=y
|
||||
CONFIG_MODULE_EMBUNIT=y
|
126
tests/senml_cbor/main.c
Normal file
126
tests/senml_cbor/main.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Short SenML CBOR test
|
||||
*
|
||||
* @author Silke Hofstra <silke@slxh.eu>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "senml/cbor.h"
|
||||
#include "fmt.h"
|
||||
|
||||
#define BUF_SIZE (128)
|
||||
|
||||
static uint8_t cbor_buf[BUF_SIZE];
|
||||
static char result[2 * BUF_SIZE];
|
||||
static char expect[] = "89A5216943424F522074657374221A608404D001616D07187802F953B0A206"
|
||||
"0102F953B0A2060202183DA2060302183DA2060402C48220190267A2060504"
|
||||
"F5A20606036752494F54204F53A20607084400010203A201626B6705183D";
|
||||
|
||||
void test_senml_encode(void)
|
||||
{
|
||||
nanocbor_encoder_t enc;
|
||||
|
||||
/* Some common attributes to set on the first element */
|
||||
senml_attr_t attr = {
|
||||
.base_name = "CBOR test",
|
||||
.base_time = senml_duration_s(1619264720),
|
||||
.update_time = senml_duration_s(120),
|
||||
.unit = SENML_UNIT_METER,
|
||||
};
|
||||
|
||||
/* A numeric (float) value */
|
||||
senml_value_t vf = { .attr = attr, .value = senml_float(61.5) };
|
||||
|
||||
/* A numeric (double) value */
|
||||
senml_value_t vd = { .attr = { .time = senml_duration_s(1) },
|
||||
.value = senml_double(61.5) };
|
||||
|
||||
/* A numeric (int) value */
|
||||
senml_value_t vi = { .attr = { .time = senml_duration_s(2) },
|
||||
.value = senml_int(61) };
|
||||
|
||||
/* A numeric (uint) value */
|
||||
senml_value_t vu = { .attr = { .time = senml_duration_s(3) },
|
||||
.value = senml_uint(61) };
|
||||
|
||||
/* A numeric (decimal fraction) value */
|
||||
senml_value_t vdf = { .attr = { .time = senml_duration_s(4) },
|
||||
.value = senml_decfrac(615, -1) };
|
||||
|
||||
/* A boolean value */
|
||||
senml_bool_value_t vb = { .attr = { .time = senml_duration_s(5) },
|
||||
.value = true };
|
||||
|
||||
/* A string value */
|
||||
char string[] = "RIOT OS";
|
||||
senml_string_value_t vs = { .attr = { .time = senml_duration_s(6) },
|
||||
.value = string, .len = sizeof string - 1 };
|
||||
|
||||
/* A data value */
|
||||
uint8_t data[] = { 0x00, 0x01, 0x02, 0x03 };
|
||||
senml_data_value_t vdat = { .attr = { .time = senml_duration_s(7) },
|
||||
.value = data, .len = sizeof data };
|
||||
|
||||
/* A numeric (float) sum value */
|
||||
senml_attr_t sum = {
|
||||
.sum = senml_int(61),
|
||||
.unit = SENML_UNIT_KILOGRAM,
|
||||
};
|
||||
|
||||
/* Initialize encoder, and start array */
|
||||
nanocbor_encoder_init(&enc, cbor_buf, sizeof cbor_buf);
|
||||
nanocbor_fmt_array(&enc, 9);
|
||||
|
||||
/* Encode the values */
|
||||
senml_encode_value_cbor(&enc, &vf);
|
||||
senml_encode_value_cbor(&enc, &vd);
|
||||
senml_encode_value_cbor(&enc, &vi);
|
||||
senml_encode_value_cbor(&enc, &vu);
|
||||
senml_encode_value_cbor(&enc, &vdf);
|
||||
senml_encode_bool_cbor(&enc, &vb);
|
||||
senml_encode_string_cbor(&enc, &vs);
|
||||
senml_encode_data_cbor(&enc, &vdat);
|
||||
senml_encode_sum_cbor(&enc, &sum);
|
||||
|
||||
size_t len = nanocbor_encoded_len(&enc);
|
||||
|
||||
fmt_bytes_hex(result, cbor_buf, len);
|
||||
|
||||
/* Compare hex result */
|
||||
TEST_ASSERT_EQUAL_INT(2 * len, sizeof expect - 1);
|
||||
TEST_ASSERT_EQUAL_INT(0, strncmp(expect, result, len));
|
||||
}
|
||||
|
||||
Test *tests_senml(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_senml_encode),
|
||||
};
|
||||
EMB_UNIT_TESTCALLER(senml_tests, NULL, NULL, fixtures);
|
||||
return (Test *)&senml_tests;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
TESTS_START();
|
||||
TESTS_RUN(tests_senml());
|
||||
TESTS_END();
|
||||
return 0;
|
||||
}
|
14
tests/senml_cbor/tests/01-run.py
Executable file
14
tests/senml_cbor/tests/01-run.py
Executable file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2017 Freie Universität Berlin
|
||||
#
|
||||
# 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.
|
||||
|
||||
import sys
|
||||
from testrunner import run_check_unittests
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(run_check_unittests())
|
7
tests/senml_phydat/Makefile
Normal file
7
tests/senml_phydat/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
USEMODULE += senml_phydat
|
||||
USEMODULE += embunit
|
||||
USEMODULE += printf_float
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
16
tests/senml_phydat/Makefile.ci
Normal file
16
tests/senml_phydat/Makefile.ci
Normal file
@ -0,0 +1,16 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atmega328p-xplained-mini \
|
||||
nucleo-f031k6 \
|
||||
nucleo-f042k6 \
|
||||
nucleo-l011k4 \
|
||||
nucleo-l031k6 \
|
||||
samd10-xmini \
|
||||
stk3200 \
|
||||
stm32f030f4-demo \
|
||||
stm32g0316-disco \
|
||||
#
|
3
tests/senml_phydat/app.config.test
Normal file
3
tests/senml_phydat/app.config.test
Normal file
@ -0,0 +1,3 @@
|
||||
CONFIG_MODULE_SENML_PHYDAT=y
|
||||
CONFIG_MODULE_EMBUNIT=y
|
||||
CONFIG_MODULE_PRINTF_FLOAT=y
|
174
tests/senml_phydat/main.c
Normal file
174
tests/senml_phydat/main.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief SenML Phydat tests
|
||||
*
|
||||
* @author Silke Hofstra <silke@slxh.eu>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "senml/phydat.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#ifndef PRIi64
|
||||
#define PRIi64 "lli"
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
phydat_t phydat;
|
||||
senml_value_t senml;
|
||||
} time_test_t;
|
||||
|
||||
typedef struct {
|
||||
phydat_t phydat;
|
||||
senml_value_t senml1;
|
||||
senml_value_t senml2;
|
||||
uint8_t dim;
|
||||
} value_test_t;
|
||||
|
||||
#define senml_s(s) { .attr = { .unit = SENML_UNIT_SECOND }, \
|
||||
.value = { SENML_TYPE_NUMERIC_INT, { .i = s } } }
|
||||
|
||||
#define senml_f(v, u) { .attr = { .unit = u }, \
|
||||
.value = { SENML_TYPE_NUMERIC_FLOAT, { .f = v } } }
|
||||
|
||||
#define senml_df(m, e, u) { .attr = { .unit = u }, \
|
||||
.value = { SENML_TYPE_NUMERIC_DECFRAC, { .df = { e, m } } } }
|
||||
|
||||
static value_test_t value_tests[] = {
|
||||
{
|
||||
.phydat = { { 360, 0, 0 }, UNIT_M, 6 },
|
||||
.senml1 = senml_f(360e6, SENML_UNIT_METER),
|
||||
.senml2 = senml_df(360, 6, SENML_UNIT_METER),
|
||||
.dim = 0
|
||||
},
|
||||
{
|
||||
.phydat = { { 864, 0, 0 }, UNIT_TIME, 2 },
|
||||
.senml1 = senml_f(86400, SENML_UNIT_SECOND),
|
||||
.senml2 = senml_df(864, 2, SENML_UNIT_SECOND),
|
||||
.dim = 0
|
||||
},
|
||||
{
|
||||
.phydat = { { 0, 144, 0 }, UNIT_TIME, 1 },
|
||||
.senml1 = senml_f(1440, SENML_UNIT_MINUTE),
|
||||
.senml2 = senml_df(144, 1, SENML_UNIT_MINUTE),
|
||||
.dim = 1
|
||||
},
|
||||
{
|
||||
.phydat = { { 0, 0, 24 }, UNIT_TIME, 0 },
|
||||
.senml1 = senml_f(24, SENML_UNIT_HOUR),
|
||||
.senml2 = senml_df(24, 0, SENML_UNIT_HOUR),
|
||||
.dim = 2
|
||||
},
|
||||
{
|
||||
.phydat = { { 0, 0, 0 }, UNIT_TEMP_F, 3 },
|
||||
.senml1 = senml_f(255.37, SENML_UNIT_KELVIN),
|
||||
.senml2 = senml_df(0, 3, SENML_UNIT_NONE),
|
||||
},
|
||||
{
|
||||
.phydat = { { 314, 0, 0 }, UNIT_G, -2 },
|
||||
.senml1 = senml_f(30.792881, SENML_UNIT_METER_PER_SQUARE_SECOND),
|
||||
.senml2 = senml_df(314, -2, SENML_UNIT_NONE),
|
||||
},
|
||||
{
|
||||
.phydat = { { 988, 0, 0 }, UNIT_BAR, -3 },
|
||||
.senml1 = senml_f(98.8e3, SENML_UNIT_PASCAL),
|
||||
.senml2 = senml_df(988, 2, SENML_UNIT_PASCAL),
|
||||
},
|
||||
{
|
||||
.phydat = { { 193, 0, 0 }, UNIT_GPM3, 5 },
|
||||
.senml1 = senml_f(19.3e3, SENML_UNIT_KILOGRAM_PER_CUBIC_METER),
|
||||
.senml2 = senml_df(193, 2, SENML_UNIT_KILOGRAM_PER_CUBIC_METER),
|
||||
},
|
||||
{
|
||||
.phydat = { { 220, 0, 0 }, UNIT_GS, 3 },
|
||||
.senml1 = senml_f(22, SENML_UNIT_TESLA),
|
||||
.senml2 = senml_df(220, -1, SENML_UNIT_TESLA),
|
||||
}
|
||||
};
|
||||
|
||||
void test_phydat_to_senml_float(void)
|
||||
{
|
||||
senml_value_t res;
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(value_tests); i++) {
|
||||
senml_value_t *exp = &(value_tests[i].senml1);
|
||||
|
||||
phydat_to_senml_float(&res, &(value_tests[i].phydat), value_tests[i].dim);
|
||||
|
||||
DEBUG("Float: %" PRIi16 "e%" PRIi16 " %s -> %.f %s\n",
|
||||
value_tests[i].phydat.val[value_tests[i].dim], value_tests[i].phydat.scale,
|
||||
phydat_unit_to_str(value_tests[i].phydat.unit),
|
||||
res.value.value.f,
|
||||
senml_unit_to_str(res.attr.unit));
|
||||
|
||||
TEST_ASSERT_EQUAL_STRING(senml_unit_to_str(exp->attr.unit),
|
||||
senml_unit_to_str(res.attr.unit));
|
||||
TEST_ASSERT_EQUAL_INT(exp->value.type, res.value.type);
|
||||
TEST_ASSERT_EQUAL_INT((int)roundf(exp->value.value.f * 100),
|
||||
(int)roundf(res.value.value.f * 100));
|
||||
}
|
||||
}
|
||||
|
||||
void test_phydat_to_senml_decimal(void)
|
||||
{
|
||||
senml_value_t res;
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(value_tests); i++) {
|
||||
senml_value_t *exp = &(value_tests[i].senml2);
|
||||
|
||||
phydat_to_senml_decimal(&res, &(value_tests[i].phydat), value_tests[i].dim);
|
||||
|
||||
DEBUG("Decimal: %" PRIi16 "e%" PRIi16 " %s -> %" PRIi32 "e%" PRIi32 " %s\n",
|
||||
value_tests[i].phydat.val[value_tests[i].dim], value_tests[i].phydat.scale,
|
||||
phydat_unit_to_str(value_tests[i].phydat.unit),
|
||||
res.value.value.df.m, res.value.value.df.e,
|
||||
senml_unit_to_str(res.attr.unit));
|
||||
|
||||
TEST_ASSERT_EQUAL_STRING(senml_unit_to_str(exp->attr.unit),
|
||||
senml_unit_to_str(res.attr.unit));
|
||||
TEST_ASSERT_EQUAL_INT(exp->value.type, res.value.type);
|
||||
TEST_ASSERT_EQUAL_INT(exp->value.value.df.m, res.value.value.df.m);
|
||||
TEST_ASSERT_EQUAL_INT(exp->value.value.df.e, res.value.value.df.e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Test *tests_senml(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
/* Don't run this test on CPUs with unpredictable rounding */
|
||||
#if !defined(__AVR__) && !defined(CPU_MSP430FXYZ)
|
||||
new_TestFixture(test_phydat_to_senml_float),
|
||||
#endif
|
||||
new_TestFixture(test_phydat_to_senml_decimal),
|
||||
};
|
||||
EMB_UNIT_TESTCALLER(senml_tests, NULL, NULL, fixtures);
|
||||
return (Test *)&senml_tests;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
TESTS_START();
|
||||
TESTS_RUN(tests_senml());
|
||||
TESTS_END();
|
||||
return 0;
|
||||
}
|
14
tests/senml_phydat/tests/01-run.py
Executable file
14
tests/senml_phydat/tests/01-run.py
Executable file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2017 Freie Universität Berlin
|
||||
#
|
||||
# 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.
|
||||
|
||||
import sys
|
||||
from testrunner import run_check_unittests
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(run_check_unittests())
|
8
tests/senml_saul/Makefile
Normal file
8
tests/senml_saul/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
USEMODULE += saul_default
|
||||
USEMODULE += senml_saul
|
||||
USEMODULE += fmt
|
||||
USEMODULE += embunit
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
12
tests/senml_saul/Makefile.ci
Normal file
12
tests/senml_saul/Makefile.ci
Normal file
@ -0,0 +1,12 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atmega328p-xplained-mini \
|
||||
nucleo-f031k6 \
|
||||
nucleo-l011k4 \
|
||||
samd10-xmini \
|
||||
stm32f030f4-demo \
|
||||
#
|
61
tests/senml_saul/main.c
Normal file
61
tests/senml_saul/main.c
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Short SenML SAUL test
|
||||
*
|
||||
* @author Silke Hofstra <silke@slxh.eu>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "senml/saul.h"
|
||||
#include "fmt.h"
|
||||
|
||||
#define BUF_SIZE (128)
|
||||
|
||||
static uint8_t cbor_buf[BUF_SIZE];
|
||||
static char result[2 * BUF_SIZE];
|
||||
static char expect[] = "9FFF";
|
||||
|
||||
void test_senml_encode(void)
|
||||
{
|
||||
size_t len = senml_saul_encode_cbor(cbor_buf, sizeof cbor_buf, saul_reg);
|
||||
|
||||
/* Encode as hex */
|
||||
fmt_bytes_hex(result, cbor_buf, len);
|
||||
|
||||
/* Compare hex result */
|
||||
TEST_ASSERT_EQUAL_INT(2 * len, sizeof expect - 1);
|
||||
TEST_ASSERT_EQUAL_INT(0, strncmp(expect, result, len));
|
||||
}
|
||||
|
||||
Test *tests_senml(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_senml_encode),
|
||||
};
|
||||
EMB_UNIT_TESTCALLER(senml_tests, NULL, NULL, fixtures);
|
||||
return (Test *)&senml_tests;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
TESTS_START();
|
||||
TESTS_RUN(tests_senml());
|
||||
TESTS_END();
|
||||
return 0;
|
||||
}
|
14
tests/senml_saul/tests/01-run.py
Executable file
14
tests/senml_saul/tests/01-run.py
Executable file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2017 Freie Universität Berlin
|
||||
#
|
||||
# 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.
|
||||
|
||||
import sys
|
||||
from testrunner import run_check_unittests
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(run_check_unittests())
|
Loading…
Reference in New Issue
Block a user