From f8565ee40672ff23a00017d7c56d1a81fea79617 Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Mon, 29 Apr 2024 11:22:05 +0200 Subject: [PATCH] Bluetooth: Mesh: avoid double conversion precision losing Commit solves situation when the level client sends Set command with exact values but Status has different levels. It happens when Level model extends the temperature model. Double conversion happens. Conversions from level to temperature and back have division result rounding that causes precision losing. Signed-off-by: Aleksandr Khromykh --- subsys/bluetooth/mesh/light_temp_srv.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/mesh/light_temp_srv.c b/subsys/bluetooth/mesh/light_temp_srv.c index 415b4687d017..5fbe1ca71009 100644 --- a/subsys/bluetooth/mesh/light_temp_srv.c +++ b/subsys/bluetooth/mesh/light_temp_srv.c @@ -179,9 +179,10 @@ static void lvl_set(struct bt_mesh_lvl_srv *lvl_srv, struct bt_mesh_light_temp_srv *srv = CONTAINER_OF(lvl_srv, struct bt_mesh_light_temp_srv, lvl); struct bt_mesh_light_temp_status status = { 0 }; + uint16_t temp = lvl_to_temp(srv, lvl_set->lvl); struct bt_mesh_light_temp_set set = { .params = { - .temp = lvl_to_temp(srv, lvl_set->lvl), + .temp = temp, .delta_uv = srv->transient.last.delta_uv, }, .transition = lvl_set->transition, @@ -194,8 +195,15 @@ static void lvl_set(struct bt_mesh_lvl_srv *lvl_srv, } if (rsp) { - rsp->current = temp_to_lvl(srv, status.current.temp); - rsp->target = temp_to_lvl(srv, status.target.temp); + /* This helps to avoid weird situation when client sets exact level value + * but after conversion to temperature and back from temperature to level, + * the level value is changed in Status. + * It happens due to the division results rounding in both conversions. + */ + rsp->current = temp == status.current.temp ? lvl_set->lvl + : temp_to_lvl(srv, status.current.temp); + rsp->target = temp == status.target.temp ? lvl_set->lvl + : temp_to_lvl(srv, status.target.temp); rsp->remaining_time = status.remaining_time; } }