Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:3ed424a8870a, committed 2018-05-02
- Comitter:
- krenbluetoothsig
- Date:
- Wed May 02 05:14:13 2018 +0000
- Child:
- 1:5186eefd678a
- Commit message:
- server; 1. NEW: project created.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CMakeLists.txt Wed May 02 05:14:13 2018 +0000
@@ -0,0 +1,10 @@
+set(QEMU_EXTRA_FLAGS -s)
+
+include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
+project(NONE)
+
+target_sources(app PRIVATE src/main.c)
+
+if(NODE_ADDR)
+ zephyr_compile_definitions(NODE_ADDR=${NODE_ADDR})
+endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.txt Wed May 02 05:14:13 2018 +0000 @@ -0,0 +1,43 @@ +This is a README for implementing micro:bit Bluetooth mesh demo. + +http://docs.zephyrproject.org/getting_started/getting_started.html#set-up-the-development-environment + +.. _ble_mesh: + +Bluetooth: Mesh +############### + +Overview +******** + +This sample demonstrates Bluetooth Mesh functionality. It has several +standard Mesh models, and supports provisioning over both the +Advertising and the GATT Provisioning Bearers (i.e. PB-ADV and PB-GATT). +The application also needs a functioning serial console, since that's +used for the Out-of-Band provisioning procedure. + +Requirements +************ + +* A board with Bluetooth LE support, or +* QEMU with BlueZ running on the host + +Building and Running +******************** + +This sample can be found under :file:`samples/bluetooth/mesh` in the +Zephyr tree. + +See :ref:`bluetooth setup section <bluetooth_setup>` for details on how +to run the sample inside QEMU. + +For other boards, build and flash the application as follows: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/mesh + :board: <board> + :goals: flash + :compact: + +Refer to your :ref:`board's documentation <boards>` for alternative +flash instructions if your board doesn't support the ``flash`` target.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prj_bbc_microbit.txt Wed May 02 05:14:13 2018 +0000 @@ -0,0 +1,41 @@ +#CONFIG_INIT_STACKS=y +CONFIG_MAIN_STACK_SIZE=512 +#CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1280 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 +CONFIG_SYS_CLOCK_TICKS_PER_SEC=250 +CONFIG_GPIO=y +CONFIG_FLASH=y +CONFIG_SOC_FLASH_NRF5=y +CONFIG_MICROBIT_DISPLAY=y +CONFIG_PWM=y +CONFIG_PWM_NRF5_SW=y + +CONFIG_BT=y +CONFIG_BT_RX_STACK_SIZE=1280 +CONFIG_BT_CTLR_DUP_FILTER_LEN=0 +CONFIG_BT_OBSERVER=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_PRIVACY=n + +CONFIG_BT_MESH=y +CONFIG_BT_MESH_RELAY=y +CONFIG_BT_MESH_RX_SDU_MAX=36 +CONFIG_BT_MESH_SUBNET_COUNT=1 +CONFIG_BT_MESH_APP_KEY_COUNT=2 +CONFIG_BT_MESH_MODEL_GROUP_COUNT=2 +CONFIG_BT_MESH_ADV_BUF_COUNT=10 +CONFIG_BT_MESH_PB_ADV=n +CONFIG_BT_MESH_CFG_CLI=y + +CONFIG_BT_DEBUG_LOG=n +CONFIG_BT_MESH_DEBUG=y +#CONFIG_BT_MESH_DEBUG_NET=y +CONFIG_BT_MESH_DEBUG_MODEL=y +#CONFIG_BT_MESH_DEBUG_TRANS=y +#CONFIG_BT_MESH_SELF_TEST=y +#CONFIG_BT_MESH_IV_UPDATE_TEST=y +#CONFIG_BT_MESH_DEBUG_PROV=y +#CONFIG_BT_MESH_DEBUG_BEACON=y +#CONFIG_BT_MESH_DEBUG_CRYPTO=y +#CONFIG_BT_MESH_DEBUG_ADV=y +#CONFIG_BT_MESH_DEBUG_ACCESS=y
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main.c Wed May 02 05:14:13 2018 +0000
@@ -0,0 +1,618 @@
+/*
+ * Copyright (c) 2018 Bluetooth SIG
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <misc/printk.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/mesh.h>
+#include <gpio.h>
+#include <board.h>
+#include <soc.h>
+#include <misc/printk.h>
+#include <ctype.h>
+#include <flash.h>
+#include <gpio.h>
+#include <pwm.h>
+
+#include <display/mb_display.h>
+
+#include <bluetooth/mesh.h>
+
+#define GROUP_ADDR 0xc000
+#define PUBLISHER_ADDR 0x000f
+#if !defined(NODE_ADDR)
+#define NODE_ADDR 0x0b02
+#endif
+
+/* Model Operation Codes */
+#define BT_MESH_MODEL_OP_GEN_ONOFF_GET BT_MESH_MODEL_OP_2(0x82, 0x01)
+#define BT_MESH_MODEL_OP_GEN_ONOFF_SET BT_MESH_MODEL_OP_2(0x82, 0x02)
+#define BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x03)
+#define BT_MESH_MODEL_OP_GEN_ONOFF_STATUS BT_MESH_MODEL_OP_2(0x82, 0x04)
+
+
+/* Button debounce timeout */
+#define BUTTON_DEBOUNCE_DELAY_MS 250
+
+/* LED matrix scroll speed */
+#define SCROLL_SPEED K_MSEC(500)
+
+/* LED matrix scroll speed */
+#define BUZZER_PIN EXT_P0_GPIO_PIN
+#define BEEP_DURATION K_MSEC(60)
+
+/* NVM offset */
+#define SEQ_PER_BIT 976
+#define SEQ_PAGE (NRF_FICR->CODEPAGESIZE * (NRF_FICR->CODESIZE - 1))
+#define SEQ_MAX (NRF_FICR->CODEPAGESIZE * 8 * SEQ_PER_BIT)
+
+/* Key definition, it's pre-configured, not need to do provisioning. */
+static const u8_t net_key[16] = {
+ 0xf1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+};
+static const u8_t dev_key[16] = {
+ 0xf1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+};
+static const u8_t app_key[16] = {
+ 0xf1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+};
+
+/* group address string. */
+const char *groupAddress2String[] = {
+ "Bedroom",
+ "Living",
+ "Dining",
+ "Garage"
+};
+
+static struct device *gpio;
+static struct device *nvm;
+static struct device *pwm;
+
+static struct k_work button_work;
+static struct k_work subscribe_work;
+static u32_t time, last_time;
+
+const u16_t net_idx;
+const u16_t app_idx;
+const u32_t iv_index;
+u8_t flags;
+u16_t addr;
+static u32_t seq;
+
+/* group address, initialized */
+u16_t groupAddress = GROUP_ADDR;
+
+u16_t board_set_target(void)
+{
+ switch (groupAddress) {
+ case GROUP_ADDR:
+ groupAddress++ ;
+ break;
+ case (GROUP_ADDR + 3):
+ groupAddress = GROUP_ADDR;
+ break;
+ default:
+ groupAddress++;
+ break;
+ }
+
+ return groupAddress;
+}
+
+void board_seq_update(u32_t seq)
+{
+ u32_t loc, seq_map;
+ int err;
+
+ if (seq % SEQ_PER_BIT) {
+ return;
+ }
+
+ loc = (SEQ_PAGE + ((seq / SEQ_PER_BIT) / 32));
+
+ err = flash_read(nvm, loc, &seq_map, sizeof(seq_map));
+ if (err) {
+ printk("flash_read err %d\n", err);
+ return;
+ }
+
+ seq_map >>= 1;
+
+ flash_write_protection_set(nvm, false);
+ err = flash_write(nvm, loc, &seq_map, sizeof(seq_map));
+ flash_write_protection_set(nvm, true);
+ if (err) {
+ printk("flash_write err %d\n", err);
+ }
+}
+
+static u32_t get_seq(void)
+{
+ u32_t seq_map, seq = 0;
+ int err, i;
+
+ for (i = 0; i < NRF_FICR->CODEPAGESIZE / sizeof(seq_map); i++) {
+ err = flash_read(nvm, SEQ_PAGE + (i * sizeof(seq_map)),
+ &seq_map, sizeof(seq_map));
+ if (err) {
+ printk("flash_read err %d\n", err);
+ return seq;
+ }
+
+ printk("seq_map 0x%08x\n", seq_map);
+
+ if (seq_map) {
+ seq = ((i * 32) +
+ (32 - popcount(seq_map))) * SEQ_PER_BIT;
+ if (!seq) {
+ return 0;
+ }
+
+ break;
+ }
+ }
+
+ seq += SEQ_PER_BIT;
+ if (seq >= SEQ_MAX) {
+ seq = 0;
+ }
+
+ if (seq) {
+ seq_map >>= 1;
+ flash_write_protection_set(nvm, false);
+ err = flash_write(nvm, SEQ_PAGE + (i * sizeof(seq_map)),
+ &seq_map, sizeof(seq_map));
+ flash_write_protection_set(nvm, true);
+ if (err) {
+ printk("flash_write err %d\n", err);
+ }
+ } else {
+ printk("Performing flash erase of page 0x%08x\n", SEQ_PAGE);
+ err = flash_erase(nvm, SEQ_PAGE, NRF_FICR->CODEPAGESIZE);
+ if (err) {
+ printk("flash_erase err %d\n", err);
+ }
+ }
+
+ return seq;
+}
+
+static void buttonA_pressed(struct k_work *work)
+{
+ struct mb_display *disp = mb_display_get();
+
+ printk("buttonA_pressed\n");
+ mb_display_print(disp, MB_DISPLAY_MODE_DEFAULT, SCROLL_SPEED, "%s",
+ groupAddress2String[groupAddress - GROUP_ADDR]);
+}
+
+static void buttonB_resubscribe(struct k_work *work)
+{
+ struct mb_display *disp = mb_display_get();
+
+ printk("change new group address to 0x%04x\n", board_set_target());
+
+ mb_display_print(disp, MB_DISPLAY_MODE_DEFAULT, SCROLL_SPEED, "%s",
+ groupAddress2String[groupAddress - GROUP_ADDR]);
+
+ // change model subscription
+ bt_mesh_cfg_mod_sub_overwrite(net_idx, addr, addr, groupAddress,
+ BT_MESH_MODEL_ID_GEN_ONOFF_SRV, NULL);
+
+ {
+ struct bt_mesh_cfg_hb_sub sub = {
+ .src = PUBLISHER_ADDR,
+ .dst = groupAddress,
+ .period = 0x10,
+ };
+
+ bt_mesh_cfg_hb_sub_set(net_idx, addr, &sub, NULL /*&status*/);
+ }
+
+}
+
+static void button_pressed(struct device *dev, struct gpio_callback *cb,
+ uint32_t pins)
+{
+
+ /*
+ * One button press within a 1 second interval sends an on message
+ * More than one button press sends an off message
+ */
+ time = k_uptime_get_32();
+
+ /* debounce the switch */
+ if (time < last_time + BUTTON_DEBOUNCE_DELAY_MS) {
+ last_time = time;
+ return;
+ }
+
+ if (pins & BIT(SW0_GPIO_PIN)) {
+ k_work_submit(&button_work);
+ }
+ else {
+ k_work_submit(&subscribe_work);
+ }
+
+ last_time = time;
+
+}
+
+static const struct {
+ char note;
+ u32_t period;
+ u32_t sharp;
+} period_map[] = {
+ { 'C', 3822, 3608 },
+ { 'D', 3405, 3214 },
+ { 'E', 3034, 3034 },
+ { 'F', 2863, 2703 },
+ { 'G', 2551, 2407 },
+ { 'A', 2273, 2145 },
+ { 'B', 2025, 2025 },
+};
+
+static u32_t get_period(char note, bool sharp)
+{
+ int i;
+
+ if (note == ' ') {
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(period_map); i++) {
+ if (period_map[i].note != note) {
+ continue;
+ }
+
+ if (sharp) {
+ return period_map[i].sharp;
+ } else {
+ return period_map[i].period;
+ }
+ }
+
+ return 1500;
+}
+
+void board_heartbeat(u8_t hops, u16_t feat)
+{
+ struct mb_display *disp = mb_display_get();
+ const struct mb_image hops_img[] = {
+ MB_IMAGE({ 1, 1, 1, 1, 1 },
+ { 1, 1, 1, 1, 1 },
+ { 1, 1, 1, 1, 1 },
+ { 1, 1, 1, 1, 1 },
+ { 1, 1, 1, 1, 1 }),
+ MB_IMAGE({ 1, 1, 1, 1, 1 },
+ { 1, 1, 1, 1, 1 },
+ { 1, 1, 0, 1, 1 },
+ { 1, 1, 1, 1, 1 },
+ { 1, 1, 1, 1, 1 }),
+ MB_IMAGE({ 1, 1, 1, 1, 1 },
+ { 1, 0, 0, 0, 1 },
+ { 1, 0, 0, 0, 1 },
+ { 1, 0, 0, 0, 1 },
+ { 1, 1, 1, 1, 1 }),
+ MB_IMAGE({ 1, 1, 1, 1, 1 },
+ { 1, 0, 0, 0, 1 },
+ { 1, 0, 0, 0, 1 },
+ { 1, 0, 0, 0, 1 },
+ { 1, 1, 1, 1, 1 }),
+ MB_IMAGE({ 1, 0, 1, 0, 1 },
+ { 0, 0, 0, 0, 0 },
+ { 1, 0, 0, 0, 1 },
+ { 0, 0, 0, 0, 0 },
+ { 1, 0, 1, 0, 1 })
+ };
+
+ printk("%u hops\n", hops);
+
+ if (hops) {
+ hops = min(hops, ARRAY_SIZE(hops_img));
+ mb_display_image(disp, MB_DISPLAY_MODE_SINGLE, K_SECONDS(2),
+ &hops_img[hops - 1], 1);
+ }
+}
+
+void board_other_dev_pressed(u16_t addr)
+{
+ struct mb_display *disp = mb_display_get();
+
+ printk("board_other_dev_pressed(0x%04x)\n", addr);
+
+ mb_display_print(disp, MB_DISPLAY_MODE_SINGLE, K_SECONDS(2),
+ "%c", groupAddress2String[groupAddress - GROUP_ADDR][0]);
+}
+
+void board_attention(bool attention)
+{
+ struct mb_display *disp = mb_display_get();
+ static const struct mb_image attn_img[] = {
+ MB_IMAGE({ 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 1, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 }),
+ MB_IMAGE({ 0, 0, 0, 0, 0 },
+ { 0, 1, 1, 1, 0 },
+ { 0, 1, 1, 1, 0 },
+ { 0, 1, 1, 1, 0 },
+ { 0, 0, 0, 0, 0 }),
+ MB_IMAGE({ 1, 1, 1, 1, 1 },
+ { 1, 1, 1, 1, 1 },
+ { 1, 1, 0, 1, 1 },
+ { 1, 1, 1, 1, 1 },
+ { 1, 1, 1, 1, 1 }),
+ MB_IMAGE({ 1, 1, 1, 1, 1 },
+ { 1, 0, 0, 0, 1 },
+ { 1, 0, 0, 0, 1 },
+ { 1, 0, 0, 0, 1 },
+ { 1, 1, 1, 1, 1 }),
+ };
+
+ if (attention) {
+ mb_display_image(disp,
+ MB_DISPLAY_MODE_DEFAULT | MB_DISPLAY_FLAG_LOOP,
+ K_MSEC(150), attn_img, ARRAY_SIZE(attn_img));
+ } else {
+ mb_display_stop(disp);
+ }
+}
+
+static void configure_button(void)
+{
+ static struct gpio_callback button_cb;
+
+ /* Initialize the button debouncer */
+ last_time = k_uptime_get_32();
+
+ k_work_init(&button_work, buttonA_pressed);
+ k_work_init(&subscribe_work, buttonB_resubscribe);
+
+ gpio = device_get_binding(SW0_GPIO_NAME);
+
+ gpio_pin_configure(gpio, SW0_GPIO_PIN,
+ (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
+ GPIO_INT_ACTIVE_LOW));
+ gpio_pin_configure(gpio, SW1_GPIO_PIN,
+ (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
+ GPIO_INT_ACTIVE_LOW));
+
+ gpio_init_callback(&button_cb, button_pressed,
+ BIT(SW0_GPIO_PIN) | BIT(SW1_GPIO_PIN));
+ gpio_add_callback(gpio, &button_cb);
+
+ gpio_pin_enable_callback(gpio, SW0_GPIO_PIN);
+ gpio_pin_enable_callback(gpio, SW1_GPIO_PIN);
+}
+
+void board_init(u16_t *addr, u32_t *seq)
+{
+ struct mb_display *disp = mb_display_get();
+
+ printk("SEQ_PAGE 0x%08x\n", SEQ_PAGE);
+
+ nvm = device_get_binding(FLASH_DEV_NAME);
+ pwm = device_get_binding(CONFIG_PWM_NRF5_SW_0_DEV_NAME);
+
+ *addr = ( (u16_t)NRF_FICR->DEVICEADDR[0] ) & 0x7fff;
+
+ printk("FICR 0x%02x\n", *addr);
+
+ *seq = get_seq();
+
+ mb_display_print(disp, MB_DISPLAY_MODE_DEFAULT, SCROLL_SPEED,
+ "%s %s", "Server", groupAddress2String[groupAddress - GROUP_ADDR]);
+
+ configure_button();
+}
+
+static void heartbeat(u8_t hops, u16_t feat)
+{
+ board_heartbeat(hops, feat);
+}
+
+static struct bt_mesh_cfg_srv cfg_srv = {
+#if defined(CONFIG_BOARD_BBC_MICROBIT)
+ .relay = BT_MESH_RELAY_ENABLED,
+ .beacon = BT_MESH_BEACON_DISABLED,
+#else
+ .relay = BT_MESH_RELAY_ENABLED,
+ .beacon = BT_MESH_BEACON_ENABLED,
+#endif
+ .frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
+ .default_ttl = 7,
+
+ /* 3 transmissions with 20ms interval */
+ .net_transmit = BT_MESH_TRANSMIT(2, 20),
+ .relay_retransmit = BT_MESH_TRANSMIT(3, 20),
+
+ .hb_sub.func = heartbeat,
+};
+
+static struct bt_mesh_cfg_cli cfg_cli = {
+};
+
+static void attention_on(struct bt_mesh_model *model)
+{
+ printk("attention_on()\n");
+ board_attention(true);
+}
+
+static void attention_off(struct bt_mesh_model *model)
+{
+ printk("attention_off()\n");
+ board_attention(false);
+}
+
+static const struct bt_mesh_health_srv_cb health_srv_cb = {
+ .attn_on = attention_on,
+ .attn_off = attention_off,
+};
+
+static struct bt_mesh_health_srv health_srv = {
+ .cb = &health_srv_cb,
+};
+
+BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0);
+BT_MESH_MODEL_PUB_DEFINE(gen_onoff_pub_srv, NULL, 2 + 2);
+BT_MESH_MODEL_PUB_DEFINE(gen_onoff_pub_cli, NULL, 2 + 2);
+
+
+static void gen_onoff_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct net_buf_simple *buf)
+{
+ struct mb_display *disp = mb_display_get();
+ uint8_t value, trans;
+ value = *buf->data++;
+ trans = *buf->data++;
+
+ printk("gen_onoff_set model 0x%04x, src 0x%04x, value:0x%02x, trans: 0x%02x\n",
+ model->id, ctx->addr, value, trans);
+ if(value){
+ mb_display_print(disp, MB_DISPLAY_MODE_SINGLE, -1,
+ "%c", groupAddress2String[groupAddress - GROUP_ADDR][0]);
+ }
+ else{
+ mb_display_stop(disp);
+ }
+
+}
+
+static void gen_onoff_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct net_buf_simple *buf)
+{
+ printk("gen_onoff_status modelId 0x%04x, src 0x%04x\n", model->id, ctx->addr);
+}
+
+/*
+ * OnOff Model Server Op Dispatch Table
+ *
+ */
+
+static const struct bt_mesh_model_op gen_onoff_srv_op[] = {
+ //{ BT_MESH_MODEL_OP_GEN_ONOFF_GET, 0, gen_onoff_get },
+ { BT_MESH_MODEL_OP_GEN_ONOFF_SET, 2, gen_onoff_set },
+ //{ BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2, gen_onoff_set_unack },
+ BT_MESH_MODEL_OP_END,
+};
+
+static struct bt_mesh_model root_models[] = {
+ BT_MESH_MODEL_CFG_SRV(&cfg_srv),
+ BT_MESH_MODEL_CFG_CLI(&cfg_cli),
+ BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op,
+ &gen_onoff_pub_srv, NULL),
+};
+
+static struct bt_mesh_elem elements[] = {
+ BT_MESH_ELEM(0, root_models, BT_MESH_MODEL_NONE),
+ //BT_MESH_ELEM(0, vnd_models, BT_MESH_MODEL_NONE),
+};
+
+static const struct bt_mesh_comp comp = {
+ .cid = BT_COMP_ID_LF,
+ .elem = elements,
+ .elem_count = ARRAY_SIZE(elements),
+};
+
+
+static void configure(void)
+{
+ printk("Configuring...\n");
+
+ /* Add Application Key */
+ bt_mesh_cfg_app_key_add(net_idx, addr, net_idx, app_idx, app_key, NULL);
+
+ /* Bind to vendor model */
+ bt_mesh_cfg_mod_app_bind(net_idx, addr, addr, app_idx,
+ BT_MESH_MODEL_ID_GEN_ONOFF_SRV, NULL);
+
+ /* Bind to Health model */
+ bt_mesh_cfg_mod_app_bind(net_idx, addr, addr, app_idx,
+ BT_MESH_MODEL_ID_HEALTH_SRV, NULL);
+
+ bt_mesh_cfg_mod_sub_add(net_idx, addr, addr, groupAddress,
+ BT_MESH_MODEL_ID_GEN_ONOFF_SRV, NULL);
+
+ {
+ struct bt_mesh_cfg_hb_sub sub = {
+ .src = PUBLISHER_ADDR,
+ .dst = groupAddress,
+ .period = 0x10,
+ };
+
+ bt_mesh_cfg_hb_sub_set(net_idx, addr, &sub, NULL);
+ printk("Subscribing to heartbeat messages, group address: 0x%04x, %s\n",
+ groupAddress, groupAddress2String[groupAddress - GROUP_ADDR]);
+ }
+
+ printk("Configuration complete\n");
+
+}
+
+static const u8_t dev_uuid[16] = { 0xdd, 0xdd };
+
+static const struct bt_mesh_prov prov = {
+ .uuid = dev_uuid,
+};
+
+static void bt_ready(int err)
+{
+ if (err) {
+ printk("Bluetooth init failed (err %d)\n", err);
+ return;
+ }
+
+ printk("Bluetooth initialized\n");
+
+ err = bt_mesh_init(&prov, &comp);
+ if (err) {
+ printk("Initializing mesh failed (err %d)\n", err);
+ return;
+ }
+
+ printk("Mesh initialized\n");
+
+ err = bt_mesh_provision(net_key, net_idx, flags, iv_index, seq, addr,
+ dev_key);
+ if (err) {
+ printk("Provisioning failed (err %d)\n", err);
+ return;
+ }
+
+ printk("Provisioning completed\n");
+
+ configure();
+}
+
+void main(void)
+{
+ int err;
+
+ printk("Initializing...\n");
+
+ board_init(&addr, &seq);
+
+ printk("Unicast address: 0x%04x, seq 0x%06x\n", addr, seq);
+
+ /* Initialize the Bluetooth Subsystem */
+ err = bt_enable(bt_ready);
+ if (err) {
+ printk("Bluetooth init failed (err %d)\n", err);
+ }
+
+ while (1) {
+ }
+
+}