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