main.c 19 KB

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