net: lwm2m: Replace float32_value_t with double

Replace the custom float32_value_t LwM2M type with native double, to
facilitate LwM2M API and improve floating point precission.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2021-07-23 16:38:23 +02:00 committed by Christopher Friedt
parent 3a3e3c041b
commit 875c75c4f9
22 changed files with 344 additions and 432 deletions

View file

@ -34,6 +34,8 @@ Changes in this release
* :c:func:`uart_tx` * :c:func:`uart_tx`
* :c:func:`uart_rx_enable` * :c:func:`uart_rx_enable`
* Replaced custom LwM2M :c:struct:`float32_value` type with a native double type.
========================== ==========================
Removed APIs in this release Removed APIs in this release

View file

@ -357,27 +357,6 @@ struct coap_block_context *lwm2m_firmware_get_block_context();
#endif #endif
#endif #endif
/**
* @brief Data structure used to represent the LwM2M float type:
* val1 is the whole number portion of the decimal
* val2 is the decimal portion *1000000 for 32bit, *1000000000 for 64bit
* Example: 123.456 == val1: 123, val2:456000
* Example: 123.000456 = val1: 123, val2:456
*/
/**
* @brief Maximum precision value for 32-bit LwM2M float val2
*/
#define LWM2M_FLOAT32_DEC_MAX 1000000
/**
* @brief 32-bit variant of the LwM2M float structure
*/
typedef struct float32_value {
int32_t val1;
int32_t val2;
} float32_value_t;
/** /**
* @brief Maximum value for ObjLnk resource fields * @brief Maximum value for ObjLnk resource fields
*/ */
@ -557,14 +536,14 @@ int lwm2m_engine_set_s64(char *pathstr, int64_t value);
int lwm2m_engine_set_bool(char *pathstr, bool value); int lwm2m_engine_set_bool(char *pathstr, bool value);
/** /**
* @brief Set resource (instance) value (32-bit float structure) * @brief Set resource (instance) value (double)
* *
* @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)" * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
* @param[in] value 32-bit float value * @param[in] value double value
* *
* @return 0 for success or negative in case of error. * @return 0 for success or negative in case of error.
*/ */
int lwm2m_engine_set_float32(char *pathstr, float32_value_t *value); int lwm2m_engine_set_float(char *pathstr, double *value);
/** /**
* @brief Set resource (instance) value (ObjLnk) * @brief Set resource (instance) value (ObjLnk)
@ -689,14 +668,14 @@ int lwm2m_engine_get_s64(char *pathstr, int64_t *value);
int lwm2m_engine_get_bool(char *pathstr, bool *value); int lwm2m_engine_get_bool(char *pathstr, bool *value);
/** /**
* @brief Get resource (instance) value (32-bit float structure) * @brief Get resource (instance) value (double)
* *
* @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)" * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
* @param[out] buf 32-bit float buffer to copy data into * @param[out] buf double buffer to copy data into
* *
* @return 0 for success or negative in case of error. * @return 0 for success or negative in case of error.
*/ */
int lwm2m_engine_get_float32(char *pathstr, float32_value_t *buf); int lwm2m_engine_get_float(char *pathstr, double *buf);
/** /**
* @brief Get resource (instance) value (ObjLnk) * @brief Get resource (instance) value (ObjLnk)

View file

@ -0,0 +1 @@
CONFIG_FPU=y

View file

@ -190,7 +190,7 @@ static void *temperature_get_buf(uint16_t obj_inst_id, uint16_t res_id,
uint16_t res_inst_id, size_t *data_len) uint16_t res_inst_id, size_t *data_len)
{ {
/* Last read temperature value, will use 25.5C if no sensor available */ /* Last read temperature value, will use 25.5C if no sensor available */
static struct float32_value v = { 25, 500000 }; static double v = 25.5;
const struct device *dev = NULL; const struct device *dev = NULL;
#if defined(CONFIG_FXOS8700_TEMP) #if defined(CONFIG_FXOS8700_TEMP)
@ -198,17 +198,21 @@ static void *temperature_get_buf(uint16_t obj_inst_id, uint16_t res_id,
#endif #endif
if (dev != NULL) { if (dev != NULL) {
struct sensor_value val;
if (sensor_sample_fetch(dev)) { if (sensor_sample_fetch(dev)) {
LOG_ERR("temperature data update failed"); LOG_ERR("temperature data update failed");
} }
sensor_channel_get(dev, SENSOR_CHAN_DIE_TEMP, sensor_channel_get(dev, SENSOR_CHAN_DIE_TEMP, &val);
(struct sensor_value *) &v);
LOG_DBG("LWM2M temperature set to %d.%d", v.val1, v.val2); v = sensor_value_to_double(&val);
LOG_DBG("LWM2M temperature set to %f", v);
} }
/* echo the value back through the engine to update min/max values */ /* echo the value back through the engine to update min/max values */
lwm2m_engine_set_float32("3303/0/5700", &v); lwm2m_engine_set_float("3303/0/5700", &v);
*data_len = sizeof(v); *data_len = sizeof(v);
return &v; return &v;
} }

View file

@ -42,11 +42,11 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
/* resource state */ /* resource state */
struct ipso_accel_data { struct ipso_accel_data {
float32_value_t x_value; double x_value;
float32_value_t y_value; double y_value;
float32_value_t z_value; double z_value;
float32_value_t min_range; double min_range;
float32_value_t max_range; double max_range;
}; };
static struct ipso_accel_data accel_data[MAX_INSTANCE_COUNT]; static struct ipso_accel_data accel_data[MAX_INSTANCE_COUNT];

View file

