Publishing for Bluetooth Asia 2018 developer session: mesh session. This repo is for GenericOnOff client side firmware.
EULA
PLEASE READ MESH_DEMO_TUTORIAL_EULA.TXT BEFORE START DEVELOPMENT.
Overview
This sample demonstrates Bluetooth Mesh functionality on micro:bit. It doesn't need provisioning because all the credential material (DevKey, NetKey, AppKey, Key Index, IVI and Unicast address) is pre-configured. This sample work as a GenericOnOff client:
- Pressing Button A on micro:bit will send GenericOnOffSet access message with on or off state alternatively and specific group address;
- Pressing Button B on micro:bit will switch the group address from 0xC000 to 0xC003 and back to 0xC000 again like round robin;
Requirements
micro:bit board
Building and Running
0. Download source code, it's zip file, the link is on this page, Download repository
.
1. Following below link to set the development environment up on your Windows computer. http://docs.zephyrproject.org/getting_started/installation_win.html . Please make sure git checkout this commit, commit: 88dfd399f480b1593a8e13f5a68d512921a55502 , the detail is here, https://github.com/zephyrproject-rtos/zephyr/commit/88dfd399f480b1593a8e13f5a68d512921a55502
2. copy zip file into ./zephyr/sample/
in the Zephyr tree.
3. unzip the file by "Extract Here".
3. access into the extracted folder and rename prj_bbc_microbit.txt
to prj_bbc_microbit.conf
4. if adopting Windows Command Prompt, use it to access into the unzip folder and type following commands on the console:
mkdir build & cd build
cmake -GNinja -DBOARD=bbc_microbit ..
ninja
if adopting MSYS2, use it to access into the unzip folder and type following commands on the console:
mkdir build & cd build
cmake -GNinja -DBOARD=bbc_microbit ..
ninja
5. connect micro:bit with your computer by USB cable, the board will be enumerated as a massive storage device;
6. drag the hex file (which is in ./zephyr/sample/[unzip folder]/build/zephyr/zephyr.hex
) into
Microbit massive storage device to flash the firmware;
7. micro:bit is ready to work as a GenericOnOff client.
Diff: src/main.c
- Revision:
- 1:fb4893064dd4
- Parent:
- 0:876e59f87d50
- Child:
- 7:6512e150f5f6
diff -r 876e59f87d50 -r fb4893064dd4 src/main.c --- a/src/main.c Tue May 01 10:22:24 2018 +0000 +++ b/src/main.c Wed May 02 04:10:40 2018 +0000 @@ -1,122 +1,244 @@ -/* main.c - Application main entry point */ - /* - * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2018 Bluetooth SIG * * SPDX-License-Identifier: Apache-2.0 */ -#include <stdio.h> - -#include <gpio.h> -#include <board.h> - #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> -#include "board.h" +#if !defined(NODE_ADDR) +#define NODE_ADDR 0x0b02 +#endif +#define CID_INTEL 0x0002 +#define MOD_INTEL 0x0000 +#define GROUP_ADDR 0xc000 +#define PUBLISHER_ADDR 0x000f + +/* 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) -#define BUTTON_DEBOUNCE_DELAY_MS 250 - +/* Publication Declarations */ +BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0); BT_MESH_MODEL_PUB_DEFINE(gen_onoff_pub_cli, NULL, 2 + 2); -static struct device *gpio; -static u8_t genericOnOffValue; -static u8_t trans_id = 0; -static u32_t time, last_time; -static struct k_work button_work; +/* Button debounce timeout */ +#define BUTTON_DEBOUNCE_DELAY_MS 250 +/* LED matrix scroll speed */ +#define SCROLL_SPEED K_MSEC(500) + +/* Buzzer definition, no used in this example. */ +#define BUZZER_PIN EXT_P0_GPIO_PIN +#define BEEP_DURATION K_MSEC(60) -static struct bt_mesh_cfg_srv cfg_srv = { - .relay = BT_MESH_RELAY_DISABLED, - .beacon = BT_MESH_BEACON_ENABLED, -#if defined(CONFIG_BT_MESH_FRIEND) - .frnd = BT_MESH_FRIEND_ENABLED, -#else - .frnd = BT_MESH_FRIEND_NOT_SUPPORTED, -#endif -#if defined(CONFIG_BT_MESH_GATT_PROXY) - .gatt_proxy = BT_MESH_GATT_PROXY_ENABLED, -#else - .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED, -#endif - .default_ttl = 7, +/* 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) - /* 3 transmissions with 20ms interval */ - .net_transmit = BT_MESH_TRANSMIT(2, 20), - .relay_retransmit = BT_MESH_TRANSMIT(2, 20), +/* 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, }; -static void gen_onoff_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct net_buf_simple *buf) -{ - u8_t state; - - state = net_buf_simple_pull_u8(buf); - - printk("Node 0x%04x OnOff status from 0x%04x with state 0x%02x", - model->elem->addr, ctx->addr, state); -} - -static const struct bt_mesh_model_op gen_onoff_cli_op[] = { - { BT_MESH_MODEL_OP_GEN_ONOFF_STATUS, 1, gen_onoff_status }, - BT_MESH_MODEL_OP_END, +/* group address string. */ +const char *groupAddress2String[] = { + "Bedroom", + "Living", + "Dining", + "Garage" }; -static struct bt_mesh_model root_models[] = { - BT_MESH_MODEL_CFG_SRV(&cfg_srv), - BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op, - &gen_onoff_pub_cli, NULL), -}; +static struct device *gpio; +static struct device *nvm; +static struct device *pwm; + +static struct k_work button_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 = NODE_ADDR; +u16_t groupAddress = GROUP_ADDR; +static u32_t seq; -static struct bt_mesh_elem elements[] = { - BT_MESH_ELEM(0, root_models, BT_MESH_MODEL_NONE), -}; +/* Transaction ID for Generic OnOff Set */ +static u8_t trans_ID = 0; + +/* GenericOnOffSet state */ +u8_t OnOff_Value = 0; + +/* Model Operation decleration */ +static void gen_onoff_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf); + +static void gen_onoff_set_unack(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf); + +static void gen_onoff_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf); -static const struct bt_mesh_comp comp = { - .cid = BT_COMP_ID_LF, - .elem = elements, - .elem_count = ARRAY_SIZE(elements), -}; +static void gen_onoff_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf); +static void genericOnOffSet(void); + -void genericOnOffSet(uint8_t value) +/* switch group address like round robin. */ +u16_t board_set_target(void) { + switch (groupAddress) { + case GROUP_ADDR: + groupAddress++; + break; + case (GROUP_ADDR + 3): + groupAddress = GROUP_ADDR; + break; + default: + groupAddress++; + break; + } - if (gen_onoff_pub_cli.addr == BT_MESH_ADDR_UNASSIGNED) { - printk("No\n"); + 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; } - printk("Yes\n"); + seq_map >>= 1; - bt_mesh_model_msg_init(gen_onoff_pub_cli.msg, - BT_MESH_MODEL_OP_GEN_ONOFF_SET); - net_buf_simple_add_u8(gen_onoff_pub_cli.msg, value); - net_buf_simple_add_u8(gen_onoff_pub_cli.msg, trans_id++); - bt_mesh_model_publish(&root_models[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); + } } -void button_send_pressed(struct k_work *work) +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; + } - genericOnOffSet(genericOnOffValue); - printk("button_send_pressed( %d )\n", genericOnOffValue); + 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; } -void button_pressed(struct device *dev, struct gpio_callback *cb, +/* Callback function for button B pressed, it's scheduled by OS, out of interrupt routine + * it's safe to stay here longer. */ +static void button_send_pressed(struct k_work *work) +{ + struct mb_display *disp = mb_display_get(); + + printk("button_send_pressed()\n"); + if(OnOff_Value % 2) { + mb_display_print(disp, MB_DISPLAY_MODE_SINGLE, 100000, + "%s", groupAddress2String[groupAddress - GROUP_ADDR]); + } + else + { + mb_display_print(disp, MB_DISPLAY_MODE_SINGLE, 100000, + "%s", " "); + } + genericOnOffSet(); +} + +/* button B callback, direct invoke by interrupt routine, need to be out of this callback ASAP. */ +static void button_pressed(struct device *dev, struct gpio_callback *cb, uint32_t pins) { + struct mb_display *disp = mb_display_get(); + /* * One button press within a 1 second interval sends an on message * More than one button press sends an off message @@ -130,62 +252,129 @@ } if (pins & BIT(SW0_GPIO_PIN)) { - genericOnOffValue = 1; + k_work_submit(&button_work); + } + else { + board_set_target(); + + mb_display_print(disp, MB_DISPLAY_MODE_DEFAULT, SCROLL_SPEED, + "%s", groupAddress2String[groupAddress - GROUP_ADDR]); } - else{ - genericOnOffValue = 0; + 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; } - //submit to ksystem - k_work_submit(&button_work); + for (i = 0; i < ARRAY_SIZE(period_map); i++) { + if (period_map[i].note != note) { + continue; + } - last_time = time; + if (sharp) { + return period_map[i].sharp; + } else { + return period_map[i].period; + } + } + + return 1500; } -static int output_number(bt_mesh_output_action_t action, uint32_t number) +void board_heartbeat(u8_t hops, u16_t feat) { struct mb_display *disp = mb_display_get(); - - printk("OOB Number: %u\n", number); - mb_display_print(disp, MB_DISPLAY_MODE_SINGLE, -1, "%d", number); - - - return 0; -} + 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 }) + }; -static int output_string(const char *str) -{ - struct mb_display *disp = mb_display_get(); + printk("%u hops\n", hops); - printk("OOB String: %s\n", str); - - mb_display_print(disp, MB_DISPLAY_MODE_SCROLL, K_SECONDS(1), "%s", str); - - return 0; + 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); + } } -static void prov_complete(u16_t net_idx, u16_t addr) +void board_attention(bool attention) { - //board_prov_complete(); -} - -static void prov_reset(void) -{ - bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT); -} + 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 }), + }; -static uint8_t dev_uuid[16] = { 0xdd, 0xdd }; - -static const struct bt_mesh_prov prov = { - .uuid = dev_uuid, - .output_size = 4, - .output_actions = BT_MESH_DISPLAY_STRING, - .output_number = output_number, - .output_string = output_string, - .complete = prov_complete, - .reset = prov_reset, -}; + 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) { @@ -198,35 +387,195 @@ gpio = device_get_binding(SW0_GPIO_NAME); - //initial button A 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_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)); - + 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(void) +void board_init(u16_t *addr, u32_t *seq) { - gpio = device_get_binding(CONFIG_GPIO_NRF5_P0_DEV_NAME); + 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", "Client", 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, +}; + +/* + * OnOff Model Client Op Dispatch Table + */ + +static const struct bt_mesh_model_op gen_onoff_cli_op[] = { + { BT_MESH_MODEL_OP_GEN_ONOFF_STATUS, 1, gen_onoff_status }, + 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_CLI, gen_onoff_cli_op, + &gen_onoff_pub_cli, NULL), +}; + +static struct bt_mesh_elem elements[] = { + BT_MESH_ELEM(0, root_models, /* 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), +}; + +/* + * Generic OnOff Model Server Message Handlers + * + * Mesh Model Specification 3.1.1 + * + */ + +static void gen_onoff_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + printk("gen_onoff_get...\n"); +} + +static void gen_onoff_set_unack(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + printk("gen_onoff_set_unack...\n"); +} + +static void gen_onoff_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *buf) +{ + printk("gen_onoff_set...\n"); + +} + +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...\n"); +} + +static void configure(void) +{ + int status; + + printk("Configuring...\n"); + + /* Add Application Key */ + status = bt_mesh_cfg_app_key_add(net_idx, addr, net_idx, app_idx, app_key, NULL); + printk("bt_mesh_cfg_app_key_add = %d \n", status); + + + /* Bind to Generic on/off client model */ + status = bt_mesh_cfg_mod_app_bind(net_idx, addr, addr, app_idx, + BT_MESH_MODEL_ID_GEN_ONOFF_CLI, NULL); + printk("bt_mesh_cfg_mod_app_bind = %d \n", status); + + status = bt_mesh_cfg_mod_sub_add(net_idx, addr, addr, + GROUP_ADDR, BT_MESH_MODEL_ID_GEN_ONOFF_CLI, NULL); + printk("bt_mesh_cfg_mod_sub_add = %d \n", status); + + + struct bt_mesh_cfg_hb_sub sub = { + .src = PUBLISHER_ADDR, + .dst = GROUP_ADDR, + .period = 0x10, + }; + + bt_mesh_cfg_hb_sub_set(net_idx, addr, &sub, NULL); + printk("Subscribing to heartbeat messages\n"); + + + 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) { - uint64_t uuidFICR = NRF_FICR->DEVICEADDR[0] | ( ( (uint64_t)(NRF_FICR->DEVICEADDR[01]) ) << 32 ); - if (err) { printk("Bluetooth init failed (err %d)\n", err); return; @@ -234,40 +583,68 @@ printk("Bluetooth initialized\n"); - board_init(); - - /* Use identity address as device UUID */ - memcpy(dev_uuid, &uuidFICR, sizeof(uint64_t)); - err = bt_mesh_init(&prov, &comp); if (err) { printk("Initializing mesh failed (err %d)\n", err); return; } - bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT); + printk("Mesh initialized\n"); - 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 board_prov_complete(void) +static void genericOnOffSet(void) { - //gpio_pin_disable_callback(gpio, SW0_GPIO_PIN); + NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = app_idx, + .addr = groupAddress, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + + /* Bind to Generic OnOff Model */ + bt_mesh_model_msg_init(&msg, BT_MESH_MODEL_OP_GEN_ONOFF_SET ); + + net_buf_simple_add_u8(&msg, OnOff_Value % 2); + OnOff_Value++; + net_buf_simple_add_u8(&msg, trans_ID++); + + if (bt_mesh_model_send(&root_models[3], &ctx, &msg, NULL, NULL)) { + printk("Unable to send Vendor Button message\n"); + } + + printk("Button message sent with addr 0x%04x\n", groupAddress); } void main(void) { int err; - struct mb_display *disp = mb_display_get(); + + printk("Initializing...\n"); - printk("GenericOnOff Client Initializing...\n"); - printk("UUID: 0x%08x%08X\n", NRF_FICR->DEVICEADDR[1], NRF_FICR->DEVICEADDR[0]); - mb_display_print(disp, MB_DISPLAY_MODE_SCROLL, K_MSEC(500), "%s", "Client"); + board_init(&addr, &seq); + printk("Unicast address: 0x%04x, name: %s, seq 0x%06x\n", addr, groupAddress2String[groupAddress - GROUP_ADDR], seq); /* Initialize the Bluetooth Subsystem */ err = bt_enable(bt_ready); if (err) { printk("Bluetooth init failed (err %d)\n", err); } + + while (1) { + + } + }