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