@ -43,9 +43,9 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
/* resource state */ /* resource state */
struct ipso_buzzer_data { struct ipso_buzzer_data {
float32_value_t level; double level;
float32_value_t delay_duration; double delay_duration;
float32_value_t min_off_time; double min_off_time;
uint64_t trigger_offset; uint64_t trigger_offset;
@ -81,14 +81,6 @@ static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][BUZZER_MAX_ID];
static struct lwm2m_engine_res_inst static struct lwm2m_engine_res_inst
res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT]; res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
static int float2ms(float32_value_t *f, uint32_t *ms)
{
*ms = f->val1 * MSEC_PER_SEC;
*ms += f->val2 / (LWM2M_FLOAT32_DEC_MAX / MSEC_PER_SEC);
return 0;
}
static int get_buzzer_index(uint16_t obj_inst_id) static int get_buzzer_index(uint16_t obj_inst_id)
{ {
int i, ret = -ENOENT; int i, ret = -ENOENT;
@ -116,7 +108,7 @@ static int start_buzzer(struct ipso_buzzer_data *buzzer)
} }
/* check min off time from last trigger_offset */ /* check min off time from last trigger_offset */
float2ms(&buzzer->min_off_time, &temp); temp = (uint32_t)(buzzer->min_off_time * MSEC_PER_SEC);
if (k_uptime_get() < buzzer->trigger_offset + temp) { if (k_uptime_get() < buzzer->trigger_offset + temp) {
return -EINVAL; return -EINVAL;
} }
@ -128,7 +120,7 @@ static int start_buzzer(struct ipso_buzzer_data *buzzer)
buzzer->obj_inst_id, DIGITAL_INPUT_STATE_RID); buzzer->obj_inst_id, DIGITAL_INPUT_STATE_RID);
lwm2m_engine_set_bool(path, true); lwm2m_engine_set_bool(path, true);
float2ms(&buzzer->delay_duration, &temp); temp = (uint32_t)(buzzer->delay_duration * MSEC_PER_SEC);
k_work_reschedule(&buzzer->buzzer_work, K_MSEC(temp)); k_work_reschedule(&buzzer->buzzer_work, K_MSEC(temp));
return 0; return 0;
@ -210,8 +202,8 @@ static struct lwm2m_engine_obj_inst *buzzer_create(uint16_t obj_inst_id)
/* Set default values */ /* Set default values */
(void)memset(&buzzer_data[avail], 0, sizeof(buzzer_data[avail])); (void)memset(&buzzer_data[avail], 0, sizeof(buzzer_data[avail]));
k_work_init_delayable(&buzzer_data[avail].buzzer_work, buzzer_work_cb); k_work_init_delayable(&buzzer_data[avail].buzzer_work, buzzer_work_cb);
buzzer_data[avail].level.val1 = 50; /* 50% */ buzzer_data[avail].level = 50; /* 50% */
buzzer_data[avail].delay_duration.val1 = 1; /* 1 seconds */ buzzer_data[avail].delay_duration = 1; /* 1 seconds */
buzzer_data[avail].obj_inst_id = obj_inst_id; buzzer_data[avail].obj_inst_id = obj_inst_id;
(void)memset(res[avail], 0, (void)memset(res[avail], 0,

View file

@ -56,12 +56,12 @@ BUILD_ASSERT(SENSOR_TYPE_STR_MAX_SIZE >=
#define RESOURCE_INSTANCE_COUNT (NUMBER_OF_OBJ_FIELDS - 1) #define RESOURCE_INSTANCE_COUNT (NUMBER_OF_OBJ_FIELDS - 1)
/* resource state variables */ /* resource state variables */
static float32_value_t sensor_value[MAX_INSTANCE_COUNT]; static double sensor_value[MAX_INSTANCE_COUNT];
static char units[MAX_INSTANCE_COUNT][UNIT_STR_MAX_SIZE]; static char units[MAX_INSTANCE_COUNT][UNIT_STR_MAX_SIZE];
static float32_value_t min_measured_value[MAX_INSTANCE_COUNT]; static double min_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t max_measured_value[MAX_INSTANCE_COUNT]; static double max_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t min_range_value[MAX_INSTANCE_COUNT]; static double min_range_value[MAX_INSTANCE_COUNT];
static float32_value_t max_range_value[MAX_INSTANCE_COUNT]; static double max_range_value[MAX_INSTANCE_COUNT];
static char app_type[MAX_INSTANCE_COUNT][APP_TYPE_STR_MAX_SIZE]; static char app_type[MAX_INSTANCE_COUNT][APP_TYPE_STR_MAX_SIZE];
static char sensor_type[MAX_INSTANCE_COUNT][SENSOR_TYPE_STR_MAX_SIZE]; static char sensor_type[MAX_INSTANCE_COUNT][SENSOR_TYPE_STR_MAX_SIZE];
@ -91,15 +91,13 @@ static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT]
static void update_min_measured(uint16_t obj_inst_id, int index) static void update_min_measured(uint16_t obj_inst_id, int index)
{ {
min_measured_value[index].val1 = sensor_value[index].val1; min_measured_value[index] = sensor_value[index];
min_measured_value[index].val2 = sensor_value[index].val2;
NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MIN_MEASURED_VALUE_RID); NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MIN_MEASURED_VALUE_RID);
} }
static void update_max_measured(uint16_t obj_inst_id, int index) static void update_max_measured(uint16_t obj_inst_id, int index)
{ {
max_measured_value[index].val1 = sensor_value[index].val1; max_measured_value[index] = sensor_value[index];
max_measured_value[index].val2 = sensor_value[index].val2;
NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MAX_MEASURED_VALUE_RID); NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MAX_MEASURED_VALUE_RID);
} }
@ -126,35 +124,15 @@ static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id,
size_t total_size) size_t total_size)
{ {
int i; int i;
bool update_min = false;
bool update_max = false;
for (i = 0; i < MAX_INSTANCE_COUNT; i++) { for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) { if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
/* update min / max */ /* update min / max */
if (sensor_value[i].val1 < min_measured_value[i].val1) { if (sensor_value[i] < min_measured_value[i]) {
update_min = true;
} else if (sensor_value[i].val1 ==
min_measured_value[i].val1 &&
sensor_value[i].val2 <
min_measured_value[i].val2) {
update_min = true;
}
if (sensor_value[i].val1 > max_measured_value[i].val1) {
update_max = true;
} else if (sensor_value[i].val1 ==
max_measured_value[i].val1 &&
sensor_value[i].val2 >
max_measured_value[i].val2) {
update_max = true;
}
if (update_min) {
update_min_measured(obj_inst_id, i); update_min_measured(obj_inst_id, i);
} }
if (update_max) { if (sensor_value[i] > max_measured_value[i]) {
update_max_measured(obj_inst_id, i); update_max_measured(obj_inst_id, i);
} }
} }
@ -190,17 +168,12 @@ static struct lwm2m_engine_obj_inst *generic_sensor_create(uint16_t obj_inst_id)
} }
/* Set default values */ /* Set default values */
sensor_value[index].val1 = 0; sensor_value[index] = 0;
sensor_value[index].val2 = 0;
units[index][0] = '\0'; units[index][0] = '\0';
min_measured_value[index].val1 = INT32_MAX; min_measured_value[index] = INT32_MAX;
min_measured_value[index].val2 = 0; max_measured_value[index] = -INT32_MAX;
max_measured_value[index].val1 = -INT32_MAX; min_range_value[index] = 0;
max_measured_value[index].val2 = 0; max_range_value[index] = 0;
min_range_value[index].val1 = 0;
min_range_value[index].val2 = 0;
max_range_value[index].val1 = 0;
max_range_value[index].val2 = 0;
app_type[index][0] = '\0'; app_type[index][0] = '\0';
strncpy(sensor_type[index], CONFIG_LWM2M_IPSO_GENERIC_SENSOR_TYPE, strncpy(sensor_type[index], CONFIG_LWM2M_IPSO_GENERIC_SENSOR_TYPE,
SENSOR_TYPE_STR_MAX_SIZE); SENSOR_TYPE_STR_MAX_SIZE);

View file

@ -45,12 +45,12 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#define RESOURCE_INSTANCE_COUNT (NUMBER_OF_OBJ_FIELDS - 1) #define RESOURCE_INSTANCE_COUNT (NUMBER_OF_OBJ_FIELDS - 1)
/* resource state variables */ /* resource state variables */
static float32_value_t sensor_value[MAX_INSTANCE_COUNT]; static double sensor_value[MAX_INSTANCE_COUNT];
static char units[MAX_INSTANCE_COUNT][UNIT_STR_MAX_SIZE]; static char units[MAX_INSTANCE_COUNT][UNIT_STR_MAX_SIZE];
static float32_value_t min_measured_value[MAX_INSTANCE_COUNT]; static double min_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t max_measured_value[MAX_INSTANCE_COUNT]; static double max_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t min_range_value[MAX_INSTANCE_COUNT]; static double min_range_value[MAX_INSTANCE_COUNT];
static float32_value_t max_range_value[MAX_INSTANCE_COUNT]; static double max_range_value[MAX_INSTANCE_COUNT];
static struct lwm2m_engine_obj sensor; static struct lwm2m_engine_obj sensor;
static struct lwm2m_engine_obj_field fields[] = { static struct lwm2m_engine_obj_field fields[] = {
@ -77,15 +77,13 @@ static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT]
static void update_min_measured(uint16_t obj_inst_id, int index) static void update_min_measured(uint16_t obj_inst_id, int index)
{ {
min_measured_value[index].val1 = sensor_value[index].val1; min_measured_value[index] = sensor_value[index];
min_measured_value[index].val2 = sensor_value[index].val2;
NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MIN_MEASURED_VALUE_RID); NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MIN_MEASURED_VALUE_RID);
} }
static void update_max_measured(uint16_t obj_inst_id, int index) static void update_max_measured(uint16_t obj_inst_id, int index)
{ {
max_measured_value[index].val1 = sensor_value[index].val1; max_measured_value[index] = sensor_value[index];
max_measured_value[index].val2 = sensor_value[index].val2;
NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MAX_MEASURED_VALUE_RID); NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MAX_MEASURED_VALUE_RID);
} }
@ -112,35 +110,15 @@ static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id,
size_t total_size) size_t total_size)
{ {
int i; int i;
bool update_min = false;
bool update_max = false;
for (i = 0; i < MAX_INSTANCE_COUNT; i++) { for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) { if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
/* update min / max */ /* update min / max */
if (sensor_value[i].val1 < min_measured_value[i].val1) { if (sensor_value[i] < min_measured_value[i]) {
update_min = true;
} else if (sensor_value[i].val1 ==
min_measured_value[i].val1 &&
sensor_value[i].val2 <
min_measured_value[i].val2) {
update_min = true;
}
if (sensor_value[i].val1 > max_measured_value[i].val1) {
update_max = true;
} else if (sensor_value[i].val1 ==
max_measured_value[i].val1 &&
sensor_value[i].val2 >
max_measured_value[i].val2) {
update_max = true;
}
if (update_min) {
update_min_measured(obj_inst_id, i); update_min_measured(obj_inst_id, i);
} }
if (update_max) { if (sensor_value[i] > max_measured_value[i]) {
update_max_measured(obj_inst_id, i); update_max_measured(obj_inst_id, i);
} }
} }
@ -177,17 +155,12 @@ humidity_sensor_create(uint16_t obj_inst_id)
} }
/* Set default values */ /* Set default values */
sensor_value[index].val1 = 0; sensor_value[index] = 0;
sensor_value[index].val2 = 0;
units[index][0] = '\0'; units[index][0] = '\0';
min_measured_value[index].val1 = INT32_MAX; min_measured_value[index] = INT32_MAX;
min_measured_value[index].val2 = 0; max_measured_value[index] = -INT32_MAX;
max_measured_value[index].val1 = -INT32_MAX; min_range_value[index] = 0;
max_measured_value[index].val2 = 0; max_range_value[index] = 0;
min_range_value[index].val1 = 0;
min_range_value[index].val2 = 0;
max_range_value[index].val1 = 0;
max_range_value[index].val2 = 0;
(void)memset(res[index], 0, (void)memset(res[index], 0,
sizeof(res[index][0]) * ARRAY_SIZE(res[index])); sizeof(res[index][0]) * ARRAY_SIZE(res[index]));

View file

