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