1 /* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
2 *
3 * Copyright (c) 2018 Vikrant More
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/drivers/gpio.h>
9
10 #include "ble_mesh.h"
11 #include "common.h"
12 #include "device_composition.h"
13 #include "state_binding.h"
14 #include "transition.h"
15 #include "storage.h"
16
17 static struct bt_mesh_health_srv health_srv = {
18 };
19
20 BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0);
21
22 /* Definitions of models publication context (Start) */
23 BT_MESH_MODEL_PUB_DEFINE(gen_onoff_srv_pub_root, NULL, 2 + 3);
24 BT_MESH_MODEL_PUB_DEFINE(gen_onoff_cli_pub_root, NULL, 2 + 4);
25
26 BT_MESH_MODEL_PUB_DEFINE(gen_level_srv_pub_root, NULL, 2 + 5);
27 BT_MESH_MODEL_PUB_DEFINE(gen_level_cli_pub_root, NULL, 2 + 7);
28
29 BT_MESH_MODEL_PUB_DEFINE(gen_def_trans_time_srv_pub, NULL, 2 + 1);
30 BT_MESH_MODEL_PUB_DEFINE(gen_def_trans_time_cli_pub, NULL, 2 + 1);
31
32 BT_MESH_MODEL_PUB_DEFINE(gen_power_onoff_srv_pub, NULL, 2 + 1);
33 BT_MESH_MODEL_PUB_DEFINE(gen_power_onoff_cli_pub, NULL, 2 + 1);
34
35 BT_MESH_MODEL_PUB_DEFINE(light_lightness_srv_pub, NULL, 2 + 5);
36 BT_MESH_MODEL_PUB_DEFINE(light_lightness_cli_pub, NULL, 2 + 5);
37
38 BT_MESH_MODEL_PUB_DEFINE(light_ctl_srv_pub, NULL, 2 + 9);
39 BT_MESH_MODEL_PUB_DEFINE(light_ctl_cli_pub, NULL, 2 + 9);
40
41 BT_MESH_MODEL_PUB_DEFINE(vnd_pub, NULL, 3 + 6);
42
43 BT_MESH_MODEL_PUB_DEFINE(gen_level_srv_pub_s0, NULL, 2 + 5);
44 BT_MESH_MODEL_PUB_DEFINE(gen_level_cli_pub_s0, NULL, 2 + 7);
45 /* Definitions of models publication context (End) */
46
47 struct lightness light;
48 struct temperature light_temp;
49 struct delta_uv duv;
50
51 struct light_ctl_state light_state = {
52 .light = &light,
53 .temp = &light_temp,
54 .duv = &duv,
55 .transition = &onoff_transition,
56 };
57
58 struct light_ctl_state *const ctl = &light_state;
59
60 /* Definitions of models user data (Start) */
61
62 struct vendor_state vnd_user_data;
63
64 /* Definitions of models user data (End) */
65
66 static const struct bt_mesh_elem elements[];
67
68 /* message handlers (Start) */
69
70 /* Generic OnOff Server message handlers */
gen_onoff_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)71 static int gen_onoff_get(const struct bt_mesh_model *model,
72 struct bt_mesh_msg_ctx *ctx,
73 struct net_buf_simple *buf)
74 {
75 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 3 + 4);
76
77 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_ONOFF_STATUS);
78 net_buf_simple_add_u8(msg, (uint8_t) get_current(ONOFF));
79
80 if (ctl->light->current == ctl->light->target) {
81 goto send;
82 }
83
84 if (ctl->transition->counter) {
85 calculate_rt(ctl->transition);
86 net_buf_simple_add_u8(msg, (uint8_t) get_target(ONOFF));
87 net_buf_simple_add_u8(msg, ctl->transition->rt);
88 }
89
90 send:
91 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
92 printk("Unable to send GEN_ONOFF_SRV Status response\n");
93 }
94
95 return 0;
96 }
97
gen_onoff_publish(const struct bt_mesh_model * model)98 void gen_onoff_publish(const struct bt_mesh_model *model)
99 {
100 int err;
101 struct net_buf_simple *msg = model->pub->msg;
102
103 if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
104 return;
105 }
106
107 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_ONOFF_STATUS);
108 net_buf_simple_add_u8(msg, (uint8_t) get_current(ONOFF));
109
110 if (ctl->transition->counter) {
111 calculate_rt(ctl->transition);
112 net_buf_simple_add_u8(msg, (uint8_t) get_target(ONOFF));
113 net_buf_simple_add_u8(msg, ctl->transition->rt);
114 }
115
116 err = bt_mesh_model_publish(model);
117 if (err) {
118 printk("bt_mesh_model_publish err %d\n", err);
119 }
120 }
121
gen_onoff_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)122 static int gen_onoff_set_unack(const struct bt_mesh_model *model,
123 struct bt_mesh_msg_ctx *ctx,
124 struct net_buf_simple *buf)
125 {
126 uint8_t tid, onoff, tt, delay;
127 int64_t now;
128
129 onoff = net_buf_simple_pull_u8(buf);
130 tid = net_buf_simple_pull_u8(buf);
131
132 if (onoff > STATE_ON) {
133 return 0;
134 }
135
136 now = k_uptime_get();
137 if (ctl->last_tid == tid &&
138 ctl->last_src_addr == ctx->addr &&
139 ctl->last_dst_addr == ctx->recv_dst &&
140 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
141 return 0;
142 }
143
144 switch (buf->len) {
145 case 0x00: /* No optional fields are available */
146 tt = ctl->tt;
147 delay = 0U;
148 break;
149 case 0x02: /* Optional fields are available */
150 tt = net_buf_simple_pull_u8(buf);
151 if ((tt & 0x3F) == 0x3F) {
152 return 0;
153 }
154
155 delay = net_buf_simple_pull_u8(buf);
156 break;
157 default:
158 return 0;
159 }
160
161 ctl->transition->counter = 0U;
162 k_timer_stop(&ctl->transition->timer);
163
164 ctl->last_tid = tid;
165 ctl->last_src_addr = ctx->addr;
166 ctl->last_dst_addr = ctx->recv_dst;
167 ctl->last_msg_timestamp = now;
168 ctl->transition->tt = tt;
169 ctl->transition->delay = delay;
170 ctl->transition->type = NON_MOVE;
171 set_target(ONOFF, &onoff);
172
173 if (ctl->light->target != ctl->light->current) {
174 set_transition_values(ONOFF);
175 } else {
176 return 0;
177 }
178
179 /* For Instantaneous Transition */
180 if (ctl->transition->counter == 0U) {
181 ctl->light->current = ctl->light->target;
182 }
183
184 ctl->transition->just_started = true;
185 gen_onoff_publish(model);
186 onoff_handler();
187
188 return 0;
189 }
190
gen_onoff_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)191 static int gen_onoff_set(const struct bt_mesh_model *model,
192 struct bt_mesh_msg_ctx *ctx,
193 struct net_buf_simple *buf)
194 {
195 uint8_t tid, onoff, tt, delay;
196 int64_t now;
197
198 onoff = net_buf_simple_pull_u8(buf);
199 tid = net_buf_simple_pull_u8(buf);
200
201 if (onoff > STATE_ON) {
202 return 0;
203 }
204
205 now = k_uptime_get();
206 if (ctl->last_tid == tid &&
207 ctl->last_src_addr == ctx->addr &&
208 ctl->last_dst_addr == ctx->recv_dst &&
209 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
210 (void)gen_onoff_get(model, ctx, buf);
211 return 0;
212 }
213
214 switch (buf->len) {
215 case 0x00: /* No optional fields are available */
216 tt = ctl->tt;
217 delay = 0U;
218 break;
219 case 0x02: /* Optional fields are available */
220 tt = net_buf_simple_pull_u8(buf);
221 if ((tt & 0x3F) == 0x3F) {
222 return 0;
223 }
224
225 delay = net_buf_simple_pull_u8(buf);
226 break;
227 default:
228 return 0;
229 }
230
231 ctl->transition->counter = 0U;
232 k_timer_stop(&ctl->transition->timer);
233
234 ctl->last_tid = tid;
235 ctl->last_src_addr = ctx->addr;
236 ctl->last_dst_addr = ctx->recv_dst;
237 ctl->last_msg_timestamp = now;
238 ctl->transition->tt = tt;
239 ctl->transition->delay = delay;
240 ctl->transition->type = NON_MOVE;
241 set_target(ONOFF, &onoff);
242
243 if (ctl->light->target != ctl->light->current) {
244 set_transition_values(ONOFF);
245 } else {
246 (void)gen_onoff_get(model, ctx, buf);
247 return 0;
248 }
249
250 /* For Instantaneous Transition */
251 if (ctl->transition->counter == 0U) {
252 ctl->light->current = ctl->light->target;
253 }
254
255 ctl->transition->just_started = true;
256 (void)gen_onoff_get(model, ctx, buf);
257 gen_onoff_publish(model);
258 onoff_handler();
259
260 return 0;
261 }
262
263 /* Generic OnOff Client message handlers */
gen_onoff_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)264 static int gen_onoff_status(const struct bt_mesh_model *model,
265 struct bt_mesh_msg_ctx *ctx,
266 struct net_buf_simple *buf)
267 {
268 printk("Acknowledgement from GEN_ONOFF_SRV\n");
269 printk("Present OnOff = %02x\n", net_buf_simple_pull_u8(buf));
270
271 if (buf->len == 2U) {
272 printk("Target OnOff = %02x\n", net_buf_simple_pull_u8(buf));
273 printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf));
274 }
275
276 return 0;
277 }
278
279 /* Generic Level (LIGHTNESS) Server message handlers */
gen_level_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)280 static int gen_level_get(const struct bt_mesh_model *model,
281 struct bt_mesh_msg_ctx *ctx,
282 struct net_buf_simple *buf)
283 {
284 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 5 + 4);
285
286 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_LEVEL_STATUS);
287 net_buf_simple_add_le16(msg, (int16_t) get_current(LEVEL_LIGHT));
288
289 if (ctl->light->current == ctl->light->target) {
290 goto send;
291 }
292
293 if (ctl->transition->counter) {
294 calculate_rt(ctl->transition);
295 net_buf_simple_add_le16(msg, (int16_t) get_target(LEVEL_LIGHT));
296 net_buf_simple_add_u8(msg, ctl->transition->rt);
297 }
298
299 send:
300 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
301 printk("Unable to send GEN_LEVEL_SRV Status response\n");
302 }
303
304 return 0;
305 }
306
gen_level_publish(const struct bt_mesh_model * model)307 void gen_level_publish(const struct bt_mesh_model *model)
308 {
309 int err;
310 struct net_buf_simple *msg = model->pub->msg;
311
312 if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
313 return;
314 }
315
316 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_LEVEL_STATUS);
317 net_buf_simple_add_le16(msg, (int16_t) get_current(LEVEL_LIGHT));
318
319 if (ctl->transition->counter) {
320 calculate_rt(ctl->transition);
321 net_buf_simple_add_le16(msg, (int16_t) get_target(LEVEL_LIGHT));
322 net_buf_simple_add_u8(msg, ctl->transition->rt);
323 }
324
325 err = bt_mesh_model_publish(model);
326 if (err) {
327 printk("bt_mesh_model_publish err %d\n", err);
328 }
329 }
330
gen_level_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)331 static int gen_level_set_unack(const struct bt_mesh_model *model,
332 struct bt_mesh_msg_ctx *ctx,
333 struct net_buf_simple *buf)
334 {
335 uint8_t tid, tt, delay;
336 int16_t level;
337 int64_t now;
338
339 level = (int16_t) net_buf_simple_pull_le16(buf);
340 tid = net_buf_simple_pull_u8(buf);
341
342 now = k_uptime_get();
343 if (ctl->last_tid == tid &&
344 ctl->last_src_addr == ctx->addr &&
345 ctl->last_dst_addr == ctx->recv_dst &&
346 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
347 return 0;
348 }
349
350 switch (buf->len) {
351 case 0x00: /* No optional fields are available */
352 tt = ctl->tt;
353 delay = 0U;
354 break;
355 case 0x02: /* Optional fields are available */
356 tt = net_buf_simple_pull_u8(buf);
357 if ((tt & 0x3F) == 0x3F) {
358 return 0;
359 }
360
361 delay = net_buf_simple_pull_u8(buf);
362 break;
363 default:
364 return 0;
365 }
366
367 ctl->transition->counter = 0U;
368 k_timer_stop(&ctl->transition->timer);
369
370 ctl->last_tid = tid;
371 ctl->last_src_addr = ctx->addr;
372 ctl->last_dst_addr = ctx->recv_dst;
373 ctl->last_msg_timestamp = now;
374 ctl->transition->tt = tt;
375 ctl->transition->delay = delay;
376 ctl->transition->type = NON_MOVE;
377 set_target(LEVEL_LIGHT, &level);
378
379 if (ctl->light->target != ctl->light->current) {
380 set_transition_values(LEVEL_LIGHT);
381 } else {
382 return 0;
383 }
384
385 /* For Instantaneous Transition */
386 if (ctl->transition->counter == 0U) {
387 ctl->light->current = ctl->light->target;
388 }
389
390 ctl->transition->just_started = true;
391 gen_level_publish(model);
392 level_lightness_handler();
393
394 return 0;
395 }
396
gen_level_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)397 static int gen_level_set(const struct bt_mesh_model *model,
398 struct bt_mesh_msg_ctx *ctx,
399 struct net_buf_simple *buf)
400 {
401 uint8_t tid, tt, delay;
402 int16_t level;
403 int64_t now;
404
405 level = (int16_t) net_buf_simple_pull_le16(buf);
406 tid = net_buf_simple_pull_u8(buf);
407
408 now = k_uptime_get();
409 if (ctl->last_tid == tid &&
410 ctl->last_src_addr == ctx->addr &&
411 ctl->last_dst_addr == ctx->recv_dst &&
412 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
413 (void)gen_level_get(model, ctx, buf);
414 return 0;
415 }
416
417 switch (buf->len) {
418 case 0x00: /* No optional fields are available */
419 tt = ctl->tt;
420 delay = 0U;
421 break;
422 case 0x02: /* Optional fields are available */
423 tt = net_buf_simple_pull_u8(buf);
424 if ((tt & 0x3F) == 0x3F) {
425 return 0;
426 }
427
428 delay = net_buf_simple_pull_u8(buf);
429 break;
430 default:
431 return 0;
432 }
433
434 ctl->transition->counter = 0U;
435 k_timer_stop(&ctl->transition->timer);
436
437 ctl->last_tid = tid;
438 ctl->last_src_addr = ctx->addr;
439 ctl->last_dst_addr = ctx->recv_dst;
440 ctl->last_msg_timestamp = now;
441 ctl->transition->tt = tt;
442 ctl->transition->delay = delay;
443 ctl->transition->type = NON_MOVE;
444 set_target(LEVEL_LIGHT, &level);
445
446 if (ctl->light->target != ctl->light->current) {
447 set_transition_values(LEVEL_LIGHT);
448 } else {
449 (void)gen_level_get(model, ctx, buf);
450 return 0;
451 }
452
453 /* For Instantaneous Transition */
454 if (ctl->transition->counter == 0U) {
455 ctl->light->current = ctl->light->target;
456 }
457
458 ctl->transition->just_started = true;
459 (void)gen_level_get(model, ctx, buf);
460 gen_level_publish(model);
461 level_lightness_handler();
462
463 return 0;
464 }
465
gen_delta_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)466 static int gen_delta_set_unack(const struct bt_mesh_model *model,
467 struct bt_mesh_msg_ctx *ctx,
468 struct net_buf_simple *buf)
469 {
470 uint8_t tid, tt, delay;
471 static int16_t last_level;
472 int32_t target, delta;
473 int64_t now;
474
475 delta = (int32_t) net_buf_simple_pull_le32(buf);
476 tid = net_buf_simple_pull_u8(buf);
477
478 now = k_uptime_get();
479 if (ctl->last_tid == tid &&
480 ctl->last_src_addr == ctx->addr &&
481 ctl->last_dst_addr == ctx->recv_dst &&
482 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
483
484 if (ctl->light->delta == delta) {
485 return 0;
486 }
487 target = last_level + delta;
488
489 } else {
490 last_level = (int16_t) get_current(LEVEL_LIGHT);
491 target = last_level + delta;
492 }
493
494 switch (buf->len) {
495 case 0x00: /* No optional fields are available */
496 tt = ctl->tt;
497 delay = 0U;
498 break;
499 case 0x02: /* Optional fields are available */
500 tt = net_buf_simple_pull_u8(buf);
501 if ((tt & 0x3F) == 0x3F) {
502 return 0;
503 }
504
505 delay = net_buf_simple_pull_u8(buf);
506 break;
507 default:
508 return 0;
509 }
510
511 ctl->transition->counter = 0U;
512 k_timer_stop(&ctl->transition->timer);
513
514 ctl->last_tid = tid;
515 ctl->last_src_addr = ctx->addr;
516 ctl->last_dst_addr = ctx->recv_dst;
517 ctl->last_msg_timestamp = now;
518 ctl->transition->tt = tt;
519 ctl->transition->delay = delay;
520 ctl->transition->type = NON_MOVE;
521
522 if (target < INT16_MIN) {
523 target = INT16_MIN;
524 } else if (target > INT16_MAX) {
525 target = INT16_MAX;
526 }
527
528 set_target(DELTA_LEVEL_LIGHT, &target);
529
530 if (ctl->light->target != ctl->light->current) {
531 set_transition_values(LEVEL_LIGHT);
532 } else {
533 return 0;
534 }
535
536 /* For Instantaneous Transition */
537 if (ctl->transition->counter == 0U) {
538 ctl->light->current = ctl->light->target;
539 }
540
541 ctl->transition->just_started = true;
542 gen_level_publish(model);
543 level_lightness_handler();
544
545 return 0;
546 }
547
gen_delta_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)548 static int gen_delta_set(const struct bt_mesh_model *model,
549 struct bt_mesh_msg_ctx *ctx,
550 struct net_buf_simple *buf)
551 {
552 uint8_t tid, tt, delay;
553 static int16_t last_level;
554 int32_t target, delta;
555 int64_t now;
556
557 delta = (int32_t) net_buf_simple_pull_le32(buf);
558 tid = net_buf_simple_pull_u8(buf);
559
560 now = k_uptime_get();
561 if (ctl->last_tid == tid &&
562 ctl->last_src_addr == ctx->addr &&
563 ctl->last_dst_addr == ctx->recv_dst &&
564 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
565
566 if (ctl->light->delta == delta) {
567 (void)gen_level_get(model, ctx, buf);
568 return 0;
569 }
570 target = last_level + delta;
571
572 } else {
573 last_level = (int16_t) get_current(LEVEL_LIGHT);
574 target = last_level + delta;
575 }
576
577 switch (buf->len) {
578 case 0x00: /* No optional fields are available */
579 tt = ctl->tt;
580 delay = 0U;
581 break;
582 case 0x02: /* Optional fields are available */
583 tt = net_buf_simple_pull_u8(buf);
584 if ((tt & 0x3F) == 0x3F) {
585 return 0;
586 }
587
588 delay = net_buf_simple_pull_u8(buf);
589 break;
590 default:
591 return 0;
592 }
593
594 ctl->transition->counter = 0U;
595 k_timer_stop(&ctl->transition->timer);
596
597 ctl->last_tid = tid;
598 ctl->last_src_addr = ctx->addr;
599 ctl->last_dst_addr = ctx->recv_dst;
600 ctl->last_msg_timestamp = now;
601 ctl->transition->tt = tt;
602 ctl->transition->delay = delay;
603 ctl->transition->type = NON_MOVE;
604
605 if (target < INT16_MIN) {
606 target = INT16_MIN;
607 } else if (target > INT16_MAX) {
608 target = INT16_MAX;
609 }
610
611 set_target(DELTA_LEVEL_LIGHT, &target);
612
613 if (ctl->light->target != ctl->light->current) {
614 set_transition_values(LEVEL_LIGHT);
615 } else {
616 (void)gen_level_get(model, ctx, buf);
617 return 0;
618 }
619
620 /* For Instantaneous Transition */
621 if (ctl->transition->counter == 0U) {
622 ctl->light->current = ctl->light->target;
623 }
624
625 ctl->transition->just_started = true;
626 (void)gen_level_get(model, ctx, buf);
627 gen_level_publish(model);
628 level_lightness_handler();
629
630 return 0;
631 }
632
gen_move_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)633 static int gen_move_set_unack(const struct bt_mesh_model *model,
634 struct bt_mesh_msg_ctx *ctx,
635 struct net_buf_simple *buf)
636 {
637 uint8_t tid, tt, delay;
638 int16_t delta;
639 uint16_t target;
640 int64_t now;
641
642 delta = (int16_t) net_buf_simple_pull_le16(buf);
643 tid = net_buf_simple_pull_u8(buf);
644
645 now = k_uptime_get();
646 if (ctl->last_tid == tid &&
647 ctl->last_src_addr == ctx->addr &&
648 ctl->last_dst_addr == ctx->recv_dst &&
649 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
650 return 0;
651 }
652
653 switch (buf->len) {
654 case 0x00: /* No optional fields are available */
655 tt = ctl->tt;
656 delay = 0U;
657 break;
658 case 0x02: /* Optional fields are available */
659 tt = net_buf_simple_pull_u8(buf);
660 if ((tt & 0x3F) == 0x3F) {
661 return 0;
662 }
663
664 delay = net_buf_simple_pull_u8(buf);
665 break;
666 default:
667 return 0;
668 }
669
670 ctl->transition->counter = 0U;
671 k_timer_stop(&ctl->transition->timer);
672
673 ctl->last_tid = tid;
674 ctl->last_src_addr = ctx->addr;
675 ctl->last_dst_addr = ctx->recv_dst;
676 ctl->last_msg_timestamp = now;
677 ctl->transition->tt = tt;
678 ctl->transition->delay = delay;
679 ctl->transition->type = MOVE;
680 ctl->light->delta = delta;
681
682 if (delta < 0) {
683 target = ctl->light->range_min;
684 } else if (delta > 0) {
685 target = ctl->light->range_max;
686 } else if (delta == 0) {
687 target = ctl->light->current;
688 }
689 set_target(MOVE_LIGHT, &target);
690
691 if (ctl->light->target != ctl->light->current) {
692 set_transition_values(MOVE_LIGHT);
693 } else {
694 return 0;
695 }
696
697 if (ctl->transition->counter == 0U) {
698 return 0;
699 }
700
701 ctl->transition->just_started = true;
702 gen_level_publish(model);
703 level_lightness_handler();
704
705 return 0;
706 }
707
gen_move_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)708 static int gen_move_set(const struct bt_mesh_model *model,
709 struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf)
710 {
711 uint8_t tid, tt, delay;
712 int16_t delta;
713 uint16_t target;
714 int64_t now;
715
716 delta = (int16_t) net_buf_simple_pull_le16(buf);
717 tid = net_buf_simple_pull_u8(buf);
718
719 now = k_uptime_get();
720 if (ctl->last_tid == tid &&
721 ctl->last_src_addr == ctx->addr &&
722 ctl->last_dst_addr == ctx->recv_dst &&
723 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
724 (void)gen_level_get(model, ctx, buf);
725 return 0;
726 }
727
728 switch (buf->len) {
729 case 0x00: /* No optional fields are available */
730 tt = ctl->tt;
731 delay = 0U;
732 break;
733 case 0x02: /* Optional fields are available */
734 tt = net_buf_simple_pull_u8(buf);
735 if ((tt & 0x3F) == 0x3F) {
736 return 0;
737 }
738
739 delay = net_buf_simple_pull_u8(buf);
740 break;
741 default:
742 return 0;
743 }
744
745 ctl->transition->counter = 0U;
746 k_timer_stop(&ctl->transition->timer);
747
748 ctl->last_tid = tid;
749 ctl->last_src_addr = ctx->addr;
750 ctl->last_dst_addr = ctx->recv_dst;
751 ctl->last_msg_timestamp = now;
752 ctl->transition->tt = tt;
753 ctl->transition->delay = delay;
754 ctl->transition->type = MOVE;
755 ctl->light->delta = delta;
756
757 if (delta < 0) {
758 target = ctl->light->range_min;
759 } else if (delta > 0) {
760 target = ctl->light->range_max;
761 } else if (delta == 0) {
762 target = ctl->light->current;
763 }
764 set_target(MOVE_LIGHT, &target);
765
766 if (ctl->light->target != ctl->light->current) {
767 set_transition_values(MOVE_LIGHT);
768 } else {
769 (void)gen_level_get(model, ctx, buf);
770 return 0;
771 }
772
773 if (ctl->transition->counter == 0U) {
774 return 0;
775 }
776
777 ctl->transition->just_started = true;
778 (void)gen_level_get(model, ctx, buf);
779 gen_level_publish(model);
780 level_lightness_handler();
781
782 return 0;
783 }
784
785 /* Generic Level Client message handlers */
gen_level_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)786 static int gen_level_status(const struct bt_mesh_model *model,
787 struct bt_mesh_msg_ctx *ctx,
788 struct net_buf_simple *buf)
789 {
790 printk("Acknowledgement from GEN_LEVEL_SRV\n");
791 printk("Present Level = %04x\n", net_buf_simple_pull_le16(buf));
792
793 if (buf->len == 3U) {
794 printk("Target Level = %04x\n", net_buf_simple_pull_le16(buf));
795 printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf));
796 }
797
798 return 0;
799 }
800
801 /* Generic Default Transition Time Server message handlers */
gen_def_trans_time_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)802 static int gen_def_trans_time_get(const struct bt_mesh_model *model,
803 struct bt_mesh_msg_ctx *ctx,
804 struct net_buf_simple *buf)
805 {
806 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 1 + 4);
807
808 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_GEN_DEF_TRANS_TIME_STATUS);
809 net_buf_simple_add_u8(msg, ctl->tt);
810
811 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
812 printk("Unable to send GEN_DEF_TT_SRV Status response\n");
813 }
814
815 return 0;
816 }
817
gen_def_trans_time_publish(const struct bt_mesh_model * model)818 static void gen_def_trans_time_publish(const struct bt_mesh_model *model)
819 {
820 int err;
821 struct net_buf_simple *msg = model->pub->msg;
822
823 if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
824 return;
825 }
826
827 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_GEN_DEF_TRANS_TIME_STATUS);
828 net_buf_simple_add_u8(msg, ctl->tt);
829
830 err = bt_mesh_model_publish(model);
831 if (err) {
832 printk("bt_mesh_model_publish err %d\n", err);
833 }
834 }
835
gen_def_trans_time_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)836 static int gen_def_trans_time_set_unack(const struct bt_mesh_model *model,
837 struct bt_mesh_msg_ctx *ctx,
838 struct net_buf_simple *buf)
839 {
840 uint8_t tt;
841
842 tt = net_buf_simple_pull_u8(buf);
843
844 if ((tt & 0x3F) == 0x3F) {
845 return 0;
846 }
847
848 if (ctl->tt != tt) {
849 ctl->tt = tt;
850
851 gen_def_trans_time_publish(model);
852 save_on_flash(GEN_DEF_TRANS_TIME_STATE);
853 }
854
855 return 0;
856 }
857
gen_def_trans_time_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)858 static int gen_def_trans_time_set(const struct bt_mesh_model *model,
859 struct bt_mesh_msg_ctx *ctx,
860 struct net_buf_simple *buf)
861 {
862 uint8_t tt;
863
864 tt = net_buf_simple_pull_u8(buf);
865
866 if ((tt & 0x3F) == 0x3F) {
867 return 0;
868 }
869
870 if (ctl->tt != tt) {
871 ctl->tt = tt;
872
873 (void)gen_def_trans_time_get(model, ctx, buf);
874 gen_def_trans_time_publish(model);
875 save_on_flash(GEN_DEF_TRANS_TIME_STATE);
876 } else {
877 (void)gen_def_trans_time_get(model, ctx, buf);
878 }
879
880 return 0;
881 }
882
883 /* Generic Default Transition Time Client message handlers */
gen_def_trans_time_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)884 static int gen_def_trans_time_status(const struct bt_mesh_model *model,
885 struct bt_mesh_msg_ctx *ctx,
886 struct net_buf_simple *buf)
887 {
888 printk("Acknowledgement from GEN_DEF_TT_SRV\n");
889 printk("Transition Time = %02x\n", net_buf_simple_pull_u8(buf));
890
891 return 0;
892 }
893
894 /* Generic Power OnOff Server message handlers */
gen_onpowerup_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)895 static int gen_onpowerup_get(const struct bt_mesh_model *model,
896 struct bt_mesh_msg_ctx *ctx,
897 struct net_buf_simple *buf)
898 {
899 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 1 + 4);
900
901 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_GEN_ONPOWERUP_STATUS);
902 net_buf_simple_add_u8(msg, ctl->onpowerup);
903
904 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
905 printk("Unable to send GEN_POWER_ONOFF_SRV Status response\n");
906 }
907
908 return 0;
909 }
910
911 /* Generic Power OnOff Client message handlers */
gen_onpowerup_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)912 static int gen_onpowerup_status(const struct bt_mesh_model *model,
913 struct bt_mesh_msg_ctx *ctx,
914 struct net_buf_simple *buf)
915 {
916 printk("Acknowledgement from GEN_POWER_ONOFF_SRV\n");
917 printk("OnPowerUp = %02x\n", net_buf_simple_pull_u8(buf));
918
919 return 0;
920 }
921
922 /* Generic Power OnOff Setup Server message handlers */
923
gen_onpowerup_publish(const struct bt_mesh_model * model)924 static void gen_onpowerup_publish(const struct bt_mesh_model *model)
925 {
926 int err;
927 struct net_buf_simple *msg = model->pub->msg;
928
929 if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
930 return;
931 }
932
933 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_GEN_ONPOWERUP_STATUS);
934 net_buf_simple_add_u8(msg, ctl->onpowerup);
935
936 err = bt_mesh_model_publish(model);
937 if (err) {
938 printk("bt_mesh_model_publish err %d\n", err);
939 }
940 }
941
gen_onpowerup_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)942 static int gen_onpowerup_set_unack(const struct bt_mesh_model *model,
943 struct bt_mesh_msg_ctx *ctx,
944 struct net_buf_simple *buf)
945 {
946 uint8_t onpowerup;
947
948 onpowerup = net_buf_simple_pull_u8(buf);
949
950 if (onpowerup > STATE_RESTORE) {
951 return 0;
952 }
953
954 if (ctl->onpowerup != onpowerup) {
955 ctl->onpowerup = onpowerup;
956
957 gen_onpowerup_publish(model);
958 save_on_flash(GEN_ONPOWERUP_STATE);
959 }
960
961 return 0;
962 }
963
gen_onpowerup_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)964 static int gen_onpowerup_set(const struct bt_mesh_model *model,
965 struct bt_mesh_msg_ctx *ctx,
966 struct net_buf_simple *buf)
967 {
968 uint8_t onpowerup;
969
970 onpowerup = net_buf_simple_pull_u8(buf);
971
972 if (onpowerup > STATE_RESTORE) {
973 return 0;
974 }
975
976 if (ctl->onpowerup != onpowerup) {
977 ctl->onpowerup = onpowerup;
978
979 (void)gen_onpowerup_get(model, ctx, buf);
980 gen_onpowerup_publish(model);
981 save_on_flash(GEN_ONPOWERUP_STATE);
982 } else {
983 (void)gen_onpowerup_get(model, ctx, buf);
984 }
985
986 return 0;
987 }
988
989 /* Vendor Model message handlers*/
vnd_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)990 static int vnd_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
991 struct net_buf_simple *buf)
992 {
993 struct net_buf_simple *msg = NET_BUF_SIMPLE(3 + 6 + 4);
994 struct vendor_state *state = model->rt->user_data;
995
996 /* This is dummy response for demo purpose */
997 state->response = 0xA578FEB3;
998
999 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_3(0x04, CID_ZEPHYR));
1000 net_buf_simple_add_le16(msg, state->current);
1001 net_buf_simple_add_le32(msg, state->response);
1002
1003 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
1004 printk("Unable to send VENDOR Status response\n");
1005 }
1006
1007 return 0;
1008 }
1009
vnd_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1010 static int vnd_set_unack(const struct bt_mesh_model *model,
1011 struct bt_mesh_msg_ctx *ctx,
1012 struct net_buf_simple *buf)
1013 {
1014 uint8_t tid;
1015 int current;
1016 int64_t now;
1017 struct vendor_state *state = model->rt->user_data;
1018
1019 current = net_buf_simple_pull_le16(buf);
1020 tid = net_buf_simple_pull_u8(buf);
1021
1022 now = k_uptime_get();
1023 if (state->last_tid == tid &&
1024 state->last_src_addr == ctx->addr &&
1025 state->last_dst_addr == ctx->recv_dst &&
1026 (now - state->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
1027 return 0;
1028 }
1029
1030 state->last_tid = tid;
1031 state->last_src_addr = ctx->addr;
1032 state->last_dst_addr = ctx->recv_dst;
1033 state->last_msg_timestamp = now;
1034 state->current = current;
1035
1036 printk("Vendor model message = %04x\n", state->current);
1037
1038 update_vnd_led_gpio();
1039
1040 return 0;
1041 }
1042
vnd_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1043 static int vnd_set(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
1044 struct net_buf_simple *buf)
1045 {
1046 (void)vnd_set_unack(model, ctx, buf);
1047 (void)vnd_get(model, ctx, buf);
1048
1049 return 0;
1050 }
1051
vnd_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1052 static int vnd_status(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
1053 struct net_buf_simple *buf)
1054 {
1055 printk("Acknowledgement from Vendor\n");
1056 printk("cmd = %04x\n", net_buf_simple_pull_le16(buf));
1057 printk("response = %08x\n", net_buf_simple_pull_le32(buf));
1058
1059 return 0;
1060 }
1061
1062 /* Light Lightness Server message handlers */
light_lightness_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1063 static int light_lightness_get(const struct bt_mesh_model *model,
1064 struct bt_mesh_msg_ctx *ctx,
1065 struct net_buf_simple *buf)
1066 {
1067 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 5 + 4);
1068
1069 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_LIGHTNESS_STATUS);
1070 net_buf_simple_add_le16(msg, (uint16_t) get_current(ACTUAL));
1071
1072 if (ctl->light->current == ctl->light->target) {
1073 goto send;
1074 }
1075
1076 if (ctl->transition->counter) {
1077 calculate_rt(ctl->transition);
1078 net_buf_simple_add_le16(msg, (uint16_t) get_target(ACTUAL));
1079 net_buf_simple_add_u8(msg, ctl->transition->rt);
1080 }
1081
1082 send:
1083 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
1084 printk("Unable to send LightLightnessAct Status response\n");
1085 }
1086
1087 return 0;
1088 }
1089
light_lightness_publish(const struct bt_mesh_model * model)1090 void light_lightness_publish(const struct bt_mesh_model *model)
1091 {
1092 int err;
1093 struct net_buf_simple *msg = model->pub->msg;
1094
1095 if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
1096 return;
1097 }
1098
1099 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_LIGHTNESS_STATUS);
1100 net_buf_simple_add_le16(msg, (uint16_t) get_current(ACTUAL));
1101
1102 if (ctl->transition->counter) {
1103 calculate_rt(ctl->transition);
1104 net_buf_simple_add_le16(msg, (uint16_t) get_target(ACTUAL));
1105 net_buf_simple_add_u8(msg, ctl->transition->rt);
1106 }
1107
1108 err = bt_mesh_model_publish(model);
1109 if (err) {
1110 printk("bt_mesh_model_publish err %d\n", err);
1111 }
1112 }
1113
light_lightness_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1114 static int light_lightness_set_unack(const struct bt_mesh_model *model,
1115 struct bt_mesh_msg_ctx *ctx,
1116 struct net_buf_simple *buf)
1117 {
1118 uint8_t tid, tt, delay;
1119 uint16_t actual;
1120 int64_t now;
1121
1122 actual = net_buf_simple_pull_le16(buf);
1123 tid = net_buf_simple_pull_u8(buf);
1124
1125 now = k_uptime_get();
1126 if (ctl->last_tid == tid &&
1127 ctl->last_src_addr == ctx->addr &&
1128 ctl->last_dst_addr == ctx->recv_dst &&
1129 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
1130 return 0;
1131 }
1132
1133 switch (buf->len) {
1134 case 0x00: /* No optional fields are available */
1135 tt = ctl->tt;
1136 delay = 0U;
1137 break;
1138 case 0x02: /* Optional fields are available */
1139 tt = net_buf_simple_pull_u8(buf);
1140 if ((tt & 0x3F) == 0x3F) {
1141 return 0;
1142 }
1143
1144 delay = net_buf_simple_pull_u8(buf);
1145 break;
1146 default:
1147 return 0;
1148 }
1149
1150 ctl->transition->counter = 0U;
1151 k_timer_stop(&ctl->transition->timer);
1152
1153 ctl->last_tid = tid;
1154 ctl->last_src_addr = ctx->addr;
1155 ctl->last_dst_addr = ctx->recv_dst;
1156 ctl->last_msg_timestamp = now;
1157 ctl->transition->tt = tt;
1158 ctl->transition->delay = delay;
1159 ctl->transition->type = NON_MOVE;
1160 set_target(ACTUAL, &actual);
1161
1162 if (ctl->light->target != ctl->light->current) {
1163 set_transition_values(ACTUAL);
1164 } else {
1165 return 0;
1166 }
1167
1168 /* For Instantaneous Transition */
1169 if (ctl->transition->counter == 0U) {
1170 ctl->light->current = ctl->light->target;
1171 }
1172
1173 ctl->transition->just_started = true;
1174 light_lightness_publish(model);
1175 light_lightness_actual_handler();
1176
1177 return 0;
1178 }
1179
light_lightness_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1180 static int light_lightness_set(const struct bt_mesh_model *model,
1181 struct bt_mesh_msg_ctx *ctx,
1182 struct net_buf_simple *buf)
1183 {
1184 uint8_t tid, tt, delay;
1185 uint16_t actual;
1186 int64_t now;
1187
1188 actual = net_buf_simple_pull_le16(buf);
1189 tid = net_buf_simple_pull_u8(buf);
1190
1191 now = k_uptime_get();
1192 if (ctl->last_tid == tid &&
1193 ctl->last_src_addr == ctx->addr &&
1194 ctl->last_dst_addr == ctx->recv_dst &&
1195 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
1196 (void)light_lightness_get(model, ctx, buf);
1197 return 0;
1198 }
1199
1200 switch (buf->len) {
1201 case 0x00: /* No optional fields are available */
1202 tt = ctl->tt;
1203 delay = 0U;
1204 break;
1205 case 0x02: /* Optional fields are available */
1206 tt = net_buf_simple_pull_u8(buf);
1207 if ((tt & 0x3F) == 0x3F) {
1208 return 0;
1209 }
1210
1211 delay = net_buf_simple_pull_u8(buf);
1212 break;
1213 default:
1214 return 0;
1215 }
1216
1217 ctl->transition->counter = 0U;
1218 k_timer_stop(&ctl->transition->timer);
1219
1220 ctl->last_tid = tid;
1221 ctl->last_src_addr = ctx->addr;
1222 ctl->last_dst_addr = ctx->recv_dst;
1223 ctl->last_msg_timestamp = now;
1224 ctl->transition->tt = tt;
1225 ctl->transition->delay = delay;
1226 ctl->transition->type = NON_MOVE;
1227 set_target(ACTUAL, &actual);
1228
1229 if (ctl->light->target != ctl->light->current) {
1230 set_transition_values(ACTUAL);
1231 } else {
1232 (void)light_lightness_get(model, ctx, buf);
1233 return 0;
1234 }
1235
1236 /* For Instantaneous Transition */
1237 if (ctl->transition->counter == 0U) {
1238 ctl->light->current = ctl->light->target;
1239 }
1240
1241 ctl->transition->just_started = true;
1242 (void)light_lightness_get(model, ctx, buf);
1243 light_lightness_publish(model);
1244 light_lightness_actual_handler();
1245
1246 return 0;
1247 }
1248
light_lightness_linear_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1249 static int light_lightness_linear_get(const struct bt_mesh_model *model,
1250 struct bt_mesh_msg_ctx *ctx,
1251 struct net_buf_simple *buf)
1252 {
1253 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 5 + 4);
1254
1255 bt_mesh_model_msg_init(msg,
1256 BT_MESH_MODEL_LIGHT_LIGHTNESS_LINEAR_STATUS);
1257 net_buf_simple_add_le16(msg, (uint16_t) get_current(LINEAR));
1258
1259 if (ctl->light->current == ctl->light->target) {
1260 goto send;
1261 }
1262
1263 if (ctl->transition->counter) {
1264 calculate_rt(ctl->transition);
1265 net_buf_simple_add_le16(msg, (uint16_t) get_target(LINEAR));
1266 net_buf_simple_add_u8(msg, ctl->transition->rt);
1267 }
1268
1269 send:
1270 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
1271 printk("Unable to send LightLightnessLin Status response\n");
1272 }
1273
1274 return 0;
1275 }
1276
light_lightness_linear_publish(const struct bt_mesh_model * model)1277 void light_lightness_linear_publish(const struct bt_mesh_model *model)
1278 {
1279 int err;
1280 struct net_buf_simple *msg = model->pub->msg;
1281
1282 if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
1283 return;
1284 }
1285
1286 bt_mesh_model_msg_init(msg,
1287 BT_MESH_MODEL_LIGHT_LIGHTNESS_LINEAR_STATUS);
1288 net_buf_simple_add_le16(msg, (uint16_t) get_current(LINEAR));
1289
1290 if (ctl->transition->counter) {
1291 calculate_rt(ctl->transition);
1292 net_buf_simple_add_le16(msg, (uint16_t) get_target(LINEAR));
1293 net_buf_simple_add_u8(msg, ctl->transition->rt);
1294 }
1295
1296 err = bt_mesh_model_publish(model);
1297 if (err) {
1298 printk("bt_mesh_model_publish err %d\n", err);
1299 }
1300 }
1301
light_lightness_linear_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1302 static int light_lightness_linear_set_unack(const struct bt_mesh_model *model,
1303 struct bt_mesh_msg_ctx *ctx,
1304 struct net_buf_simple *buf)
1305 {
1306 uint8_t tid, tt, delay;
1307 uint16_t linear;
1308 int64_t now;
1309
1310 linear = net_buf_simple_pull_le16(buf);
1311 tid = net_buf_simple_pull_u8(buf);
1312
1313 now = k_uptime_get();
1314 if (ctl->last_tid == tid &&
1315 ctl->last_src_addr == ctx->addr &&
1316 ctl->last_dst_addr == ctx->recv_dst &&
1317 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
1318 return 0;
1319 }
1320
1321 switch (buf->len) {
1322 case 0x00: /* No optional fields are available */
1323 tt = ctl->tt;
1324 delay = 0U;
1325 break;
1326 case 0x02: /* Optional fields are available */
1327 tt = net_buf_simple_pull_u8(buf);
1328 if ((tt & 0x3F) == 0x3F) {
1329 return 0;
1330 }
1331
1332 delay = net_buf_simple_pull_u8(buf);
1333 break;
1334 default:
1335 return 0;
1336 }
1337
1338 ctl->transition->counter = 0U;
1339 k_timer_stop(&ctl->transition->timer);
1340
1341 ctl->last_tid = tid;
1342 ctl->last_src_addr = ctx->addr;
1343 ctl->last_dst_addr = ctx->recv_dst;
1344 ctl->last_msg_timestamp = now;
1345 ctl->transition->tt = tt;
1346 ctl->transition->delay = delay;
1347 ctl->transition->type = NON_MOVE;
1348 set_target(LINEAR, &linear);
1349
1350 if (ctl->light->target != ctl->light->current) {
1351 set_transition_values(LINEAR);
1352 } else {
1353 return 0;
1354 }
1355
1356 /* For Instantaneous Transition */
1357 if (ctl->transition->counter == 0U) {
1358 ctl->light->current = ctl->light->target;
1359 }
1360
1361 ctl->transition->just_started = true;
1362 light_lightness_linear_publish(model);
1363 light_lightness_linear_handler();
1364
1365 return 0;
1366 }
1367
light_lightness_linear_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1368 static int light_lightness_linear_set(const struct bt_mesh_model *model,
1369 struct bt_mesh_msg_ctx *ctx,
1370 struct net_buf_simple *buf)
1371 {
1372 uint8_t tid, tt, delay;
1373 uint16_t linear;
1374 int64_t now;
1375
1376 linear = net_buf_simple_pull_le16(buf);
1377 tid = net_buf_simple_pull_u8(buf);
1378
1379 now = k_uptime_get();
1380 if (ctl->last_tid == tid &&
1381 ctl->last_src_addr == ctx->addr &&
1382 ctl->last_dst_addr == ctx->recv_dst &&
1383 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
1384 (void)light_lightness_linear_get(model, ctx, buf);
1385 return 0;
1386 }
1387
1388 switch (buf->len) {
1389 case 0x00: /* No optional fields are available */
1390 tt = ctl->tt;
1391 delay = 0U;
1392 break;
1393 case 0x02: /* Optional fields are available */
1394 tt = net_buf_simple_pull_u8(buf);
1395 if ((tt & 0x3F) == 0x3F) {
1396 return 0;
1397 }
1398
1399 delay = net_buf_simple_pull_u8(buf);
1400 break;
1401 default:
1402 return 0;
1403 }
1404
1405 ctl->transition->counter = 0U;
1406 k_timer_stop(&ctl->transition->timer);
1407
1408 ctl->last_tid = tid;
1409 ctl->last_src_addr = ctx->addr;
1410 ctl->last_dst_addr = ctx->recv_dst;
1411 ctl->last_msg_timestamp = now;
1412 ctl->transition->tt = tt;
1413 ctl->transition->delay = delay;
1414 ctl->transition->type = NON_MOVE;
1415 set_target(LINEAR, &linear);
1416
1417 if (ctl->light->target != ctl->light->current) {
1418 set_transition_values(LINEAR);
1419 } else {
1420 (void)light_lightness_linear_get(model, ctx, buf);
1421 return 0;
1422 }
1423
1424 /* For Instantaneous Transition */
1425 if (ctl->transition->counter == 0U) {
1426 ctl->light->current = ctl->light->target;
1427 }
1428
1429 ctl->transition->just_started = true;
1430 (void)light_lightness_linear_get(model, ctx, buf);
1431 light_lightness_linear_publish(model);
1432 light_lightness_linear_handler();
1433
1434 return 0;
1435 }
1436
light_lightness_last_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1437 static int light_lightness_last_get(const struct bt_mesh_model *model,
1438 struct bt_mesh_msg_ctx *ctx,
1439 struct net_buf_simple *buf)
1440 {
1441 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 2 + 4);
1442
1443 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_LIGHTNESS_LAST_STATUS);
1444 net_buf_simple_add_le16(msg, ctl->light->last);
1445
1446 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
1447 printk("Unable to send LightLightnessLast Status response\n");
1448 }
1449
1450 return 0;
1451 }
1452
light_lightness_default_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1453 static int light_lightness_default_get(const struct bt_mesh_model *model,
1454 struct bt_mesh_msg_ctx *ctx,
1455 struct net_buf_simple *buf)
1456 {
1457 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 2 + 4);
1458
1459 bt_mesh_model_msg_init(msg,
1460 BT_MESH_MODEL_LIGHT_LIGHTNESS_DEFAULT_STATUS);
1461 net_buf_simple_add_le16(msg, ctl->light->def);
1462
1463 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
1464 printk("Unable to send LightLightnessDef Status response\n");
1465 }
1466
1467 return 0;
1468 }
1469
light_lightness_range_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1470 static int light_lightness_range_get(const struct bt_mesh_model *model,
1471 struct bt_mesh_msg_ctx *ctx,
1472 struct net_buf_simple *buf)
1473 {
1474 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 5 + 4);
1475
1476 ctl->light->status_code = RANGE_SUCCESSFULLY_UPDATED;
1477
1478 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_LIGHTNESS_RANGE_STATUS);
1479 net_buf_simple_add_u8(msg, ctl->light->status_code);
1480 net_buf_simple_add_le16(msg, ctl->light->range_min);
1481 net_buf_simple_add_le16(msg, ctl->light->range_max);
1482
1483 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
1484 printk("Unable to send LightLightnessRange Status response\n");
1485 }
1486
1487 return 0;
1488 }
1489
1490 /* Light Lightness Setup Server message handlers */
1491
light_lightness_default_publish(const struct bt_mesh_model * model)1492 static void light_lightness_default_publish(const struct bt_mesh_model *model)
1493 {
1494 int err;
1495 struct net_buf_simple *msg = model->pub->msg;
1496
1497 if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
1498 return;
1499 }
1500
1501 bt_mesh_model_msg_init(msg,
1502 BT_MESH_MODEL_LIGHT_LIGHTNESS_DEFAULT_STATUS);
1503 net_buf_simple_add_le16(msg, ctl->light->def);
1504
1505 err = bt_mesh_model_publish(model);
1506 if (err) {
1507 printk("bt_mesh_model_publish err %d\n", err);
1508 }
1509 }
1510
light_lightness_default_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1511 static int light_lightness_default_set_unack(const struct bt_mesh_model *model,
1512 struct bt_mesh_msg_ctx *ctx,
1513 struct net_buf_simple *buf)
1514 {
1515 uint16_t lightness;
1516
1517 lightness = net_buf_simple_pull_le16(buf);
1518 lightness = constrain_lightness(lightness);
1519
1520 if (ctl->light->def != lightness) {
1521 ctl->light->def = lightness;
1522
1523 light_lightness_default_publish(model);
1524 save_on_flash(DEF_STATES);
1525 }
1526
1527 return 0;
1528 }
1529
light_lightness_default_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1530 static int light_lightness_default_set(const struct bt_mesh_model *model,
1531 struct bt_mesh_msg_ctx *ctx,
1532 struct net_buf_simple *buf)
1533 {
1534 uint16_t lightness;
1535
1536 lightness = net_buf_simple_pull_le16(buf);
1537 lightness = constrain_lightness(lightness);
1538
1539 if (ctl->light->def != lightness) {
1540 ctl->light->def = lightness;
1541
1542 (void)light_lightness_default_get(model, ctx, buf);
1543 light_lightness_default_publish(model);
1544 save_on_flash(DEF_STATES);
1545 } else {
1546 (void)light_lightness_default_get(model, ctx, buf);
1547 }
1548
1549 return 0;
1550 }
1551
light_lightness_range_publish(const struct bt_mesh_model * model)1552 static void light_lightness_range_publish(const struct bt_mesh_model *model)
1553 {
1554 int err;
1555 struct net_buf_simple *msg = model->pub->msg;
1556
1557 if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
1558 return;
1559 }
1560
1561 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_LIGHTNESS_RANGE_STATUS);
1562 net_buf_simple_add_u8(msg, ctl->light->status_code);
1563 net_buf_simple_add_le16(msg, ctl->light->range_min);
1564 net_buf_simple_add_le16(msg, ctl->light->range_max);
1565
1566 err = bt_mesh_model_publish(model);
1567 if (err) {
1568 printk("bt_mesh_model_publish err %d\n", err);
1569 }
1570 }
1571
light_lightness_range_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1572 static int light_lightness_range_set_unack(const struct bt_mesh_model *model,
1573 struct bt_mesh_msg_ctx *ctx,
1574 struct net_buf_simple *buf)
1575 {
1576 uint16_t min, max;
1577
1578 min = net_buf_simple_pull_le16(buf);
1579 max = net_buf_simple_pull_le16(buf);
1580
1581 if (min == 0U || max == 0U) {
1582 return 0;
1583 }
1584
1585 if (min <= max) {
1586 ctl->light->status_code = RANGE_SUCCESSFULLY_UPDATED;
1587
1588 if (ctl->light->range_min != min ||
1589 ctl->light->range_max != max) {
1590
1591 ctl->light->range_min = min;
1592 ctl->light->range_max = max;
1593
1594 light_lightness_range_publish(model);
1595 save_on_flash(LIGHTNESS_RANGE);
1596 }
1597 } else {
1598 /* The provided value for Range Max cannot be set */
1599 ctl->light->status_code = CANNOT_SET_RANGE_MAX;
1600 return 0;
1601 }
1602
1603 return 0;
1604 }
1605
light_lightness_range_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1606 static int light_lightness_range_set(const struct bt_mesh_model *model,
1607 struct bt_mesh_msg_ctx *ctx,
1608 struct net_buf_simple *buf)
1609 {
1610 uint16_t min, max;
1611
1612 min = net_buf_simple_pull_le16(buf);
1613 max = net_buf_simple_pull_le16(buf);
1614
1615 if (min == 0U || max == 0U) {
1616 return 0;
1617 }
1618
1619 if (min <= max) {
1620 ctl->light->status_code = RANGE_SUCCESSFULLY_UPDATED;
1621
1622 if (ctl->light->range_min != min ||
1623 ctl->light->range_max != max) {
1624
1625 ctl->light->range_min = min;
1626 ctl->light->range_max = max;
1627
1628 (void)light_lightness_range_get(model, ctx, buf);
1629 light_lightness_range_publish(model);
1630 save_on_flash(LIGHTNESS_RANGE);
1631 } else {
1632 (void)light_lightness_range_get(model, ctx, buf);
1633 }
1634 } else {
1635 /* The provided value for Range Max cannot be set */
1636 ctl->light->status_code = CANNOT_SET_RANGE_MAX;
1637 return 0;
1638 }
1639
1640 return 0;
1641 }
1642
1643 /* Light Lightness Client message handlers */
light_lightness_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1644 static int light_lightness_status(const struct bt_mesh_model *model,
1645 struct bt_mesh_msg_ctx *ctx,
1646 struct net_buf_simple *buf)
1647 {
1648 printk("Acknowledgement from LIGHT_LIGHTNESS_SRV (Actual)\n");
1649 printk("Present Lightness = %04x\n", net_buf_simple_pull_le16(buf));
1650
1651 if (buf->len == 3U) {
1652 printk("Target Lightness = %04x\n",
1653 net_buf_simple_pull_le16(buf));
1654 printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf));
1655 }
1656
1657 return 0;
1658 }
1659
light_lightness_linear_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1660 static int light_lightness_linear_status(const struct bt_mesh_model *model,
1661 struct bt_mesh_msg_ctx *ctx,
1662 struct net_buf_simple *buf)
1663 {
1664 printk("Acknowledgement from LIGHT_LIGHTNESS_SRV (Linear)\n");
1665 printk("Present Lightness = %04x\n", net_buf_simple_pull_le16(buf));
1666
1667 if (buf->len == 3U) {
1668 printk("Target Lightness = %04x\n",
1669 net_buf_simple_pull_le16(buf));
1670 printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf));
1671 }
1672
1673 return 0;
1674 }
1675
light_lightness_last_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1676 static int light_lightness_last_status(const struct bt_mesh_model *model,
1677 struct bt_mesh_msg_ctx *ctx,
1678 struct net_buf_simple *buf)
1679 {
1680 printk("Acknowledgement from LIGHT_LIGHTNESS_SRV (Last)\n");
1681 printk("Lightness = %04x\n", net_buf_simple_pull_le16(buf));
1682
1683 return 0;
1684 }
1685
light_lightness_default_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1686 static int light_lightness_default_status(const struct bt_mesh_model *model,
1687 struct bt_mesh_msg_ctx *ctx,
1688 struct net_buf_simple *buf)
1689 {
1690 printk("Acknowledgement from LIGHT_LIGHTNESS_SRV (Default)\n");
1691 printk("Lightness = %04x\n", net_buf_simple_pull_le16(buf));
1692
1693 return 0;
1694 }
1695
light_lightness_range_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1696 static int light_lightness_range_status(const struct bt_mesh_model *model,
1697 struct bt_mesh_msg_ctx *ctx,
1698 struct net_buf_simple *buf)
1699 {
1700 printk("Acknowledgement from LIGHT_LIGHTNESS_SRV (Lightness Range)\n");
1701 printk("Status Code = %02x\n", net_buf_simple_pull_u8(buf));
1702 printk("Range Min = %04x\n", net_buf_simple_pull_le16(buf));
1703 printk("Range Max = %04x\n", net_buf_simple_pull_le16(buf));
1704
1705 return 0;
1706 }
1707
1708 /* Light CTL Server message handlers */
light_ctl_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1709 static int light_ctl_get(const struct bt_mesh_model *model,
1710 struct bt_mesh_msg_ctx *ctx,
1711 struct net_buf_simple *buf)
1712 {
1713 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 9 + 4);
1714
1715 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_CTL_STATUS);
1716 net_buf_simple_add_le16(msg, (uint16_t) get_current(CTL_LIGHT));
1717 net_buf_simple_add_le16(msg, (uint16_t) get_current(CTL_TEMP));
1718
1719 if (ctl->light->current == ctl->light->target &&
1720 ctl->temp->current == ctl->temp->target) {
1721 goto send;
1722 }
1723
1724 if (ctl->transition->counter) {
1725 calculate_rt(ctl->transition);
1726 net_buf_simple_add_le16(msg, (uint16_t) get_target(CTL_LIGHT));
1727 net_buf_simple_add_le16(msg, (uint16_t) get_target(CTL_TEMP));
1728 net_buf_simple_add_u8(msg, ctl->transition->rt);
1729 }
1730
1731 send:
1732 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
1733 printk("Unable to send LightCTL Status response\n");
1734 }
1735
1736 return 0;
1737 }
1738
light_ctl_publish(const struct bt_mesh_model * model)1739 void light_ctl_publish(const struct bt_mesh_model *model)
1740 {
1741 int err;
1742 struct net_buf_simple *msg = model->pub->msg;
1743
1744 if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
1745 return;
1746 }
1747
1748 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_CTL_STATUS);
1749
1750 /* Here, as per Model specification, status should be
1751 * made up of lightness & temperature values only
1752 */
1753 net_buf_simple_add_le16(msg, (uint16_t) get_current(CTL_LIGHT));
1754 net_buf_simple_add_le16(msg, (uint16_t) get_current(CTL_TEMP));
1755
1756 if (ctl->transition->counter) {
1757 calculate_rt(ctl->transition);
1758 net_buf_simple_add_le16(msg, (uint16_t) get_target(CTL_LIGHT));
1759 net_buf_simple_add_le16(msg, (uint16_t) get_target(CTL_TEMP));
1760 net_buf_simple_add_u8(msg, ctl->transition->rt);
1761 }
1762
1763 err = bt_mesh_model_publish(model);
1764 if (err) {
1765 printk("bt_mesh_model_publish err %d\n", err);
1766 }
1767 }
1768
light_ctl_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1769 static int light_ctl_set_unack(const struct bt_mesh_model *model,
1770 struct bt_mesh_msg_ctx *ctx,
1771 struct net_buf_simple *buf)
1772 {
1773 uint8_t tid, tt, delay;
1774 int16_t delta_uv;
1775 uint16_t lightness, temp;
1776 int64_t now;
1777
1778 lightness = net_buf_simple_pull_le16(buf);
1779 temp = net_buf_simple_pull_le16(buf);
1780 delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
1781 tid = net_buf_simple_pull_u8(buf);
1782
1783 if (temp < TEMP_MIN || temp > TEMP_MAX) {
1784 return 0;
1785 }
1786
1787 now = k_uptime_get();
1788 if (ctl->last_tid == tid &&
1789 ctl->last_src_addr == ctx->addr &&
1790 ctl->last_dst_addr == ctx->recv_dst &&
1791 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
1792 return 0;
1793 }
1794
1795 switch (buf->len) {
1796 case 0x00: /* No optional fields are available */
1797 tt = ctl->tt;
1798 delay = 0U;
1799 break;
1800 case 0x02: /* Optional fields are available */
1801 tt = net_buf_simple_pull_u8(buf);
1802 if ((tt & 0x3F) == 0x3F) {
1803 return 0;
1804 }
1805
1806 delay = net_buf_simple_pull_u8(buf);
1807 break;
1808 default:
1809 return 0;
1810 }
1811
1812 ctl->transition->counter = 0U;
1813 k_timer_stop(&ctl->transition->timer);
1814
1815 ctl->last_tid = tid;
1816 ctl->last_src_addr = ctx->addr;
1817 ctl->last_dst_addr = ctx->recv_dst;
1818 ctl->last_msg_timestamp = now;
1819 ctl->transition->tt = tt;
1820 ctl->transition->delay = delay;
1821 ctl->transition->type = NON_MOVE;
1822 set_target(CTL_LIGHT, &lightness);
1823 set_target(CTL_TEMP, &temp);
1824 set_target(CTL_DELTA_UV, &delta_uv);
1825
1826 if (ctl->light->target != ctl->light->current ||
1827 ctl->temp->target != ctl->temp->current ||
1828 ctl->duv->target != ctl->duv->current) {
1829 set_transition_values(CTL_LIGHT);
1830 } else {
1831 return 0;
1832 }
1833
1834 /* For Instantaneous Transition */
1835 if (ctl->transition->counter == 0U) {
1836 ctl->light->current = ctl->light->target;
1837 ctl->temp->current = ctl->temp->target;
1838 ctl->duv->current = ctl->duv->target;
1839 }
1840
1841 ctl->transition->just_started = true;
1842 light_ctl_publish(model);
1843 light_ctl_handler();
1844
1845 return 0;
1846 }
1847
light_ctl_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1848 static int light_ctl_set(const struct bt_mesh_model *model,
1849 struct bt_mesh_msg_ctx *ctx,
1850 struct net_buf_simple *buf)
1851 {
1852 uint8_t tid, tt, delay;
1853 int16_t delta_uv;
1854 uint16_t lightness, temp;
1855 int64_t now;
1856
1857 lightness = net_buf_simple_pull_le16(buf);
1858 temp = net_buf_simple_pull_le16(buf);
1859 delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
1860 tid = net_buf_simple_pull_u8(buf);
1861
1862 if (temp < TEMP_MIN || temp > TEMP_MAX) {
1863 return 0;
1864 }
1865
1866 now = k_uptime_get();
1867 if (ctl->last_tid == tid &&
1868 ctl->last_src_addr == ctx->addr &&
1869 ctl->last_dst_addr == ctx->recv_dst &&
1870 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
1871 (void)light_ctl_get(model, ctx, buf);
1872 return 0;
1873 }
1874
1875 switch (buf->len) {
1876 case 0x00: /* No optional fields are available */
1877 tt = ctl->tt;
1878 delay = 0U;
1879 break;
1880 case 0x02: /* Optional fields are available */
1881 tt = net_buf_simple_pull_u8(buf);
1882 if ((tt & 0x3F) == 0x3F) {
1883 return 0;
1884 }
1885
1886 delay = net_buf_simple_pull_u8(buf);
1887 break;
1888 default:
1889 return 0;
1890 }
1891
1892 ctl->transition->counter = 0U;
1893 k_timer_stop(&ctl->transition->timer);
1894
1895 ctl->last_tid = tid;
1896 ctl->last_src_addr = ctx->addr;
1897 ctl->last_dst_addr = ctx->recv_dst;
1898 ctl->last_msg_timestamp = now;
1899 ctl->transition->tt = tt;
1900 ctl->transition->delay = delay;
1901 ctl->transition->type = NON_MOVE;
1902 set_target(CTL_LIGHT, &lightness);
1903 set_target(CTL_TEMP, &temp);
1904 set_target(CTL_DELTA_UV, &delta_uv);
1905
1906 if (ctl->light->target != ctl->light->current ||
1907 ctl->temp->target != ctl->temp->current ||
1908 ctl->duv->target != ctl->duv->current) {
1909 set_transition_values(CTL_LIGHT);
1910 } else {
1911 (void)light_ctl_get(model, ctx, buf);
1912 return 0;
1913 }
1914
1915 /* For Instantaneous Transition */
1916 if (ctl->transition->counter == 0U) {
1917 ctl->light->current = ctl->light->target;
1918 ctl->temp->current = ctl->temp->target;
1919 ctl->duv->current = ctl->duv->target;
1920 }
1921
1922 ctl->transition->just_started = true;
1923 (void)light_ctl_get(model, ctx, buf);
1924 light_ctl_publish(model);
1925 light_ctl_handler();
1926
1927 return 0;
1928 }
1929
light_ctl_temp_range_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1930 static int light_ctl_temp_range_get(const struct bt_mesh_model *model,
1931 struct bt_mesh_msg_ctx *ctx,
1932 struct net_buf_simple *buf)
1933 {
1934 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 5 + 4);
1935
1936 ctl->temp->status_code = RANGE_SUCCESSFULLY_UPDATED;
1937
1938 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_CTL_TEMP_RANGE_STATUS);
1939 net_buf_simple_add_u8(msg, ctl->temp->status_code);
1940 net_buf_simple_add_le16(msg, ctl->temp->range_min);
1941 net_buf_simple_add_le16(msg, ctl->temp->range_max);
1942
1943 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
1944 printk("Unable to send LightCTL Temp Range Status response\n");
1945 }
1946
1947 return 0;
1948 }
1949
light_ctl_default_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1950 static int light_ctl_default_get(const struct bt_mesh_model *model,
1951 struct bt_mesh_msg_ctx *ctx,
1952 struct net_buf_simple *buf)
1953 {
1954 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 6 + 4);
1955
1956 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_CTL_DEFAULT_STATUS);
1957 net_buf_simple_add_le16(msg, ctl->light->def);
1958 net_buf_simple_add_le16(msg, ctl->temp->def);
1959 net_buf_simple_add_le16(msg, ctl->duv->def);
1960
1961 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
1962 printk("Unable to send LightCTL Default Status response\n");
1963 }
1964
1965 return 0;
1966 }
1967
1968 /* Light CTL Setup Server message handlers */
1969
light_ctl_default_publish(const struct bt_mesh_model * model)1970 static void light_ctl_default_publish(const struct bt_mesh_model *model)
1971 {
1972 int err;
1973 struct net_buf_simple *msg = model->pub->msg;
1974
1975 if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
1976 return;
1977 }
1978
1979 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_CTL_DEFAULT_STATUS);
1980 net_buf_simple_add_le16(msg, ctl->light->def);
1981 net_buf_simple_add_le16(msg, ctl->temp->def);
1982 net_buf_simple_add_le16(msg, ctl->duv->def);
1983
1984 err = bt_mesh_model_publish(model);
1985 if (err) {
1986 printk("bt_mesh_model_publish err %d\n", err);
1987 }
1988 }
1989
light_ctl_default_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1990 static int light_ctl_default_set_unack(const struct bt_mesh_model *model,
1991 struct bt_mesh_msg_ctx *ctx,
1992 struct net_buf_simple *buf)
1993 {
1994 uint16_t lightness, temp;
1995 int16_t delta_uv;
1996
1997 lightness = net_buf_simple_pull_le16(buf);
1998 temp = net_buf_simple_pull_le16(buf);
1999 delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
2000
2001 if (temp < TEMP_MIN || temp > TEMP_MAX) {
2002 return 0;
2003 }
2004
2005 lightness = constrain_lightness(lightness);
2006 temp = constrain_temperature(temp);
2007
2008 if (ctl->light->def != lightness || ctl->temp->def != temp ||
2009 ctl->duv->def != delta_uv) {
2010 ctl->light->def = lightness;
2011 ctl->temp->def = temp;
2012 ctl->duv->def = delta_uv;
2013
2014 light_ctl_default_publish(model);
2015 save_on_flash(DEF_STATES);
2016 }
2017
2018 return 0;
2019 }
2020
light_ctl_default_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2021 static int light_ctl_default_set(const struct bt_mesh_model *model,
2022 struct bt_mesh_msg_ctx *ctx,
2023 struct net_buf_simple *buf)
2024 {
2025 uint16_t lightness, temp;
2026 int16_t delta_uv;
2027
2028 lightness = net_buf_simple_pull_le16(buf);
2029 temp = net_buf_simple_pull_le16(buf);
2030 delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
2031
2032 if (temp < TEMP_MIN || temp > TEMP_MAX) {
2033 return 0;
2034 }
2035
2036 lightness = constrain_lightness(lightness);
2037 temp = constrain_temperature(temp);
2038
2039 if (ctl->light->def != lightness || ctl->temp->def != temp ||
2040 ctl->duv->def != delta_uv) {
2041 ctl->light->def = lightness;
2042 ctl->temp->def = temp;
2043 ctl->duv->def = delta_uv;
2044
2045 (void)light_ctl_default_get(model, ctx, buf);
2046 light_ctl_default_publish(model);
2047 save_on_flash(DEF_STATES);
2048 } else {
2049 (void)light_ctl_default_get(model, ctx, buf);
2050 }
2051
2052 return 0;
2053 }
2054
light_ctl_temp_range_publish(const struct bt_mesh_model * model)2055 static void light_ctl_temp_range_publish(const struct bt_mesh_model *model)
2056 {
2057 int err;
2058 struct net_buf_simple *msg = model->pub->msg;
2059
2060 if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
2061 return;
2062 }
2063
2064 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_CTL_TEMP_RANGE_STATUS);
2065 net_buf_simple_add_u8(msg, ctl->temp->status_code);
2066 net_buf_simple_add_le16(msg, ctl->temp->range_min);
2067 net_buf_simple_add_le16(msg, ctl->temp->range_max);
2068
2069 err = bt_mesh_model_publish(model);
2070 if (err) {
2071 printk("bt_mesh_model_publish err %d\n", err);
2072 }
2073 }
2074
light_ctl_temp_range_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2075 static int light_ctl_temp_range_set_unack(const struct bt_mesh_model *model,
2076 struct bt_mesh_msg_ctx *ctx,
2077 struct net_buf_simple *buf)
2078 {
2079 uint16_t min, max;
2080
2081 min = net_buf_simple_pull_le16(buf);
2082 max = net_buf_simple_pull_le16(buf);
2083
2084 /* This is as per 6.1.3.1 in Mesh Model Specification */
2085 if (min < TEMP_MIN || min > TEMP_MAX ||
2086 max < TEMP_MIN || max > TEMP_MAX) {
2087 return 0;
2088 }
2089
2090 if (min <= max) {
2091 ctl->temp->status_code = RANGE_SUCCESSFULLY_UPDATED;
2092
2093 if (ctl->temp->range_min != min ||
2094 ctl->temp->range_max != max) {
2095
2096 ctl->temp->range_min = min;
2097 ctl->temp->range_max = max;
2098
2099 light_ctl_temp_range_publish(model);
2100 save_on_flash(TEMPERATURE_RANGE);
2101 }
2102 } else {
2103 /* The provided value for Range Max cannot be set */
2104 ctl->temp->status_code = CANNOT_SET_RANGE_MAX;
2105 return 0;
2106 }
2107
2108 return 0;
2109 }
2110
light_ctl_temp_range_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2111 static int light_ctl_temp_range_set(const struct bt_mesh_model *model,
2112 struct bt_mesh_msg_ctx *ctx,
2113 struct net_buf_simple *buf)
2114 {
2115 uint16_t min, max;
2116
2117 min = net_buf_simple_pull_le16(buf);
2118 max = net_buf_simple_pull_le16(buf);
2119
2120 /* This is as per 6.1.3.1 in Mesh Model Specification */
2121 if (min < TEMP_MIN || min > TEMP_MAX ||
2122 max < TEMP_MIN || max > TEMP_MAX) {
2123 return 0;
2124 }
2125
2126 if (min <= max) {
2127 ctl->temp->status_code = RANGE_SUCCESSFULLY_UPDATED;
2128
2129 if (ctl->temp->range_min != min ||
2130 ctl->temp->range_max != max) {
2131
2132 ctl->temp->range_min = min;
2133 ctl->temp->range_max = max;
2134
2135 (void)light_ctl_temp_range_get(model, ctx, buf);
2136 light_ctl_temp_range_publish(model);
2137 save_on_flash(TEMPERATURE_RANGE);
2138 } else {
2139 (void)light_ctl_temp_range_get(model, ctx, buf);
2140 }
2141 } else {
2142 /* The provided value for Range Max cannot be set */
2143 ctl->temp->status_code = CANNOT_SET_RANGE_MAX;
2144 return 0;
2145 }
2146
2147 return 0;
2148 }
2149
2150 /* Light CTL Client message handlers */
light_ctl_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2151 static int light_ctl_status(const struct bt_mesh_model *model,
2152 struct bt_mesh_msg_ctx *ctx,
2153 struct net_buf_simple *buf)
2154 {
2155 printk("Acknowledgement from LIGHT_CTL_SRV\n");
2156 printk("Present CTL Lightness = %04x\n", net_buf_simple_pull_le16(buf));
2157 printk("Present CTL Temperature = %04x\n",
2158 net_buf_simple_pull_le16(buf));
2159
2160 if (buf->len == 5U) {
2161 printk("Target CTL Lightness = %04x\n",
2162 net_buf_simple_pull_le16(buf));
2163 printk("Target CTL Temperature = %04x\n",
2164 net_buf_simple_pull_le16(buf));
2165 printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf));
2166 }
2167
2168 return 0;
2169 }
2170
light_ctl_temp_range_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2171 static int light_ctl_temp_range_status(const struct bt_mesh_model *model,
2172 struct bt_mesh_msg_ctx *ctx,
2173 struct net_buf_simple *buf)
2174 {
2175 printk("Acknowledgement from LIGHT_CTL_SRV (Temperature Range)\n");
2176 printk("Status Code = %02x\n", net_buf_simple_pull_u8(buf));
2177 printk("Range Min = %04x\n", net_buf_simple_pull_le16(buf));
2178 printk("Range Max = %04x\n", net_buf_simple_pull_le16(buf));
2179
2180 return 0;
2181 }
2182
light_ctl_temp_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2183 static int light_ctl_temp_status(const struct bt_mesh_model *model,
2184 struct bt_mesh_msg_ctx *ctx,
2185 struct net_buf_simple *buf)
2186 {
2187 printk("Acknowledgement from LIGHT_CTL_TEMP_SRV\n");
2188 printk("Present CTL Temperature = %04x\n",
2189 net_buf_simple_pull_le16(buf));
2190 printk("Present CTL Delta UV = %04x\n",
2191 net_buf_simple_pull_le16(buf));
2192
2193 if (buf->len == 5U) {
2194 printk("Target CTL Temperature = %04x\n",
2195 net_buf_simple_pull_le16(buf));
2196 printk("Target CTL Delta UV = %04x\n",
2197 net_buf_simple_pull_le16(buf));
2198 printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf));
2199 }
2200
2201 return 0;
2202 }
2203
light_ctl_default_status(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2204 static int light_ctl_default_status(const struct bt_mesh_model *model,
2205 struct bt_mesh_msg_ctx *ctx,
2206 struct net_buf_simple *buf)
2207 {
2208 printk("Acknowledgement from LIGHT_CTL_SRV (Default)\n");
2209 printk("Lightness = %04x\n", net_buf_simple_pull_le16(buf));
2210 printk("Temperature = %04x\n", net_buf_simple_pull_le16(buf));
2211 printk("Delta UV = %04x\n", net_buf_simple_pull_le16(buf));
2212
2213 return 0;
2214 }
2215
2216 /* Light CTL Temp. Server message handlers */
light_ctl_temp_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2217 static int light_ctl_temp_get(const struct bt_mesh_model *model,
2218 struct bt_mesh_msg_ctx *ctx,
2219 struct net_buf_simple *buf)
2220 {
2221 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 9 + 4);
2222
2223 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_CTL_TEMP_STATUS);
2224 net_buf_simple_add_le16(msg, (uint16_t) get_current(CTL_TEMP));
2225 net_buf_simple_add_le16(msg, (int16_t) get_current(CTL_DELTA_UV));
2226
2227 if (ctl->temp->current == ctl->temp->target &&
2228 ctl->duv->current == ctl->duv->target) {
2229 goto send;
2230 }
2231
2232 if (ctl->transition->counter) {
2233 calculate_rt(ctl->transition);
2234 net_buf_simple_add_le16(msg, (uint16_t) get_target(CTL_TEMP));
2235 net_buf_simple_add_le16(msg, (int16_t) get_target(CTL_DELTA_UV));
2236 net_buf_simple_add_u8(msg, ctl->transition->rt);
2237 }
2238
2239 send:
2240 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
2241 printk("Unable to send LightCTL Temp. Status response\n");
2242 }
2243
2244 return 0;
2245 }
2246
light_ctl_temp_publish(const struct bt_mesh_model * model)2247 void light_ctl_temp_publish(const struct bt_mesh_model *model)
2248 {
2249 int err;
2250 struct net_buf_simple *msg = model->pub->msg;
2251
2252 if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
2253 return;
2254 }
2255
2256 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_CTL_TEMP_STATUS);
2257 net_buf_simple_add_le16(msg, (uint16_t) get_current(CTL_TEMP));
2258 net_buf_simple_add_le16(msg, (int16_t) get_current(CTL_DELTA_UV));
2259
2260 if (ctl->transition->counter) {
2261 calculate_rt(ctl->transition);
2262 net_buf_simple_add_le16(msg, (uint16_t) get_target(CTL_TEMP));
2263 net_buf_simple_add_le16(msg, (int16_t) get_target(CTL_DELTA_UV));
2264 net_buf_simple_add_u8(msg, ctl->transition->rt);
2265 }
2266
2267 err = bt_mesh_model_publish(model);
2268 if (err) {
2269 printk("bt_mesh_model_publish err %d\n", err);
2270 }
2271 }
2272
light_ctl_temp_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2273 static int light_ctl_temp_set_unack(const struct bt_mesh_model *model,
2274 struct bt_mesh_msg_ctx *ctx,
2275 struct net_buf_simple *buf)
2276 {
2277 uint8_t tid, tt, delay;
2278 int16_t delta_uv;
2279 uint16_t temp;
2280 int64_t now;
2281
2282 temp = net_buf_simple_pull_le16(buf);
2283 delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
2284 tid = net_buf_simple_pull_u8(buf);
2285
2286 if (temp < TEMP_MIN || temp > TEMP_MAX) {
2287 return 0;
2288 }
2289
2290 now = k_uptime_get();
2291 if (ctl->last_tid == tid &&
2292 ctl->last_src_addr == ctx->addr &&
2293 ctl->last_dst_addr == ctx->recv_dst &&
2294 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
2295 return 0;
2296 }
2297
2298 switch (buf->len) {
2299 case 0x00: /* No optional fields are available */
2300 tt = ctl->tt;
2301 delay = 0U;
2302 break;
2303 case 0x02: /* Optional fields are available */
2304 tt = net_buf_simple_pull_u8(buf);
2305 if ((tt & 0x3F) == 0x3F) {
2306 return 0;
2307 }
2308
2309 delay = net_buf_simple_pull_u8(buf);
2310 break;
2311 default:
2312 return 0;
2313 }
2314
2315 ctl->transition->counter = 0U;
2316 k_timer_stop(&ctl->transition->timer);
2317
2318 ctl->last_tid = tid;
2319 ctl->last_src_addr = ctx->addr;
2320 ctl->last_dst_addr = ctx->recv_dst;
2321 ctl->last_msg_timestamp = now;
2322 ctl->transition->tt = tt;
2323 ctl->transition->delay = delay;
2324 ctl->transition->type = NON_MOVE;
2325 set_target(CTL_TEMP, &temp);
2326 set_target(CTL_DELTA_UV, &delta_uv);
2327
2328 if (ctl->temp->target != ctl->temp->current ||
2329 ctl->duv->target != ctl->duv->current) {
2330 set_transition_values(CTL_TEMP);
2331 } else {
2332 return 0;
2333 }
2334
2335 /* For Instantaneous Transition */
2336 if (ctl->transition->counter == 0U) {
2337 ctl->temp->current = ctl->temp->target;
2338 ctl->duv->current = ctl->duv->target;
2339 }
2340
2341 ctl->transition->just_started = true;
2342 light_ctl_temp_publish(model);
2343 light_ctl_temp_handler();
2344
2345 return 0;
2346 }
2347
light_ctl_temp_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2348 static int light_ctl_temp_set(const struct bt_mesh_model *model,
2349 struct bt_mesh_msg_ctx *ctx,
2350 struct net_buf_simple *buf)
2351 {
2352 uint8_t tid, tt, delay;
2353 int16_t delta_uv;
2354 uint16_t temp;
2355 int64_t now;
2356
2357 temp = net_buf_simple_pull_le16(buf);
2358 delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
2359 tid = net_buf_simple_pull_u8(buf);
2360
2361 if (temp < TEMP_MIN || temp > TEMP_MAX) {
2362 return 0;
2363 }
2364
2365 now = k_uptime_get();
2366 if (ctl->last_tid == tid &&
2367 ctl->last_src_addr == ctx->addr &&
2368 ctl->last_dst_addr == ctx->recv_dst &&
2369 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
2370 (void)light_ctl_temp_get(model, ctx, buf);
2371 return 0;
2372 }
2373
2374 switch (buf->len) {
2375 case 0x00: /* No optional fields are available */
2376 tt = ctl->tt;
2377 delay = 0U;
2378 break;
2379 case 0x02: /* Optional fields are available */
2380 tt = net_buf_simple_pull_u8(buf);
2381 if ((tt & 0x3F) == 0x3F) {
2382 return 0;
2383 }
2384
2385 delay = net_buf_simple_pull_u8(buf);
2386 break;
2387 default:
2388 return 0;
2389 }
2390
2391 ctl->transition->counter = 0U;
2392 k_timer_stop(&ctl->transition->timer);
2393
2394 ctl->last_tid = tid;
2395 ctl->last_src_addr = ctx->addr;
2396 ctl->last_dst_addr = ctx->recv_dst;
2397 ctl->last_msg_timestamp = now;
2398 ctl->transition->tt = tt;
2399 ctl->transition->delay = delay;
2400 ctl->transition->type = NON_MOVE;
2401 set_target(CTL_TEMP, &temp);
2402 set_target(CTL_DELTA_UV, &delta_uv);
2403
2404 if (ctl->temp->target != ctl->temp->current ||
2405 ctl->duv->target != ctl->duv->current) {
2406 set_transition_values(CTL_TEMP);
2407 } else {
2408 (void)light_ctl_temp_get(model, ctx, buf);
2409 return 0;
2410 }
2411
2412 /* For Instantaneous Transition */
2413 if (ctl->transition->counter == 0U) {
2414 ctl->temp->current = ctl->temp->target;
2415 ctl->duv->current = ctl->duv->target;
2416 }
2417
2418 ctl->transition->just_started = true;
2419 (void)light_ctl_temp_get(model, ctx, buf);
2420 light_ctl_temp_publish(model);
2421 light_ctl_temp_handler();
2422
2423 return 0;
2424 }
2425
2426 /* Generic Level (TEMPERATURE) Server message handlers */
gen_level_get_temp(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2427 static int gen_level_get_temp(const struct bt_mesh_model *model,
2428 struct bt_mesh_msg_ctx *ctx,
2429 struct net_buf_simple *buf)
2430 {
2431 struct net_buf_simple *msg = NET_BUF_SIMPLE(2 + 5 + 4);
2432
2433 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_LEVEL_STATUS);
2434 net_buf_simple_add_le16(msg, (int16_t) get_current(LEVEL_TEMP));
2435
2436 if (ctl->temp->current == ctl->temp->target) {
2437 goto send;
2438 }
2439
2440 if (ctl->transition->counter) {
2441 calculate_rt(ctl->transition);
2442 net_buf_simple_add_le16(msg, (int16_t) get_target(LEVEL_TEMP));
2443 net_buf_simple_add_u8(msg, ctl->transition->rt);
2444 }
2445
2446 send:
2447 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
2448 printk("Unable to send GEN_LEVEL_SRV Status response\n");
2449 }
2450
2451 return 0;
2452 }
2453
gen_level_publish_temp(const struct bt_mesh_model * model)2454 void gen_level_publish_temp(const struct bt_mesh_model *model)
2455 {
2456 int err;
2457 struct net_buf_simple *msg = model->pub->msg;
2458
2459 if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
2460 return;
2461 }
2462
2463 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_LEVEL_STATUS);
2464 net_buf_simple_add_le16(msg, (int16_t) get_current(LEVEL_TEMP));
2465
2466 if (ctl->transition->counter) {
2467 calculate_rt(ctl->transition);
2468 net_buf_simple_add_le16(msg, (int16_t) get_target(LEVEL_TEMP));
2469 net_buf_simple_add_u8(msg, ctl->transition->rt);
2470 }
2471
2472 err = bt_mesh_model_publish(model);
2473 if (err) {
2474 printk("bt_mesh_model_publish err %d\n", err);
2475 }
2476 }
2477
gen_level_set_unack_temp(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2478 static int gen_level_set_unack_temp(const struct bt_mesh_model *model,
2479 struct bt_mesh_msg_ctx *ctx,
2480 struct net_buf_simple *buf)
2481 {
2482 uint8_t tid, tt, delay;
2483 int16_t level;
2484 int64_t now;
2485
2486 level = (int16_t) net_buf_simple_pull_le16(buf);
2487 tid = net_buf_simple_pull_u8(buf);
2488
2489 now = k_uptime_get();
2490 if (ctl->last_tid == tid &&
2491 ctl->last_src_addr == ctx->addr &&
2492 ctl->last_dst_addr == ctx->recv_dst &&
2493 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
2494 return 0;
2495 }
2496
2497 switch (buf->len) {
2498 case 0x00: /* No optional fields are available */
2499 tt = ctl->tt;
2500 delay = 0U;
2501 break;
2502 case 0x02: /* Optional fields are available */
2503 tt = net_buf_simple_pull_u8(buf);
2504 if ((tt & 0x3F) == 0x3F) {
2505 return 0;
2506 }
2507
2508 delay = net_buf_simple_pull_u8(buf);
2509 break;
2510 default:
2511 return 0;
2512 }
2513
2514 ctl->transition->counter = 0U;
2515 k_timer_stop(&ctl->transition->timer);
2516
2517 ctl->last_tid = tid;
2518 ctl->last_src_addr = ctx->addr;
2519 ctl->last_dst_addr = ctx->recv_dst;
2520 ctl->last_msg_timestamp = now;
2521 ctl->transition->tt = tt;
2522 ctl->transition->delay = delay;
2523 ctl->transition->type = NON_MOVE;
2524 set_target(LEVEL_TEMP, &level);
2525
2526 if (ctl->temp->target != ctl->temp->current) {
2527 set_transition_values(LEVEL_TEMP);
2528 } else {
2529 return 0;
2530 }
2531
2532 /* For Instantaneous Transition */
2533 if (ctl->transition->counter == 0U) {
2534 ctl->temp->current = ctl->temp->target;
2535 }
2536
2537 ctl->transition->just_started = true;
2538 gen_level_publish_temp(model);
2539 level_temp_handler();
2540
2541 return 0;
2542 }
2543
gen_level_set_temp(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2544 static int gen_level_set_temp(const struct bt_mesh_model *model,
2545 struct bt_mesh_msg_ctx *ctx,
2546 struct net_buf_simple *buf)
2547 {
2548 uint8_t tid, tt, delay;
2549 int16_t level;
2550 int64_t now;
2551
2552 level = (int16_t) net_buf_simple_pull_le16(buf);
2553 tid = net_buf_simple_pull_u8(buf);
2554
2555 now = k_uptime_get();
2556 if (ctl->last_tid == tid &&
2557 ctl->last_src_addr == ctx->addr &&
2558 ctl->last_dst_addr == ctx->recv_dst &&
2559 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
2560 (void)gen_level_get_temp(model, ctx, buf);
2561 return 0;
2562 }
2563
2564 switch (buf->len) {
2565 case 0x00: /* No optional fields are available */
2566 tt = ctl->tt;
2567 delay = 0U;
2568 break;
2569 case 0x02: /* Optional fields are available */
2570 tt = net_buf_simple_pull_u8(buf);
2571 if ((tt & 0x3F) == 0x3F) {
2572 return 0;
2573 }
2574
2575 delay = net_buf_simple_pull_u8(buf);
2576 break;
2577 default:
2578 return 0;
2579 }
2580
2581 ctl->transition->counter = 0U;
2582 k_timer_stop(&ctl->transition->timer);
2583
2584 ctl->last_tid = tid;
2585 ctl->last_src_addr = ctx->addr;
2586 ctl->last_dst_addr = ctx->recv_dst;
2587 ctl->last_msg_timestamp = now;
2588 ctl->transition->tt = tt;
2589 ctl->transition->delay = delay;
2590 ctl->transition->type = NON_MOVE;
2591 set_target(LEVEL_TEMP, &level);
2592
2593 if (ctl->temp->target != ctl->temp->current) {
2594 set_transition_values(LEVEL_TEMP);
2595 } else {
2596 (void)gen_level_get_temp(model, ctx, buf);
2597 return 0;
2598 }
2599
2600 /* For Instantaneous Transition */
2601 if (ctl->transition->counter == 0U) {
2602 ctl->temp->current = ctl->temp->target;
2603 }
2604
2605 ctl->transition->just_started = true;
2606 (void)gen_level_get_temp(model, ctx, buf);
2607 gen_level_publish_temp(model);
2608 level_temp_handler();
2609
2610 return 0;
2611 }
2612
gen_delta_set_unack_temp(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2613 static int gen_delta_set_unack_temp(const struct bt_mesh_model *model,
2614 struct bt_mesh_msg_ctx *ctx,
2615 struct net_buf_simple *buf)
2616 {
2617 uint8_t tid, tt, delay;
2618 static int16_t last_level;
2619 int32_t target, delta;
2620 int64_t now;
2621
2622 delta = (int32_t) net_buf_simple_pull_le32(buf);
2623 tid = net_buf_simple_pull_u8(buf);
2624
2625 now = k_uptime_get();
2626 if (ctl->last_tid == tid &&
2627 ctl->last_src_addr == ctx->addr &&
2628 ctl->last_dst_addr == ctx->recv_dst &&
2629 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
2630
2631 if (ctl->temp->delta == delta) {
2632 return 0;
2633 }
2634 target = last_level + delta;
2635
2636 } else {
2637 last_level = (int16_t) get_current(LEVEL_TEMP);
2638 target = last_level + delta;
2639 }
2640
2641 switch (buf->len) {
2642 case 0x00: /* No optional fields are available */
2643 tt = ctl->tt;
2644 delay = 0U;
2645 break;
2646 case 0x02: /* Optional fields are available */
2647 tt = net_buf_simple_pull_u8(buf);
2648 if ((tt & 0x3F) == 0x3F) {
2649 return 0;
2650 }
2651
2652 delay = net_buf_simple_pull_u8(buf);
2653 break;
2654 default:
2655 return 0;
2656 }
2657
2658 ctl->transition->counter = 0U;
2659 k_timer_stop(&ctl->transition->timer);
2660
2661 ctl->last_tid = tid;
2662 ctl->last_src_addr = ctx->addr;
2663 ctl->last_dst_addr = ctx->recv_dst;
2664 ctl->last_msg_timestamp = now;
2665 ctl->transition->tt = tt;
2666 ctl->transition->delay = delay;
2667 ctl->transition->type = NON_MOVE;
2668
2669 if (target < INT16_MIN) {
2670 target = INT16_MIN;
2671 } else if (target > INT16_MAX) {
2672 target = INT16_MAX;
2673 }
2674
2675 set_target(LEVEL_TEMP, &target);
2676
2677 if (ctl->temp->target != ctl->temp->current) {
2678 set_transition_values(LEVEL_TEMP);
2679 } else {
2680 return 0;
2681 }
2682
2683 /* For Instantaneous Transition */
2684 if (ctl->transition->counter == 0U) {
2685 ctl->temp->current = ctl->temp->target;
2686 }
2687
2688 ctl->transition->just_started = true;
2689 gen_level_publish_temp(model);
2690 level_temp_handler();
2691
2692 return 0;
2693 }
2694
gen_delta_set_temp(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2695 static int gen_delta_set_temp(const struct bt_mesh_model *model,
2696 struct bt_mesh_msg_ctx *ctx,
2697 struct net_buf_simple *buf)
2698 {
2699 uint8_t tid, tt, delay;
2700 static int16_t last_level;
2701 int32_t target, delta;
2702 int64_t now;
2703
2704 delta = (int32_t) net_buf_simple_pull_le32(buf);
2705 tid = net_buf_simple_pull_u8(buf);
2706
2707 now = k_uptime_get();
2708 if (ctl->last_tid == tid &&
2709 ctl->last_src_addr == ctx->addr &&
2710 ctl->last_dst_addr == ctx->recv_dst &&
2711 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
2712
2713 if (ctl->temp->delta == delta) {
2714 (void)gen_level_get_temp(model, ctx, buf);
2715 return 0;
2716 }
2717 target = last_level + delta;
2718
2719 } else {
2720 last_level = (int16_t) get_current(LEVEL_TEMP);
2721 target = last_level + delta;
2722 }
2723
2724 switch (buf->len) {
2725 case 0x00: /* No optional fields are available */
2726 tt = ctl->tt;
2727 delay = 0U;
2728 break;
2729 case 0x02: /* Optional fields are available */
2730 tt = net_buf_simple_pull_u8(buf);
2731 if ((tt & 0x3F) == 0x3F) {
2732 return 0;
2733 }
2734
2735 delay = net_buf_simple_pull_u8(buf);
2736 break;
2737 default:
2738 return 0;
2739 }
2740
2741 ctl->transition->counter = 0U;
2742 k_timer_stop(&ctl->transition->timer);
2743
2744 ctl->last_tid = tid;
2745 ctl->last_src_addr = ctx->addr;
2746 ctl->last_dst_addr = ctx->recv_dst;
2747 ctl->last_msg_timestamp = now;
2748 ctl->transition->tt = tt;
2749 ctl->transition->delay = delay;
2750 ctl->transition->type = NON_MOVE;
2751
2752 if (target < INT16_MIN) {
2753 target = INT16_MIN;
2754 } else if (target > INT16_MAX) {
2755 target = INT16_MAX;
2756 }
2757
2758 set_target(LEVEL_TEMP, &target);
2759
2760 if (ctl->temp->target != ctl->temp->current) {
2761 set_transition_values(LEVEL_TEMP);
2762 } else {
2763 (void)gen_level_get_temp(model, ctx, buf);
2764 return 0;
2765 }
2766
2767 /* For Instantaneous Transition */
2768 if (ctl->transition->counter == 0U) {
2769 ctl->temp->current = ctl->temp->target;
2770 }
2771
2772 ctl->transition->just_started = true;
2773 (void)gen_level_get_temp(model, ctx, buf);
2774 gen_level_publish_temp(model);
2775 level_temp_handler();
2776
2777 return 0;
2778 }
2779
gen_move_set_unack_temp(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2780 static int gen_move_set_unack_temp(const struct bt_mesh_model *model,
2781 struct bt_mesh_msg_ctx *ctx,
2782 struct net_buf_simple *buf)
2783 {
2784 uint8_t tid, tt, delay;
2785 int16_t delta;
2786 uint16_t target;
2787 int64_t now;
2788
2789 delta = (int16_t) net_buf_simple_pull_le16(buf);
2790 tid = net_buf_simple_pull_u8(buf);
2791
2792 now = k_uptime_get();
2793 if (ctl->last_tid == tid &&
2794 ctl->last_src_addr == ctx->addr &&
2795 ctl->last_dst_addr == ctx->recv_dst &&
2796 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
2797 return 0;
2798 }
2799
2800 switch (buf->len) {
2801 case 0x00: /* No optional fields are available */
2802 tt = ctl->tt;
2803 delay = 0U;
2804 break;
2805 case 0x02: /* Optional fields are available */
2806 tt = net_buf_simple_pull_u8(buf);
2807 if ((tt & 0x3F) == 0x3F) {
2808 return 0;
2809 }
2810
2811 delay = net_buf_simple_pull_u8(buf);
2812 break;
2813 default:
2814 return 0;
2815 }
2816
2817 ctl->transition->counter = 0U;
2818 k_timer_stop(&ctl->transition->timer);
2819
2820 ctl->last_tid = tid;
2821 ctl->last_src_addr = ctx->addr;
2822 ctl->last_dst_addr = ctx->recv_dst;
2823 ctl->last_msg_timestamp = now;
2824 ctl->transition->tt = tt;
2825 ctl->transition->delay = delay;
2826 ctl->transition->type = MOVE;
2827 ctl->temp->delta = delta;
2828
2829 if (delta < 0) {
2830 target = ctl->temp->range_min;
2831 } else if (delta > 0) {
2832 target = ctl->temp->range_max;
2833 } else if (delta == 0) {
2834 target = ctl->temp->current;
2835 }
2836 set_target(MOVE_TEMP, &target);
2837
2838 if (ctl->temp->target != ctl->temp->current) {
2839 set_transition_values(MOVE_TEMP);
2840 } else {
2841 return 0;
2842 }
2843
2844 if (ctl->transition->counter == 0U) {
2845 return 0;
2846 }
2847
2848 ctl->transition->just_started = true;
2849 gen_level_publish_temp(model);
2850 level_temp_handler();
2851
2852 return 0;
2853 }
2854
gen_move_set_temp(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2855 static int gen_move_set_temp(const struct bt_mesh_model *model,
2856 struct bt_mesh_msg_ctx *ctx,
2857 struct net_buf_simple *buf)
2858 {
2859 uint8_t tid, tt, delay;
2860 int16_t delta;
2861 uint16_t target;
2862 int64_t now;
2863
2864 delta = (int16_t) net_buf_simple_pull_le16(buf);
2865 tid = net_buf_simple_pull_u8(buf);
2866
2867 now = k_uptime_get();
2868 if (ctl->last_tid == tid &&
2869 ctl->last_src_addr == ctx->addr &&
2870 ctl->last_dst_addr == ctx->recv_dst &&
2871 (now - ctl->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
2872 (void)gen_level_get_temp(model, ctx, buf);
2873 return 0;
2874 }
2875
2876 switch (buf->len) {
2877 case 0x00: /* No optional fields are available */
2878 tt = ctl->tt;
2879 delay = 0U;
2880 break;
2881 case 0x02: /* Optional fields are available */
2882 tt = net_buf_simple_pull_u8(buf);
2883 if ((tt & 0x3F) == 0x3F) {
2884 return 0;
2885 }
2886
2887 delay = net_buf_simple_pull_u8(buf);
2888 break;
2889 default:
2890 return 0;
2891 }
2892
2893 ctl->transition->counter = 0U;
2894 k_timer_stop(&ctl->transition->timer);
2895
2896 ctl->last_tid = tid;
2897 ctl->last_src_addr = ctx->addr;
2898 ctl->last_dst_addr = ctx->recv_dst;
2899 ctl->last_msg_timestamp = now;
2900 ctl->transition->tt = tt;
2901 ctl->transition->delay = delay;
2902 ctl->transition->type = MOVE;
2903 ctl->temp->delta = delta;
2904
2905 if (delta < 0) {
2906 target = ctl->temp->range_min;
2907 } else if (delta > 0) {
2908 target = ctl->temp->range_max;
2909 } else if (delta == 0) {
2910 target = ctl->temp->current;
2911 }
2912 set_target(MOVE_TEMP, &target);
2913
2914 if (ctl->temp->target != ctl->temp->current) {
2915 set_transition_values(MOVE_TEMP);
2916 } else {
2917 (void)gen_level_get_temp(model, ctx, buf);
2918 return 0;
2919 }
2920
2921 if (ctl->transition->counter == 0U) {
2922 return 0;
2923 }
2924
2925 ctl->transition->just_started = true;
2926 (void)gen_level_get_temp(model, ctx, buf);
2927 gen_level_publish_temp(model);
2928 level_temp_handler();
2929
2930 return 0;
2931 }
2932
2933 /* Generic Level (TEMPERATURE) Client message handlers */
gen_level_status_temp(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2934 static int gen_level_status_temp(const struct bt_mesh_model *model,
2935 struct bt_mesh_msg_ctx *ctx,
2936 struct net_buf_simple *buf)
2937 {
2938 printk("Acknowledgement from GEN_LEVEL_SRV\n");
2939 printk("Present Level = %04x\n", net_buf_simple_pull_le16(buf));
2940
2941 if (buf->len == 3U) {
2942 printk("Target Level = %04x\n", net_buf_simple_pull_le16(buf));
2943 printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf));
2944 }
2945
2946 return 0;
2947 }
2948
2949
2950 /* message handlers (End) */
2951
2952 /* Mapping of message handlers for Generic OnOff Server (0x1000) */
2953 static const struct bt_mesh_model_op gen_onoff_srv_op[] = {
2954 { BT_MESH_MODEL_OP_2(0x82, 0x01), BT_MESH_LEN_EXACT(0), gen_onoff_get },
2955 { BT_MESH_MODEL_OP_2(0x82, 0x02), BT_MESH_LEN_MIN(2), gen_onoff_set },
2956 { BT_MESH_MODEL_OP_2(0x82, 0x03), BT_MESH_LEN_MIN(2), gen_onoff_set_unack },
2957 BT_MESH_MODEL_OP_END,
2958 };
2959
2960 /* Mapping of message handlers for Generic OnOff Client (0x1001) */
2961 static const struct bt_mesh_model_op gen_onoff_cli_op[] = {
2962 { BT_MESH_MODEL_OP_2(0x82, 0x04), BT_MESH_LEN_MIN(1), gen_onoff_status },
2963 BT_MESH_MODEL_OP_END,
2964 };
2965
2966 /* Mapping of message handlers for Generic Level (Light) Server (0x1002) */
2967 static const struct bt_mesh_model_op gen_level_srv_op[] = {
2968 { BT_MESH_MODEL_OP_2(0x82, 0x05), BT_MESH_LEN_EXACT(0), gen_level_get },
2969 { BT_MESH_MODEL_OP_2(0x82, 0x06), BT_MESH_LEN_MIN(3), gen_level_set },
2970 { BT_MESH_MODEL_OP_2(0x82, 0x07), BT_MESH_LEN_MIN(3), gen_level_set_unack },
2971 { BT_MESH_MODEL_OP_2(0x82, 0x09), BT_MESH_LEN_MIN(5), gen_delta_set },
2972 { BT_MESH_MODEL_OP_2(0x82, 0x0A), BT_MESH_LEN_MIN(5), gen_delta_set_unack },
2973 { BT_MESH_MODEL_OP_2(0x82, 0x0B), BT_MESH_LEN_MIN(3), gen_move_set },
2974 { BT_MESH_MODEL_OP_2(0x82, 0x0C), BT_MESH_LEN_MIN(3), gen_move_set_unack },
2975 BT_MESH_MODEL_OP_END,
2976 };
2977
2978 /* Mapping of message handlers for Generic Level (Light) Client (0x1003) */
2979 static const struct bt_mesh_model_op gen_level_cli_op[] = {
2980 { BT_MESH_MODEL_OP_2(0x82, 0x08), BT_MESH_LEN_MIN(2), gen_level_status },
2981 BT_MESH_MODEL_OP_END,
2982 };
2983
2984 /* Mapping of message handlers for Generic Default TT Server (0x1004) */
2985 static const struct bt_mesh_model_op gen_def_trans_time_srv_op[] = {
2986 { BT_MESH_MODEL_OP_2(0x82, 0x0D), BT_MESH_LEN_EXACT(0), gen_def_trans_time_get },
2987 { BT_MESH_MODEL_OP_2(0x82, 0x0E), BT_MESH_LEN_EXACT(1), gen_def_trans_time_set },
2988 { BT_MESH_MODEL_OP_2(0x82, 0x0F), BT_MESH_LEN_EXACT(1), gen_def_trans_time_set_unack },
2989 BT_MESH_MODEL_OP_END,
2990 };
2991
2992 /* Mapping of message handlers for Generic Default TT Client (0x1005) */
2993 static const struct bt_mesh_model_op gen_def_trans_time_cli_op[] = {
2994 { BT_MESH_MODEL_OP_2(0x82, 0x10), BT_MESH_LEN_EXACT(1), gen_def_trans_time_status },
2995 BT_MESH_MODEL_OP_END,
2996 };
2997
2998 /* Mapping of message handlers for Generic Power OnOff Server (0x1006) */
2999 static const struct bt_mesh_model_op gen_power_onoff_srv_op[] = {
3000 { BT_MESH_MODEL_OP_2(0x82, 0x11), BT_MESH_LEN_MIN(0), gen_onpowerup_get },
3001 BT_MESH_MODEL_OP_END,
3002 };
3003
3004 /* Mapping of message handlers for Generic Power OnOff Setup Server (0x1007) */
3005 static const struct bt_mesh_model_op gen_power_onoff_setup_srv_op[] = {
3006 { BT_MESH_MODEL_OP_2(0x82, 0x13), BT_MESH_LEN_EXACT(1), gen_onpowerup_set },
3007 { BT_MESH_MODEL_OP_2(0x82, 0x14), BT_MESH_LEN_EXACT(1), gen_onpowerup_set_unack },
3008 BT_MESH_MODEL_OP_END,
3009 };
3010
3011 /* Mapping of message handlers for Generic Power OnOff Client (0x1008) */
3012 static const struct bt_mesh_model_op gen_power_onoff_cli_op[] = {
3013 { BT_MESH_MODEL_OP_2(0x82, 0x12), BT_MESH_LEN_EXACT(1), gen_onpowerup_status },
3014 BT_MESH_MODEL_OP_END,
3015 };
3016
3017 /* Mapping of message handlers for Light Lightness Server (0x1300) */
3018 static const struct bt_mesh_model_op light_lightness_srv_op[] = {
3019 { BT_MESH_MODEL_OP_2(0x82, 0x4B), BT_MESH_LEN_EXACT(0), light_lightness_get },
3020 { BT_MESH_MODEL_OP_2(0x82, 0x4C), BT_MESH_LEN_MIN(3), light_lightness_set },
3021 { BT_MESH_MODEL_OP_2(0x82, 0x4D), BT_MESH_LEN_MIN(3), light_lightness_set_unack },
3022 { BT_MESH_MODEL_OP_2(0x82, 0x4F), BT_MESH_LEN_EXACT(0), light_lightness_linear_get },
3023 { BT_MESH_MODEL_OP_2(0x82, 0x50), BT_MESH_LEN_MIN(3), light_lightness_linear_set },
3024 { BT_MESH_MODEL_OP_2(0x82, 0x51), BT_MESH_LEN_MIN(3),
3025 light_lightness_linear_set_unack },
3026 { BT_MESH_MODEL_OP_2(0x82, 0x53), BT_MESH_LEN_EXACT(0), light_lightness_last_get },
3027 { BT_MESH_MODEL_OP_2(0x82, 0x55), BT_MESH_LEN_EXACT(0), light_lightness_default_get },
3028 { BT_MESH_MODEL_OP_2(0x82, 0x57), BT_MESH_LEN_EXACT(0), light_lightness_range_get },
3029 BT_MESH_MODEL_OP_END,
3030 };
3031
3032 /* Mapping of message handlers for Light Lightness Setup Server (0x1301) */
3033 static const struct bt_mesh_model_op light_lightness_setup_srv_op[] = {
3034 { BT_MESH_MODEL_OP_2(0x82, 0x59), BT_MESH_LEN_EXACT(2), light_lightness_default_set },
3035 { BT_MESH_MODEL_OP_2(0x82, 0x5A), BT_MESH_LEN_EXACT(2),
3036 light_lightness_default_set_unack },
3037 { BT_MESH_MODEL_OP_2(0x82, 0x5B), BT_MESH_LEN_EXACT(4), light_lightness_range_set },
3038 { BT_MESH_MODEL_OP_2(0x82, 0x5C), BT_MESH_LEN_EXACT(4), light_lightness_range_set_unack },
3039 BT_MESH_MODEL_OP_END,
3040 };
3041
3042 /* Mapping of message handlers for Light Lightness Client (0x1302) */
3043 static const struct bt_mesh_model_op light_lightness_cli_op[] = {
3044 { BT_MESH_MODEL_OP_2(0x82, 0x4E), BT_MESH_LEN_MIN(2), light_lightness_status },
3045 { BT_MESH_MODEL_OP_2(0x82, 0x52), BT_MESH_LEN_MIN(2), light_lightness_linear_status },
3046 { BT_MESH_MODEL_OP_2(0x82, 0x54), BT_MESH_LEN_EXACT(2), light_lightness_last_status },
3047 { BT_MESH_MODEL_OP_2(0x82, 0x56), BT_MESH_LEN_EXACT(2), light_lightness_default_status },
3048 { BT_MESH_MODEL_OP_2(0x82, 0x58), BT_MESH_LEN_EXACT(5), light_lightness_range_status },
3049 BT_MESH_MODEL_OP_END,
3050 };
3051
3052 /* Mapping of message handlers for Light CTL Server (0x1303) */
3053 static const struct bt_mesh_model_op light_ctl_srv_op[] = {
3054 { BT_MESH_MODEL_OP_2(0x82, 0x5D), BT_MESH_LEN_EXACT(0), light_ctl_get },
3055 { BT_MESH_MODEL_OP_2(0x82, 0x5E), BT_MESH_LEN_MIN(7), light_ctl_set },
3056 { BT_MESH_MODEL_OP_2(0x82, 0x5F), BT_MESH_LEN_MIN(7), light_ctl_set_unack },
3057 { BT_MESH_MODEL_OP_2(0x82, 0x62), BT_MESH_LEN_EXACT(0), light_ctl_temp_range_get },
3058 { BT_MESH_MODEL_OP_2(0x82, 0x67), BT_MESH_LEN_EXACT(0), light_ctl_default_get },
3059 BT_MESH_MODEL_OP_END,
3060 };
3061
3062 /* Mapping of message handlers for Light CTL Setup Server (0x1304) */
3063 static const struct bt_mesh_model_op light_ctl_setup_srv_op[] = {
3064 { BT_MESH_MODEL_OP_2(0x82, 0x69), BT_MESH_LEN_EXACT(6), light_ctl_default_set },
3065 { BT_MESH_MODEL_OP_2(0x82, 0x6A), BT_MESH_LEN_EXACT(6), light_ctl_default_set_unack },
3066 { BT_MESH_MODEL_OP_2(0x82, 0x6B), BT_MESH_LEN_EXACT(4), light_ctl_temp_range_set },
3067 { BT_MESH_MODEL_OP_2(0x82, 0x6C), BT_MESH_LEN_EXACT(4), light_ctl_temp_range_set_unack },
3068 BT_MESH_MODEL_OP_END,
3069 };
3070
3071 /* Mapping of message handlers for Light CTL Client (0x1305) */
3072 static const struct bt_mesh_model_op light_ctl_cli_op[] = {
3073 { BT_MESH_MODEL_OP_2(0x82, 0x60), BT_MESH_LEN_MIN(4), light_ctl_status },
3074 { BT_MESH_MODEL_OP_2(0x82, 0x63), BT_MESH_LEN_EXACT(5), light_ctl_temp_range_status },
3075 { BT_MESH_MODEL_OP_2(0x82, 0x66), BT_MESH_LEN_MIN(4), light_ctl_temp_status },
3076 { BT_MESH_MODEL_OP_2(0x82, 0x68), BT_MESH_LEN_EXACT(6), light_ctl_default_status },
3077 BT_MESH_MODEL_OP_END,
3078 };
3079
3080 /* Mapping of message handlers for Light CTL Temp. Server (0x1306) */
3081 static const struct bt_mesh_model_op light_ctl_temp_srv_op[] = {
3082 { BT_MESH_MODEL_OP_2(0x82, 0x61), BT_MESH_LEN_EXACT(0), light_ctl_temp_get },
3083 { BT_MESH_MODEL_OP_2(0x82, 0x64), BT_MESH_LEN_MIN(5), light_ctl_temp_set },
3084 { BT_MESH_MODEL_OP_2(0x82, 0x65), BT_MESH_LEN_MIN(5), light_ctl_temp_set_unack },
3085 BT_MESH_MODEL_OP_END,
3086 };
3087
3088 /* Mapping of message handlers for Vendor (0x4321) */
3089 static const struct bt_mesh_model_op vnd_ops[] = {
3090 { BT_MESH_MODEL_OP_3(0x01, CID_ZEPHYR), BT_MESH_LEN_EXACT(0), vnd_get },
3091 { BT_MESH_MODEL_OP_3(0x02, CID_ZEPHYR), BT_MESH_LEN_EXACT(3), vnd_set },
3092 { BT_MESH_MODEL_OP_3(0x03, CID_ZEPHYR), BT_MESH_LEN_EXACT(3), vnd_set_unack },
3093 { BT_MESH_MODEL_OP_3(0x04, CID_ZEPHYR), BT_MESH_LEN_EXACT(6), vnd_status },
3094 BT_MESH_MODEL_OP_END,
3095 };
3096
3097 /* Mapping of message handlers for Generic Level (Temp.) Server (0x1002) */
3098 static const struct bt_mesh_model_op gen_level_srv_op_temp[] = {
3099 { BT_MESH_MODEL_OP_2(0x82, 0x05), BT_MESH_LEN_EXACT(0), gen_level_get_temp },
3100 { BT_MESH_MODEL_OP_2(0x82, 0x06), BT_MESH_LEN_MIN(3), gen_level_set_temp },
3101 { BT_MESH_MODEL_OP_2(0x82, 0x07), BT_MESH_LEN_MIN(3), gen_level_set_unack_temp },
3102 { BT_MESH_MODEL_OP_2(0x82, 0x09), BT_MESH_LEN_MIN(5), gen_delta_set_temp },
3103 { BT_MESH_MODEL_OP_2(0x82, 0x0A), BT_MESH_LEN_MIN(5), gen_delta_set_unack_temp },
3104 { BT_MESH_MODEL_OP_2(0x82, 0x0B), BT_MESH_LEN_MIN(3), gen_move_set_temp },
3105 { BT_MESH_MODEL_OP_2(0x82, 0x0C), BT_MESH_LEN_MIN(3), gen_move_set_unack_temp },
3106 BT_MESH_MODEL_OP_END,
3107 };
3108
3109 /* Mapping of message handlers for Generic Level (Temp.) Client (0x1003) */
3110 static const struct bt_mesh_model_op gen_level_cli_op_temp[] = {
3111 { BT_MESH_MODEL_OP_2(0x82, 0x08), BT_MESH_LEN_MIN(2), gen_level_status_temp },
3112 BT_MESH_MODEL_OP_END,
3113 };
3114
3115 const struct bt_mesh_model root_models[] = {
3116 BT_MESH_MODEL_CFG_SRV,
3117 BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
3118
3119 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV,
3120 gen_onoff_srv_op, &gen_onoff_srv_pub_root,
3121 NULL),
3122 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI,
3123 gen_onoff_cli_op, &gen_onoff_cli_pub_root,
3124 NULL),
3125
3126 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_SRV,
3127 gen_level_srv_op, &gen_level_srv_pub_root,
3128 NULL),
3129 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_CLI,
3130 gen_level_cli_op, &gen_level_cli_pub_root,
3131 NULL),
3132
3133 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV,
3134 gen_def_trans_time_srv_op,
3135 &gen_def_trans_time_srv_pub,
3136 NULL),
3137 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_CLI,
3138 gen_def_trans_time_cli_op,
3139 &gen_def_trans_time_cli_pub,
3140 NULL),
3141
3142 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV,
3143 gen_power_onoff_srv_op, &gen_power_onoff_srv_pub,
3144 NULL),
3145 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV,
3146 gen_power_onoff_setup_srv_op,
3147 &gen_power_onoff_srv_pub,
3148 NULL),
3149 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_POWER_ONOFF_CLI,
3150 gen_power_onoff_cli_op, &gen_power_onoff_cli_pub,
3151 NULL),
3152
3153 BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV,
3154 light_lightness_srv_op, &light_lightness_srv_pub,
3155 NULL),
3156 BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV,
3157 light_lightness_setup_srv_op,
3158 &light_lightness_srv_pub,
3159 NULL),
3160 BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_CLI,
3161 light_lightness_cli_op, &light_lightness_cli_pub,
3162 NULL),
3163
3164 BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_CTL_SRV,
3165 light_ctl_srv_op, &light_ctl_srv_pub,
3166 NULL),
3167 BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV,
3168 light_ctl_setup_srv_op, &light_ctl_srv_pub,
3169 NULL),
3170 BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_CTL_CLI,
3171 light_ctl_cli_op, &light_ctl_cli_pub,
3172 NULL),
3173 };
3174
3175 const struct bt_mesh_model vnd_models[] = {
3176 BT_MESH_MODEL_VND(CID_ZEPHYR, 0x4321, vnd_ops,
3177 &vnd_pub, &vnd_user_data),
3178 };
3179
3180 const struct bt_mesh_model s0_models[] = {
3181 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_SRV,
3182 gen_level_srv_op_temp, &gen_level_srv_pub_s0,
3183 NULL),
3184 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_CLI,
3185 gen_level_cli_op_temp, &gen_level_cli_pub_s0,
3186 NULL),
3187
3188 BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV,
3189 light_ctl_temp_srv_op, &light_ctl_srv_pub,
3190 NULL),
3191 };
3192
3193 static const struct bt_mesh_elem elements[] = {
3194 BT_MESH_ELEM(0, root_models, vnd_models),
3195 BT_MESH_ELEM(0, s0_models, BT_MESH_MODEL_NONE),
3196 };
3197
3198 const struct bt_mesh_comp comp = {
3199 .cid = CID_ZEPHYR,
3200 .elem = elements,
3201 .elem_count = ARRAY_SIZE(elements),
3202 };
3203