@ -45,8 +45,8 @@ static bool on_off_value[MAX_INSTANCE_COUNT];
static uint8_t dimmer_value[MAX_INSTANCE_COUNT]; static uint8_t dimmer_value[MAX_INSTANCE_COUNT];
static int32_t on_time_value[MAX_INSTANCE_COUNT]; static int32_t on_time_value[MAX_INSTANCE_COUNT];
static uint32_t on_time_offset[MAX_INSTANCE_COUNT]; static uint32_t on_time_offset[MAX_INSTANCE_COUNT];
static float32_value_t cumulative_active_value[MAX_INSTANCE_COUNT]; static double cumulative_active_value[MAX_INSTANCE_COUNT];
static float32_value_t power_factor_value[MAX_INSTANCE_COUNT]; static double power_factor_value[MAX_INSTANCE_COUNT];
static char colour[MAX_INSTANCE_COUNT][LIGHT_STRING_LONG]; static char colour[MAX_INSTANCE_COUNT][LIGHT_STRING_LONG];
static char units[MAX_INSTANCE_COUNT][LIGHT_STRING_SHORT]; static char units[MAX_INSTANCE_COUNT][LIGHT_STRING_SHORT];
@ -148,10 +148,8 @@ static struct lwm2m_engine_obj_inst *light_control_create(uint16_t obj_inst_id)
dimmer_value[avail] = 0U; dimmer_value[avail] = 0U;
on_time_value[avail] = 0; on_time_value[avail] = 0;
on_time_offset[avail] = 0U; on_time_offset[avail] = 0U;
cumulative_active_value[avail].val1 = 0; cumulative_active_value[avail] = 0;
cumulative_active_value[avail].val2 = 0; power_factor_value[avail] = 0;
power_factor_value[avail].val1 = 0;
power_factor_value[avail].val2 = 0;
colour[avail][0] = '\0'; colour[avail][0] = '\0';
units[avail][0] = '\0'; units[avail][0] = '\0';

View file

@ -45,12 +45,12 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#define RESOURCE_INSTANCE_COUNT (NUMBER_OF_OBJ_FIELDS - 1) #define RESOURCE_INSTANCE_COUNT (NUMBER_OF_OBJ_FIELDS - 1)
/* resource state variables */ /* resource state variables */
static float32_value_t sensor_value[MAX_INSTANCE_COUNT]; static double sensor_value[MAX_INSTANCE_COUNT];
static char units[MAX_INSTANCE_COUNT][UNIT_STR_MAX_SIZE]; static char units[MAX_INSTANCE_COUNT][UNIT_STR_MAX_SIZE];
static float32_value_t min_measured_value[MAX_INSTANCE_COUNT]; static double min_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t max_measured_value[MAX_INSTANCE_COUNT]; static double max_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t min_range_value[MAX_INSTANCE_COUNT]; static double min_range_value[MAX_INSTANCE_COUNT];
static float32_value_t max_range_value[MAX_INSTANCE_COUNT]; static double max_range_value[MAX_INSTANCE_COUNT];
static struct lwm2m_engine_obj sensor; static struct lwm2m_engine_obj sensor;
static struct lwm2m_engine_obj_field fields[] = { static struct lwm2m_engine_obj_field fields[] = {
@ -78,15 +78,13 @@ static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT]
static void update_min_measured(uint16_t obj_inst_id, int index) static void update_min_measured(uint16_t obj_inst_id, int index)
{ {
min_measured_value[index].val1 = sensor_value[index].val1; min_measured_value[index] = sensor_value[index];
min_measured_value[index].val2 = sensor_value[index].val2;
NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MIN_MEASURED_VALUE_RID); NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MIN_MEASURED_VALUE_RID);
} }
static void update_max_measured(uint16_t obj_inst_id, int index) static void update_max_measured(uint16_t obj_inst_id, int index)
{ {
max_measured_value[index].val1 = sensor_value[index].val1; max_measured_value[index] = sensor_value[index];
max_measured_value[index].val2 = sensor_value[index].val2;
NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MAX_MEASURED_VALUE_RID); NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MAX_MEASURED_VALUE_RID);
} }
@ -113,35 +111,15 @@ static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id,
size_t total_size) size_t total_size)
{ {
int i; int i;
bool update_min = false;
bool update_max = false;
for (i = 0; i < MAX_INSTANCE_COUNT; i++) { for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) { if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
/* update min / max */ /* update min / max */
if (sensor_value[i].val1 < min_measured_value[i].val1) { if (sensor_value[i] < min_measured_value[i]) {
update_min = true;
} else if (sensor_value[i].val1 ==
min_measured_value[i].val1 &&
sensor_value[i].val2 <
min_measured_value[i].val2) {
update_min = true;
}
if (sensor_value[i].val1 > max_measured_value[i].val1) {
update_max = true;
} else if (sensor_value[i].val1 ==
max_measured_value[i].val1 &&
sensor_value[i].val2 >
max_measured_value[i].val2) {
update_max = true;
}
if (update_min) {
update_min_measured(obj_inst_id, i); update_min_measured(obj_inst_id, i);
} }
if (update_max) { if (sensor_value[i] > max_measured_value[i]) {
update_max_measured(obj_inst_id, i); update_max_measured(obj_inst_id, i);
} }
} }
@ -178,17 +156,12 @@ pressure_sensor_create(uint16_t obj_inst_id)
} }
/* Set default values */ /* Set default values */
sensor_value[index].val1 = 0; sensor_value[index] = 0;
sensor_value[index].val2 = 0;
units[index][0] = '\0'; units[index][0] = '\0';
min_measured_value[index].val1 = INT32_MAX; min_measured_value[index] = INT32_MAX;
min_measured_value[index].val2 = 0; max_measured_value[index] = -INT32_MAX;
max_measured_value[index].val1 = -INT32_MAX; min_range_value[index] = 0;
max_measured_value[index].val2 = 0; max_range_value[index] = 0;
min_range_value[index].val1 = 0;
min_range_value[index].val2 = 0;
max_range_value[index].val1 = 0;
max_range_value[index].val2 = 0;
(void)memset(res[index], 0, (void)memset(res[index], 0,
sizeof(res[index][0]) * ARRAY_SIZE(res[index])); sizeof(res[index][0]) * ARRAY_SIZE(res[index]));

View file

@ -46,12 +46,12 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#define RESOURCE_INSTANCE_COUNT (TEMP_MAX_ID - 1) #define RESOURCE_INSTANCE_COUNT (TEMP_MAX_ID - 1)
/* resource state variables */ /* resource state variables */
static float32_value_t sensor_value[MAX_INSTANCE_COUNT]; static double sensor_value[MAX_INSTANCE_COUNT];
static char units[MAX_INSTANCE_COUNT][UNIT_STR_MAX_SIZE]; static char units[MAX_INSTANCE_COUNT][UNIT_STR_MAX_SIZE];
static float32_value_t min_measured_value[MAX_INSTANCE_COUNT]; static double min_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t max_measured_value[MAX_INSTANCE_COUNT]; static double max_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t min_range_value[MAX_INSTANCE_COUNT]; static double min_range_value[MAX_INSTANCE_COUNT];
static float32_value_t max_range_value[MAX_INSTANCE_COUNT]; static double max_range_value[MAX_INSTANCE_COUNT];
static struct lwm2m_engine_obj temp_sensor; static struct lwm2m_engine_obj temp_sensor;
static struct lwm2m_engine_obj_field fields[] = { static struct lwm2m_engine_obj_field fields[] = {
@ -78,16 +78,14 @@ static struct lwm2m_engine_res_inst
static void update_min_measured(uint16_t obj_inst_id, int index) static void update_min_measured(uint16_t obj_inst_id, int index)
{ {
min_measured_value[index].val1 = sensor_value[index].val1; min_measured_value[index] = sensor_value[index];
min_measured_value[index].val2 = sensor_value[index].val2;
NOTIFY_OBSERVER(IPSO_OBJECT_TEMP_SENSOR_ID, obj_inst_id, NOTIFY_OBSERVER(IPSO_OBJECT_TEMP_SENSOR_ID, obj_inst_id,
MIN_MEASURED_VALUE_RID); MIN_MEASURED_VALUE_RID);
} }
static void update_max_measured(uint16_t obj_inst_id, int index) static void update_max_measured(uint16_t obj_inst_id, int index)
{ {
max_measured_value[index].val1 = sensor_value[index].val1; max_measured_value[index] = sensor_value[index];
max_measured_value[index].val2 = sensor_value[index].val2;
NOTIFY_OBSERVER(IPSO_OBJECT_TEMP_SENSOR_ID, obj_inst_id, NOTIFY_OBSERVER(IPSO_OBJECT_TEMP_SENSOR_ID, obj_inst_id,
MAX_MEASURED_VALUE_RID); MAX_MEASURED_VALUE_RID);
} }
@ -115,35 +113,15 @@ static int sensor_value_write_cb(uint16_t obj_inst_id,
bool last_block, size_t total_size) bool last_block, size_t total_size)
{ {
int i; int i;
bool update_min = false;
bool update_max = false;
for (i = 0; i < MAX_INSTANCE_COUNT; i++) { for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) { if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
/* update min / max */ /* update min / max */
if (sensor_value[i].val1 < min_measured_value[i].val1) { if (sensor_value[i] < min_measured_value[i]) {
update_min = true;
} else if (sensor_value[i].val1 ==
min_measured_value[i].val1 &&
sensor_value[i].val2 <
min_measured_value[i].val2) {
update_min = true;
}
if (sensor_value[i].val1 > max_measured_value[i].val1) {
update_max = true;
} else if (sensor_value[i].val1 ==
max_measured_value[i].val1 &&
sensor_value[i].val2 >
max_measured_value[i].val2) {
update_max = true;
}
if (update_min) {
update_min_measured(obj_inst_id, i); update_min_measured(obj_inst_id, i);
} }
if (update_max) { if (sensor_value[i] > max_measured_value[i]) {
update_max_measured(obj_inst_id, i); update_max_measured(obj_inst_id, i);
} }
} }
@ -178,17 +156,12 @@ static struct lwm2m_engine_obj_inst *temp_sensor_create(uint16_t obj_inst_id)
} }
/* Set default values */ /* Set default values */
sensor_value[index].val1 = 0; sensor_value[index] = 0;
sensor_value[index].val2 = 0;
units[index][0] = '\0'; units[index][0] = '\0';
min_measured_value[index].val1 = INT32_MAX; min_measured_value[index] = INT32_MAX;
min_measured_value[index].val2 = 0; max_measured_value[index] = -INT32_MAX;
max_measured_value[index].val1 = -INT32_MAX; min_range_value[index] = 0;
max_measured_value[index].val2 = 0; max_range_value[index] = 0;
min_range_value[index].val1 = 0;
min_range_value[index].val2 = 0;
max_range_value[index].val1 = 0;
max_range_value[index].val2 = 0;
(void)memset(res[index], 0, (void)memset(res[index], 0,
sizeof(res[index][0]) * ARRAY_SIZE(res[index])); sizeof(res[index][0]) * ARRAY_SIZE(res[index]));

