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_rx_enable`
* Replaced custom LwM2M :c:struct:`float32_value` type with a native double type.
==========================
Removed APIs in this release

View file

@ -357,27 +357,6 @@ struct coap_block_context *lwm2m_firmware_get_block_context();
#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
*/
@ -557,14 +536,14 @@ int lwm2m_engine_set_s64(char *pathstr, int64_t 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] value 32-bit float value
* @param[in] value double value
*
* @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)
@ -689,14 +668,14 @@ int lwm2m_engine_get_s64(char *pathstr, int64_t *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[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.
*/
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)

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)
{
/* 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;
#if defined(CONFIG_FXOS8700_TEMP)
@ -198,17 +198,21 @@ static void *temperature_get_buf(uint16_t obj_inst_id, uint16_t res_id,
#endif
if (dev != NULL) {
struct sensor_value val;
if (sensor_sample_fetch(dev)) {
LOG_ERR("temperature data update failed");
}
sensor_channel_get(dev, SENSOR_CHAN_DIE_TEMP,
(struct sensor_value *) &v);
LOG_DBG("LWM2M temperature set to %d.%d", v.val1, v.val2);
sensor_channel_get(dev, SENSOR_CHAN_DIE_TEMP, &val);
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 */
lwm2m_engine_set_float32("3303/0/5700", &v);
lwm2m_engine_set_float("3303/0/5700", &v);
*data_len = sizeof(v);
return &v;
}

View file

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

View file

@ -43,9 +43,9 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
/* resource state */
struct ipso_buzzer_data {
float32_value_t level;
float32_value_t delay_duration;
float32_value_t min_off_time;
double level;
double delay_duration;
double min_off_time;
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
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)
{
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 */
float2ms(&buzzer->min_off_time, &temp);
temp = (uint32_t)(buzzer->min_off_time * MSEC_PER_SEC);
if (k_uptime_get() < buzzer->trigger_offset + temp) {
return -EINVAL;
}
@ -128,7 +120,7 @@ static int start_buzzer(struct ipso_buzzer_data *buzzer)
buzzer->obj_inst_id, DIGITAL_INPUT_STATE_RID);
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));
return 0;
@ -210,8 +202,8 @@ static struct lwm2m_engine_obj_inst *buzzer_create(uint16_t obj_inst_id)
/* Set default values */
(void)memset(&buzzer_data[avail], 0, sizeof(buzzer_data[avail]));
k_work_init_delayable(&buzzer_data[avail].buzzer_work, buzzer_work_cb);
buzzer_data[avail].level.val1 = 50; /* 50% */
buzzer_data[avail].delay_duration.val1 = 1; /* 1 seconds */
buzzer_data[avail].level = 50; /* 50% */
buzzer_data[avail].delay_duration = 1; /* 1 seconds */
buzzer_data[avail].obj_inst_id = obj_inst_id;
(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)
/* 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 float32_value_t min_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t max_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t min_range_value[MAX_INSTANCE_COUNT];
static float32_value_t max_range_value[MAX_INSTANCE_COUNT];
static double min_measured_value[MAX_INSTANCE_COUNT];
static double max_measured_value[MAX_INSTANCE_COUNT];
static double min_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 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)
{
min_measured_value[index].val1 = sensor_value[index].val1;
min_measured_value[index].val2 = sensor_value[index].val2;
min_measured_value[index] = sensor_value[index];
NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MIN_MEASURED_VALUE_RID);
}
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].val2 = sensor_value[index].val2;
max_measured_value[index] = sensor_value[index];
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)
{
int i;
bool update_min = false;
bool update_max = false;
for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
/* update min / max */
if (sensor_value[i].val1 < min_measured_value[i].val1) {
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) {
if (sensor_value[i] < min_measured_value[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);
}
}
@ -190,17 +168,12 @@ static struct lwm2m_engine_obj_inst *generic_sensor_create(uint16_t obj_inst_id)
}
/* Set default values */
sensor_value[index].val1 = 0;
sensor_value[index].val2 = 0;
sensor_value[index] = 0;
units[index][0] = '\0';
min_measured_value[index].val1 = INT32_MAX;
min_measured_value[index].val2 = 0;
max_measured_value[index].val1 = -INT32_MAX;
max_measured_value[index].val2 = 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;
min_measured_value[index] = INT32_MAX;
max_measured_value[index] = -INT32_MAX;
min_range_value[index] = 0;
max_range_value[index] = 0;
app_type[index][0] = '\0';
strncpy(sensor_type[index], CONFIG_LWM2M_IPSO_GENERIC_SENSOR_TYPE,
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)
/* 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 float32_value_t min_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t max_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t min_range_value[MAX_INSTANCE_COUNT];
static float32_value_t max_range_value[MAX_INSTANCE_COUNT];
static double min_measured_value[MAX_INSTANCE_COUNT];
static double max_measured_value[MAX_INSTANCE_COUNT];
static double min_range_value[MAX_INSTANCE_COUNT];
static double max_range_value[MAX_INSTANCE_COUNT];
static struct lwm2m_engine_obj sensor;
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)
{
min_measured_value[index].val1 = sensor_value[index].val1;
min_measured_value[index].val2 = sensor_value[index].val2;
min_measured_value[index] = sensor_value[index];
NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MIN_MEASURED_VALUE_RID);
}
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].val2 = sensor_value[index].val2;
max_measured_value[index] = sensor_value[index];
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)
{
int i;
bool update_min = false;
bool update_max = false;
for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
/* update min / max */
if (sensor_value[i].val1 < min_measured_value[i].val1) {
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) {
if (sensor_value[i] < min_measured_value[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);
}
}
@ -177,17 +155,12 @@ humidity_sensor_create(uint16_t obj_inst_id)
}
/* Set default values */
sensor_value[index].val1 = 0;
sensor_value[index].val2 = 0;
sensor_value[index] = 0;
units[index][0] = '\0';
min_measured_value[index].val1 = INT32_MAX;
min_measured_value[index].val2 = 0;
max_measured_value[index].val1 = -INT32_MAX;
max_measured_value[index].val2 = 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;
min_measured_value[index] = INT32_MAX;
max_measured_value[index] = -INT32_MAX;
min_range_value[index] = 0;
max_range_value[index] = 0;
(void)memset(res[index], 0,
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 int32_t on_time_value[MAX_INSTANCE_COUNT];
static uint32_t on_time_offset[MAX_INSTANCE_COUNT];
static float32_value_t cumulative_active_value[MAX_INSTANCE_COUNT];
static float32_value_t power_factor_value[MAX_INSTANCE_COUNT];
static double cumulative_active_value[MAX_INSTANCE_COUNT];
static double power_factor_value[MAX_INSTANCE_COUNT];
static char colour[MAX_INSTANCE_COUNT][LIGHT_STRING_LONG];
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;
on_time_value[avail] = 0;
on_time_offset[avail] = 0U;
cumulative_active_value[avail].val1 = 0;
cumulative_active_value[avail].val2 = 0;
power_factor_value[avail].val1 = 0;
power_factor_value[avail].val2 = 0;
cumulative_active_value[avail] = 0;
power_factor_value[avail] = 0;
colour[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)
/* 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 float32_value_t min_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t max_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t min_range_value[MAX_INSTANCE_COUNT];
static float32_value_t max_range_value[MAX_INSTANCE_COUNT];
static double min_measured_value[MAX_INSTANCE_COUNT];
static double max_measured_value[MAX_INSTANCE_COUNT];
static double min_range_value[MAX_INSTANCE_COUNT];
static double max_range_value[MAX_INSTANCE_COUNT];
static struct lwm2m_engine_obj sensor;
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)
{
min_measured_value[index].val1 = sensor_value[index].val1;
min_measured_value[index].val2 = sensor_value[index].val2;
min_measured_value[index] = sensor_value[index];
NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MIN_MEASURED_VALUE_RID);
}
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].val2 = sensor_value[index].val2;
max_measured_value[index] = sensor_value[index];
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)
{
int i;
bool update_min = false;
bool update_max = false;
for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
/* update min / max */
if (sensor_value[i].val1 < min_measured_value[i].val1) {
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) {
if (sensor_value[i] < min_measured_value[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);
}
}
@ -178,17 +156,12 @@ pressure_sensor_create(uint16_t obj_inst_id)
}
/* Set default values */
sensor_value[index].val1 = 0;
sensor_value[index].val2 = 0;
sensor_value[index] = 0;
units[index][0] = '\0';
min_measured_value[index].val1 = INT32_MAX;
min_measured_value[index].val2 = 0;
max_measured_value[index].val1 = -INT32_MAX;
max_measured_value[index].val2 = 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;
min_measured_value[index] = INT32_MAX;
max_measured_value[index] = -INT32_MAX;
min_range_value[index] = 0;
max_range_value[index] = 0;
(void)memset(res[index], 0,
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)
/* 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 float32_value_t min_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t max_measured_value[MAX_INSTANCE_COUNT];
static float32_value_t min_range_value[MAX_INSTANCE_COUNT];
static float32_value_t max_range_value[MAX_INSTANCE_COUNT];
static double min_measured_value[MAX_INSTANCE_COUNT];
static double max_measured_value[MAX_INSTANCE_COUNT];
static double min_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_field fields[] = {
@ -78,16 +78,14 @@ static struct lwm2m_engine_res_inst
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].val2 = sensor_value[index].val2;
min_measured_value[index] = sensor_value[index];
NOTIFY_OBSERVER(IPSO_OBJECT_TEMP_SENSOR_ID, obj_inst_id,
MIN_MEASURED_VALUE_RID);
}
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].val2 = sensor_value[index].val2;
max_measured_value[index] = sensor_value[index];
NOTIFY_OBSERVER(IPSO_OBJECT_TEMP_SENSOR_ID, obj_inst_id,
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)
{
int i;
bool update_min = false;
bool update_max = false;
for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
/* update min / max */
if (sensor_value[i].val1 < min_measured_value[i].val1) {
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) {
if (sensor_value[i] < min_measured_value[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);
}
}
@ -178,17 +156,12 @@ static struct lwm2m_engine_obj_inst *temp_sensor_create(uint16_t obj_inst_id)
}
/* Set default values */
sensor_value[index].val1 = 0;
sensor_value[index].val2 = 0;
sensor_value[index] = 0;
units[index][0] = '\0';
min_measured_value[index].val1 = INT32_MAX;
min_measured_value[index].val2 = 0;
max_measured_value[index].val1 = -INT32_MAX;
max_measured_value[index].val2 = 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;
min_measured_value[index] = INT32_MAX;
max_measured_value[index] = -INT32_MAX;
min_range_value[index] = 0;
max_range_value[index] = 0;
(void)memset(res[index], 0,
sizeof(res[index][0]) * ARRAY_SIZE(res[index]));

View file

@ -46,10 +46,10 @@ enum ipso_timer_mode {
/* resource state */
struct ipso_timer_data {
float32_value_t delay_duration;
float32_value_t remaining_time;
float32_value_t min_off_time;
float32_value_t cumulative_time;
double delay_duration;
double remaining_time;
double min_off_time;
double cumulative_time;
uint64_t trigger_offset;
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
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)
{
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 */
float2ms(&timer->min_off_time, &temp);
temp = timer->min_off_time * MSEC_PER_SEC;
if (k_uptime_get() < timer->trigger_offset + temp) {
return -EINVAL;
}
@ -143,7 +127,7 @@ static int start_timer(struct ipso_timer_data *timer)
timer->obj_inst_id, DIGITAL_STATE_RID);
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));
return 0;
@ -183,12 +167,11 @@ static void *remaining_time_read_cb(uint16_t obj_inst_id,
}
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);
ms2float(temp, &timer_data[i].remaining_time);
timer_data[i].remaining_time = (double)temp / MSEC_PER_SEC;
} else {
timer_data[i].remaining_time.val1 = 0;
timer_data[i].remaining_time.val2 = 0;
timer_data[i].remaining_time = 0;
}
*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;
}
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);
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 */
(void)memset(&timer_data[avail], 0, sizeof(timer_data[avail]));
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].timer_mode = TIMER_MODE_ONE_SHOT;
timer_data[avail].obj_inst_id = obj_inst_id;

View file

@ -86,9 +86,9 @@ struct observe_node {
struct notification_attrs {
/* use to determine which value is set */
float32_value_t gt;
float32_value_t lt;
float32_value_t st;
double gt;
double lt;
double st;
int32_t pmin;
int32_t pmax;
uint8_t flags;
@ -1596,10 +1596,7 @@ static int lwm2m_engine_set(char *pathstr, void *value, uint16_t len)
break;
case LWM2M_RES_TYPE_FLOAT:
((float32_value_t *)data_ptr)->val1 =
((float32_value_t *)value)->val1;
((float32_value_t *)data_ptr)->val2 =
((float32_value_t *)value)->val2;
*(double *)data_ptr = *(double *)value;
break;
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);
}
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)
@ -1830,10 +1827,7 @@ static int lwm2m_engine_get(char *pathstr, void *buf, uint16_t buflen)
break;
case LWM2M_RES_TYPE_FLOAT:
((float32_value_t *)buf)->val1 =
((float32_value_t *)data_ptr)->val1;
((float32_value_t *)buf)->val2 =
((float32_value_t *)data_ptr)->val2;
*(double *)buf = *(double *)data_ptr;
break;
case LWM2M_RES_TYPE_OBJLNK:
@ -1915,9 +1909,9 @@ int lwm2m_engine_get_bool(char *pathstr, bool *value)
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)
@ -2325,8 +2319,8 @@ static int lwm2m_read_handler(struct lwm2m_engine_obj_inst *obj_inst,
break;
case LWM2M_RES_TYPE_FLOAT:
engine_put_float32fix(&msg->out, &msg->path,
(float32_value_t *)data_ptr);
engine_put_float(&msg->out, &msg->path,
(double *)data_ptr);
break;
case LWM2M_RES_TYPE_OBJLNK:
@ -2594,9 +2588,8 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst,
break;
case LWM2M_RES_TYPE_FLOAT:
engine_get_float32fix(&msg->in,
(float32_value_t *)write_buf);
len = sizeof(float32_value_t);
engine_get_float(&msg->in, (double *)write_buf);
len = sizeof(double);
break;
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 */
for (i = 0; i < nr_opt; i++) {
int limit = MIN(options[i].len, 5), plen = 0, vlen;
float32_value_t val = { 0 };
struct lwm2m_attr val = { 0 };
type = 0U;
/* search for '=' */
@ -2758,7 +2751,7 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj,
(void)memset(nattr_ptrs[type], 0,
type <= LWM2M_ATTR_PMAX ? sizeof(int32_t) :
sizeof(float32_value_t));
sizeof(double));
continue;
}
@ -2785,10 +2778,10 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj,
ret = -EINVAL;
}
val.val1 = v;
val.int_val = v;
} else {
/* gt/lt/st: type float */
ret = lwm2m_atof32(opt_buf, &val);
ret = lwm2m_atof(opt_buf, &val.float_val);
}
if (ret < 0) {
@ -2799,9 +2792,10 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj,
}
if (type <= LWM2M_ATTR_PMAX) {
*(int32_t *)nattr_ptrs[type] = val.val1;
*(int32_t *)nattr_ptrs[type] = val.int_val;
} 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);
@ -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.lt.val1 < nattrs.gt.val1) ||
(nattrs.lt.val2 < nattrs.gt.val2))) {
if (nattrs.lt > nattrs.gt) {
LOG_DBG("lt > gt");
return -EEXIST;
}
if (nattrs.flags & BIT(LWM2M_ATTR_STEP)) {
int32_t st1 = nattrs.st.val1 * 2 +
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))) {
if (nattrs.lt + 2 * nattrs.st > nattrs.gt) {
LOG_DBG("lt + 2*st > gt");
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];
update_observe_node = true;
LOG_DBG("Update %s to %d", log_strdup(LWM2M_ATTR_STR[type]),
attr->int_val);
} else {
if (!memcmp(&attr->float_val, nattr_ptrs[type],
sizeof(float32_value_t))) {
if (attr->float_val == *(double *)nattr_ptrs[type]) {
continue;
}
memcpy(&attr->float_val, nattr_ptrs[type],
sizeof(float32_value_t));
}
attr->float_val = *(double *)nattr_ptrs[type];
LOG_DBG("Update %s to %d.%06d",
log_strdup(LWM2M_ATTR_STR[type]),
attr->float_val.val1, attr->float_val.val2);
LOG_DBG("Update %s to %f", log_strdup(LWM2M_ATTR_STR[type]),
attr->float_val);
}
}
/* 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) {
attr->int_val = *(int32_t *)nattr_ptrs[type];
update_observe_node = true;
LOG_DBG("Add %s to %d", log_strdup(LWM2M_ATTR_STR[type]),
attr->int_val);
} else {
memcpy(&attr->float_val, nattr_ptrs[type],
sizeof(float32_value_t));
attr->float_val = *(double *)nattr_ptrs[type];
LOG_DBG("Add %s to %f", log_strdup(LWM2M_ATTR_STR[type]),
attr->float_val);
}
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 */

View file

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

View file

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

View file

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

View file

@ -9,6 +9,7 @@
#include "lwm2m_engine.h"
#include "lwm2m_rw_link_format.h"
#include "lwm2m_util.h"
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)
{
struct lwm2m_attr *attr = NULL;
int used, base, ret;
uint8_t digit;
int32_t fraction;
int used, ret;
int len = 0;
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;
}
/* Assuming integer will have float_val.val2 set as 0. */
used = snprintk(buf, buflen, ";%s=%s%d%s",
name,
attr->float_val.val1 == 0 &&
attr->float_val.val2 < 0 ? "-" : "",
attr->float_val.val1,
attr->float_val.val2 != 0 ? "." : "");
if (used < 0 || used >= buflen) {
return -ENOMEM;
if (attr->type <= LWM2M_ATTR_PMAX) {
used = snprintk(buf, buflen, ";%s=%d", name, attr->int_val);
} else {
uint8_t float_buf[32];
used = lwm2m_ftoa(&attr->float_val, float_buf,
sizeof(float_buf), 4);
if (used < 0 || used >= sizeof(float_buf)) {
return -ENOMEM;
}
used = snprintk(buf, buflen, ";%s=%s", name, float_buf);
}
base = 100000;
fraction = attr->float_val.val2 < 0 ?
-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;
if (used < 0 || used >= buflen) {
return -ENOMEM;
}
len += used;

View file

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

View file

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

View file

@ -5,6 +5,7 @@
*/
#include <kernel.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "lwm2m_util.h"
@ -12,10 +13,17 @@
#define SHIFT_LEFT(v, o, m) (((v) << (o)) & (m))
#define SHIFT_RIGHT(v, o, m) (((v) >> (o)) & (m))
/* convert from float32 to binary32 */
int lwm2m_f32_to_b32(float32_value_t *f32, uint8_t *b32, size_t len)
#define PRECISION64_LEN 17U
#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 val1 = (int32_t)*in;
int32_t val2 = (*in - (int32_t)*in) * PRECISION32;
int i;
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 */
if (f32->val1 == 0 && f32->val2 == 0) {
if (val1 == 0 && val2 == 0) {
memset(b32, 0, len);
return 0;
}
/* sign handled later */
v = abs(f32->val1);
v = abs(val1);
/* add whole value to fraction */
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 */
v = abs(f32->val2);
v = abs(val2);
/* add decimal to fraction */
i = e;
while (v > 0 && i < 23) {
v *= 2;
if (!f && e < 0 && v < LWM2M_FLOAT32_DEC_MAX) {
if (!f && e < 0 && v < PRECISION32) {
/* handle -e */
e--;
continue;
} else if (v >= LWM2M_FLOAT32_DEC_MAX) {
v -= LWM2M_FLOAT32_DEC_MAX;
} else if (v >= PRECISION32) {
v -= PRECISION32;
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);
/* sign: bit 31 */
if (f32->val1 == 0) {
b32[0] = f32->val2 < 0 ? 0x80 : 0;
if (val1 == 0) {
b32[0] = val2 < 0 ? 0x80 : 0;
} else {
b32[0] = f32->val1 < 0 ? 0x80 : 0;
b32[0] = val1 < 0 ? 0x80 : 0;
}
/* 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;
}
/* convert from float32 to binary64 */
int lwm2m_f32_to_b64(float32_value_t *f32, uint8_t *b64, size_t len)
/* convert from float to binary64 */
int lwm2m_float_to_b64(double *in, uint8_t *b64, size_t len)
{
int64_t v, f = 0;
int32_t e = -1;
int64_t val1 = (int64_t)*in;
int64_t val2 = (*in - (int64_t)*in) * PRECISION64;
int i;
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 */
if (f32->val1 == 0 && f32->val2 == 0) {
if (val1 == 0 && val2 == 0) {
memset(b64, 0, len);
return 0;
}
/* sign handled later */
v = abs(f32->val1);
v = llabs(val1);
/* add whole value to fraction */
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 */
v = abs(f32->val2);
v = llabs(val2);
/* add decimal to fraction */
i = e;
while (v > 0 && i < 52) {
v *= 2;
if (!f && e < 0 && v < LWM2M_FLOAT32_DEC_MAX) {
if (!f && e < 0 && v < PRECISION64) {
/* handle -e */
e--;
continue;
} else if (v >= LWM2M_FLOAT32_DEC_MAX) {
v -= LWM2M_FLOAT32_DEC_MAX;
} else if (v >= PRECISION64) {
v -= PRECISION64;
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);
/* sign: bit 63 */
if (f32->val1 == 0) {
b64[0] = f32->val2 < 0 ? 0x80 : 0;
if (val1 == 0) {
b64[0] = val2 < 0 ? 0x80 : 0;
} else {
b64[0] = f32->val1 < 0 ? 0x80 : 0;
b64[0] = val1 < 0 ? 0x80 : 0;
}
/* 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;
}
/* convert from binary32 to float32 */
int lwm2m_b32_to_f32(uint8_t *b32, size_t len, float32_value_t *f32)
/* convert from binary32 to float */
int lwm2m_b32_to_float(uint8_t *b32, size_t len, double *out)
{
int32_t f, k, i, e;
bool sign = false;
int32_t val1, val2;
if (len != 4) {
return -EINVAL;
}
f32->val1 = 0;
f32->val2 = 0;
val1 = 0;
val2 = 0;
/* calc sign: bit 31 */
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;
}
f32->val1 = (f >> (23 - e)) * (sign ? -1 : 1);
val1 = (f >> (23 - e)) * (sign ? -1 : 1);
}
/* calculate the rest of the decimal */
k = LWM2M_FLOAT32_DEC_MAX;
k = PRECISION32;
/* account for -e */
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--) {
k /= 2;
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;
}
/* convert from binary64 to float32 */
int lwm2m_b64_to_f32(uint8_t *b64, size_t len, float32_value_t *f32)
/* convert from binary64 to float */
int lwm2m_b64_to_float(uint8_t *b64, size_t len, double *out)
{
int64_t f, k;
int i, e;
bool sign = false;
int64_t val1, val2;
if (len != 8) {
return -EINVAL;
}
f32->val1 = 0LL;
f32->val2 = 0LL;
val1 = 0LL;
val2 = 0LL;
/* calc sign: bit 63 */
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;
}
f32->val1 = (f >> (52 - e)) * (sign ? -1 : 1);
val1 = (f >> (52 - e)) * (sign ? -1 : 1);
}
/* calculate the rest of the decimal */
k = LWM2M_FLOAT32_DEC_MAX;
k = PRECISION64;
/* account for -e */
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--) {
k /= 2;
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;
}
int lwm2m_atof32(const char *input, float32_value_t *out)
int lwm2m_atof(const char *input, double *out)
{
char *pos, *end, buf[24];
long val;
int32_t base = LWM2M_FLOAT32_DEC_MAX, sign = 1;
int64_t base = PRECISION64, sign = 1;
int64_t val1, val2;
if (!input || !out) {
return -EINVAL;
@ -326,18 +351,71 @@ int lwm2m_atof32(const char *input, float32_value_t *out)
return -EINVAL;
}
out->val1 = (int32_t) val;
out->val2 = 0;
val1 = (int64_t)val;
val2 = 0;
if (!pos) {
return 0;
}
while (*(++pos) && base > 1 && isdigit((unsigned char)*pos)) {
out->val2 = out->val2 * 10 + (*pos - '0');
val2 = val2 * 10 + (*pos - '0');
base /= 10;
}
out->val2 *= sign * base;
val2 *= sign * base;
*out = (double)val1 + (double)val2 / PRECISION64;
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>
/* convert float struct to binary format */
int lwm2m_f32_to_b32(float32_value_t *f32, uint8_t *b32, size_t len);
int lwm2m_f32_to_b64(float32_value_t *f32, uint8_t *b64, size_t len);
/* convert float to binary format */
int lwm2m_float_to_b32(double *in, uint8_t *b32, size_t len);
int lwm2m_float_to_b64(double *in, uint8_t *b64, size_t len);
/* convert binary format to float struct */
int lwm2m_b32_to_f32(uint8_t *b32, size_t len, float32_value_t *f32);
int lwm2m_b64_to_f32(uint8_t *b64, size_t len, float32_value_t *f32);
/* convert binary format to float */
int lwm2m_b32_to_float(uint8_t *b32, size_t len, double *out);
int lwm2m_b64_to_float(uint8_t *b64, size_t len, double *out);
/* convert string to float struct */
int lwm2m_atof32(const char *input, float32_value_t *out);
/* convert string to float */
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_ */