1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <string.h>
9 #include <zephyr/sys/printk.h>
10
11 #include <zephyr/bluetooth/bluetooth.h>
12 #include <zephyr/bluetooth/mesh.h>
13 #include <zephyr/bluetooth/hci.h>
14
15 #include <zephyr/drivers/sensor.h>
16
17 #include "mesh.h"
18 #include "board.h"
19
20 #define MOD_LF 0x0000
21 #define OP_HELLO 0xbb
22 #define OP_HEARTBEAT 0xbc
23 #define OP_BADUSER 0xbd
24 #define OP_VND_HELLO BT_MESH_MODEL_OP_3(OP_HELLO, BT_COMP_ID_LF)
25 #define OP_VND_HEARTBEAT BT_MESH_MODEL_OP_3(OP_HEARTBEAT, BT_COMP_ID_LF)
26 #define OP_VND_BADUSER BT_MESH_MODEL_OP_3(OP_BADUSER, BT_COMP_ID_LF)
27
28 #define IV_INDEX 0
29 #define DEFAULT_TTL 31
30 #define GROUP_ADDR 0xc123
31 #define NET_IDX 0x000
32 #define APP_IDX 0x000
33 #define FLAGS 0
34
35 /* Maximum characters in "hello" message */
36 #define HELLO_MAX 8
37
38 #define MAX_SENS_STATUS_LEN 8
39
40 #define SENS_PROP_ID_PRESENT_DEVICE_TEMP 0x0054
41
42 enum {
43 SENSOR_HDR_A = 0,
44 SENSOR_HDR_B = 1,
45 };
46
47 struct sensor_hdr_a {
48 uint16_t prop_id:11;
49 uint16_t length:4;
50 uint16_t format:1;
51 } __packed;
52
53 struct sensor_hdr_b {
54 uint8_t length:7;
55 uint8_t format:1;
56 uint16_t prop_id;
57 } __packed;
58
59 static struct k_work hello_work;
60 static struct k_work baduser_work;
61 static struct k_work mesh_start_work;
62
63 /* Definitions of models user data (Start) */
64 static struct led_onoff_state led_onoff_state[] = {
65 /* Use LED 0 for this model */
66 { .dev_id = 0 },
67 };
68
heartbeat(const struct bt_mesh_hb_sub * sub,uint8_t hops,uint16_t feat)69 static void heartbeat(const struct bt_mesh_hb_sub *sub, uint8_t hops,
70 uint16_t feat)
71 {
72 board_show_text("Heartbeat Received", false, K_SECONDS(2));
73 }
74
75 BT_MESH_HB_CB_DEFINE(hb_cb) = {
76 .recv = heartbeat,
77 };
78
show_mesh_status(bool mesh_started_ok,int addr)79 static void show_mesh_status(bool mesh_started_ok, int addr)
80 {
81 if (!mesh_started_ok) {
82 board_show_text("Starting Mesh Failed", false, K_SECONDS(2));
83 } else {
84 char buf[32];
85
86 snprintk(buf, sizeof(buf), "Mesh Started\nAddr: 0x%04x", addr);
87 board_show_text(buf, false, K_SECONDS(4));
88 }
89 }
90
cfg_cli_app_key_status_cb(struct bt_mesh_cfg_cli * cli,uint16_t addr,uint8_t status,uint16_t net_idx,uint16_t app_idx)91 static void cfg_cli_app_key_status_cb(struct bt_mesh_cfg_cli *cli, uint16_t
92 addr, uint8_t status, uint16_t net_idx,
93 uint16_t app_idx)
94 {
95 struct bt_mesh_cfg_cli_mod_pub pub = {
96 .addr = GROUP_ADDR,
97 .app_idx = APP_IDX,
98 .ttl = DEFAULT_TTL,
99 .period = BT_MESH_PUB_PERIOD_SEC(10),
100 };
101 int err;
102
103 /* Bind to vendor model */
104 err = bt_mesh_cfg_cli_mod_app_bind_vnd(NET_IDX, addr, addr, APP_IDX,
105 MOD_LF, BT_COMP_ID_LF, NULL);
106 if (err) {
107 printk("Failed to bind to vendor model (err %d)\n", err);
108 goto end;
109 }
110
111 err = bt_mesh_cfg_cli_mod_app_bind(NET_IDX, addr, addr, APP_IDX,
112 BT_MESH_MODEL_ID_GEN_ONOFF_SRV, NULL);
113 if (err) {
114 printk("Failed to bind to vendor model (err %d)\n", err);
115 goto end;
116 }
117
118 err = bt_mesh_cfg_cli_mod_app_bind(NET_IDX, addr, addr, APP_IDX,
119 BT_MESH_MODEL_ID_SENSOR_SRV, NULL);
120 if (err) {
121 printk("Failed to bind to vendor model (err %d)\n", err);
122 goto end;
123 }
124
125 /* Bind to Health model */
126 err = bt_mesh_cfg_cli_mod_app_bind(NET_IDX, addr, addr, APP_IDX,
127 BT_MESH_MODEL_ID_HEALTH_SRV, NULL);
128 if (err) {
129 printk("Failed to bind to Health Server (err %d)\n", err);
130 goto end;
131 }
132
133 /* Add model subscription */
134 err = bt_mesh_cfg_cli_mod_sub_add_vnd(NET_IDX, addr, addr, GROUP_ADDR,
135 MOD_LF, BT_COMP_ID_LF, NULL);
136 if (err) {
137 printk("Failed to add subscription (err %d)\n", err);
138 goto end;
139 }
140
141 err = bt_mesh_cfg_cli_mod_pub_set_vnd(NET_IDX, addr, addr, MOD_LF,
142 BT_COMP_ID_LF, &pub, NULL);
143 if (err) {
144 printk("Failed to set publication (err %d)\n", err);
145 goto end;
146 }
147
148 printk("Configuration complete\n");
149
150 end:
151 show_mesh_status(err == 0, addr);
152 }
153
154 static const struct bt_mesh_cfg_cli_cb cfg_cli_cb = {
155 .app_key_status = cfg_cli_app_key_status_cb,
156 };
157
158 static struct bt_mesh_cfg_cli cfg_cli = {
159 .cb = &cfg_cli_cb,
160 };
161
attention_on(const struct bt_mesh_model * model)162 static void attention_on(const struct bt_mesh_model *model)
163 {
164 board_show_text("Attention!", false, K_SECONDS(2));
165 }
166
attention_off(const struct bt_mesh_model * model)167 static void attention_off(const struct bt_mesh_model *model)
168 {
169 board_refresh_display();
170 }
171
172 static const struct bt_mesh_health_srv_cb health_srv_cb = {
173 .attn_on = attention_on,
174 .attn_off = attention_off,
175 };
176
177 static struct bt_mesh_health_srv health_srv = {
178 .cb = &health_srv_cb,
179 };
180
181 /* 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)182 static int gen_onoff_get(const struct bt_mesh_model *model,
183 struct bt_mesh_msg_ctx *ctx,
184 struct net_buf_simple *buf)
185 {
186 NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
187 struct led_onoff_state *state = model->rt->user_data;
188
189 printk("addr 0x%04x onoff 0x%02x\n",
190 bt_mesh_model_elem(model)->rt->addr, state->current);
191 bt_mesh_model_msg_init(&msg, BT_MESH_MODEL_OP_GEN_ONOFF_STATUS);
192 net_buf_simple_add_u8(&msg, state->current);
193
194 if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
195 printk("Unable to send On Off Status response\n");
196 }
197
198 return 0;
199 }
200
gen_onoff_set_unack(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)201 static int gen_onoff_set_unack(const struct bt_mesh_model *model,
202 struct bt_mesh_msg_ctx *ctx,
203 struct net_buf_simple *buf)
204 {
205 struct net_buf_simple *msg = model->pub->msg;
206 struct led_onoff_state *state = model->rt->user_data;
207 int err;
208 uint8_t tid, onoff;
209 int64_t now;
210
211 onoff = net_buf_simple_pull_u8(buf);
212 tid = net_buf_simple_pull_u8(buf);
213
214 if (onoff > STATE_ON) {
215 printk("Wrong state received\n");
216
217 return 0;
218 }
219
220 now = k_uptime_get();
221 if (state->last_tid == tid && state->last_tx_addr == ctx->addr &&
222 (now - state->last_msg_timestamp <= (6 * MSEC_PER_SEC))) {
223 printk("Already received message\n");
224 }
225
226 state->current = onoff;
227 state->last_tid = tid;
228 state->last_tx_addr = ctx->addr;
229 state->last_msg_timestamp = now;
230
231 printk("addr 0x%02x state 0x%02x\n",
232 bt_mesh_model_elem(model)->rt->addr, state->current);
233
234 if (set_led_state(state->dev_id, onoff)) {
235 printk("Failed to set led state\n");
236
237 return 0;
238 }
239
240 /*
241 * If a server has a publish address, it is required to
242 * publish status on a state change
243 *
244 * See Mesh Profile Specification 3.7.6.1.2
245 *
246 * Only publish if there is an assigned address
247 */
248
249 if (state->previous != state->current &&
250 model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
251 printk("publish last 0x%02x cur 0x%02x\n",
252 state->previous, state->current);
253 state->previous = state->current;
254 bt_mesh_model_msg_init(msg,
255 BT_MESH_MODEL_OP_GEN_ONOFF_STATUS);
256 net_buf_simple_add_u8(msg, state->current);
257 err = bt_mesh_model_publish(model);
258 if (err) {
259 printk("bt_mesh_model_publish err %d\n", err);
260 }
261 }
262
263 return 0;
264 }
265
gen_onoff_set(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)266 static int gen_onoff_set(const struct bt_mesh_model *model,
267 struct bt_mesh_msg_ctx *ctx,
268 struct net_buf_simple *buf)
269 {
270 (void)gen_onoff_set_unack(model, ctx, buf);
271 (void)gen_onoff_get(model, ctx, buf);
272
273 return 0;
274 }
275
sensor_desc_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)276 static int sensor_desc_get(const struct bt_mesh_model *model,
277 struct bt_mesh_msg_ctx *ctx,
278 struct net_buf_simple *buf)
279 {
280 /* TODO */
281 return 0;
282 }
283
sens_temperature_celsius_fill(struct net_buf_simple * msg)284 static void sens_temperature_celsius_fill(struct net_buf_simple *msg)
285 {
286 struct sensor_hdr_a hdr;
287 /* TODO Get only temperature from sensor */
288 struct sensor_value val[2];
289 int16_t temp_degrees;
290
291 hdr.format = SENSOR_HDR_A;
292 hdr.length = sizeof(temp_degrees);
293 hdr.prop_id = SENS_PROP_ID_PRESENT_DEVICE_TEMP;
294
295 get_hdc1010_val(val);
296 temp_degrees = sensor_value_to_double(&val[0]) * 100;
297
298 net_buf_simple_add_mem(msg, &hdr, sizeof(hdr));
299 net_buf_simple_add_le16(msg, temp_degrees);
300 }
301
sens_unknown_fill(uint16_t id,struct net_buf_simple * msg)302 static void sens_unknown_fill(uint16_t id, struct net_buf_simple *msg)
303 {
304 struct sensor_hdr_b hdr;
305
306 /*
307 * When the message is a response to a Sensor Get message that
308 * identifies a sensor property that does not exist on the element, the
309 * Length field shall represent the value of zero and the Raw Value for
310 * that property shall be omitted. (Mesh model spec 1.0, 4.2.14).
311 *
312 * The length zero is represented using the format B and the special
313 * value 0x7F.
314 */
315 hdr.format = SENSOR_HDR_B;
316 hdr.length = 0x7FU;
317 hdr.prop_id = id;
318
319 net_buf_simple_add_mem(msg, &hdr, sizeof(hdr));
320 }
321
sensor_create_status(uint16_t id,struct net_buf_simple * msg)322 static void sensor_create_status(uint16_t id, struct net_buf_simple *msg)
323 {
324 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_SENS_STATUS);
325
326 switch (id) {
327 case SENS_PROP_ID_PRESENT_DEVICE_TEMP:
328 sens_temperature_celsius_fill(msg);
329 break;
330 default:
331 sens_unknown_fill(id, msg);
332 break;
333 }
334 }
335
sensor_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)336 static int sensor_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
337 struct net_buf_simple *buf)
338 {
339 NET_BUF_SIMPLE_DEFINE(msg, 1 + MAX_SENS_STATUS_LEN + 4);
340 uint16_t sensor_id;
341
342 sensor_id = net_buf_simple_pull_le16(buf);
343 sensor_create_status(sensor_id, &msg);
344
345 if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
346 printk("Unable to send Sensor get status response\n");
347 }
348
349 return 0;
350 }
351
sensor_col_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)352 static int sensor_col_get(const struct bt_mesh_model *model,
353 struct bt_mesh_msg_ctx *ctx,
354 struct net_buf_simple *buf)
355 {
356 /* TODO */
357 return 0;
358 }
359
sensor_series_get(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)360 static int sensor_series_get(const struct bt_mesh_model *model,
361 struct bt_mesh_msg_ctx *ctx,
362 struct net_buf_simple *buf)
363 {
364 /* TODO */
365 return 0;
366 }
367
368 /* Definitions of models publication context (Start) */
369 BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0);
370 BT_MESH_MODEL_PUB_DEFINE(gen_onoff_srv_pub_root, NULL, 2 + 3);
371
372 /* Mapping of message handlers for Generic OnOff Server (0x1000) */
373 static const struct bt_mesh_model_op gen_onoff_srv_op[] = {
374 { BT_MESH_MODEL_OP_GEN_ONOFF_GET, BT_MESH_LEN_EXACT(0), gen_onoff_get },
375 { BT_MESH_MODEL_OP_GEN_ONOFF_SET, BT_MESH_LEN_MIN(2), gen_onoff_set },
376 { BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, BT_MESH_LEN_MIN(2), gen_onoff_set_unack },
377 BT_MESH_MODEL_OP_END,
378 };
379
380 /* Mapping of message handlers for Sensor Server (0x1100) */
381 static const struct bt_mesh_model_op sensor_srv_op[] = {
382 { BT_MESH_MODEL_OP_SENS_DESC_GET, BT_MESH_LEN_EXACT(0), sensor_desc_get },
383 { BT_MESH_MODEL_OP_SENS_GET, BT_MESH_LEN_EXACT(2), sensor_get },
384 { BT_MESH_MODEL_OP_SENS_COL_GET, BT_MESH_LEN_EXACT(2), sensor_col_get },
385 { BT_MESH_MODEL_OP_SENS_SERIES_GET, BT_MESH_LEN_EXACT(2), sensor_series_get },
386 };
387
388 static const struct bt_mesh_model root_models[] = {
389 BT_MESH_MODEL_CFG_SRV,
390 BT_MESH_MODEL_CFG_CLI(&cfg_cli),
391 BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
392 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV,
393 gen_onoff_srv_op, &gen_onoff_srv_pub_root,
394 &led_onoff_state[0]),
395 BT_MESH_MODEL(BT_MESH_MODEL_ID_SENSOR_SRV,
396 sensor_srv_op, NULL, NULL),
397 };
398
vnd_hello(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)399 static int vnd_hello(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
400 struct net_buf_simple *buf)
401 {
402 char str[32];
403 size_t len;
404
405 printk("Hello message from 0x%04x\n", ctx->addr);
406
407 if (ctx->addr == bt_mesh_model_elem(model)->rt->addr) {
408 printk("Ignoring message from self\n");
409 return 0;
410 }
411
412 len = MIN(buf->len, HELLO_MAX);
413 memcpy(str, buf->data, len);
414 str[len] = '\0';
415
416 board_add_hello(ctx->addr, str);
417
418 strcat(str, " says hi!");
419 board_show_text(str, false, K_SECONDS(3));
420
421 board_blink_leds();
422
423 return 0;
424 }
425
vnd_baduser(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)426 static int vnd_baduser(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
427 struct net_buf_simple *buf)
428 {
429 char str[32];
430 size_t len;
431
432 printk("\"Bad user\" message from 0x%04x\n", ctx->addr);
433
434 if (ctx->addr == bt_mesh_model_elem(model)->rt->addr) {
435 printk("Ignoring message from self\n");
436 return 0;
437 }
438
439 len = MIN(buf->len, HELLO_MAX);
440 memcpy(str, buf->data, len);
441 str[len] = '\0';
442
443 strcat(str, " is misbehaving!");
444 board_show_text(str, false, K_SECONDS(3));
445
446 board_blink_leds();
447
448 return 0;
449 }
450
vnd_heartbeat(const struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)451 static int vnd_heartbeat(const struct bt_mesh_model *model,
452 struct bt_mesh_msg_ctx *ctx,
453 struct net_buf_simple *buf)
454 {
455 uint8_t init_ttl, hops;
456
457 /* Ignore messages from self */
458 if (ctx->addr == bt_mesh_model_elem(model)->rt->addr) {
459 return 0;
460 }
461
462 init_ttl = net_buf_simple_pull_u8(buf);
463 hops = init_ttl - ctx->recv_ttl + 1;
464
465 printk("Heartbeat from 0x%04x over %u hop%s\n", ctx->addr,
466 hops, hops == 1U ? "" : "s");
467
468 board_add_heartbeat(ctx->addr, hops);
469
470 return 0;
471 }
472
473 static const struct bt_mesh_model_op vnd_ops[] = {
474 { OP_VND_HELLO, BT_MESH_LEN_MIN(1), vnd_hello },
475 { OP_VND_HEARTBEAT, BT_MESH_LEN_MIN(1), vnd_heartbeat },
476 { OP_VND_BADUSER, BT_MESH_LEN_MIN(1), vnd_baduser },
477 BT_MESH_MODEL_OP_END,
478 };
479
pub_update(const struct bt_mesh_model * mod)480 static int pub_update(const struct bt_mesh_model *mod)
481 {
482 struct net_buf_simple *msg = mod->pub->msg;
483
484 printk("Preparing to send heartbeat\n");
485
486 bt_mesh_model_msg_init(msg, OP_VND_HEARTBEAT);
487 net_buf_simple_add_u8(msg, DEFAULT_TTL);
488
489 return 0;
490 }
491
492 BT_MESH_MODEL_PUB_DEFINE(vnd_pub, pub_update, 3 + 1);
493
494 static const struct bt_mesh_model vnd_models[] = {
495 BT_MESH_MODEL_VND(BT_COMP_ID_LF, MOD_LF, vnd_ops, &vnd_pub, NULL),
496 };
497
498 static const struct bt_mesh_elem elements[] = {
499 BT_MESH_ELEM(0, root_models, vnd_models),
500 };
501
502 static const struct bt_mesh_comp comp = {
503 .cid = BT_COMP_ID_LF,
504 .elem = elements,
505 .elem_count = ARRAY_SIZE(elements),
506 };
507
first_name_len(const char * name)508 static size_t first_name_len(const char *name)
509 {
510 size_t len;
511
512 for (len = 0; *name; name++, len++) {
513 switch (*name) {
514 case ' ':
515 case ',':
516 case '\n':
517 return len;
518 }
519 }
520
521 return len;
522 }
523
send_hello(struct k_work * work)524 static void send_hello(struct k_work *work)
525 {
526 NET_BUF_SIMPLE_DEFINE(msg, 3 + HELLO_MAX + 4);
527 struct bt_mesh_msg_ctx ctx = {
528 .app_idx = APP_IDX,
529 .addr = GROUP_ADDR,
530 .send_ttl = DEFAULT_TTL,
531 };
532 const char *name = bt_get_name();
533
534 bt_mesh_model_msg_init(&msg, OP_VND_HELLO);
535 net_buf_simple_add_mem(&msg, name,
536 MIN(HELLO_MAX, first_name_len(name)));
537
538 if (bt_mesh_model_send(&vnd_models[0], &ctx, &msg, NULL, NULL) == 0) {
539 board_show_text("Saying \"hi!\" to everyone", false,
540 K_SECONDS(2));
541 } else {
542 board_show_text("Sending Failed!", false, K_SECONDS(2));
543 }
544 }
545
mesh_send_hello(void)546 void mesh_send_hello(void)
547 {
548 k_work_submit(&hello_work);
549 }
550
send_baduser(struct k_work * work)551 static void send_baduser(struct k_work *work)
552 {
553 NET_BUF_SIMPLE_DEFINE(msg, 3 + HELLO_MAX + 4);
554 struct bt_mesh_msg_ctx ctx = {
555 .app_idx = APP_IDX,
556 .addr = GROUP_ADDR,
557 .send_ttl = DEFAULT_TTL,
558 };
559 const char *name = bt_get_name();
560
561 bt_mesh_model_msg_init(&msg, OP_VND_BADUSER);
562 net_buf_simple_add_mem(&msg, name,
563 MIN(HELLO_MAX, first_name_len(name)));
564
565 if (bt_mesh_model_send(&vnd_models[0], &ctx, &msg, NULL, NULL) == 0) {
566 board_show_text("Bad user!", false, K_SECONDS(2));
567 } else {
568 board_show_text("Sending Failed!", false, K_SECONDS(2));
569 }
570 }
571
mesh_send_baduser(void)572 void mesh_send_baduser(void)
573 {
574 k_work_submit(&baduser_work);
575 }
576
provision_and_configure(void)577 static int provision_and_configure(void)
578 {
579 static const uint8_t net_key[16] = {
580 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
581 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
582 };
583 static const uint8_t app_key[16] = {
584 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
585 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
586 };
587 uint8_t dev_key[16];
588 uint16_t addr;
589 int err;
590
591 err = bt_rand(dev_key, sizeof(dev_key));
592 if (err) {
593 return err;
594 }
595
596 do {
597 err = bt_rand(&addr, sizeof(addr));
598 if (err) {
599 return err;
600 }
601 } while (!addr);
602
603 /* Make sure it's a unicast address (highest bit unset) */
604 addr &= ~0x8000;
605
606 err = bt_mesh_provision(net_key, NET_IDX, FLAGS, IV_INDEX, addr, dev_key);
607 if (err) {
608 return err;
609 }
610
611 printk("Configuring...\n");
612
613 /* Add Application Key */
614 err = bt_mesh_cfg_cli_app_key_add(NET_IDX, addr, NET_IDX, APP_IDX,
615 app_key, NULL);
616 if (err) {
617 printk("Failed to add application key (err %d)\n", err);
618 return err;
619 }
620
621 return addr;
622 }
623
start_mesh(struct k_work * work)624 static void start_mesh(struct k_work *work)
625 {
626 int err;
627
628 err = provision_and_configure();
629 if (err < 0) {
630 printk("Provisioning failed (err %d)\n", err);
631 }
632 }
633
mesh_start(void)634 void mesh_start(void)
635 {
636 k_work_submit(&mesh_start_work);
637 }
638
mesh_is_initialized(void)639 bool mesh_is_initialized(void)
640 {
641 return elements[0].rt->addr != BT_MESH_ADDR_UNASSIGNED;
642 }
643
mesh_get_addr(void)644 uint16_t mesh_get_addr(void)
645 {
646 return elements[0].rt->addr;
647 }
648
mesh_init(void)649 int mesh_init(void)
650 {
651 static const uint8_t dev_uuid[16] = { 0xc0, 0xff, 0xee };
652 static const struct bt_mesh_prov prov = {
653 .uuid = dev_uuid,
654 };
655
656 k_work_init(&hello_work, send_hello);
657 k_work_init(&baduser_work, send_baduser);
658 k_work_init(&mesh_start_work, start_mesh);
659
660 return bt_mesh_init(&prov, &comp);
661 }
662