View file

@ -46,10 +46,10 @@ enum ipso_timer_mode {
/* resource state */ /* resource state */
struct ipso_timer_data { struct ipso_timer_data {
float32_value_t delay_duration; double delay_duration;
float32_value_t remaining_time; double remaining_time;
float32_value_t min_off_time; double min_off_time;
float32_value_t cumulative_time; double cumulative_time;
uint64_t trigger_offset; uint64_t trigger_offset;
uint32_t trigger_counter; uint32_t trigger_counter;
@ -85,22 +85,6 @@ static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][TIMER_MAX_ID];
static struct lwm2m_engine_res_inst static struct lwm2m_engine_res_inst
res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT]; res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
static int ms2float(uint32_t ms, float32_value_t *f)
{
f->val1 = ms / MSEC_PER_SEC;
f->val2 = (ms % MSEC_PER_SEC) * (LWM2M_FLOAT32_DEC_MAX / MSEC_PER_SEC);
return 0;
}
static int float2ms(float32_value_t *f, uint32_t *ms)
{
*ms = f->val1 * MSEC_PER_SEC;
*ms += f->val2 / (LWM2M_FLOAT32_DEC_MAX / MSEC_PER_SEC);
return 0;
}
static int get_timer_index(uint16_t obj_inst_id) static int get_timer_index(uint16_t obj_inst_id)
{ {
int i, ret = -ENOENT; int i, ret = -ENOENT;
@ -129,7 +113,7 @@ static int start_timer(struct ipso_timer_data *timer)
} }
/* check min off time from last trigger_offset */ /* check min off time from last trigger_offset */
float2ms(&timer->min_off_time, &temp); temp = timer->min_off_time * MSEC_PER_SEC;
if (k_uptime_get() < timer->trigger_offset + temp) { if (k_uptime_get() < timer->trigger_offset + temp) {
return -EINVAL; return -EINVAL;
} }
@ -143,7 +127,7 @@ static int start_timer(struct ipso_timer_data *timer)
timer->obj_inst_id, DIGITAL_STATE_RID); timer->obj_inst_id, DIGITAL_STATE_RID);
lwm2m_engine_set_bool(path, true); lwm2m_engine_set_bool(path, true);
float2ms(&timer->delay_duration, &temp); temp = timer->delay_duration * MSEC_PER_SEC;
k_work_reschedule(&timer->timer_work, K_MSEC(temp)); k_work_reschedule(&timer->timer_work, K_MSEC(temp));
return 0; return 0;
@ -183,12 +167,11 @@ static void *remaining_time_read_cb(uint16_t obj_inst_id,
} }
if (timer_data[i].active) { if (timer_data[i].active) {
float2ms(&timer_data[i].delay_duration, &temp); temp = timer_data[i].delay_duration * MSEC_PER_SEC;
temp -= (k_uptime_get() - timer_data[i].trigger_offset); temp -= (k_uptime_get() - timer_data[i].trigger_offset);
ms2float(temp, &timer_data[i].remaining_time); timer_data[i].remaining_time = (double)temp / MSEC_PER_SEC;
} else { } else {
timer_data[i].remaining_time.val1 = 0; timer_data[i].remaining_time = 0;
timer_data[i].remaining_time.val2 = 0;
} }
*data_len = sizeof(timer_data[i].remaining_time); *data_len = sizeof(timer_data[i].remaining_time);
@ -212,7 +195,7 @@ static void *cumulative_time_read_cb(uint16_t obj_inst_id,
temp += k_uptime_get() - timer_data[i].trigger_offset; temp += k_uptime_get() - timer_data[i].trigger_offset;
} }
ms2float(temp, &timer_data[i].cumulative_time); timer_data[i].cumulative_time = (double)temp / MSEC_PER_SEC;
*data_len = sizeof(timer_data[i].cumulative_time); *data_len = sizeof(timer_data[i].cumulative_time);
return &timer_data[i].cumulative_time; return &timer_data[i].cumulative_time;
@ -318,7 +301,7 @@ static struct lwm2m_engine_obj_inst *timer_create(uint16_t obj_inst_id)
/* Set default values */ /* Set default values */
(void)memset(&timer_data[avail], 0, sizeof(timer_data[avail])); (void)memset(&timer_data[avail], 0, sizeof(timer_data[avail]));
k_work_init_delayable(&timer_data[avail].timer_work, timer_work_cb); k_work_init_delayable(&timer_data[avail].timer_work, timer_work_cb);
timer_data[avail].delay_duration.val1 = 5; /* 5 seconds */ timer_data[avail].delay_duration = 5; /* 5 seconds */
timer_data[avail].enabled = true; timer_data[avail].enabled = true;
timer_data[avail].timer_mode = TIMER_MODE_ONE_SHOT; timer_data[avail].timer_mode = TIMER_MODE_ONE_SHOT;
timer_data[avail].obj_inst_id = obj_inst_id; timer_data[avail].obj_inst_id = obj_inst_id;

View file

