1 /* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
2  *
3  * SPDX-FileCopyrightText: 2018 Vikrant More
4  * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include "btc_ble_mesh_generic_model.h"
10 #include "btc_ble_mesh_lighting_model.h"
11 #include "btc_ble_mesh_time_scene_model.h"
12 #include "btc_ble_mesh_sensor_model.h"
13 
14 #include "mesh_config.h"
15 #include "model_opcode.h"
16 #include "state_transition.h"
17 
18 #if (CONFIG_BLE_MESH_GENERIC_SERVER || \
19      CONFIG_BLE_MESH_TIME_SCENE_SERVER || \
20      CONFIG_BLE_MESH_LIGHTING_SERVER)
21 
22 /* Function to calculate Remaining Time (Start) */
23 
bt_mesh_server_calc_remain_time(struct bt_mesh_state_transition * transition)24 void bt_mesh_server_calc_remain_time(struct bt_mesh_state_transition *transition)
25 {
26     uint8_t steps = 0U, resolution = 0U;
27     int32_t duration_remainder = 0;
28     int64_t now = 0;
29 
30     if (transition->just_started) {
31         transition->remain_time = transition->trans_time;
32     } else {
33         now = k_uptime_get();
34         duration_remainder = transition->total_duration -
35                              (now - transition->start_timestamp);
36         if (duration_remainder > 620000) {
37             /* > 620 seconds -> resolution = 0b11 [10 minutes] */
38             resolution = 0x03;
39             steps = duration_remainder / 600000;
40         } else if (duration_remainder > 62000) {
41             /* > 62 seconds -> resolution = 0b10 [10 seconds] */
42             resolution = 0x02;
43             steps = duration_remainder / 10000;
44         } else if (duration_remainder > 6200) {
45             /* > 6.2 seconds -> resolution = 0b01 [1 seconds] */
46             resolution = 0x01;
47             steps = duration_remainder / 1000;
48         } else if (duration_remainder > 0) {
49             /* <= 6.2 seconds -> resolution = 0b00 [100 ms] */
50             resolution = 0x00;
51             steps = duration_remainder / 100;
52         } else {
53             resolution = 0x00;
54             steps = 0x00;
55         }
56 
57         transition->remain_time = (resolution << 6) | steps;
58     }
59 }
60 
61 /* Function to calculate Remaining Time (End) */
62 
tt_values_calculator(struct bt_mesh_state_transition * transition)63 static void tt_values_calculator(struct bt_mesh_state_transition *transition)
64 {
65     uint8_t steps_multiplier = 0U, resolution = 0U;
66 
67     resolution = (transition->trans_time >> 6);
68     steps_multiplier = (transition->trans_time & 0x3F);
69 
70     switch (resolution) {
71     case 0: /* 100ms */
72         transition->total_duration = steps_multiplier * 100;
73         break;
74     case 1: /* 1 second */
75         transition->total_duration = steps_multiplier * 1000;
76         break;
77     case 2: /* 10 seconds */
78         transition->total_duration = steps_multiplier * 10000;
79         break;
80     case 3: /* 10 minutes */
81         transition->total_duration = steps_multiplier * 600000;
82         break;
83     }
84 
85     transition->counter = ((float) transition->total_duration / 100);
86 
87     if (transition->counter > BLE_MESH_DEVICE_SPECIFIC_RESOLUTION) {
88         transition->counter = BLE_MESH_DEVICE_SPECIFIC_RESOLUTION;
89     }
90 }
91 
transition_time_values(struct bt_mesh_state_transition * transition,uint8_t trans_time,uint8_t delay)92 static void transition_time_values(struct bt_mesh_state_transition *transition,
93                                    uint8_t trans_time, uint8_t delay)
94 {
95     transition->trans_time = trans_time;
96     transition->delay = delay;
97 
98     if (trans_time == 0U) {
99         return;
100     }
101 
102     tt_values_calculator(transition);
103     transition->quo_tt = transition->total_duration / transition->counter;
104 }
105 
transition_timer_start(struct bt_mesh_state_transition * transition)106 static void transition_timer_start(struct bt_mesh_state_transition *transition)
107 {
108     transition->start_timestamp = k_uptime_get();
109     k_delayed_work_submit_periodic(&transition->timer, K_MSEC(transition->quo_tt));
110     bt_mesh_atomic_set_bit(transition->flag, BLE_MESH_TRANS_TIMER_START);
111 }
112 
transition_timer_stop(struct bt_mesh_state_transition * transition)113 static void transition_timer_stop(struct bt_mesh_state_transition *transition)
114 {
115     k_delayed_work_cancel(&transition->timer);
116     bt_mesh_atomic_clear_bit(transition->flag, BLE_MESH_TRANS_TIMER_START);
117 }
118 
119 #if CONFIG_BLE_MESH_GENERIC_SERVER
generic_onoff_tt_values(struct bt_mesh_gen_onoff_srv * srv,uint8_t trans_time,uint8_t delay)120 void generic_onoff_tt_values(struct bt_mesh_gen_onoff_srv *srv,
121                              uint8_t trans_time, uint8_t delay)
122 {
123     return transition_time_values(&srv->transition, trans_time, delay);
124 }
125 
generic_level_tt_values(struct bt_mesh_gen_level_srv * srv,uint8_t trans_time,uint8_t delay)126 void generic_level_tt_values(struct bt_mesh_gen_level_srv *srv,
127                              uint8_t trans_time, uint8_t delay)
128 {
129     transition_time_values(&srv->transition, trans_time, delay);
130     srv->tt_delta_level =
131         ((float) (srv->state.level - srv->state.target_level) / srv->transition.counter);
132 }
133 
generic_power_level_tt_values(struct bt_mesh_gen_power_level_srv * srv,uint8_t trans_time,uint8_t delay)134 void generic_power_level_tt_values(struct bt_mesh_gen_power_level_srv *srv,
135                                    uint8_t trans_time, uint8_t delay)
136 {
137     transition_time_values(&srv->transition, trans_time, delay);
138     srv->tt_delta_level =
139         ((float) (srv->state->power_actual - srv->state->target_power_actual) / srv->transition.counter);
140 }
141 #endif /* CONFIG_BLE_MESH_GENERIC_SERVER */
142 
143 #if CONFIG_BLE_MESH_LIGHTING_SERVER
light_lightness_actual_tt_values(struct bt_mesh_light_lightness_srv * srv,uint8_t trans_time,uint8_t delay)144 void light_lightness_actual_tt_values(struct bt_mesh_light_lightness_srv *srv,
145                                       uint8_t trans_time, uint8_t delay)
146 {
147     transition_time_values(&srv->actual_transition, trans_time, delay);
148     srv->tt_delta_lightness_actual =
149         ((float) (srv->state->lightness_actual - srv->state->target_lightness_actual) / srv->actual_transition.counter);
150 }
151 
light_lightness_linear_tt_values(struct bt_mesh_light_lightness_srv * srv,uint8_t trans_time,uint8_t delay)152 void light_lightness_linear_tt_values(struct bt_mesh_light_lightness_srv *srv,
153                                       uint8_t trans_time, uint8_t delay)
154 {
155     transition_time_values(&srv->linear_transition, trans_time, delay);
156     srv->tt_delta_lightness_linear =
157         ((float) (srv->state->lightness_linear - srv->state->target_lightness_linear) / srv->linear_transition.counter);
158 }
159 
light_ctl_tt_values(struct bt_mesh_light_ctl_srv * srv,uint8_t trans_time,uint8_t delay)160 void light_ctl_tt_values(struct bt_mesh_light_ctl_srv *srv,
161                          uint8_t trans_time, uint8_t delay)
162 {
163     transition_time_values(&srv->transition, trans_time, delay);
164     srv->tt_delta_lightness =
165         ((float) (srv->state->lightness - srv->state->target_lightness) / srv->transition.counter);
166     srv->tt_delta_temperature =
167         ((float) (srv->state->temperature - srv->state->target_temperature) / srv->transition.counter);
168     srv->tt_delta_delta_uv =
169         ((float) (srv->state->delta_uv - srv->state->target_delta_uv) / srv->transition.counter);
170 }
171 
light_ctl_temp_tt_values(struct bt_mesh_light_ctl_temp_srv * srv,uint8_t trans_time,uint8_t delay)172 void light_ctl_temp_tt_values(struct bt_mesh_light_ctl_temp_srv *srv,
173                               uint8_t trans_time, uint8_t delay)
174 {
175     transition_time_values(&srv->transition, trans_time, delay);
176     srv->tt_delta_temperature =
177         ((float) (srv->state->temperature - srv->state->target_temperature) / srv->transition.counter);
178     srv->tt_delta_delta_uv =
179         ((float) (srv->state->delta_uv - srv->state->target_delta_uv) / srv->transition.counter);
180 }
181 
light_hsl_tt_values(struct bt_mesh_light_hsl_srv * srv,uint8_t trans_time,uint8_t delay)182 void light_hsl_tt_values(struct bt_mesh_light_hsl_srv *srv,
183                          uint8_t trans_time, uint8_t delay)
184 {
185     transition_time_values(&srv->transition, trans_time, delay);
186     srv->tt_delta_lightness =
187         ((float) (srv->state->lightness - srv->state->target_lightness) / srv->transition.counter);
188     srv->tt_delta_hue =
189         ((float) (srv->state->hue - srv->state->target_hue) / srv->transition.counter);
190     srv->tt_delta_saturation =
191         ((float) (srv->state->saturation - srv->state->target_saturation) / srv->transition.counter);
192 }
193 
light_hsl_hue_tt_values(struct bt_mesh_light_hsl_hue_srv * srv,uint8_t trans_time,uint8_t delay)194 void light_hsl_hue_tt_values(struct bt_mesh_light_hsl_hue_srv *srv,
195                              uint8_t trans_time, uint8_t delay)
196 {
197     transition_time_values(&srv->transition, trans_time, delay);
198     srv->tt_delta_hue =
199         ((float) (srv->state->hue - srv->state->target_hue) / srv->transition.counter);
200 }
201 
light_hsl_sat_tt_values(struct bt_mesh_light_hsl_sat_srv * srv,uint8_t trans_time,uint8_t delay)202 void light_hsl_sat_tt_values(struct bt_mesh_light_hsl_sat_srv *srv,
203                              uint8_t trans_time, uint8_t delay)
204 {
205     transition_time_values(&srv->transition, trans_time, delay);
206     srv->tt_delta_saturation =
207         ((float) (srv->state->saturation - srv->state->target_saturation) / srv->transition.counter);
208 }
209 
light_xyl_tt_values(struct bt_mesh_light_xyl_srv * srv,uint8_t trans_time,uint8_t delay)210 void light_xyl_tt_values(struct bt_mesh_light_xyl_srv *srv,
211                          uint8_t trans_time, uint8_t delay)
212 {
213     transition_time_values(&srv->transition, trans_time, delay);
214     srv->tt_delta_lightness =
215         ((float) (srv->state->lightness - srv->state->target_lightness) / srv->transition.counter);
216     srv->tt_delta_x =
217         ((float) (srv->state->x - srv->state->target_x) / srv->transition.counter);
218     srv->tt_delta_y =
219         ((float) (srv->state->y - srv->state->target_y) / srv->transition.counter);
220 }
221 
light_lc_tt_values(struct bt_mesh_light_lc_srv * srv,uint8_t trans_time,uint8_t delay)222 void light_lc_tt_values(struct bt_mesh_light_lc_srv *srv,
223                         uint8_t trans_time, uint8_t delay)
224 {
225     transition_time_values(&srv->transition, trans_time, delay);
226 }
227 #endif /* CONFIG_BLE_MESH_LIGHTING_SERVER */
228 
229 #if CONFIG_BLE_MESH_TIME_SCENE_SERVER
scene_tt_values(struct bt_mesh_scene_srv * srv,uint8_t trans_time,uint8_t delay)230 void scene_tt_values(struct bt_mesh_scene_srv *srv, uint8_t trans_time, uint8_t delay)
231 {
232     transition_time_values(&srv->transition, trans_time, delay);
233 }
234 #endif /* CONFIG_BLE_MESH_TIME_SCENE_SERVER */
235 
236 /* Timers related handlers & threads (Start) */
237 
238 #if CONFIG_BLE_MESH_GENERIC_SERVER
generic_onoff_work_handler(struct k_work * work)239 void generic_onoff_work_handler(struct k_work *work)
240 {
241     struct bt_mesh_gen_onoff_srv *srv =
242         CONTAINER_OF(work, struct bt_mesh_gen_onoff_srv, transition.timer.work);
243     struct bt_mesh_msg_ctx *ctx = NULL;
244     bt_mesh_gen_server_state_change_t change = {0};
245 
246     if (srv == NULL || srv->transition.timer.work._reserved == NULL) {
247         BT_ERR("%s, Invalid parameter", __func__);
248         return;
249     }
250 
251     bt_mesh_generic_server_lock();
252 
253     ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
254 
255     if (srv->transition.just_started) {
256         srv->transition.just_started = false;
257         if (srv->transition.counter == 0U) {
258             change.gen_onoff_set.onoff = srv->state.onoff;
259             bt_mesh_generic_server_cb_evt_to_btc(
260                 BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
261             bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
262         } else {
263             /**
264              * Because binary states cannot support transitions, when changing to
265              * 0x01 (On), the Generic OnOff state shall change immediately when
266              * the transition starts, and when changing to 0x00, the state shall
267              * change when the transition finishes.
268              */
269             if (srv->state.target_onoff == BLE_MESH_STATE_ON) {
270                 srv->state.onoff = BLE_MESH_STATE_ON;
271                 change.gen_onoff_set.onoff = srv->state.onoff;
272                 bt_mesh_generic_server_cb_evt_to_btc(
273                     BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
274             }
275             transition_timer_start(&srv->transition);
276         }
277 
278         bt_mesh_generic_server_unlock();
279         return;
280     }
281 
282     if (srv->transition.counter != 0U) {
283         srv->transition.counter--;
284     }
285 
286     if (srv->transition.counter == 0U) {
287         transition_timer_stop(&srv->transition);
288         srv->state.onoff = srv->state.target_onoff;
289         if (srv->state.target_onoff != BLE_MESH_STATE_ON) {
290             change.gen_onoff_set.onoff = srv->state.onoff;
291             bt_mesh_generic_server_cb_evt_to_btc(
292                 BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
293         }
294     }
295 
296     gen_onoff_publish(srv->model);
297 
298     bt_mesh_generic_server_unlock();
299     return;
300 }
301 
generic_level_work_handler(struct k_work * work)302 void generic_level_work_handler(struct k_work *work)
303 {
304     struct bt_mesh_gen_level_srv *srv =
305         CONTAINER_OF(work, struct bt_mesh_gen_level_srv, transition.timer.work);
306     struct bt_mesh_msg_ctx *ctx = NULL;
307     bt_mesh_gen_server_state_change_t change = {0};
308 
309     if (srv == NULL || srv->transition.timer.work._reserved == NULL) {
310         BT_ERR("%s, Invalid parameter", __func__);
311         return;
312     }
313 
314     bt_mesh_generic_server_lock();
315 
316     ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
317 
318     if (srv->transition.just_started) {
319         srv->transition.just_started = false;
320         if (srv->transition.counter == 0U) {
321             switch (ctx->recv_op) {
322             case BLE_MESH_MODEL_OP_GEN_LEVEL_SET:
323             case BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK:
324                 change.gen_level_set.level = srv->state.level;
325                 break;
326             case BLE_MESH_MODEL_OP_GEN_DELTA_SET:
327             case BLE_MESH_MODEL_OP_GEN_DELTA_SET_UNACK:
328                 change.gen_delta_set.level = srv->state.level;
329                 break;
330             case BLE_MESH_MODEL_OP_GEN_MOVE_SET:
331             case BLE_MESH_MODEL_OP_GEN_MOVE_SET_UNACK:
332                 change.gen_move_set.level = srv->state.level;
333                 break;
334             }
335             bt_mesh_generic_server_cb_evt_to_btc(
336                 BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
337             bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
338         } else {
339             transition_timer_start(&srv->transition);
340         }
341 
342         bt_mesh_generic_server_unlock();
343         return;
344     }
345 
346     if (srv->transition.counter != 0U) {
347         srv->transition.counter--;
348         srv->state.level -= srv->tt_delta_level;
349     }
350 
351     if (srv->transition.counter == 0U) {
352         transition_timer_stop(&srv->transition);
353         srv->state.level = srv->state.target_level;
354     }
355 
356     switch (ctx->recv_op) {
357     case BLE_MESH_MODEL_OP_GEN_LEVEL_SET:
358     case BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK:
359         change.gen_level_set.level = srv->state.level;
360         break;
361     case BLE_MESH_MODEL_OP_GEN_DELTA_SET:
362     case BLE_MESH_MODEL_OP_GEN_DELTA_SET_UNACK:
363         change.gen_delta_set.level = srv->state.level;
364         break;
365     case BLE_MESH_MODEL_OP_GEN_MOVE_SET:
366     case BLE_MESH_MODEL_OP_GEN_MOVE_SET_UNACK:
367         change.gen_move_set.level = srv->state.level;
368         break;
369     }
370     bt_mesh_generic_server_cb_evt_to_btc(
371         BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
372 
373     gen_level_publish(srv->model);
374 
375     bt_mesh_generic_server_unlock();
376     return;
377 }
378 
generic_power_level_work_handler(struct k_work * work)379 void generic_power_level_work_handler(struct k_work *work)
380 {
381     struct bt_mesh_gen_power_level_srv *srv =
382         CONTAINER_OF(work, struct bt_mesh_gen_power_level_srv, transition.timer.work);
383     struct bt_mesh_msg_ctx *ctx = NULL;
384     bt_mesh_gen_server_state_change_t change = {0};
385 
386     if (srv == NULL || srv->state == NULL ||
387             srv->transition.timer.work._reserved == NULL) {
388         BT_ERR("%s, Invalid parameter", __func__);
389         return;
390     }
391 
392     bt_mesh_generic_server_lock();
393 
394     ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
395 
396     if (srv->transition.just_started) {
397         srv->transition.just_started = false;
398         if (srv->transition.counter == 0U) {
399             change.gen_power_level_set.power = srv->state->power_actual;
400             bt_mesh_generic_server_cb_evt_to_btc(
401                 BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
402             bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
403         } else {
404             transition_timer_start(&srv->transition);
405         }
406 
407         bt_mesh_generic_server_unlock();
408         return;
409     }
410 
411     if (srv->transition.counter != 0U) {
412         srv->transition.counter--;
413         srv->state->power_actual -= srv->tt_delta_level;
414     }
415 
416     if (srv->transition.counter == 0U) {
417         transition_timer_stop(&srv->transition);
418 
419         srv->state->power_actual = srv->state->target_power_actual;
420         /**
421          * Whenever the Generic Power Actual state is changed to a non-zero value
422          * as a result of a non-transactional message or a completed sequence of
423          * transactional messages, the value of the Generic Power Last state shall
424          * be set to the value of the Generic Power Actual state.
425          */
426         if (srv->state->power_actual) {
427             srv->state->power_last = srv->state->power_actual;
428         }
429     }
430 
431     change.gen_power_level_set.power = srv->state->power_actual;
432     bt_mesh_generic_server_cb_evt_to_btc(
433         BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
434 
435     gen_power_level_publish(srv->model, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS);
436 
437     bt_mesh_generic_server_unlock();
438     return;
439 }
440 #endif /* CONFIG_BLE_MESH_GENERIC_SERVER */
441 
442 #if CONFIG_BLE_MESH_LIGHTING_SERVER
light_lightness_actual_work_handler(struct k_work * work)443 void light_lightness_actual_work_handler(struct k_work *work)
444 {
445     struct bt_mesh_light_lightness_srv *srv =
446         CONTAINER_OF(work, struct bt_mesh_light_lightness_srv, actual_transition.timer.work);
447     struct bt_mesh_msg_ctx *ctx = NULL;
448     bt_mesh_light_server_state_change_t change = {0};
449 
450     if (srv == NULL || srv->state == NULL ||
451             srv->actual_transition.timer.work._reserved == NULL) {
452         BT_ERR("%s, Invalid parameter", __func__);
453         return;
454     }
455 
456     bt_mesh_light_server_lock();
457 
458     ctx = (struct bt_mesh_msg_ctx *)srv->actual_transition.timer.work._reserved;
459 
460     if (srv->actual_transition.just_started) {
461         srv->actual_transition.just_started = false;
462         if (srv->actual_transition.counter == 0U) {
463             change.lightness_set.lightness = srv->state->lightness_actual;
464             bt_mesh_lighting_server_cb_evt_to_btc(
465                 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
466             bt_mesh_atomic_clear_bit(srv->actual_transition.flag, BLE_MESH_TRANS_TIMER_START);
467         } else {
468             transition_timer_start(&srv->actual_transition);
469         }
470 
471         bt_mesh_light_server_unlock();
472         return;
473     }
474 
475     if (srv->actual_transition.counter != 0U) {
476         srv->actual_transition.counter--;
477         srv->state->lightness_actual -= srv->tt_delta_lightness_actual;
478     }
479 
480     if (srv->actual_transition.counter == 0U) {
481         transition_timer_stop(&srv->actual_transition);
482 
483         srv->state->lightness_actual = srv->state->target_lightness_actual;
484         /**
485          * Whenever the Light Lightness Actual state is changed with a non-
486          * transactional message or a completed sequence of transactional
487          * messages to a non-zero value, the value of the Light Lightness
488          * Last shall be set to the value of the Light Lightness Actual.
489          */
490         if (srv->state->lightness_actual) {
491             srv->state->lightness_last = srv->state->lightness_actual;
492         }
493     }
494 
495     change.lightness_set.lightness = srv->state->lightness_actual;
496     bt_mesh_lighting_server_cb_evt_to_btc(
497         BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
498 
499     light_lightness_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS);
500 
501     bt_mesh_light_server_unlock();
502     return;
503 }
504 
light_lightness_linear_work_handler(struct k_work * work)505 void light_lightness_linear_work_handler(struct k_work *work)
506 {
507     struct bt_mesh_light_lightness_srv *srv =
508         CONTAINER_OF(work, struct bt_mesh_light_lightness_srv, linear_transition.timer.work);
509     struct bt_mesh_msg_ctx *ctx = NULL;
510     bt_mesh_light_server_state_change_t change = {0};
511 
512     if (srv == NULL || srv->state == NULL ||
513             srv->linear_transition.timer.work._reserved == NULL) {
514         BT_ERR("%s, Invalid parameter", __func__);
515         return;
516     }
517 
518     bt_mesh_light_server_lock();
519 
520     ctx = (struct bt_mesh_msg_ctx *)srv->linear_transition.timer.work._reserved;
521 
522     if (srv->linear_transition.just_started) {
523         srv->linear_transition.just_started = false;
524         if (srv->linear_transition.counter == 0U) {
525             change.lightness_linear_set.lightness = srv->state->lightness_linear;
526             bt_mesh_lighting_server_cb_evt_to_btc(
527                 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
528             bt_mesh_atomic_clear_bit(srv->linear_transition.flag, BLE_MESH_TRANS_TIMER_START);
529         } else {
530             transition_timer_start(&srv->linear_transition);
531         }
532 
533         bt_mesh_light_server_unlock();
534         return;
535     }
536 
537     if (srv->linear_transition.counter != 0U) {
538         srv->linear_transition.counter--;
539         srv->state->lightness_linear -= srv->tt_delta_lightness_linear;
540     }
541 
542     if (srv->linear_transition.counter == 0U) {
543         transition_timer_stop(&srv->linear_transition);
544         srv->state->lightness_linear = srv->state->target_lightness_linear;
545     }
546 
547     change.lightness_linear_set.lightness = srv->state->lightness_linear;
548     bt_mesh_lighting_server_cb_evt_to_btc(
549         BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
550 
551     light_lightness_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS);
552 
553     bt_mesh_light_server_unlock();
554     return;
555 }
556 
light_ctl_work_handler(struct k_work * work)557 void light_ctl_work_handler(struct k_work *work)
558 {
559     struct bt_mesh_light_ctl_srv *srv =
560         CONTAINER_OF(work, struct bt_mesh_light_ctl_srv, transition.timer.work);
561     struct bt_mesh_msg_ctx *ctx = NULL;
562     bt_mesh_light_server_state_change_t change = {0};
563 
564     if (srv == NULL || srv->state == NULL ||
565             srv->transition.timer.work._reserved == NULL) {
566         BT_ERR("%s, Invalid parameter", __func__);
567         return;
568     }
569 
570     bt_mesh_light_server_lock();
571 
572     ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
573 
574     if (srv->transition.just_started) {
575         srv->transition.just_started = false;
576         if (srv->transition.counter == 0U) {
577             change.ctl_set.lightness = srv->state->lightness;
578             change.ctl_set.temperature = srv->state->temperature;
579             change.ctl_set.delta_uv = srv->state->delta_uv;
580             bt_mesh_lighting_server_cb_evt_to_btc(
581                 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
582             bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
583         } else {
584             transition_timer_start(&srv->transition);
585         }
586 
587         bt_mesh_light_server_unlock();
588         return;
589     }
590 
591     if (srv->transition.counter != 0U) {
592         srv->transition.counter--;
593         srv->state->lightness -= srv->tt_delta_lightness;
594         srv->state->temperature -= srv->tt_delta_temperature;
595         srv->state->delta_uv -= srv->tt_delta_delta_uv;
596     }
597 
598     if (srv->transition.counter == 0U) {
599         transition_timer_stop(&srv->transition);
600         srv->state->lightness = srv->state->target_lightness;
601         srv->state->temperature = srv->state->target_temperature;
602         srv->state->delta_uv = srv->state->target_delta_uv;
603     }
604 
605     change.ctl_set.lightness = srv->state->lightness;
606     change.ctl_set.temperature = srv->state->temperature;
607     change.ctl_set.delta_uv = srv->state->delta_uv;
608     bt_mesh_lighting_server_cb_evt_to_btc(
609         BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
610 
611     light_ctl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS);
612 
613     bt_mesh_light_server_unlock();
614     return;
615 }
616 
light_ctl_temp_work_handler(struct k_work * work)617 void light_ctl_temp_work_handler(struct k_work *work)
618 {
619     struct bt_mesh_light_ctl_temp_srv *srv =
620         CONTAINER_OF(work, struct bt_mesh_light_ctl_temp_srv, transition.timer.work);
621     struct bt_mesh_msg_ctx *ctx = NULL;
622     bt_mesh_light_server_state_change_t change = {0};
623 
624     if (srv == NULL || srv->state == NULL ||
625             srv->transition.timer.work._reserved == NULL) {
626         BT_ERR("%s, Invalid parameter", __func__);
627         return;
628     }
629 
630     bt_mesh_light_server_lock();
631 
632     ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
633 
634     if (srv->transition.just_started) {
635         srv->transition.just_started = false;
636         if (srv->transition.counter == 0U) {
637             change.ctl_temp_set.temperature = srv->state->temperature;
638             change.ctl_temp_set.delta_uv = srv->state->delta_uv;
639             bt_mesh_lighting_server_cb_evt_to_btc(
640                 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
641             bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
642         } else {
643             transition_timer_start(&srv->transition);
644         }
645 
646         bt_mesh_light_server_unlock();
647         return;
648     }
649 
650     if (srv->transition.counter != 0U) {
651         srv->transition.counter--;
652         srv->state->temperature -= srv->tt_delta_temperature;
653         srv->state->delta_uv -= srv->tt_delta_delta_uv;
654     }
655 
656     if (srv->transition.counter == 0U) {
657         transition_timer_stop(&srv->transition);
658         srv->state->temperature = srv->state->target_temperature;
659         srv->state->delta_uv = srv->state->target_delta_uv;
660     }
661 
662     change.ctl_temp_set.temperature = srv->state->temperature;
663     change.ctl_temp_set.delta_uv = srv->state->delta_uv;
664     bt_mesh_lighting_server_cb_evt_to_btc(
665         BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
666 
667     light_ctl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS);
668 
669     bt_mesh_light_server_unlock();
670     return;
671 }
672 
light_hsl_work_handler(struct k_work * work)673 void light_hsl_work_handler(struct k_work *work)
674 {
675     struct bt_mesh_light_hsl_srv *srv =
676         CONTAINER_OF(work, struct bt_mesh_light_hsl_srv, transition.timer.work);
677     struct bt_mesh_msg_ctx *ctx = NULL;
678     bt_mesh_light_server_state_change_t change = {0};
679 
680     if (srv == NULL || srv->state == NULL ||
681             srv->transition.timer.work._reserved == NULL) {
682         BT_ERR("%s, Invalid parameter", __func__);
683         return;
684     }
685 
686     bt_mesh_light_server_lock();
687 
688     ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
689 
690     if (srv->transition.just_started) {
691         srv->transition.just_started = false;
692         if (srv->transition.counter == 0U) {
693             change.hsl_set.lightness = srv->state->lightness;
694             change.hsl_set.hue = srv->state->hue;
695             change.hsl_set.saturation = srv->state->saturation;
696             bt_mesh_lighting_server_cb_evt_to_btc(
697                 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
698             bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
699         } else {
700             transition_timer_start(&srv->transition);
701         }
702 
703         bt_mesh_light_server_unlock();
704         return;
705     }
706 
707     if (srv->transition.counter != 0U) {
708         srv->transition.counter--;
709         srv->state->lightness -= srv->tt_delta_lightness;
710         srv->state->hue -= srv->tt_delta_hue;
711         srv->state->saturation -= srv->tt_delta_saturation;
712     }
713 
714     if (srv->transition.counter == 0U) {
715         transition_timer_stop(&srv->transition);
716         srv->state->lightness = srv->state->target_lightness;
717         srv->state->hue = srv->state->target_hue;
718         srv->state->saturation = srv->state->target_saturation;
719     }
720 
721     change.hsl_set.lightness = srv->state->lightness;
722     change.hsl_set.hue = srv->state->hue;
723     change.hsl_set.saturation = srv->state->saturation;
724     bt_mesh_lighting_server_cb_evt_to_btc(
725         BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
726 
727     light_hsl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS);
728 
729     bt_mesh_light_server_unlock();
730     return;
731 }
732 
light_hsl_hue_work_handler(struct k_work * work)733 void light_hsl_hue_work_handler(struct k_work *work)
734 {
735     struct bt_mesh_light_hsl_hue_srv *srv =
736         CONTAINER_OF(work, struct bt_mesh_light_hsl_hue_srv, transition.timer.work);
737     struct bt_mesh_msg_ctx *ctx = NULL;
738     bt_mesh_light_server_state_change_t change = {0};
739 
740     if (srv == NULL || srv->state == NULL ||
741             srv->transition.timer.work._reserved == NULL) {
742         BT_ERR("%s, Invalid parameter", __func__);
743         return;
744     }
745 
746     bt_mesh_light_server_lock();
747 
748     ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
749 
750     if (srv->transition.just_started) {
751         srv->transition.just_started = false;
752         if (srv->transition.counter == 0U) {
753             change.hsl_hue_set.hue = srv->state->hue;
754             bt_mesh_lighting_server_cb_evt_to_btc(
755                 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
756             bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
757         } else {
758             transition_timer_start(&srv->transition);
759         }
760 
761         bt_mesh_light_server_unlock();
762         return;
763     }
764 
765     if (srv->transition.counter != 0U) {
766         srv->transition.counter--;
767         srv->state->hue -= srv->tt_delta_hue;
768     }
769 
770     if (srv->transition.counter == 0U) {
771         transition_timer_stop(&srv->transition);
772         srv->state->hue = srv->state->target_hue;
773     }
774 
775     change.hsl_hue_set.hue = srv->state->hue;
776     bt_mesh_lighting_server_cb_evt_to_btc(
777         BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
778 
779     light_hsl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS);
780 
781     bt_mesh_light_server_unlock();
782     return;
783 }
784 
light_hsl_sat_work_handler(struct k_work * work)785 void light_hsl_sat_work_handler(struct k_work *work)
786 {
787     struct bt_mesh_light_hsl_sat_srv *srv =
788         CONTAINER_OF(work, struct bt_mesh_light_hsl_sat_srv, transition.timer.work);
789     struct bt_mesh_msg_ctx *ctx = NULL;
790     bt_mesh_light_server_state_change_t change = {0};
791 
792     if (srv == NULL || srv->state == NULL ||
793             srv->transition.timer.work._reserved == NULL) {
794         BT_ERR("%s, Invalid parameter", __func__);
795         return;
796     }
797 
798     bt_mesh_light_server_lock();
799 
800     ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
801 
802     if (srv->transition.just_started) {
803         srv->transition.just_started = false;
804         if (srv->transition.counter == 0U) {
805             change.hsl_saturation_set.saturation = srv->state->saturation;
806             bt_mesh_lighting_server_cb_evt_to_btc(
807                 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
808             bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
809         } else {
810             transition_timer_start(&srv->transition);
811         }
812 
813         bt_mesh_light_server_unlock();
814         return;
815     }
816 
817     if (srv->transition.counter != 0U) {
818         srv->transition.counter--;
819         srv->state->saturation -= srv->tt_delta_saturation;
820     }
821 
822     if (srv->transition.counter == 0U) {
823         transition_timer_stop(&srv->transition);
824         srv->state->saturation = srv->state->target_saturation;
825     }
826 
827     change.hsl_saturation_set.saturation = srv->state->saturation;
828     bt_mesh_lighting_server_cb_evt_to_btc(
829         BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
830 
831     light_hsl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS);
832 
833     bt_mesh_light_server_unlock();
834     return;
835 }
836 
light_xyl_work_handler(struct k_work * work)837 void light_xyl_work_handler(struct k_work *work)
838 {
839     struct bt_mesh_light_xyl_srv *srv =
840         CONTAINER_OF(work, struct bt_mesh_light_xyl_srv, transition.timer.work);
841     struct bt_mesh_msg_ctx *ctx = NULL;
842     bt_mesh_light_server_state_change_t change = {0};
843 
844     if (srv == NULL || srv->state == NULL ||
845             srv->transition.timer.work._reserved == NULL) {
846         BT_ERR("%s, Invalid parameter", __func__);
847         return;
848     }
849 
850     bt_mesh_light_server_lock();
851 
852     ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
853 
854     if (srv->transition.just_started) {
855         srv->transition.just_started = false;
856         if (srv->transition.counter == 0U) {
857             change.xyl_set.lightness = srv->state->lightness;
858             change.xyl_set.x = srv->state->x;
859             change.xyl_set.y = srv->state->y;
860             bt_mesh_lighting_server_cb_evt_to_btc(
861                 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
862             bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
863         } else {
864             transition_timer_start(&srv->transition);
865         }
866 
867         bt_mesh_light_server_unlock();
868         return;
869     }
870 
871     if (srv->transition.counter != 0U) {
872         srv->transition.counter--;
873         srv->state->lightness -= srv->tt_delta_lightness;
874         srv->state->x -= srv->tt_delta_x;
875         srv->state->y -= srv->tt_delta_y;
876     }
877 
878     if (srv->transition.counter == 0U) {
879         transition_timer_stop(&srv->transition);
880         srv->state->lightness = srv->state->target_lightness;
881         srv->state->x = srv->state->target_x;
882         srv->state->y = srv->state->target_y;
883     }
884 
885     change.xyl_set.lightness = srv->state->lightness;
886     change.xyl_set.x = srv->state->x;
887     change.xyl_set.y = srv->state->y;
888     bt_mesh_lighting_server_cb_evt_to_btc(
889         BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
890 
891     light_xyl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS);
892 
893     bt_mesh_light_server_unlock();
894     return;
895 }
896 
light_lc_work_handler(struct k_work * work)897 void light_lc_work_handler(struct k_work *work)
898 {
899     struct bt_mesh_light_lc_srv *srv =
900         CONTAINER_OF(work, struct bt_mesh_light_lc_srv, transition.timer.work);
901     struct bt_mesh_msg_ctx *ctx = NULL;
902     bt_mesh_light_server_state_change_t change = {0};
903 
904     if (srv == NULL || srv->transition.timer.work._reserved == NULL) {
905         BT_ERR("%s, Invalid parameter", __func__);
906         return;
907     }
908 
909     bt_mesh_light_server_lock();
910 
911     ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
912 
913     if (srv->transition.just_started) {
914         srv->transition.just_started = false;
915         if (srv->transition.counter == 0U) {
916             change.lc_light_onoff_set.onoff = srv->lc->state.light_onoff;
917             bt_mesh_lighting_server_cb_evt_to_btc(
918                 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
919             bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
920         } else {
921             /**
922              * Because binary states cannot support transitions, when changing to
923              * 0x01 (On), the Generic OnOff state shall change immediately when
924              * the transition starts, and when changing to 0x00, the state shall
925              * change when the transition finishes.
926              */
927             if (srv->lc->state.target_light_onoff == BLE_MESH_STATE_ON) {
928                 srv->lc->state.light_onoff = BLE_MESH_STATE_ON;
929                 bt_mesh_light_server_state_change_t change = {
930                     .lc_light_onoff_set.onoff = srv->lc->state.light_onoff,
931                 };
932                 bt_mesh_lighting_server_cb_evt_to_btc(
933                     BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
934             }
935             transition_timer_start(&srv->transition);
936         }
937 
938         bt_mesh_light_server_unlock();
939         return;
940     }
941 
942     if (srv->transition.counter != 0U) {
943         srv->transition.counter--;
944     }
945 
946     if (srv->transition.counter == 0U) {
947         transition_timer_stop(&srv->transition);
948         srv->lc->state.light_onoff = srv->lc->state.target_light_onoff;
949         if (srv->lc->state.light_onoff != BLE_MESH_STATE_ON) {
950             change.lc_light_onoff_set.onoff = srv->lc->state.light_onoff;
951             bt_mesh_lighting_server_cb_evt_to_btc(
952                 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
953         }
954     }
955 
956     light_lc_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS);
957 
958     bt_mesh_light_server_unlock();
959     return;
960 }
961 #endif /* CONFIG_BLE_MESH_LIGHTING_SERVER */
962 
963 #if CONFIG_BLE_MESH_TIME_SCENE_SERVER
scene_recall_work_handler(struct k_work * work)964 void scene_recall_work_handler(struct k_work *work)
965 {
966     struct bt_mesh_scene_srv *srv =
967         CONTAINER_OF(work, struct bt_mesh_scene_srv, transition.timer.work);
968     struct bt_mesh_msg_ctx *ctx = NULL;
969     bt_mesh_time_scene_server_state_change_t change = {0};
970 
971     if (srv == NULL || srv->state == NULL ||
972             srv->transition.timer.work._reserved == NULL) {
973         BT_ERR("%s, Invalid parameter", __func__);
974         return;
975     }
976 
977     bt_mesh_time_scene_server_lock();
978 
979     ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
980 
981     if (srv->transition.just_started) {
982         srv->transition.just_started = false;
983         if (srv->transition.counter == 0U) {
984             change.scene_recall.scene_number = srv->state->current_scene;
985             bt_mesh_time_scene_server_cb_evt_to_btc(
986                 BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
987             bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
988         } else {
989             transition_timer_start(&srv->transition);
990         }
991 
992         bt_mesh_time_scene_server_unlock();
993         return;
994     }
995 
996     if (srv->transition.counter != 0U) {
997         srv->transition.counter--;
998     }
999 
1000     if (srv->transition.counter == 0U) {
1001         transition_timer_stop(&srv->transition);
1002         srv->state->current_scene = srv->state->target_scene;
1003         srv->state->in_progress = false;
1004         srv->state->target_scene = INVALID_SCENE_NUMBER;
1005     }
1006 
1007     change.scene_recall.scene_number = srv->state->current_scene;
1008     bt_mesh_time_scene_server_cb_evt_to_btc(
1009         BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, srv->model, ctx, (const uint8_t *)&change, sizeof(change));
1010 
1011     scene_publish(srv->model, ctx, BLE_MESH_MODEL_OP_SCENE_STATUS);
1012 
1013     bt_mesh_time_scene_server_unlock();
1014     return;
1015 }
1016 #endif /* CONFIG_BLE_MESH_TIME_SCENE_SERVER */
1017 
1018 /* Timers related handlers & threads (End) */
1019 
bt_mesh_server_stop_transition(struct bt_mesh_state_transition * transition)1020 void bt_mesh_server_stop_transition(struct bt_mesh_state_transition *transition)
1021 {
1022     memset(transition, 0x0, offsetof(struct bt_mesh_state_transition, flag));
1023     if (bt_mesh_atomic_test_and_clear_bit(transition->flag, BLE_MESH_TRANS_TIMER_START)) {
1024         k_delayed_work_cancel(&transition->timer);
1025     }
1026 }
1027 
bt_mesh_server_start_transition(struct bt_mesh_state_transition * transition)1028 void bt_mesh_server_start_transition(struct bt_mesh_state_transition *transition)
1029 {
1030     if (transition->delay) {
1031         k_delayed_work_submit(&transition->timer, K_MSEC(5 * transition->delay));
1032         bt_mesh_atomic_set_bit(transition->flag, BLE_MESH_TRANS_TIMER_START);
1033     } else {
1034         k_work_submit(&transition->timer.work);
1035     }
1036 }
1037 
1038 /* Messages handlers (End) */
1039 
1040 #endif /* (CONFIG_BLE_MESH_GENERIC_SERVER || \
1041            CONFIG_BLE_MESH_TIME_SCENE_SERVER || \
1042            CONFIG_BLE_MESH_LIGHTING_SERVER) */
1043