Commit b6f69a6d authored by Robert Lubos's avatar Robert Lubos Committed by Christopher Friedt
Browse files

net: lwm2m: Align float handling with specification



According to the specificaion, resources are not predefined to use 32 or
64 bit floating point numbers, but should rather accept any of them (as
indicated by the size of the TLV in the message). This lead to issues
for instance with Eclipse Leshan LWM2M server, where Leshan sent 64-bit
value, while Zephyr expected 32-bit, making it impossible to write
the resource.

Therefore, unify the float usage to 32-bit float representation and fix
the TLV parsing functions, to accept values sent as either 32 or 64 bit
float.

Signed-off-by: default avatarRobert Lubos <robert.lubos@nordicsemi.no>
parent 9cdc1bb9
Loading
Loading
Loading
Loading
+0 −33
Original line number Diff line number Diff line
@@ -378,19 +378,6 @@ typedef struct float32_value {
	int32_t val2;
} float32_value_t;

/**
 * @brief Maximum precision value for 64-bit LwM2M float val2
 */
#define LWM2M_FLOAT64_DEC_MAX 1000000000LL

/**
 * @brief 32-bit variant of the LwM2M float structure
 */
typedef struct float64_value {
	int64_t val1;
	int64_t val2;
} float64_value_t;

/**
 * @brief Maximum value for ObjLnk resource fields
 */
@@ -579,16 +566,6 @@ int lwm2m_engine_set_bool(char *pathstr, bool value);
 */
int lwm2m_engine_set_float32(char *pathstr, float32_value_t *value);

/**
 * @brief Set resource (instance) value (64-bit float structure)
 *
 * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
 * @param[in] value 64-bit float value
 *
 * @return 0 for success or negative in case of error.
 */
int lwm2m_engine_set_float64(char *pathstr, float64_value_t *value);

/**
 * @brief Set resource (instance) value (ObjLnk)
 *
@@ -721,16 +698,6 @@ int lwm2m_engine_get_bool(char *pathstr, bool *value);
 */
int lwm2m_engine_get_float32(char *pathstr, float32_value_t *buf);

/**
 * @brief Get resource (instance) value (64-bit float structure)
 *
 * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
 * @param[out] buf 64-bit float buffer to copy data into
 *
 * @return 0 for success or negative in case of error.
 */
int lwm2m_engine_get_float64(char *pathstr, float64_value_t *buf);

/**
 * @brief Get resource (instance) value (ObjLnk)
 *
+6 −6
Original line number Diff line number Diff line
@@ -53,16 +53,16 @@ static struct ipso_accel_data accel_data[MAX_INSTANCE_COUNT];

static struct lwm2m_engine_obj accel;
static struct lwm2m_engine_obj_field fields[] = {
	OBJ_FIELD_DATA(X_VALUE_RID, R, FLOAT32),
	OBJ_FIELD_DATA(Y_VALUE_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(Z_VALUE_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(X_VALUE_RID, R, FLOAT),
	OBJ_FIELD_DATA(Y_VALUE_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(Z_VALUE_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(SENSOR_UNITS_RID, R_OPT, STRING),
	OBJ_FIELD_DATA(MIN_RANGE_VALUE_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(MAX_RANGE_VALUE_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(MIN_RANGE_VALUE_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(MAX_RANGE_VALUE_RID, R_OPT, FLOAT),
#if defined(CONFIG_LWM2M_IPSO_ACCELEROMETER_VERSION_1_1)
	OBJ_FIELD_DATA(APPLICATION_TYPE_RID, RW_OPT, STRING),
	OBJ_FIELD_DATA(TIMESTAMP_RID, R_OPT, TIME),
	OBJ_FIELD_DATA(FRACTIONAL_TIMESTAMP_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(FRACTIONAL_TIMESTAMP_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(MEASUREMENT_QUALITY_INDICATOR_RID, R_OPT, U8),
	OBJ_FIELD_DATA(MEASUREMENT_QUALITY_LEVEL_RID, R_OPT, U8),
#endif
+8 −8
Original line number Diff line number Diff line
@@ -44,8 +44,8 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
/* resource state */
struct ipso_buzzer_data {
	float32_value_t level;
	float64_value_t delay_duration;
	float64_value_t min_off_time;
	float32_value_t delay_duration;
	float32_value_t min_off_time;