@ -86,9 +86,9 @@ struct observe_node {
struct notification_attrs { struct notification_attrs {
/* use to determine which value is set */ /* use to determine which value is set */
float32_value_t gt; double gt;
float32_value_t lt; double lt;
float32_value_t st; double st;
int32_t pmin; int32_t pmin;
int32_t pmax; int32_t pmax;
uint8_t flags; uint8_t flags;
@ -1596,10 +1596,7 @@ static int lwm2m_engine_set(char *pathstr, void *value, uint16_t len)
break; break;
case LWM2M_RES_TYPE_FLOAT: case LWM2M_RES_TYPE_FLOAT:
((float32_value_t *)data_ptr)->val1 = *(double *)data_ptr = *(double *)value;
((float32_value_t *)value)->val1;
((float32_value_t *)data_ptr)->val2 =
((float32_value_t *)value)->val2;
break; break;
case LWM2M_RES_TYPE_OBJLNK: case LWM2M_RES_TYPE_OBJLNK:
@ -1685,9 +1682,9 @@ int lwm2m_engine_set_bool(char *pathstr, bool value)
return lwm2m_engine_set(pathstr, &temp, 1); return lwm2m_engine_set(pathstr, &temp, 1);
} }
int lwm2m_engine_set_float32(char *pathstr, float32_value_t *value) int lwm2m_engine_set_float(char *pathstr, double *value)
{ {
return lwm2m_engine_set(pathstr, value, sizeof(float32_value_t)); return lwm2m_engine_set(pathstr, value, sizeof(double));
} }
int lwm2m_engine_set_objlnk(char *pathstr, struct lwm2m_objlnk *value) int lwm2m_engine_set_objlnk(char *pathstr, struct lwm2m_objlnk *value)
@ -1830,10 +1827,7 @@ static int lwm2m_engine_get(char *pathstr, void *buf, uint16_t buflen)
break; break;
case LWM2M_RES_TYPE_FLOAT: case LWM2M_RES_TYPE_FLOAT:
((float32_value_t *)buf)->val1 = *(double *)buf = *(double *)data_ptr;
((float32_value_t *)data_ptr)->val1;
((float32_value_t *)buf)->val2 =
((float32_value_t *)data_ptr)->val2;
break; break;
case LWM2M_RES_TYPE_OBJLNK: case LWM2M_RES_TYPE_OBJLNK:
@ -1915,9 +1909,9 @@ int lwm2m_engine_get_bool(char *pathstr, bool *value)
return ret; return ret;
} }
int lwm2m_engine_get_float32(char *pathstr, float32_value_t *buf) int lwm2m_engine_get_float(char *pathstr, double *buf)
{ {
return lwm2m_engine_get(pathstr, buf, sizeof(float32_value_t)); return lwm2m_engine_get(pathstr, buf, sizeof(double));
} }
int lwm2m_engine_get_objlnk(char *pathstr, struct lwm2m_objlnk *buf) int lwm2m_engine_get_objlnk(char *pathstr, struct lwm2m_objlnk *buf)
@ -2325,8 +2319,8 @@ static int lwm2m_read_handler(struct lwm2m_engine_obj_inst *obj_inst,
break; break;
case LWM2M_RES_TYPE_FLOAT: case LWM2M_RES_TYPE_FLOAT:
engine_put_float32fix(&msg->out, &msg->path, engine_put_float(&msg->out, &msg->path,
(float32_value_t *)data_ptr); (double *)data_ptr);
break; break;
case LWM2M_RES_TYPE_OBJLNK: case LWM2M_RES_TYPE_OBJLNK:
@ -2594,9 +2588,8 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst,
break; break;
case LWM2M_RES_TYPE_FLOAT: case LWM2M_RES_TYPE_FLOAT:
engine_get_float32fix(&msg->in, engine_get_float(&msg->in, (double *)write_buf);
(float32_value_t *)write_buf); len = sizeof(double);
len = sizeof(float32_value_t);
break; break;
case LWM2M_RES_TYPE_OBJLNK: case LWM2M_RES_TYPE_OBJLNK:
@ -2725,7 +2718,7 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj,
/* loop through options to parse attribute */ /* loop through options to parse attribute */
for (i = 0; i < nr_opt; i++) { for (i = 0; i < nr_opt; i++) {
int limit = MIN(options[i].len, 5), plen = 0, vlen; int limit = MIN(options[i].len, 5), plen = 0, vlen;
float32_value_t val = { 0 }; struct lwm2m_attr val = { 0 };
type = 0U; type = 0U;
/* search for '=' */ /* search for '=' */
@ -2758,7 +2751,7 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj,
(void)memset(nattr_ptrs[type], 0, (void)memset(nattr_ptrs[type], 0,
type <= LWM2M_ATTR_PMAX ? sizeof(int32_t) : type <= LWM2M_ATTR_PMAX ? sizeof(int32_t) :
sizeof(float32_value_t)); sizeof(double));
continue; continue;
} }
@ -2785,10 +2778,10 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj,
ret = -EINVAL; ret = -EINVAL;
} }
val.val1 = v; val.int_val = v;
} else { } else {
/* gt/lt/st: type float */ /* gt/lt/st: type float */
ret = lwm2m_atof32(opt_buf, &val); ret = lwm2m_atof(opt_buf, &val.float_val);
} }
if (ret < 0) { if (ret < 0) {
@ -2799,9 +2792,10 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj,
} }
if (type <= LWM2M_ATTR_PMAX) { if (type <= LWM2M_ATTR_PMAX) {
*(int32_t *)nattr_ptrs[type] = val.val1; *(int32_t *)nattr_ptrs[type] = val.int_val;
} else { } else {
memcpy(nattr_ptrs[type], &val, sizeof(float32_value_t)); memcpy(nattr_ptrs[type], &val.float_val,
sizeof(val.float_val));
} }
nattrs.flags |= BIT(type); nattrs.flags |= BIT(type);
@ -2814,18 +2808,13 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj,
} }
if (nattrs.flags & (BIT(LWM2M_ATTR_LT) | BIT(LWM2M_ATTR_GT))) { if (nattrs.flags & (BIT(LWM2M_ATTR_LT) | BIT(LWM2M_ATTR_GT))) {
if (!((nattrs.lt.val1 < nattrs.gt.val1) || if (nattrs.lt > nattrs.gt) {
(nattrs.lt.val2 < nattrs.gt.val2))) {
LOG_DBG("lt > gt"); LOG_DBG("lt > gt");
return -EEXIST; return -EEXIST;
} }
if (nattrs.flags & BIT(LWM2M_ATTR_STEP)) { if (nattrs.flags & BIT(LWM2M_ATTR_STEP)) {
int32_t st1 = nattrs.st.val1 * 2 + if (nattrs.lt + 2 * nattrs.st > nattrs.gt) {
nattrs.st.val2 * 2 / 1000000;
int32_t st2 = nattrs.st.val2 * 2 % 1000000;
if (!(((nattrs.lt.val1 + st1) < nattrs.gt.val1) ||
((nattrs.lt.val2 + st2) < nattrs.gt.val2))) {
LOG_DBG("lt + 2*st > gt"); LOG_DBG("lt + 2*st > gt");
return -EEXIST; return -EEXIST;
} }
@ -2862,19 +2851,19 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj,
attr->int_val = *(int32_t *)nattr_ptrs[type]; attr->int_val = *(int32_t *)nattr_ptrs[type];
update_observe_node = true; update_observe_node = true;
LOG_DBG("Update %s to %d", log_strdup(LWM2M_ATTR_STR[type]),
attr->int_val);
} else { } else {
if (!memcmp(&attr->float_val, nattr_ptrs[type], if (attr->float_val == *(double *)nattr_ptrs[type]) {
sizeof(float32_value_t))) {
continue; continue;
} }
memcpy(&attr->float_val, nattr_ptrs[type], attr->float_val = *(double *)nattr_ptrs[type];
sizeof(float32_value_t));
}
LOG_DBG("Update %s to %d.%06d", LOG_DBG("Update %s to %f", log_strdup(LWM2M_ATTR_STR[type]),
log_strdup(LWM2M_ATTR_STR[type]), attr->float_val);
attr->float_val.val1, attr->float_val.val2); }
} }
/* add attribute to obj/obj_inst/res */ /* add attribute to obj/obj_inst/res */
@ -2901,14 +2890,17 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj,
if (type <= LWM2M_ATTR_PMAX) { if (type <= LWM2M_ATTR_PMAX) {
attr->int_val = *(int32_t *)nattr_ptrs[type]; attr->int_val = *(int32_t *)nattr_ptrs[type];
update_observe_node = true; update_observe_node = true;
LOG_DBG("Add %s to %d", log_strdup(LWM2M_ATTR_STR[type]),
attr->int_val);
} else { } else {
memcpy(&attr->float_val, nattr_ptrs[type], attr->float_val = *(double *)nattr_ptrs[type];
sizeof(float32_value_t));
LOG_DBG("Add %s to %f", log_strdup(LWM2M_ATTR_STR[type]),
attr->float_val);
} }
nattrs.flags &= ~BIT(type); nattrs.flags &= ~BIT(type);
LOG_DBG("Add %s to %d.%06d", log_strdup(LWM2M_ATTR_STR[type]),
attr->float_val.val1, attr->float_val.val2);
} }
/* check only pmin/pmax */ /* check only pmin/pmax */

View file

@ -37,11 +37,11 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#define RESOURCE_INSTANCE_COUNT (LOCATION_MAX_ID) #define RESOURCE_INSTANCE_COUNT (LOCATION_MAX_ID)
/* resource state */ /* resource state */
static float32_value_t latitude; static double latitude;
static float32_value_t longitude; static double longitude;
static float32_value_t altitude; static double altitude;
static float32_value_t radius; static double radius;
static float32_value_t speed; static double speed;
static int32_t timestamp; static int32_t timestamp;
static struct lwm2m_engine_obj location; static struct lwm2m_engine_obj location;

View file

