xref: /nrf52832-nimble/packages/NimBLE-latest/apps/blemesh_models_example_1/src/main.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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