	uint64_t trigger_offset;

@@ -61,9 +61,9 @@ static struct ipso_buzzer_data buzzer_data[MAX_INSTANCE_COUNT];
static struct lwm2m_engine_obj buzzer;
static struct lwm2m_engine_obj_field fields[] = {
	OBJ_FIELD_DATA(ON_OFF_RID, RW, BOOL),
	OBJ_FIELD_DATA(LEVEL_RID, RW_OPT, FLOAT32),
	OBJ_FIELD_DATA(DELAY_DURATION_RID, RW_OPT, FLOAT64),
	OBJ_FIELD_DATA(MINIMUM_OFF_TIME_RID, RW, FLOAT64),
	OBJ_FIELD_DATA(LEVEL_RID, RW_OPT, FLOAT),
	OBJ_FIELD_DATA(DELAY_DURATION_RID, RW_OPT, FLOAT),
	OBJ_FIELD_DATA(MINIMUM_OFF_TIME_RID, RW, FLOAT),
	OBJ_FIELD_DATA(APPLICATION_TYPE_RID, RW_OPT, STRING),
	/* This field is actually not in the spec, so nothing sets it except
	 * here users can listen for post_write events to it for buzzer on/off
@@ -72,7 +72,7 @@ static struct lwm2m_engine_obj_field fields[] = {
	OBJ_FIELD_DATA(DIGITAL_INPUT_STATE_RID, R, BOOL),
#if defined(CONFIG_LWM2M_IPSO_BUZZER_VERSION_1_1)
	OBJ_FIELD_DATA(TIMESTAMP_RID, R_OPT, TIME),
	OBJ_FIELD_DATA(FRACTIONAL_TIMESTAMP_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(FRACTIONAL_TIMESTAMP_RID, R_OPT, FLOAT),
#endif
};

@@ -81,10 +81,10 @@ static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][BUZZER_MAX_ID];
static struct lwm2m_engine_res_inst
		res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];

static int float2ms(float64_value_t *f, uint32_t *ms)
static int float2ms(float32_value_t *f, uint32_t *ms)
{
	*ms = f->val1 * MSEC_PER_SEC;
	*ms += f->val2 / (LWM2M_FLOAT64_DEC_MAX / MSEC_PER_SEC);
	*ms += f->val2 / (LWM2M_FLOAT32_DEC_MAX / MSEC_PER_SEC);

	return 0;
}
+6 −6
Original line number Diff line number Diff line
@@ -67,18 +67,18 @@ static char sensor_type[MAX_INSTANCE_COUNT][SENSOR_TYPE_STR_MAX_SIZE];

static struct lwm2m_engine_obj sensor;
static struct lwm2m_engine_obj_field fields[] = {
	OBJ_FIELD_DATA(SENSOR_VALUE_RID, R, FLOAT32),
	OBJ_FIELD_DATA(SENSOR_VALUE_RID, R, FLOAT),
	OBJ_FIELD_DATA(SENSOR_UNITS_RID, R_OPT, STRING),
	OBJ_FIELD_DATA(MIN_MEASURED_VALUE_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(MAX_MEASURED_VALUE_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(MIN_RANGE_VALUE_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(MAX_RANGE_VALUE_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(MIN_MEASURED_VALUE_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(MAX_MEASURED_VALUE_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(MIN_RANGE_VALUE_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(MAX_RANGE_VALUE_RID, R_OPT, FLOAT),
	OBJ_FIELD_EXECUTE_OPT(RESET_MIN_MAX_MEASURED_VALUES_RID),
	OBJ_FIELD_DATA(APPLICATION_TYPE_RID, RW_OPT, STRING),
	OBJ_FIELD_DATA(SENSOR_TYPE_RID, R_OPT, STRING),
#if defined(CONFIG_LWM2M_IPSO_GENERIC_SENSOR_VERSION_1_1)
	OBJ_FIELD_DATA(TIMESTAMP_RID, R_OPT, TIME),
	OBJ_FIELD_DATA(FRACTIONAL_TIMESTAMP_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(FRACTIONAL_TIMESTAMP_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(MEASUREMENT_QUALITY_INDICATOR_RID, R_OPT, U8),
	OBJ_FIELD_DATA(MEASUREMENT_QUALITY_LEVEL_RID, R_OPT, U8),
#endif
+6 −6
Original line number Diff line number Diff line
@@ -54,17 +54,17 @@ static float32_value_t max_range_value[MAX_INSTANCE_COUNT];

static struct lwm2m_engine_obj sensor;
static struct lwm2m_engine_obj_field fields[] = {
	OBJ_FIELD_DATA(SENSOR_VALUE_RID, R, FLOAT32),
	OBJ_FIELD_DATA(SENSOR_VALUE_RID, R, FLOAT),
	OBJ_FIELD_DATA(SENSOR_UNITS_RID, R_OPT, STRING),
	OBJ_FIELD_DATA(MIN_MEASURED_VALUE_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(MAX_MEASURED_VALUE_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(MIN_RANGE_VALUE_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(MAX_RANGE_VALUE_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(MIN_MEASURED_VALUE_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(MAX_MEASURED_VALUE_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(MIN_RANGE_VALUE_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(MAX_RANGE_VALUE_RID, R_OPT, FLOAT),
	OBJ_FIELD_EXECUTE_OPT(RESET_MIN_MAX_MEASURED_VALUES_RID),
#if defined(CONFIG_LWM2M_IPSO_HUMIDITY_SENSOR_VERSION_1_1)
	OBJ_FIELD_DATA(APPLICATION_TYPE_RID, RW_OPT, STRING),
	OBJ_FIELD_DATA(TIMESTAMP_RID, R_OPT, TIME),
	OBJ_FIELD_DATA(FRACTIONAL_TIMESTAMP_RID, R_OPT, FLOAT32),
	OBJ_FIELD_DATA(FRACTIONAL_TIMESTAMP_RID, R_OPT, FLOAT),
	OBJ_FIELD_DATA(MEASUREMENT_QUALITY_INDICATOR_RID, R_OPT, U8),
	OBJ_FIELD_DATA(MEASUREMENT_QUALITY_LEVEL_RID, R_OPT, U8),
#endif
Loading