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:
- 0:876e59f87d50
- Child:
- 1:fb4893064dd4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.c Tue May 01 10:22:24 2018 +0000 @@ -0,0 +1,273 @@ +/* main.c - Application main entry point */ + +/* + * Copyright (c) 2017 Intel Corporation + * + * 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 <display/mb_display.h> + + +#include "board.h" + +#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 + +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; + + +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, + + /* 3 transmissions with 20ms interval */ + .net_transmit = BT_MESH_TRANSMIT(2, 20), + .relay_retransmit = BT_MESH_TRANSMIT(2, 20), +}; + + +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, +}; + +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 bt_mesh_elem elements[] = { + BT_MESH_ELEM(0, root_models, BT_MESH_MODEL_NONE), +}; + +static const struct bt_mesh_comp comp = { + .cid = BT_COMP_ID_LF, + .elem = elements, + .elem_count = ARRAY_SIZE(elements), +}; + +void genericOnOffSet(uint8_t value) +{ + + if (gen_onoff_pub_cli.addr == BT_MESH_ADDR_UNASSIGNED) { + printk("No\n"); + return; + } + + printk("Yes\n"); + + 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]); +} + +void button_send_pressed(struct k_work *work) +{ + + genericOnOffSet(genericOnOffValue); + printk("button_send_pressed( %d )\n", genericOnOffValue); +} + +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)) { + genericOnOffValue = 1; + } + else{ + genericOnOffValue = 0; + } + + //submit to ksystem + k_work_submit(&button_work); + + last_time = time; +} + + +static int output_number(bt_mesh_output_action_t action, uint32_t number) +{ + 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; +} + +static int output_string(const char *str) +{ + struct mb_display *disp = mb_display_get(); + + printk("OOB String: %s\n", str); + + mb_display_print(disp, MB_DISPLAY_MODE_SCROLL, K_SECONDS(1), "%s", str); + + return 0; +} + +static void prov_complete(u16_t net_idx, u16_t addr) +{ + //board_prov_complete(); +} + +static void prov_reset(void) +{ + bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT); +} + +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, +}; + +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, button_send_pressed); + + 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_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(void) +{ + gpio = device_get_binding(CONFIG_GPIO_NRF5_P0_DEV_NAME); + + configure_button(); +} + +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; + } + + 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"); +} + +void board_prov_complete(void) +{ + //gpio_pin_disable_callback(gpio, SW0_GPIO_PIN); +} + +void main(void) +{ + int err; + struct mb_display *disp = mb_display_get(); + + 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"); + + + /* Initialize the Bluetooth Subsystem */ + err = bt_enable(bt_ready); + if (err) { + printk("Bluetooth init failed (err %d)\n", err); + } +}