@ -347,7 +347,7 @@ struct lwm2m_attr {
/* values */ /* values */
union { union {
float32_value_t float_val; double float_val;
int32_t int_val; int32_t int_val;
}; };
@ -515,9 +515,9 @@ struct lwm2m_writer {
size_t (*put_string)(struct lwm2m_output_context *out, size_t (*put_string)(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path, struct lwm2m_obj_path *path,
char *buf, size_t buflen); char *buf, size_t buflen);
size_t (*put_float32fix)(struct lwm2m_output_context *out, size_t (*put_float)(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path, struct lwm2m_obj_path *path,
float32_value_t *value); double *value);
size_t (*put_bool)(struct lwm2m_output_context *out, size_t (*put_bool)(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path, struct lwm2m_obj_path *path,
bool value); bool value);
@ -538,8 +538,8 @@ struct lwm2m_reader {
int64_t *value); int64_t *value);
size_t (*get_string)(struct lwm2m_input_context *in, size_t (*get_string)(struct lwm2m_input_context *in,
uint8_t *buf, size_t buflen); uint8_t *buf, size_t buflen);
size_t (*get_float32fix)(struct lwm2m_input_context *in, size_t (*get_float)(struct lwm2m_input_context *in,
float32_value_t *value); double *value);
size_t (*get_bool)(struct lwm2m_input_context *in, size_t (*get_bool)(struct lwm2m_input_context *in,
bool *value); bool *value);
size_t (*get_opaque)(struct lwm2m_input_context *in, size_t (*get_opaque)(struct lwm2m_input_context *in,
@ -703,11 +703,11 @@ static inline size_t engine_put_string(struct lwm2m_output_context *out,
return out->writer->put_string(out, path, buf, buflen); return out->writer->put_string(out, path, buf, buflen);
} }
static inline size_t engine_put_float32fix(struct lwm2m_output_context *out, static inline size_t engine_put_float(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path, struct lwm2m_obj_path *path,
float32_value_t *value) double *value)
{ {
return out->writer->put_float32fix(out, path, value); return out->writer->put_float(out, path, value);
} }
static inline size_t engine_put_bool(struct lwm2m_output_context *out, static inline size_t engine_put_bool(struct lwm2m_output_context *out,
@ -763,10 +763,10 @@ static inline size_t engine_get_string(struct lwm2m_input_context *in,
return in->reader->get_string(in, buf, buflen); return in->reader->get_string(in, buf, buflen);
} }
static inline size_t engine_get_float32fix(struct lwm2m_input_context *in, static inline size_t engine_get_float(struct lwm2m_input_context *in,
float32_value_t *value) double *value)
{ {
return in->reader->get_float32fix(in, value); return in->reader->get_float(in, value);
} }
static inline size_t engine_get_bool(struct lwm2m_input_context *in, static inline size_t engine_get_bool(struct lwm2m_input_context *in,

View file

@ -491,14 +491,14 @@ static size_t put_string(struct lwm2m_output_context *out,
return len; return len;
} }
static size_t put_float32fix(struct lwm2m_output_context *out, static size_t put_float(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path, struct lwm2m_obj_path *path,
float32_value_t *value) double *value)
{ {
size_t len; size_t len;
len = put_json_prefix(out, path, "\"v\""); len = put_json_prefix(out, path, "\"v\"");
len += plain_text_put_float32fix(out, path, value); len += plain_text_put_float(out, path, value);
len += put_json_postfix(out); len += put_json_postfix(out);
return len; return len;
} }
@ -612,8 +612,8 @@ static size_t get_string(struct lwm2m_input_context *in,
return fd->value_len; return fd->value_len;
} }
static size_t get_float32fix(struct lwm2m_input_context *in, static size_t get_float(struct lwm2m_input_context *in,
float32_value_t *value) double *value)
{ {
struct json_in_formatter_data *fd; struct json_in_formatter_data *fd;
@ -652,7 +652,7 @@ static size_t get_float32fix(struct lwm2m_input_context *in,
buf[i] = '\0'; buf[i] = '\0';
if (lwm2m_atof32(buf, value) != 0) { if (lwm2m_atof(buf, value) != 0) {
LOG_ERR("Failed to parse float value"); LOG_ERR("Failed to parse float value");
} }
@ -729,7 +729,7 @@ const struct lwm2m_writer json_writer = {
.put_s32 = put_s32, .put_s32 = put_s32,
.put_s64 = put_s64, .put_s64 = put_s64,
.put_string = put_string, .put_string = put_string,
.put_float32fix = put_float32fix, .put_float = put_float,
.put_bool = put_bool, .put_bool = put_bool,
.put_objlnk = put_objlnk, .put_objlnk = put_objlnk,
}; };
@ -738,7 +738,7 @@ const struct lwm2m_reader json_reader = {
.get_s32 = get_s32, .get_s32 = get_s32,
.get_s64 = get_s64, .get_s64 = get_s64,
.get_string = get_string, .get_string = get_string,
.get_float32fix = get_float32fix, .get_float = get_float,
.get_bool = get_bool, .get_bool = get_bool,
.get_opaque = get_opaque, .get_opaque = get_opaque,
.get_objlnk = get_objlnk, .get_objlnk = get_objlnk,

View file

@ -9,6 +9,7 @@
#include "lwm2m_engine.h" #include "lwm2m_engine.h"
#include "lwm2m_rw_link_format.h" #include "lwm2m_rw_link_format.h"
#include "lwm2m_util.h"
LOG_MODULE_REGISTER(net_lwm2m_link_format, CONFIG_LWM2M_LOG_LEVEL); LOG_MODULE_REGISTER(net_lwm2m_link_format, CONFIG_LWM2M_LOG_LEVEL);
@ -158,9 +159,7 @@ static int put_corelink_attributes(struct lwm2m_output_context *out,
uint16_t buflen) uint16_t buflen)
{ {
struct lwm2m_attr *attr = NULL; struct lwm2m_attr *attr = NULL;
int used, base, ret; int used, ret;
uint8_t digit;
int32_t fraction;
int len = 0; int len = 0;
while ((attr = lwm2m_engine_get_next_attr(ref, attr)) != NULL) { while ((attr = lwm2m_engine_get_next_attr(ref, attr)) != NULL) {
@ -171,25 +170,22 @@ static int put_corelink_attributes(struct lwm2m_output_context *out,
continue; continue;
} }
/* Assuming integer will have float_val.val2 set as 0. */ if (attr->type <= LWM2M_ATTR_PMAX) {
used = snprintk(buf, buflen, ";%s=%s%d%s", used = snprintk(buf, buflen, ";%s=%d", name, attr->int_val);
name, } else {
attr->float_val.val1 == 0 && uint8_t float_buf[32];
attr->float_val.val2 < 0 ? "-" : "",
attr->float_val.val1, used = lwm2m_ftoa(&attr->float_val, float_buf,
attr->float_val.val2 != 0 ? "." : ""); sizeof(float_buf), 4);
if (used < 0 || used >= buflen) { if (used < 0 || used >= sizeof(float_buf)) {
return -ENOMEM; return -ENOMEM;
}
used = snprintk(buf, buflen, ";%s=%s", name, float_buf);
} }
base = 100000; if (used < 0 || used >= buflen) {
fraction = attr->float_val.val2 < 0 ? return -ENOMEM;
-attr->float_val.val2 : attr->float_val.val2;
while (fraction && used < buflen && base > 0) {
digit = fraction / base;
buf[used++] = '0' + digit;
fraction -= digit * base;
base /= 10;
} }
len += used; len += used;

View file

@ -510,30 +510,30 @@ static size_t put_string(struct lwm2m_output_context *out,
return len; return len;
} }
static size_t put_float32fix(struct lwm2m_output_context *out, static size_t put_float(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path, struct lwm2m_obj_path *path,
float32_value_t *value) double *value)
{ {
struct tlv_out_formatter_data *fd; struct tlv_out_formatter_data *fd;
size_t len; size_t len;
struct oma_tlv tlv; struct oma_tlv tlv;
int ret; int ret;
uint8_t b32[4]; uint8_t b64[8];
fd = engine_get_out_user_data(out); fd = engine_get_out_user_data(out);
if (!fd) { if (!fd) {
return 0; return 0;
} }
ret = lwm2m_f32_to_b32(value, b32, sizeof(b32)); ret = lwm2m_float_to_b64(value, b64, sizeof(b64));
if (ret < 0) { if (ret < 0) {
LOG_ERR("float32 conversion error: %d", ret); LOG_ERR("float32 conversion error: %d", ret);
return 0; return 0;
} }
tlv_setup(&tlv, tlv_calc_type(fd->writer_flags), tlv_setup(&tlv, tlv_calc_type(fd->writer_flags),
tlv_calc_id(fd->writer_flags, path), sizeof(b32)); tlv_calc_id(fd->writer_flags, path), sizeof(b64));
len = oma_tlv_put(&tlv, out, b32, false); len = oma_tlv_put(&tlv, out, b64, false);
return len; return len;
} }
@ -647,8 +647,8 @@ static size_t get_string(struct lwm2m_input_context *in,
} }
/* convert float to fixpoint */ /* convert float to fixpoint */
static size_t get_float32fix(struct lwm2m_input_context *in, static size_t get_float(struct lwm2m_input_context *in,
float32_value_t *value) double *value)
{ {
struct oma_tlv tlv; struct oma_tlv tlv;
size_t size = oma_tlv_get(&tlv, in, false); size_t size = oma_tlv_get(&tlv, in, false);
@ -679,9 +679,9 @@ static size_t get_float32fix(struct lwm2m_input_context *in,
} }
if (tlv.length == 4U) { if (tlv.length == 4U) {
ret = lwm2m_b32_to_f32(buf, 4, value); ret = lwm2m_b32_to_float(buf, 4, value);
} else { } else {
ret = lwm2m_b64_to_f32(buf, 8, value); ret = lwm2m_b64_to_float(buf, 8, value);
} }
if (ret < 0) { if (ret < 0) {
@ -752,7 +752,7 @@ const struct lwm2m_writer oma_tlv_writer = {
.put_s32 = put_s32, .put_s32 = put_s32,
.put_s64 = put_s64, .put_s64 = put_s64,
.put_string = put_string, .put_string = put_string,
.put_float32fix = put_float32fix, .put_float = put_float,
.put_bool = put_bool, .put_bool = put_bool,
.put_opaque = put_opaque, .put_opaque = put_opaque,
.put_objlnk = put_objlnk, .put_objlnk = put_objlnk,
@ -762,7 +762,7 @@ const struct lwm2m_reader oma_tlv_reader = {
.get_s32 = get_s32, .get_s32 = get_s32,
.get_s64 = get_s64, .get_s64 = get_s64,
.get_string = get_string, .get_string = get_string,
.get_float32fix = get_float32fix, .get_float = get_float,
.get_bool = get_bool, .get_bool = get_bool,
.get_opaque = get_opaque, .get_opaque = get_opaque,
.get_objlnk = get_objlnk, .get_objlnk = get_objlnk,

View file

@ -74,7 +74,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#include "lwm2m_util.h" #include "lwm2m_util.h"
/* some temporary buffer space for format conversions */ /* some temporary buffer space for format conversions */
static char pt_buffer[42]; /* can handle float64 format */ static char pt_buffer[42];
size_t plain_text_put_format(struct lwm2m_output_context *out, size_t plain_text_put_format(struct lwm2m_output_context *out,
const char *format, ...) const char *format, ...)
@ -122,29 +122,22 @@ static size_t put_s64(struct lwm2m_output_context *out,
return plain_text_put_format(out, "%lld", value); return plain_text_put_format(out, "%lld", value);
} }
size_t plain_text_put_float32fix(struct lwm2m_output_context *out, size_t plain_text_put_float(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path, struct lwm2m_obj_path *path,
float32_value_t *value) double *value)
{ {
size_t len; int len = lwm2m_ftoa(value, pt_buffer, sizeof(pt_buffer), 15);
char buf[sizeof("000000")];
/* value of 123 -> "000123" -- ignore sign */ if (len < 0 || len >= sizeof(pt_buffer)) {
len = snprintk(buf, sizeof(buf), "%06d", abs(value->val2)); LOG_ERR("Failed to encode float value");
if (len != 6U) { return 0;
strcpy(buf, "0");
} else {
/* clear ending zeroes, but leave 1 if needed */
while (len > 1U && buf[len - 1] == '0') {
buf[--len] = '\0';
}
} }
return plain_text_put_format(out, "%s%d.%s", if (buf_append(CPKT_BUF_WRITE(out->out_cpkt), pt_buffer, len) < 0) {
/* handle negative val2 when val1 is 0 */ return 0;
(value->val1 == 0 && value->val2 < 0) ? }
"-" : "",
value->val1, buf); return (size_t)len;
} }
static size_t put_string(struct lwm2m_output_context *out, static size_t put_string(struct lwm2m_output_context *out,
@ -253,8 +246,8 @@ static size_t get_string(struct lwm2m_input_context *in,
return (size_t)in_len; return (size_t)in_len;
} }
static size_t get_float32fix(struct lwm2m_input_context *in, static size_t get_float(struct lwm2m_input_context *in,
float32_value_t *value) double *value)
{ {
size_t i = 0, len = 0; size_t i = 0, len = 0;
bool has_dot = false; bool has_dot = false;
@ -290,7 +283,7 @@ static size_t get_float32fix(struct lwm2m_input_context *in,
buf[i] = '\0'; buf[i] = '\0';
if (lwm2m_atof32(buf, value) != 0) { if (lwm2m_atof(buf, value) != 0) {
LOG_ERR("Failed to parse float value"); LOG_ERR("Failed to parse float value");
} }
@ -380,7 +373,7 @@ const struct lwm2m_writer plain_text_writer = {
.put_s32 = put_s32, .put_s32 = put_s32,
.put_s64 = put_s64, .put_s64 = put_s64,
.put_string = put_string, .put_string = put_string,
.put_float32fix = plain_text_put_float32fix, .put_float = plain_text_put_float,
.put_bool = put_bool, .put_bool = put_bool,
.put_objlnk = put_objlnk, .put_objlnk = put_objlnk,
}; };
@ -389,7 +382,7 @@ const struct lwm2m_reader plain_text_reader = {
.get_s32 = get_s32, .get_s32 = get_s32,
.get_s64 = get_s64, .get_s64 = get_s64,
.get_string = get_string, .get_string = get_string,
.get_float32fix = get_float32fix, .get_float = get_float,
.get_bool = get_bool, .get_bool = get_bool,
.get_opaque = get_opaque, .get_opaque = get_opaque,
.get_objlnk = get_objlnk, .get_objlnk = get_objlnk,

View file

@ -52,9 +52,9 @@ extern const struct lwm2m_reader plain_text_reader;
size_t plain_text_put_format(struct lwm2m_output_context *out, size_t plain_text_put_format(struct lwm2m_output_context *out,
const char *format, ...); const char *format, ...);
size_t plain_text_put_float32fix(struct lwm2m_output_context *out, size_t plain_text_put_float(struct lwm2m_output_context *out,
struct lwm2m_obj_path *path, struct lwm2m_obj_path *path,
float32_value_t *value); double *value);
int do_read_op_plain_text(struct lwm2m_message *msg, int content_format); int do_read_op_plain_text(struct lwm2m_message *msg, int content_format);

View file

@ -5,6 +5,7 @@
*/ */
#include <kernel.h> #include <kernel.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include "lwm2m_util.h" #include "lwm2m_util.h"
@ -12,10 +13,17 @@
#define SHIFT_LEFT(v, o, m) (((v) << (o)) & (m)) #define SHIFT_LEFT(v, o, m) (((v) << (o)) & (m))
#define SHIFT_RIGHT(v, o, m) (((v) >> (o)) & (m)) #define SHIFT_RIGHT(v, o, m) (((v) >> (o)) & (m))
/* convert from float32 to binary32 */ #define PRECISION64_LEN 17U
int lwm2m_f32_to_b32(float32_value_t *f32, uint8_t *b32, size_t len) #define PRECISION64 100000000000000000ULL
#define PRECISION32 1000000000UL
/* convert from float to binary32 */
int lwm2m_float_to_b32(double *in, uint8_t *b32, size_t len)
{ {
int32_t e = -1, v, f = 0; int32_t e = -1, v, f = 0;
int32_t val1 = (int32_t)*in;
int32_t val2 = (*in - (int32_t)*in) * PRECISION32;
int i; int i;
if (len != 4) { if (len != 4) {
@ -23,13 +31,13 @@ int lwm2m_f32_to_b32(float32_value_t *f32, uint8_t *b32, size_t len)
} }
/* handle zero value special case */ /* handle zero value special case */
if (f32->val1 == 0 && f32->val2 == 0) { if (val1 == 0 && val2 == 0) {
memset(b32, 0, len); memset(b32, 0, len);
return 0; return 0;
} }
/* sign handled later */ /* sign handled later */
v = abs(f32->val1); v = abs(val1);
/* add whole value to fraction */ /* add whole value to fraction */
while (v > 0) { while (v > 0) {
@ -44,18 +52,18 @@ int lwm2m_f32_to_b32(float32_value_t *f32, uint8_t *b32, size_t len)
} }
/* sign handled later */ /* sign handled later */
v = abs(f32->val2); v = abs(val2);
/* add decimal to fraction */ /* add decimal to fraction */
i = e; i = e;
while (v > 0 && i < 23) { while (v > 0 && i < 23) {
v *= 2; v *= 2;
if (!f && e < 0 && v < LWM2M_FLOAT32_DEC_MAX) { if (!f && e < 0 && v < PRECISION32) {
/* handle -e */ /* handle -e */
e--; e--;
continue; continue;
} else if (v >= LWM2M_FLOAT32_DEC_MAX) { } else if (v >= PRECISION32) {
v -= LWM2M_FLOAT32_DEC_MAX; v -= PRECISION32;
f |= 1 << (22 - i); f |= 1 << (22 - i);
} }
@ -72,10 +80,10 @@ int lwm2m_f32_to_b32(float32_value_t *f32, uint8_t *b32, size_t len)
memset(b32, 0, len); memset(b32, 0, len);
/* sign: bit 31 */ /* sign: bit 31 */
if (f32->val1 == 0) { if (val1 == 0) {
b32[0] = f32->val2 < 0 ? 0x80 : 0; b32[0] = val2 < 0 ? 0x80 : 0;
} else { } else {
b32[0] = f32->val1 < 0 ? 0x80 : 0; b32[0] = val1 < 0 ? 0x80 : 0;
} }
/* exponent: bits 30-23 */ /* exponent: bits 30-23 */
@ -91,11 +99,13 @@ int lwm2m_f32_to_b32(float32_value_t *f32, uint8_t *b32, size_t len)
return 0; return 0;
} }
/* convert from float32 to binary64 */ /* convert from float to binary64 */
int lwm2m_f32_to_b64(float32_value_t *f32, uint8_t *b64, size_t len) int lwm2m_float_to_b64(double *in, uint8_t *b64, size_t len)
{ {
int64_t v, f = 0; int64_t v, f = 0;
int32_t e = -1; int32_t e = -1;
int64_t val1 = (int64_t)*in;
int64_t val2 = (*in - (int64_t)*in) * PRECISION64;
int i; int i;
if (len != 8) { if (len != 8) {
@ -103,13 +113,13 @@ int lwm2m_f32_to_b64(float32_value_t *f32, uint8_t *b64, size_t len)
} }
/* handle zero value special case */ /* handle zero value special case */
if (f32->val1 == 0 && f32->val2 == 0) { if (val1 == 0 && val2 == 0) {
memset(b64, 0, len); memset(b64, 0, len);
return 0; return 0;
} }
/* sign handled later */ /* sign handled later */
v = abs(f32->val1); v = llabs(val1);
/* add whole value to fraction */ /* add whole value to fraction */
while (v > 0) { while (v > 0) {
@ -124,18 +134,18 @@ int lwm2m_f32_to_b64(float32_value_t *f32, uint8_t *b64, size_t len)
} }
/* sign handled later */ /* sign handled later */
v = abs(f32->val2); v = llabs(val2);
/* add decimal to fraction */ /* add decimal to fraction */
i = e; i = e;
while (v > 0 && i < 52) { while (v > 0 && i < 52) {
v *= 2; v *= 2;
if (!f && e < 0 && v < LWM2M_FLOAT32_DEC_MAX) { if (!f && e < 0 && v < PRECISION64) {
/* handle -e */ /* handle -e */
e--; e--;
continue; continue;
} else if (v >= LWM2M_FLOAT32_DEC_MAX) { } else if (v >= PRECISION64) {
v -= LWM2M_FLOAT32_DEC_MAX; v -= PRECISION64;
f |= (int64_t)1 << (51 - i); f |= (int64_t)1 << (51 - i);
} }
@ -152,10 +162,10 @@ int lwm2m_f32_to_b64(float32_value_t *f32, uint8_t *b64, size_t len)
memset(b64, 0, len); memset(b64, 0, len);
/* sign: bit 63 */ /* sign: bit 63 */
if (f32->val1 == 0) { if (val1 == 0) {
b64[0] = f32->val2 < 0 ? 0x80 : 0; b64[0] = val2 < 0 ? 0x80 : 0;
} else { } else {
b64[0] = f32->val1 < 0 ? 0x80 : 0; b64[0] = val1 < 0 ? 0x80 : 0;
} }
/* exponent: bits 62-52 */ /* exponent: bits 62-52 */
@ -175,18 +185,19 @@ int lwm2m_f32_to_b64(float32_value_t *f32, uint8_t *b64, size_t len)
return 0; return 0;
} }
/* convert from binary32 to float32 */ /* convert from binary32 to float */
int lwm2m_b32_to_f32(uint8_t *b32, size_t len, float32_value_t *f32) int lwm2m_b32_to_float(uint8_t *b32, size_t len, double *out)
{ {
int32_t f, k, i, e; int32_t f, k, i, e;
bool sign = false; bool sign = false;
int32_t val1, val2;
if (len != 4) { if (len != 4) {
return -EINVAL; return -EINVAL;
} }
f32->val1 = 0; val1 = 0;
f32->val2 = 0; val2 = 0;
/* calc sign: bit 31 */ /* calc sign: bit 31 */
sign = SHIFT_RIGHT(b32[0], 7, 0x1); sign = SHIFT_RIGHT(b32[0], 7, 0x1);
@ -211,11 +222,11 @@ int lwm2m_b32_to_f32(uint8_t *b32, size_t len, float32_value_t *f32)
e = 23; e = 23;
} }
f32->val1 = (f >> (23 - e)) * (sign ? -1 : 1); val1 = (f >> (23 - e)) * (sign ? -1 : 1);
} }
/* calculate the rest of the decimal */ /* calculate the rest of the decimal */
k = LWM2M_FLOAT32_DEC_MAX; k = PRECISION32;
/* account for -e */ /* account for -e */
while (e < -1) { while (e < -1) {
@ -226,27 +237,34 @@ int lwm2m_b32_to_f32(uint8_t *b32, size_t len, float32_value_t *f32)
for (i = 22 - e; i >= 0; i--) { for (i = 22 - e; i >= 0; i--) {
k /= 2; k /= 2;
if (f & (1 << i)) { if (f & (1 << i)) {
f32->val2 += k; val2 += k;
} }
} }
if (sign) {
*out = (double)val1 - (double)val2 / PRECISION32;
} else {
*out = (double)val1 + (double)val2 / PRECISION32;
}
return 0; return 0;
} }
/* convert from binary64 to float32 */ /* convert from binary64 to float */
int lwm2m_b64_to_f32(uint8_t *b64, size_t len, float32_value_t *f32) int lwm2m_b64_to_float(uint8_t *b64, size_t len, double *out)
{ {
int64_t f, k; int64_t f, k;
int i, e; int i, e;
bool sign = false; bool sign = false;
int64_t val1, val2;
if (len != 8) { if (len != 8) {
return -EINVAL; return -EINVAL;
} }
f32->val1 = 0LL; val1 = 0LL;
f32->val2 = 0LL; val2 = 0LL;
/* calc sign: bit 63 */ /* calc sign: bit 63 */
sign = SHIFT_RIGHT(b64[0], 7, 0x1); sign = SHIFT_RIGHT(b64[0], 7, 0x1);
@ -275,11 +293,11 @@ int lwm2m_b64_to_f32(uint8_t *b64, size_t len, float32_value_t *f32)
e = 52; e = 52;
} }
f32->val1 = (f >> (52 - e)) * (sign ? -1 : 1); val1 = (f >> (52 - e)) * (sign ? -1 : 1);
} }
/* calculate the rest of the decimal */ /* calculate the rest of the decimal */
k = LWM2M_FLOAT32_DEC_MAX; k = PRECISION64;
/* account for -e */ /* account for -e */
while (e < -1) { while (e < -1) {
@ -290,19 +308,26 @@ int lwm2m_b64_to_f32(uint8_t *b64, size_t len, float32_value_t *f32)
for (i = 51 - e; i >= 0; i--) { for (i = 51 - e; i >= 0; i--) {
k /= 2; k /= 2;
if (f & ((int64_t)1 << i)) { if (f & ((int64_t)1 << i)) {
f32->val2 += k; val2 += k;
} }
} }
if (sign) {
*out = (double)val1 - (double)val2 / PRECISION64;
} else {
*out = (double)val1 + (double)val2 / PRECISION64;
}
return 0; return 0;
} }
int lwm2m_atof32(const char *input, float32_value_t *out) int lwm2m_atof(const char *input, double *out)
{ {
char *pos, *end, buf[24]; char *pos, *end, buf[24];
long val; long val;
int32_t base = LWM2M_FLOAT32_DEC_MAX, sign = 1; int64_t base = PRECISION64, sign = 1;
int64_t val1, val2;
if (!input || !out) { if (!input || !out) {
return -EINVAL; return -EINVAL;
@ -326,18 +351,71 @@ int lwm2m_atof32(const char *input, float32_value_t *out)
return -EINVAL; return -EINVAL;
} }
out->val1 = (int32_t) val; val1 = (int64_t)val;
out->val2 = 0; val2 = 0;
if (!pos) { if (!pos) {
return 0; return 0;
} }
while (*(++pos) && base > 1 && isdigit((unsigned char)*pos)) { while (*(++pos) && base > 1 && isdigit((unsigned char)*pos)) {
out->val2 = out->val2 * 10 + (*pos - '0'); val2 = val2 * 10 + (*pos - '0');
base /= 10; base /= 10;
} }
out->val2 *= sign * base; val2 *= sign * base;
*out = (double)val1 + (double)val2 / PRECISION64;
return !*pos || base == 1 ? 0 : -EINVAL; return !*pos || base == 1 ? 0 : -EINVAL;
} }
int lwm2m_ftoa(double *input, char *out, size_t outlen, int8_t dec_limit)
{
size_t len;
char buf[PRECISION64_LEN + 1];
int64_t val1 = (int64_t)*input;
int64_t val2 = (*input - (int64_t)*input) * PRECISION64;
len = snprintk(buf, sizeof(buf), "%0*lld", PRECISION64_LEN, llabs(val2));
if (len != PRECISION64_LEN) {
strcpy(buf, "0");
} else {
/* Round the value to the specified decimal point. */
if (dec_limit > 0 && dec_limit < sizeof(buf) &&
buf[dec_limit] != '\0') {
bool round_up = buf[dec_limit] >= '5';
buf[dec_limit] = '\0';
len = dec_limit;
while (round_up && dec_limit > 0) {
dec_limit--;
buf[dec_limit]++;
if (buf[dec_limit] > '9') {
buf[dec_limit] = '0';
} else {
round_up = false;
}
}
if (round_up) {
if (*input < 0) {
val1--;
} else {
val1++;
}
}
}
/* clear ending zeroes, but leave 1 if needed */
while (len > 1U && buf[len - 1] == '0') {
buf[--len] = '\0';
}
}
return snprintk(out, outlen, "%s%lld.%s",
/* handle negative val2 when val1 is 0 */
(val1 == 0 && val2 < 0) ? "-" : "", val1, buf);
}

View file

@ -9,15 +9,17 @@
#include <net/lwm2m.h> #include <net/lwm2m.h>
/* convert float struct to binary format */ /* convert float to binary format */
int lwm2m_f32_to_b32(float32_value_t *f32, uint8_t *b32, size_t len); int lwm2m_float_to_b32(double *in, uint8_t *b32, size_t len);
int lwm2m_f32_to_b64(float32_value_t *f32, uint8_t *b64, size_t len); int lwm2m_float_to_b64(double *in, uint8_t *b64, size_t len);
/* convert binary format to float struct */ /* convert binary format to float */
int lwm2m_b32_to_f32(uint8_t *b32, size_t len, float32_value_t *f32); int lwm2m_b32_to_float(uint8_t *b32, size_t len, double *out);
int lwm2m_b64_to_f32(uint8_t *b64, size_t len, float32_value_t *f32); int lwm2m_b64_to_float(uint8_t *b64, size_t len, double *out);
/* convert string to float struct */ /* convert string to float */
int lwm2m_atof32(const char *input, float32_value_t *out); int lwm2m_atof(const char *input, double *out);
/* convert float to string */
int lwm2m_ftoa(double *input, char *out, size_t outlen, int8_t dec_limit);
#endif /* LWM2M_UTIL_H_ */ #endif /* LWM2M_UTIL_H_ */