1 /* main.c - Application main entry point */
2
3 /*
4 * Copyright (c) 2017 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 /*
10 * This application is specific to the Nordic nRF52840-PDK board.
11 *
12 * It supports the 4 buttons and 4 LEDs as mesh clients and servers.
13 *
14 * Prior to provisioning, a button inverts the state of the
15 * corresponding LED.
16 *
17 * Button and LED 1 are in the root node.
18 * The 3 remaining button/LED pairs are in element 1 through 3.
19 * Assuming the provisioner assigns 0x100 to the root node,
20 * the secondary elements will appear at 0x101, 0x102 and 0x103.
21 *
22 * It's anticipated that after provisioning, the button clients would
23 * be configured to publish and the LED servers to subscribe.
24 *
25 * If a LED server is provided with a publish address, it will
26 * also publish its status on a state change.
27 *
28 * Messages from a button to its corresponding LED are ignored as
29 * the LED's state has already been changed locally by the button client.
30 *
31 * The buttons are debounced at a nominal 250ms. That value can be
32 * changed as needed.
33 *
34 */
35
36 #include "os/mynewt.h"
37 #include "bsp/bsp.h"
38 #include "console/console.h"
39 #include "hal/hal_gpio.h"
40 #include "host/ble_hs.h"
41 #include "mesh/glue.h"
42 #include "mesh/mesh.h"
43
44 #define CID_RUNTIME 0x05C3
45
46 /* Model Operation Codes */
47 #define BT_MESH_MODEL_OP_GEN_ONOFF_GET BT_MESH_MODEL_OP_2(0x82, 0x01)
48 #define BT_MESH_MODEL_OP_GEN_ONOFF_SET BT_MESH_MODEL_OP_2(0x82, 0x02)
49 #define BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x03)
50 #define BT_MESH_MODEL_OP_GEN_ONOFF_STATUS BT_MESH_MODEL_OP_2(0x82, 0x04)
51
52 static void gen_onoff_set(struct bt_mesh_model *model,
53 struct bt_mesh_msg_ctx *ctx,
54 struct os_mbuf *buf);
55
56 static void gen_onoff_set_unack(struct bt_mesh_model *model,
57 struct bt_mesh_msg_ctx *ctx,
58 struct os_mbuf *buf);
59
60 static void gen_onoff_get(struct bt_mesh_model *model,
61 struct bt_mesh_msg_ctx *ctx,
62 struct os_mbuf *buf);
63
64 static void gen_onoff_status(struct bt_mesh_model *model,
65 struct bt_mesh_msg_ctx *ctx,
66 struct os_mbuf *buf);
67
68 /*
69 * Server Configuration Declaration
70 */
71
72 static struct bt_mesh_cfg_srv cfg_srv = {
73 .relay = BT_MESH_RELAY_DISABLED,
74 .beacon = BT_MESH_BEACON_ENABLED,
75 #if defined(CONFIG_BT_MESH_FRIEND)
76 .frnd = BT_MESH_FRIEND_ENABLED,
77 #else
78 .frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
79 #endif
80 #if defined(CONFIG_BT_MESH_GATT_PROXY)
81 .gatt_proxy = BT_MESH_GATT_PROXY_ENABLED,
82 #else
83 .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
84 #endif
85 .default_ttl = 7,
86
87 /* 3 transmissions with 20ms interval */
88 .net_transmit = BT_MESH_TRANSMIT(2, 20),
89 .relay_retransmit = BT_MESH_TRANSMIT(2, 20),
90 };
91
92 /*
93 * Client Configuration Declaration
94 */
95
96 static struct bt_mesh_cfg_cli cfg_cli = {
97 };
98
99 /*
100 * Health Server Declaration
101 */
102
103 static struct bt_mesh_health_srv health_srv = {
104 };
105
106 /*
107 * Publication Declarations
108 *
109 * The publication messages are initialized to the
110 * the size of the opcode + content
111 *
112 * For publication, the message must be in static or global as
113 * it is re-transmitted several times. This occurs
114 * after the function that called bt_mesh_model_publish() has
115 * exited and the stack is no longer valid.
116 *
117 * Note that the additional 4 bytes for the AppMIC is not needed
118 * because it is added to a stack variable at the time a
119 * transmission occurs.
120 *
121 */
122
123 static struct bt_mesh_model_pub health_pub;
124 static struct bt_mesh_model_pub gen_onoff_pub_srv;
125 static struct bt_mesh_model_pub gen_onoff_pub_cli;
126 static struct bt_mesh_model_pub gen_onoff_pub_srv_s_0;
127 static struct bt_mesh_model_pub gen_onoff_pub_cli_s_0;
128 static struct bt_mesh_model_pub gen_onoff_pub_srv_s_1;
129 static struct bt_mesh_model_pub gen_onoff_pub_cli_s_1;
130 static struct bt_mesh_model_pub gen_onoff_pub_srv_s_2;
131 static struct bt_mesh_model_pub gen_onoff_pub_cli_s_2;
132
133 static struct os_mbuf *bt_mesh_pub_msg_health_pub;
134 static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_srv;
135 static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_cli;
136 static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_srv_s_0;
137 static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_cli_s_0;
138 static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_srv_s_1;
139 static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_cli_s_1;
140 static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_srv_s_2;
141 static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_cli_s_2;
142
init_pub(void)143 void init_pub(void)
144 {
145 bt_mesh_pub_msg_health_pub = NET_BUF_SIMPLE(1 + 3 + 0);
146 bt_mesh_pub_msg_gen_onoff_pub_srv = NET_BUF_SIMPLE(2 + 2);
147 bt_mesh_pub_msg_gen_onoff_pub_cli = NET_BUF_SIMPLE(2 + 2);
148 bt_mesh_pub_msg_gen_onoff_pub_srv_s_0 = NET_BUF_SIMPLE(2 + 2);
149 bt_mesh_pub_msg_gen_onoff_pub_cli_s_0 = NET_BUF_SIMPLE(2 + 2);
150 bt_mesh_pub_msg_gen_onoff_pub_srv_s_1 = NET_BUF_SIMPLE(2 + 2);
151 bt_mesh_pub_msg_gen_onoff_pub_cli_s_1 = NET_BUF_SIMPLE(2 + 2);
152 bt_mesh_pub_msg_gen_onoff_pub_srv_s_2 = NET_BUF_SIMPLE(2 + 2);
153 bt_mesh_pub_msg_gen_onoff_pub_cli_s_2 = NET_BUF_SIMPLE(2 + 2);
154
155 health_pub.msg = bt_mesh_pub_msg_health_pub;
156 gen_onoff_pub_srv.msg = bt_mesh_pub_msg_gen_onoff_pub_srv;
157 gen_onoff_pub_cli.msg = bt_mesh_pub_msg_gen_onoff_pub_cli;
158 gen_onoff_pub_srv_s_0.msg = bt_mesh_pub_msg_gen_onoff_pub_srv_s_0;
159 gen_onoff_pub_cli_s_0.msg = bt_mesh_pub_msg_gen_onoff_pub_cli_s_0;
160 gen_onoff_pub_srv_s_1.msg = bt_mesh_pub_msg_gen_onoff_pub_srv_s_1;
161 gen_onoff_pub_cli_s_1.msg = bt_mesh_pub_msg_gen_onoff_pub_cli_s_1;
162 gen_onoff_pub_srv_s_2.msg = bt_mesh_pub_msg_gen_onoff_pub_srv_s_2;
163 gen_onoff_pub_cli_s_2.msg = bt_mesh_pub_msg_gen_onoff_pub_cli_s_2;
164 }
165
166 /*
167 * Models in an element must have unique op codes.
168 *
169 * The mesh stack dispatches a message to the first model in an element
170 * that is also bound to an app key and supports the op code in the
171 * received message.
172 *
173 */
174
175 /*
176 * OnOff Model Server Op Dispatch Table
177 *
178 */
179
180 static const struct bt_mesh_model_op gen_onoff_srv_op[] = {
181 { BT_MESH_MODEL_OP_GEN_ONOFF_GET, 0, gen_onoff_get },
182 { BT_MESH_MODEL_OP_GEN_ONOFF_SET, 2, gen_onoff_set },
183 { BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2, gen_onoff_set_unack },
184 BT_MESH_MODEL_OP_END,
185 };
186
187 /*
188 * OnOff Model Client Op Dispatch Table
189 */
190
191 static const struct bt_mesh_model_op gen_onoff_cli_op[] = {
192 { BT_MESH_MODEL_OP_GEN_ONOFF_STATUS, 1, gen_onoff_status },
193 BT_MESH_MODEL_OP_END,
194 };
195
196 struct onoff_state {
197 u8_t current;
198 u8_t previous;
199 u8_t led_gpio_pin;
200 };
201
202 /*
203 * Declare and Initialize Element Contexts
204 * Change to select different GPIO output pins
205 */
206
207 static struct onoff_state onoff_state_arr[] = {
208 { .led_gpio_pin = LED_1 },
209 { .led_gpio_pin = LED_2 },
210 { .led_gpio_pin = LED_3 },
211 { .led_gpio_pin = LED_4 },
212 };
213
214 /*
215 *
216 * Element Model Declarations
217 *
218 * Element 0 Root Models
219 */
220
221 static struct bt_mesh_model root_models[] = {
222 BT_MESH_MODEL_CFG_SRV(&cfg_srv),
223 BT_MESH_MODEL_CFG_CLI(&cfg_cli),
224 BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
225 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op,
226 &gen_onoff_pub_srv, &onoff_state_arr[0]),
227 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op,
228 &gen_onoff_pub_cli, &onoff_state_arr[0]),
229 };
230
231 /*
232 * Element 1 Models
233 */
234
235 static struct bt_mesh_model secondary_0_models[] = {
236 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op,
237 &gen_onoff_pub_srv_s_0, &onoff_state_arr[1]),
238 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op,
239 &gen_onoff_pub_cli_s_0, &onoff_state_arr[1]),
240 };
241
242 /*
243 * Element 2 Models
244 */
245
246 static struct bt_mesh_model secondary_1_models[] = {
247 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op,
248 &gen_onoff_pub_srv_s_1, &onoff_state_arr[2]),
249 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op,
250 &gen_onoff_pub_cli_s_1, &onoff_state_arr[2]),
251 };
252
253 /*
254 * Element 3 Models
255 */
256
257 static struct bt_mesh_model secondary_2_models[] = {
258 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op,
259 &gen_onoff_pub_srv_s_2, &onoff_state_arr[3]),
260 BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op,
261 &gen_onoff_pub_cli_s_2, &onoff_state_arr[3]),
262 };
263
264 /*
265 * Button to Client Model Assignments
266 */
267
268 struct bt_mesh_model *mod_cli_sw[] = {
269 &root_models[4],
270 &secondary_0_models[1],
271 &secondary_1_models[1],
272 &secondary_2_models[1],
273 };
274
275 /*
276 * LED to Server Model Assigmnents
277 */
278
279 struct bt_mesh_model *mod_srv_sw[] = {
280 &root_models[3],
281 &secondary_0_models[0],
282 &secondary_1_models[0],
283 &secondary_2_models[0],
284 };
285
286 /*
287 * Root and Secondary Element Declarations
288 */
289
290 static struct bt_mesh_elem elements[] = {
291 BT_MESH_ELEM(0, root_models, BT_MESH_MODEL_NONE),
292 BT_MESH_ELEM(0, secondary_0_models, BT_MESH_MODEL_NONE),
293 BT_MESH_ELEM(0, secondary_1_models, BT_MESH_MODEL_NONE),
294 BT_MESH_ELEM(0, secondary_2_models, BT_MESH_MODEL_NONE),
295 };
296
297 static const struct bt_mesh_comp comp = {
298 .cid = CID_RUNTIME,
299 .elem = elements,
300 .elem_count = ARRAY_SIZE(elements),
301 };
302
303 struct sw {
304 u8_t sw_num;
305 u8_t onoff_state;
306 struct ble_npl_callout button_work;
307 struct k_delayed_work button_timer;
308 };
309
310
311 static u8_t button_press_cnt;
312 static struct sw sw;
313
314 static u8_t trans_id;
315 static u32_t time, last_time;
316 static u16_t primary_addr;
317 static u16_t primary_net_idx;
318
319 /*
320 * Generic OnOff Model Server Message Handlers
321 *
322 * Mesh Model Specification 3.1.1
323 *
324 */
325
gen_onoff_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)326 static void gen_onoff_get(struct bt_mesh_model *model,
327 struct bt_mesh_msg_ctx *ctx,
328 struct os_mbuf *buf)
329 {
330 struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
331 struct onoff_state *state = model->user_data;
332
333 BT_INFO("addr 0x%04x onoff 0x%02x",
334 bt_mesh_model_elem(model)->addr, state->current);
335 bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_ONOFF_STATUS);
336 net_buf_simple_add_u8(msg, state->current);
337
338 if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
339 BT_ERR("Unable to send On Off Status response");
340 }
341
342 os_mbuf_free_chain(msg);
343 }
344
gen_onoff_set_unack(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)345 static void gen_onoff_set_unack(struct bt_mesh_model *model,
346 struct bt_mesh_msg_ctx *ctx,
347 struct os_mbuf *buf)
348 {
349 struct os_mbuf *msg = model->pub->msg;
350 struct onoff_state *state = model->user_data;
351 int err;
352
353 state->current = net_buf_simple_pull_u8(buf);
354 BT_INFO("addr 0x%02x state 0x%02x",
355 bt_mesh_model_elem(model)->addr, state->current);
356
357 /* Pin set low turns on LED's on the nrf52840-pca10056 board */
358 hal_gpio_write(state->led_gpio_pin,
359 state->current ? 0 : 1);
360
361 /*
362 * If a server has a publish address, it is required to
363 * publish status on a state change
364 *
365 * See Mesh Profile Specification 3.7.6.1.2
366 *
367 * Only publish if there is an assigned address
368 */
369
370 if (state->previous != state->current &&
371 model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
372 BT_INFO("publish last 0x%02x cur 0x%02x",
373 state->previous,
374 state->current);
375 state->previous = state->current;
376 bt_mesh_model_msg_init(msg,
377 BT_MESH_MODEL_OP_GEN_ONOFF_STATUS);
378 net_buf_simple_add_u8(msg, state->current);
379 err = bt_mesh_model_publish(model);
380 if (err) {
381 BT_ERR("bt_mesh_model_publish err %d", err);
382 }
383 }
384 }
385
gen_onoff_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)386 static void gen_onoff_set(struct bt_mesh_model *model,
387 struct bt_mesh_msg_ctx *ctx,
388 struct os_mbuf *buf)
389 {
390 BT_INFO("");
391
392 gen_onoff_set_unack(model, ctx, buf);
393 gen_onoff_get(model, ctx, buf);
394 }
395
gen_onoff_status(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)396 static void gen_onoff_status(struct bt_mesh_model *model,
397 struct bt_mesh_msg_ctx *ctx,
398 struct os_mbuf *buf)
399 {
400 u8_t state;
401
402 state = net_buf_simple_pull_u8(buf);
403
404 BT_INFO("Node 0x%04x OnOff status from 0x%04x with state 0x%02x",
405 bt_mesh_model_elem(model)->addr, ctx->addr, state);
406 }
407
output_number(bt_mesh_output_action_t action,u32_t number)408 static int output_number(bt_mesh_output_action_t action, u32_t number)
409 {
410 BT_INFO("OOB Number %u", number);
411 return 0;
412 }
413
output_string(const char * str)414 static int output_string(const char *str)
415 {
416 BT_INFO("OOB String %s", str);
417 return 0;
418 }
419
prov_complete(u16_t net_idx,u16_t addr)420 static void prov_complete(u16_t net_idx, u16_t addr)
421 {
422 BT_INFO("provisioning complete for net_idx 0x%04x addr 0x%04x",
423 net_idx, addr);
424 primary_addr = addr;
425 primary_net_idx = net_idx;
426 }
427
prov_reset(void)428 static void prov_reset(void)
429 {
430 bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
431 }
432
433 static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
434
435 #define BUTTON_DEBOUNCE_DELAY_MS 250
436
437 /*
438 * Map GPIO pins to button number
439 * Change to select different GPIO input pins
440 */
441
pin_to_sw(int pin_pos)442 static uint8_t pin_to_sw(int pin_pos)
443 {
444 switch (pin_pos) {
445 case BUTTON_1: return 0;
446 case BUTTON_2: return 1;
447 case BUTTON_3: return 2;
448 case BUTTON_4: return 3;
449 default:break;
450 }
451
452 BT_ERR("No match for GPIO pin 0x%08x", pin_pos);
453 return 0;
454 }
455
button_pressed(struct os_event * ev)456 static void button_pressed(struct os_event *ev)
457 {
458 int pin_pos = (int ) ev->ev_arg;
459 /*
460 * One button press within a 1 second interval sends an on message
461 * More than one button press sends an off message
462 */
463
464 time = k_uptime_get_32();
465
466 /* debounce the switch */
467 if (time < last_time + BUTTON_DEBOUNCE_DELAY_MS) {
468 last_time = time;
469 return;
470 }
471
472 if (button_press_cnt == 0) {
473 k_delayed_work_submit(&sw.button_timer, K_SECONDS(1));
474 }
475
476 BT_INFO("button_press_cnt 0x%02x", button_press_cnt);
477 button_press_cnt++;
478
479 /* The variable pin_pos is the pin position in the GPIO register,
480 * not the pin number. It's assumed that only one bit is set.
481 */
482
483 sw.sw_num = pin_to_sw(pin_pos);
484 last_time = time;
485 }
486
487 /*
488 * Button Count Timer Worker
489 */
490
button_cnt_timer(struct ble_npl_event * work)491 static void button_cnt_timer(struct ble_npl_event *work)
492 {
493 struct sw *button_sw = work->ev.ev_arg;
494
495 button_sw->onoff_state = button_press_cnt == 1 ? 1 : 0;
496 BT_INFO("button_press_cnt 0x%02x onoff_state 0x%02x",
497 button_press_cnt, button_sw->onoff_state);
498 button_press_cnt = 0;
499 k_work_submit(&sw.button_work);
500 }
501
502 /*
503 * Button Pressed Worker Task
504 */
505
button_pressed_worker(struct ble_npl_event * work)506 static void button_pressed_worker(struct ble_npl_event *work)
507 {
508 struct os_mbuf *msg = NET_BUF_SIMPLE(1);
509 struct bt_mesh_model *mod_cli, *mod_srv;
510 struct bt_mesh_model_pub *pub_cli, *pub_srv;
511 struct sw *sw = work->ev.ev_arg;
512 u8_t sw_idx = sw->sw_num;
513 int err;
514
515 mod_cli = mod_cli_sw[sw_idx];
516 pub_cli = mod_cli->pub;
517
518 mod_srv = mod_srv_sw[sw_idx];
519 pub_srv = mod_srv->pub;
520 (void)pub_srv;
521
522 /* If unprovisioned, just call the set function.
523 * The intent is to have switch-like behavior
524 * prior to provisioning. Once provisioned,
525 * the button and its corresponding led are no longer
526 * associated and act independently. So, if a button is to
527 * control its associated led after provisioning, the button
528 * must be configured to either publish to the led's unicast
529 * address or a group to which the led is subscribed.
530 */
531
532 if (primary_addr == BT_MESH_ADDR_UNASSIGNED) {
533 struct bt_mesh_msg_ctx ctx = {
534 .addr = sw_idx + primary_addr,
535 };
536
537 /* This is a dummy message sufficient
538 * for the led server
539 */
540
541 net_buf_simple_add_u8(msg, sw->onoff_state);
542 gen_onoff_set_unack(mod_srv, &ctx, msg);
543 goto done;
544 }
545
546 if (pub_cli->addr == BT_MESH_ADDR_UNASSIGNED) {
547 goto done;
548 }
549
550 BT_INFO("publish to 0x%04x onoff 0x%04x sw_idx 0x%04x",
551 pub_cli->addr, sw->onoff_state, sw_idx);
552 bt_mesh_model_msg_init(pub_cli->msg,
553 BT_MESH_MODEL_OP_GEN_ONOFF_SET);
554 net_buf_simple_add_u8(pub_cli->msg, sw->onoff_state);
555 net_buf_simple_add_u8(pub_cli->msg, trans_id++);
556 err = bt_mesh_model_publish(mod_cli);
557 if (err) {
558 BT_ERR("bt_mesh_model_publish err %d", err);
559 }
560
561 done:
562 os_mbuf_free_chain(msg);
563 }
564
565 /* Disable OOB security for SILabs Android app */
566
567 static const struct bt_mesh_prov prov = {
568 .uuid = dev_uuid,
569 #if 1
570 .output_size = 6,
571 .output_actions = (BT_MESH_DISPLAY_NUMBER | BT_MESH_DISPLAY_STRING),
572 .output_number = output_number,
573 .output_string = output_string,
574 #else
575 .output_size = 0,
576 .output_actions = 0,
577 .output_number = 0,
578 #endif
579 .complete = prov_complete,
580 .reset = prov_reset,
581 };
582
init_led(u8_t dev)583 void init_led(u8_t dev)
584 {
585 hal_gpio_init_out(onoff_state_arr[dev].led_gpio_pin, 1);
586 }
587
588 static struct os_event button_event;
589
590 static void
gpio_irq_handler(void * arg)591 gpio_irq_handler(void *arg)
592 {
593 button_event.ev_arg = arg;
594 os_eventq_put(os_eventq_dflt_get(), &button_event);
595 }
596
init_button(int button)597 void init_button(int button)
598 {
599 button_event.ev_cb = button_pressed;
600
601 hal_gpio_irq_init(button, gpio_irq_handler, (void *)button,
602 HAL_GPIO_TRIG_FALLING, HAL_GPIO_PULL_UP);
603 hal_gpio_irq_enable(button);
604 }
605
606 static void
blemesh_on_reset(int reason)607 blemesh_on_reset(int reason)
608 {
609 BLE_HS_LOG(ERROR, "Resetting state; reason=%d\n", reason);
610 }
611
612 static void
blemesh_on_sync(void)613 blemesh_on_sync(void)
614 {
615 int err;
616 ble_addr_t addr;
617
618 console_printf("Bluetooth initialized\n");
619
620 /* Use NRPA */
621 err = ble_hs_id_gen_rnd(1, &addr);
622 assert(err == 0);
623 err = ble_hs_id_set_rnd(addr.val);
624 assert(err == 0);
625
626 err = bt_mesh_init(addr.type, &prov, &comp);
627 if (err) {
628 console_printf("Initializing mesh failed (err %d)\n", err);
629 return;
630 }
631
632 if (IS_ENABLED(CONFIG_SETTINGS)) {
633 settings_load();
634 }
635
636 if (bt_mesh_is_provisioned()) {
637 console_printf("Mesh network restored from flash\n");
638 }
639
640 bt_mesh_prov_enable(BT_MESH_PROV_GATT | BT_MESH_PROV_ADV);
641
642 console_printf("Mesh initialized\n");
643 }
644
main(void)645 int main(void)
646 {
647 #ifdef ARCH_sim
648 mcu_sim_parse_args(argc, argv);
649 #endif
650
651 /* Initialize OS */
652 sysinit();
653
654 BT_INFO("Initializing...");
655
656 /* Initialize the button debouncer */
657 last_time = k_uptime_get_32();
658
659 /* Initialize button worker task*/
660 k_work_init(&sw.button_work, button_pressed_worker);
661 k_work_add_arg(&sw.button_work, &sw);
662
663 /* Initialize button count timer */
664 k_delayed_work_init(&sw.button_timer, button_cnt_timer);
665 k_delayed_work_add_arg(&sw.button_timer, &sw);
666
667 /* Initialize LED's */
668 init_led(0);
669 init_led(1);
670 init_led(2);
671 init_led(3);
672
673 init_button(BUTTON_1);
674 init_button(BUTTON_2);
675 init_button(BUTTON_3);
676 init_button(BUTTON_4);
677
678 init_pub();
679
680 /* Initialize the NimBLE host configuration. */
681 ble_hs_cfg.reset_cb = blemesh_on_reset;
682 ble_hs_cfg.sync_cb = blemesh_on_sync;
683 ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
684
685 while (1) {
686 os_eventq_run(os_eventq_dflt_get());
687 }
688
689 return 0;
690 }
691