summaryrefslogtreecommitdiff
path: root/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.c')
-rw-r--r--src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.c313
1 files changed, 313 insertions, 0 deletions
diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.c b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.c
new file mode 100644
index 00000000..ee999172
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "console/console.h"
+#include "mesh/mesh.h"
+
+#include "mesh_badge.h"
+#include "mesh.h"
+#include "board.h"
+
+#define BT_COMP_ID_LF 0x05f1
+
+#define MOD_LF 0x0000
+#define OP_HELLO 0xbb
+#define OP_HEARTBEAT 0xbc
+#define OP_VND_HELLO BT_MESH_MODEL_OP_3(OP_HELLO, BT_COMP_ID_LF)
+#define OP_VND_HEARTBEAT BT_MESH_MODEL_OP_3(OP_HEARTBEAT, BT_COMP_ID_LF)
+
+#define DEFAULT_TTL 31
+#define GROUP_ADDR 0xc123
+#define NET_IDX 0x000
+#define APP_IDX 0x000
+#define FLAGS 0
+static struct ble_npl_callout hello_work;
+static struct ble_npl_callout mesh_start_work;
+
+static void heartbeat(const struct bt_mesh_hb_sub *sub, uint8_t hops,
+ uint16_t feat)
+{
+ board_show_text("Heartbeat Received", false, K_SECONDS(2));
+}
+
+static struct bt_mesh_cfg_cli cfg_cli = {
+};
+
+static void attention_on(struct bt_mesh_model *model)
+{
+ board_show_text("Attention!", false, K_SECONDS(2));
+}
+
+static void attention_off(struct bt_mesh_model *model)
+{
+ board_refresh_display();
+}
+
+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,
+};
+
+static struct os_mbuf *bt_mesh_pub_msg_health_pub;
+static struct bt_mesh_model_pub health_pub;
+
+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 void vnd_hello(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ char str[32];
+ size_t len;
+
+ printk("Hello message from 0x%04x\n", ctx->addr);
+
+ if (ctx->addr == bt_mesh_model_elem(model)->addr) {
+ printk("Ignoring message from self\n");
+ return;
+ }
+
+ len = min(buf->om_len, 8);
+ memcpy(str, buf->om_data, len);
+ str[len] = '\0';
+
+ board_add_hello(ctx->addr, str);
+
+ strcpy(str + len, " says hi!");
+
+ board_show_text(str, false, K_SECONDS(3));
+
+ board_blink_leds();
+}
+
+static void vnd_heartbeat(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ uint8_t init_ttl, hops;
+
+ /* Ignore messages from self */
+ if (ctx->addr == bt_mesh_model_elem(model)->addr) {
+ return;
+ }
+
+ init_ttl = net_buf_simple_pull_u8(buf);
+ hops = init_ttl - ctx->recv_ttl + 1;
+
+ printk("Heartbeat from 0x%04x over %u hop%s\n", ctx->addr,
+ hops, hops == 1 ? "" : "s");
+
+ board_add_heartbeat(ctx->addr, hops);
+}
+
+static const struct bt_mesh_model_op vnd_ops[] = {
+ { OP_VND_HELLO, 1, vnd_hello },
+ { OP_VND_HEARTBEAT, 1, vnd_heartbeat },
+ BT_MESH_MODEL_OP_END,
+};
+
+static int pub_update(struct bt_mesh_model *mod)
+{
+ struct os_mbuf *msg = mod->pub->msg;
+
+ printk("Preparing to send heartbeat\n");
+
+ bt_mesh_model_msg_init(msg, OP_VND_HEARTBEAT);
+ net_buf_simple_add_u8(msg, DEFAULT_TTL);
+
+ return 0;
+}
+
+static struct os_mbuf *bt_mesh_pub_msg_vnd_pub;
+static struct bt_mesh_model_pub vnd_pub;
+
+static struct bt_mesh_model vnd_models[] = {
+ BT_MESH_MODEL_VND(BT_COMP_ID_LF, MOD_LF, vnd_ops, &vnd_pub, 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 size_t first_name_len(const char *name)
+{
+ size_t len;
+
+ for (len = 0; *name; name++, len++) {
+ switch (*name) {
+ case ' ':
+ case ',':
+ case '\n':
+ return len;
+ }
+ }
+
+ return len;
+}
+
+static void send_hello(struct ble_npl_event *work)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(3 + 8 + 4);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = NET_IDX,
+ .app_idx = APP_IDX,
+ .addr = GROUP_ADDR,
+ .send_ttl = DEFAULT_TTL,
+ };
+ const char *name = bt_get_name();
+
+ bt_mesh_model_msg_init(msg, OP_VND_HELLO);
+ net_buf_simple_add_mem(msg, name, first_name_len(name));
+
+ if (bt_mesh_model_send(&vnd_models[0], &ctx, msg, NULL, NULL) == 0) {
+ board_show_text("Saying \"hi!\" to everyone", false,
+ K_SECONDS(2));
+ } else {
+ board_show_text("Sending Failed!", false, K_SECONDS(2));
+ }
+
+ os_mbuf_free_chain(msg);
+}
+
+void mesh_send_hello(void)
+{
+ k_work_submit(&hello_work);
+}
+
+static int provision_and_configure(void)
+{
+ static const uint8_t net_key[16] = {
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
+ };
+ static const uint8_t app_key[16] = {
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ };
+ static const uint16_t iv_index;
+ struct bt_mesh_cfg_mod_pub pub = {
+ .addr = GROUP_ADDR,
+ .app_idx = APP_IDX,
+ .ttl = DEFAULT_TTL,
+ .period = BT_MESH_PUB_PERIOD_SEC(10),
+ };
+ uint8_t dev_key[16];
+ uint16_t addr;
+ int err;
+
+ err = bt_rand(dev_key, sizeof(dev_key));
+ if (err) {
+ return err;
+ }
+
+ do {
+ err = bt_rand(&addr, sizeof(addr));
+ if (err) {
+ return err;
+ }
+ } while (!addr);
+
+ /* Make sure it's a unicast address (highest bit unset) */
+ addr &= ~0x8000;
+
+ err = bt_mesh_provision(net_key, NET_IDX, FLAGS, iv_index, addr,
+ dev_key);
+ if (err) {
+ return err;
+ }
+
+ 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_vnd(NET_IDX, addr, addr, APP_IDX,
+ MOD_LF, BT_COMP_ID_LF, NULL);
+
+ /* Bind to Health model */
+ bt_mesh_cfg_mod_app_bind(NET_IDX, addr, addr, APP_IDX,
+ BT_MESH_MODEL_ID_HEALTH_SRV, NULL);
+
+ /* Add model subscription */
+ bt_mesh_cfg_mod_sub_add_vnd(NET_IDX, addr, addr, GROUP_ADDR,
+ MOD_LF, BT_COMP_ID_LF, NULL);
+
+ bt_mesh_cfg_mod_pub_set_vnd(NET_IDX, addr, addr, MOD_LF, BT_COMP_ID_LF,
+ &pub, NULL);
+
+ printk("Configuration complete\n");
+
+ return addr;
+}
+
+static void start_mesh(struct ble_npl_event *work)
+{
+ int err;
+
+ err = provision_and_configure();
+ if (err < 0) {
+ board_show_text("Starting Mesh Failed", false,
+ K_SECONDS(2));
+ } else {
+ char buf[32];
+
+ snprintk(buf, sizeof(buf),
+ "Mesh Started\nAddr: 0x%04x", err);
+ board_show_text(buf, false, K_SECONDS(4));
+ }
+}
+
+void mesh_start(void)
+{
+ k_work_submit(&mesh_start_work);
+}
+
+bool mesh_is_initialized(void)
+{
+ return bt_mesh_is_provisioned();
+}
+
+uint16_t mesh_get_addr(void)
+{
+ return elements[0].addr;
+}
+
+int mesh_init(uint8_t addr_type)
+{
+ static const uint8_t dev_uuid[16] = { 0xc0, 0xff, 0xee };
+ static const struct bt_mesh_prov prov = {
+ .uuid = dev_uuid,
+ };
+
+ hb_cb = { .recv = heartbeat };
+
+ bt_mesh_pub_msg_health_pub = NET_BUF_SIMPLE(0);
+ health_pub.msg = bt_mesh_pub_msg_health_pub;
+
+ bt_mesh_pub_msg_vnd_pub = NET_BUF_SIMPLE(3 + 1);
+ vnd_pub.msg = bt_mesh_pub_msg_vnd_pub;
+ vnd_pub.update = pub_update;
+
+ k_work_init(&hello_work, send_hello);
+ k_work_init(&mesh_start_work, start_mesh);
+
+ return bt_mesh_init(addr_type, &prov, &comp);
+}