You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
293 lines
6.1 KiB
293 lines
6.1 KiB
/* main.c - Application main entry point */ |
|
|
|
/* |
|
* Copyright (c) 2017 Intel Corporation |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#include <zephyr/sys/printk.h> |
|
|
|
#include <zephyr/settings/settings.h> |
|
|
|
#include <zephyr/bluetooth/bluetooth.h> |
|
#include <zephyr/bluetooth/mesh.h> |
|
|
|
#include "board.h" |
|
|
|
#define MOD_LF 0x0000 |
|
|
|
#define GROUP_ADDR 0xc000 |
|
#define PUBLISHER_ADDR 0x000f |
|
|
|
#define OP_VENDOR_BUTTON BT_MESH_MODEL_OP_3(0x00, BT_COMP_ID_LF) |
|
|
|
static const uint8_t net_key[16] = { |
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, |
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, |
|
}; |
|
static const uint8_t dev_key[16] = { |
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, |
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, |
|
}; |
|
static const uint8_t app_key[16] = { |
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, |
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, |
|
}; |
|
static const uint16_t net_idx; |
|
static const uint16_t app_idx; |
|
static const uint32_t iv_index; |
|
static uint8_t flags; |
|
static uint16_t addr = NODE_ADDR; |
|
|
|
static void heartbeat(const struct bt_mesh_hb_sub *sub, uint8_t hops, |
|
uint16_t feat) |
|
{ |
|
board_heartbeat(hops, feat); |
|
board_play("100H"); |
|
} |
|
|
|
static struct bt_mesh_cfg_cli cfg_cli = { |
|
}; |
|
|
|
static void attention_on(struct bt_mesh_model *model) |
|
{ |
|
printk("attention_on()\n"); |
|
board_attention(true); |
|
board_play("100H100C100H100C100H100C"); |
|
} |
|
|
|
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); |
|
|
|
static struct bt_mesh_model root_models[] = { |
|
BT_MESH_MODEL_CFG_SRV, |
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli), |
|
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), |
|
}; |
|
|
|
static int vnd_button_pressed(struct bt_mesh_model *model, |
|
struct bt_mesh_msg_ctx *ctx, |
|
struct net_buf_simple *buf) |
|
{ |
|
printk("src 0x%04x\n", ctx->addr); |
|
|
|
if (ctx->addr == bt_mesh_model_elem(model)->addr) { |
|
return 0; |
|
} |
|
|
|
board_other_dev_pressed(ctx->addr); |
|
board_play("100G200 100G"); |
|
|
|
return 0; |
|
} |
|
|
|
static const struct bt_mesh_model_op vnd_ops[] = { |
|
{ OP_VENDOR_BUTTON, BT_MESH_LEN_EXACT(0), vnd_button_pressed }, |
|
BT_MESH_MODEL_OP_END, |
|
}; |
|
|
|
static struct bt_mesh_model vnd_models[] = { |
|
BT_MESH_MODEL_VND(BT_COMP_ID_LF, MOD_LF, vnd_ops, NULL, NULL), |
|
}; |
|
|
|
static struct bt_mesh_elem elements[] = { |
|
BT_MESH_ELEM(0, root_models, vnd_models), |
|
}; |
|
|
|
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_cli_app_key_add(net_idx, addr, net_idx, app_idx, app_key, NULL); |
|
|
|
/* Bind to vendor model */ |
|
bt_mesh_cfg_cli_mod_app_bind_vnd(net_idx, addr, addr, app_idx, MOD_LF, BT_COMP_ID_LF, NULL); |
|
|
|
/* Bind to Health model */ |
|
bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_HEALTH_SRV, |
|
NULL); |
|
|
|
/* Add model subscription */ |
|
bt_mesh_cfg_cli_mod_sub_add_vnd(net_idx, addr, addr, GROUP_ADDR, MOD_LF, BT_COMP_ID_LF, |
|
NULL); |
|
|
|
#if NODE_ADDR == PUBLISHER_ADDR |
|
{ |
|
struct bt_mesh_cfg_cli_hb_pub pub = { |
|
.dst = GROUP_ADDR, |
|
.count = 0xff, |
|
.period = 0x05, |
|
.ttl = 0x07, |
|
.feat = 0, |
|
.net_idx = net_idx, |
|
}; |
|
|
|
bt_mesh_cfg_cli_hb_pub_set(net_idx, addr, &pub, NULL); |
|
printk("Publishing heartbeat messages\n"); |
|
} |
|
#endif |
|
printk("Configuration complete\n"); |
|
|
|
board_play("100C100D100E100F100G100A100H"); |
|
} |
|
|
|
static const uint8_t dev_uuid[16] = { 0xdd, 0xdd }; |
|
|
|
static const struct bt_mesh_prov prov = { |
|
.uuid = dev_uuid, |
|
}; |
|
|
|
BT_MESH_HB_CB_DEFINE(hb_cb) = { |
|
.recv = heartbeat, |
|
}; |
|
|
|
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"); |
|
|
|
if (IS_ENABLED(CONFIG_BT_SETTINGS)) { |
|
printk("Loading stored settings\n"); |
|
settings_load(); |
|
} |
|
|
|
err = bt_mesh_provision(net_key, net_idx, flags, iv_index, addr, |
|
dev_key); |
|
if (err == -EALREADY) { |
|
printk("Using stored settings\n"); |
|
} else if (err) { |
|
printk("Provisioning failed (err %d)\n", err); |
|
return; |
|
} else { |
|
printk("Provisioning completed\n"); |
|
configure(); |
|
} |
|
|
|
#if NODE_ADDR != PUBLISHER_ADDR |
|
/* Heartbeat subscription is a temporary state (due to there |
|
* not being an "indefinite" value for the period, so it never |
|
* gets stored persistently. Therefore, we always have to configure |
|
* it explicitly. |
|
*/ |
|
{ |
|
struct bt_mesh_cfg_cli_hb_sub sub = { |
|
.src = PUBLISHER_ADDR, |
|
.dst = GROUP_ADDR, |
|
.period = 0x10, |
|
}; |
|
|
|
bt_mesh_cfg_cli_hb_sub_set(net_idx, addr, &sub, NULL); |
|
printk("Subscribing to heartbeat messages\n"); |
|
} |
|
#endif |
|
} |
|
|
|
static uint16_t target = GROUP_ADDR; |
|
|
|
void board_button_1_pressed(void) |
|
{ |
|
NET_BUF_SIMPLE_DEFINE(msg, 3 + 4); |
|
struct bt_mesh_msg_ctx ctx = { |
|
.app_idx = app_idx, |
|
.addr = target, |
|
.send_ttl = BT_MESH_TTL_DEFAULT, |
|
}; |
|
|
|
/* Bind to Health model */ |
|
bt_mesh_model_msg_init(&msg, OP_VENDOR_BUTTON); |
|
|
|
if (bt_mesh_model_send(&vnd_models[0], &ctx, &msg, NULL, NULL)) { |
|
printk("Unable to send Vendor Button message\n"); |
|
} |
|
|
|
printk("Button message sent with OpCode 0x%08x\n", OP_VENDOR_BUTTON); |
|
} |
|
|
|
uint16_t board_set_target(void) |
|
{ |
|
switch (target) { |
|
case GROUP_ADDR: |
|
target = 1U; |
|
break; |
|
case 9: |
|
target = GROUP_ADDR; |
|
break; |
|
default: |
|
target++; |
|
break; |
|
} |
|
|
|
return target; |
|
} |
|
|
|
static K_SEM_DEFINE(tune_sem, 0, 1); |
|
static const char *tune_str; |
|
|
|
void board_play(const char *str) |
|
{ |
|
tune_str = str; |
|
k_sem_give(&tune_sem); |
|
} |
|
|
|
int main(void) |
|
{ |
|
int err; |
|
|
|
printk("Initializing...\n"); |
|
|
|
err = board_init(&addr); |
|
if (err) { |
|
printk("Board initialization failed\n"); |
|
return 0; |
|
} |
|
|
|
printk("Unicast address: 0x%04x\n", addr); |
|
|
|
/* Initialize the Bluetooth Subsystem */ |
|
err = bt_enable(bt_ready); |
|
if (err) { |
|
printk("Bluetooth init failed (err %d)\n", err); |
|
return 0; |
|
} |
|
|
|
while (1) { |
|
k_sem_take(&tune_sem, K_FOREVER); |
|
board_play_tune(tune_str); |
|
} |
|
|
|
return 0; |
|
}
|
|
|