michal-narajowski closed pull request #11: mesh: Add example implementation of 
generic onoff and level models
URL: https://github.com/apache/mynewt-nimble/pull/11
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/nimble/host/mesh/include/mesh/glue.h 
b/nimble/host/mesh/include/mesh/glue.h
index 26ba98f2b..bcea0a7ca 100644
--- a/nimble/host/mesh/include/mesh/glue.h
+++ b/nimble/host/mesh/include/mesh/glue.h
@@ -46,6 +46,7 @@
 #define u8_t    uint8_t
 #define s8_t    int8_t
 #define u16_t   uint16_t
+#define s16_t   int16_t
 #define u32_t   uint32_t
 #define u64_t   uint64_t
 #define s64_t   int64_t
diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c
index e8bef8049..2fb3fec66 100644
--- a/nimble/host/mesh/src/access.c
+++ b/nimble/host/mesh/src/access.c
@@ -22,6 +22,9 @@
 #include "transport.h"
 #include "access.h"
 #include "foundation.h"
+#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
+#include "model_cli.h"
+#endif
 
 static const struct bt_mesh_comp *dev_comp;
 static u16_t dev_primary_addr;
@@ -38,6 +41,10 @@ static const struct {
 #if MYNEWT_VAL(BLE_MESH_HEALTH_CLI)
        { BT_MESH_MODEL_ID_HEALTH_CLI, bt_mesh_health_cli_init },
 #endif
+#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
+       { BT_MESH_MODEL_ID_GEN_ONOFF_CLI, bt_mesh_gen_model_cli_init },
+       { BT_MESH_MODEL_ID_GEN_LEVEL_CLI, bt_mesh_gen_model_cli_init },
+#endif
 };
 
 void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
diff --git a/nimble/host/mesh/src/light_model.c 
b/nimble/host/mesh/src/light_model.c
new file mode 100644
index 000000000..0fd4d767b
--- /dev/null
+++ b/nimble/host/mesh/src/light_model.c
@@ -0,0 +1,174 @@
+
+#include "syscfg/syscfg.h"
+
+#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
+
+#include "mesh/mesh.h"
+#include "bsp.h"
+#include "pwm/pwm.h"
+#include "light_model.h"
+
+struct pwm_dev *pwm0;
+struct pwm_dev *pwm1;
+struct pwm_dev *pwm2;
+struct pwm_dev *pwm3;
+static uint16_t top_val;
+
+static u8_t gen_onoff_state;
+static s16_t gen_level_state;
+
+static void light_set_lightness(u8_t percentage)
+{
+       int rc;
+
+       uint16_t pwm_val = (uint16_t) (percentage * top_val / 100);
+
+       rc = pwm_enable_duty_cycle(pwm0, 0, pwm_val);
+       assert(rc == 0);
+       rc = pwm_enable_duty_cycle(pwm1, 0, pwm_val);
+       assert(rc == 0);
+       rc = pwm_enable_duty_cycle(pwm2, 0, pwm_val);
+       assert(rc == 0);
+       rc = pwm_enable_duty_cycle(pwm3, 0, pwm_val);
+       assert(rc == 0);
+}
+
+static void update_light_state(void)
+{
+       int level = gen_level_state;
+
+       if (level > 100) {
+               level = 100;
+       }
+       if (level < 0) {
+               level = 0;
+       }
+
+       if (gen_onoff_state == 0) {
+               level = 0;
+       }
+
+       light_set_lightness((uint8_t) level);
+}
+
+int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state)
+{
+       *state = gen_onoff_state;
+       return 0;
+}
+
+int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state)
+{
+       gen_onoff_state = state;
+       update_light_state();
+       return 0;
+}
+
+int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level)
+{
+       *level = gen_level_state;
+       return 0;
+}
+
+int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level)
+{
+       gen_level_state = level;
+       if (gen_level_state > 0) {
+               gen_onoff_state = 1;
+       }
+       if (gen_level_state <= 0) {
+               gen_onoff_state = 0;
+       }
+       update_light_state();
+       return 0;
+}
+
+static struct pwm_dev_interrupt_cfg led1_conf = {
+       .cfg = {
+               .pin = LED_1,
+               .inverted = true,
+               .n_cycles = 0,
+               .interrupts_cfg = true,
+       },
+       .int_prio = 3,
+};
+
+static struct pwm_dev_interrupt_cfg led2_conf = {
+       .cfg = {
+               .pin = LED_2,
+               .inverted = true,
+               .n_cycles = 0,
+               .interrupts_cfg = true,
+       },
+       .int_prio = 3,
+};
+
+static struct pwm_dev_interrupt_cfg led3_conf = {
+       .cfg = {
+               .pin = LED_3,
+               .inverted = true,
+               .n_cycles = 0,
+               .interrupts_cfg = true,
+       },
+       .int_prio = 3,
+};
+
+static struct pwm_dev_interrupt_cfg led4_conf = {
+       .cfg = {
+               .pin = LED_4,
+               .inverted = true,
+               .n_cycles = 0,
+               .interrupts_cfg = true,
+       },
+       .int_prio = 3,
+};
+
+int pwm_init(void)
+{
+       int rc;
+
+       led1_conf.seq_end_data = &led1_conf;
+       led2_conf.seq_end_data = &led2_conf;
+       led3_conf.seq_end_data = &led3_conf;
+       led4_conf.seq_end_data = &led4_conf;
+
+       pwm0 = (struct pwm_dev *) os_dev_open("pwm0", 0, NULL);
+       assert(pwm0);
+       pwm1 = (struct pwm_dev *) os_dev_open("pwm1", 0, NULL);
+       assert(pwm1);
+       pwm2 = (struct pwm_dev *) os_dev_open("pwm2", 0, NULL);
+       assert(pwm2);
+       pwm3 = (struct pwm_dev *) os_dev_open("pwm3", 0, NULL);
+       assert(pwm3);
+
+       /* set the PWM frequency */
+       pwm_set_frequency(pwm0, 1000);
+       pwm_set_frequency(pwm1, 1000);
+       pwm_set_frequency(pwm2, 1000);
+       pwm_set_frequency(pwm3, 1000);
+       top_val = (uint16_t) pwm_get_top_value(pwm0);
+
+       rc = pwm_chan_config(pwm0, 0, (struct pwm_chan_cfg*) &led1_conf);
+       assert(rc == 0);
+       rc = pwm_chan_config(pwm1, 0, (struct pwm_chan_cfg*) &led2_conf);
+       assert(rc == 0);
+       rc = pwm_chan_config(pwm2, 0, (struct pwm_chan_cfg*) &led3_conf);
+       assert(rc == 0);
+       rc = pwm_chan_config(pwm3, 0, (struct pwm_chan_cfg*) &led4_conf);
+       assert(rc == 0);
+
+       update_light_state();
+
+       return rc;
+}
+#endif
+
+int light_model_init(void)
+{
+#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
+       return pwm_init();
+#else
+       return 0;
+#endif
+}
+
diff --git a/nimble/host/mesh/src/light_model.h 
b/nimble/host/mesh/src/light_model.h
new file mode 100644
index 000000000..732e45bd7
--- /dev/null
+++ b/nimble/host/mesh/src/light_model.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef __BT_MESH_LIGHT_MODEL_H
+#define __BT_MESH_LIGHT_MODEL_H
+
+#include "syscfg/syscfg.h"
+#include "mesh/mesh.h"
+
+#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
+int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state);
+int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state);
+int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level);
+int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level);
+int light_model_init(void);
+#else
+static inline int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t 
*state) { return 0; }
+static inline int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t 
state) { return 0; }
+static inline int light_model_gen_level_get(struct bt_mesh_model *model, s16_t 
*level) { return 0; }
+static inline int light_model_gen_level_set(struct bt_mesh_model *model, s16_t 
level) { return 0; }
+static inline int light_model_init(void) { return 0; }
+#endif
+
+#endif
diff --git a/nimble/host/mesh/src/mesh_priv.h b/nimble/host/mesh/src/mesh_priv.h
index c8e869731..044444c5d 100644
--- a/nimble/host/mesh/src/mesh_priv.h
+++ b/nimble/host/mesh/src/mesh_priv.h
@@ -16,6 +16,19 @@
 #define BT_MESH_ADDR_IS_VIRTUAL(addr) ((addr) >= 0x8000 && (addr) < 0xc000)
 #define BT_MESH_ADDR_IS_RFU(addr) ((addr) >= 0xff00 && (addr) <= 0xfffb)
 
+#define OP_GEN_ONOFF_GET               BT_MESH_MODEL_OP_2(0x82, 0x01)
+#define OP_GEN_ONOFF_SET               BT_MESH_MODEL_OP_2(0x82, 0x02)
+#define OP_GEN_ONOFF_SET_UNACK         BT_MESH_MODEL_OP_2(0x82, 0x03)
+#define OP_GEN_ONOFF_STATUS            BT_MESH_MODEL_OP_2(0x82, 0x04)
+#define OP_GEN_LEVEL_GET               BT_MESH_MODEL_OP_2(0x82, 0x05)
+#define OP_GEN_LEVEL_SET               BT_MESH_MODEL_OP_2(0x82, 0x06)
+#define OP_GEN_LEVEL_SET_UNACK         BT_MESH_MODEL_OP_2(0x82, 0x07)
+#define OP_GEN_LEVEL_STATUS            BT_MESH_MODEL_OP_2(0x82, 0x08)
+#define OP_GEN_DELTA_SET               BT_MESH_MODEL_OP_2(0x82, 0x09)
+#define OP_GEN_DELTA_SET_UNACK         BT_MESH_MODEL_OP_2(0x82, 0x0a)
+#define OP_GEN_MOVE_SET                BT_MESH_MODEL_OP_2(0x82, 0x0b)
+#define OP_GEN_MOVE_SET_UNACK          BT_MESH_MODEL_OP_2(0x82, 0x0c)
+
 bool bt_mesh_is_provisioned(void);
 
 #endif
diff --git a/nimble/host/mesh/src/model_cli.c b/nimble/host/mesh/src/model_cli.c
new file mode 100644
index 000000000..3df5c695c
--- /dev/null
+++ b/nimble/host/mesh/src/model_cli.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <mesh/mesh.h>
+
+#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_MODEL))
+#include "model_cli.h"
+#include "mesh_priv.h"
+
+static s32_t msg_timeout = K_SECONDS(5);
+
+struct bt_mesh_gen_model_cli gen_onoff_cli;
+struct bt_mesh_gen_model_cli gen_level_cli;
+
+static u8_t transaction_id = 0;
+
+struct gen_onoff_param {
+    u8_t *state;
+};
+
+struct gen_level_param {
+    s16_t *level;
+};
+
+static void gen_onoff_status(struct bt_mesh_model *model,
+                            struct bt_mesh_msg_ctx *ctx,
+                            struct os_mbuf *buf)
+{
+       struct bt_mesh_gen_model_cli *cli = model->user_data;
+       struct gen_onoff_param *param;
+       u8_t state;
+
+
+       BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+              ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+              bt_hex(buf->om_data, buf->om_len));
+
+       if (cli->op_pending != OP_GEN_ONOFF_STATUS) {
+               BT_WARN("Unexpected Generic OnOff Status message");
+               return;
+       }
+
+       param = cli->op_param;
+
+       state = net_buf_simple_pull_u8(buf);
+       if (param->state) {
+               *param->state = state;
+       }
+
+       BT_DBG("state: %d", state);
+
+       transaction_id++;
+
+       k_sem_give(&cli->op_sync);
+}
+
+static void gen_level_status(struct bt_mesh_model *model,
+                            struct bt_mesh_msg_ctx *ctx,
+                            struct os_mbuf *buf)
+{
+       struct bt_mesh_gen_model_cli *cli = model->user_data;
+       struct gen_level_param *param;
+       s16_t level;
+
+
+       BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+              ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+              bt_hex(buf->om_data, buf->om_len));
+
+       if (cli->op_pending != OP_GEN_LEVEL_STATUS) {
+               BT_WARN("Unexpected Generic LEVEL Status message");
+               return;
+       }
+
+       param = cli->op_param;
+
+       level = net_buf_simple_pull_le16(buf);
+       if (param->level) {
+               *param->level = level;
+       }
+
+       BT_DBG("level: %d", level);
+
+       transaction_id++;
+
+       k_sem_give(&cli->op_sync);
+}
+
+const struct bt_mesh_model_op gen_onoff_cli_op[] = {
+       { OP_GEN_ONOFF_STATUS, 1, gen_onoff_status },
+       BT_MESH_MODEL_OP_END,
+};
+
+const struct bt_mesh_model_op gen_level_cli_op[] = {
+       { OP_GEN_LEVEL_STATUS, 2, gen_level_status },
+       BT_MESH_MODEL_OP_END,
+};
+
+static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, u32_t op)
+{
+       int err;
+
+       BT_DBG("");
+
+       cli->op_param = param;
+       cli->op_pending = op;
+
+       err = k_sem_take(&cli->op_sync, msg_timeout);
+
+       cli->op_pending = 0;
+       cli->op_param = NULL;
+
+       return err;
+}
+
+int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx,
+                         u8_t *state)
+{
+       struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
+       struct bt_mesh_msg_ctx ctx = {
+               .net_idx = net_idx,
+               .app_idx = app_idx,
+               .addr = addr,
+               .send_ttl = BT_MESH_TTL_DEFAULT,
+       };
+       struct gen_onoff_param param = {
+               .state = state,
+       };
+       int err;
+
+       bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_GET);
+
+       err = bt_mesh_model_send(gen_onoff_cli.model, &ctx, msg, NULL, NULL);
+       if (err) {
+               BT_ERR("model_send() failed (err %d)", err);
+               goto done;
+       }
+
+       err = cli_wait(&gen_onoff_cli, &param, OP_GEN_ONOFF_STATUS);
+done:
+       os_mbuf_free_chain(msg);
+       return err;
+}
+
+int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx,
+                         u8_t val, u8_t *state)
+{
+       struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4);
+       struct bt_mesh_msg_ctx ctx = {
+               .net_idx = net_idx,
+               .app_idx = app_idx,
+               .addr = addr,
+               .send_ttl = BT_MESH_TTL_DEFAULT,
+       };
+       struct gen_onoff_param param = {
+               .state = state,
+       };
+       int err;
+
+       if (state) {
+               bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_SET);
+       } else {
+               bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_SET_UNACK);
+       }
+
+       net_buf_simple_add_u8(msg, val);
+       net_buf_simple_add_u8(msg, transaction_id);
+
+       err = bt_mesh_model_send(gen_onoff_cli.model, &ctx, msg, NULL, NULL);
+       if (err) {
+               BT_ERR("model_send() failed (err %d)", err);
+               goto done;
+       }
+
+       if (!state) {
+               goto done;
+       }
+
+       err = cli_wait(&gen_onoff_cli, &param, OP_GEN_ONOFF_STATUS);
+done:
+       os_mbuf_free_chain(msg);
+       return err;
+}
+
+int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx,
+                         s16_t *level)
+{
+       struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
+       struct bt_mesh_msg_ctx ctx = {
+               .net_idx = net_idx,
+               .app_idx = app_idx,
+               .addr = addr,
+               .send_ttl = BT_MESH_TTL_DEFAULT,
+       };
+       struct gen_level_param param = {
+               .level = level,
+       };
+       int err;
+
+       bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_GET);
+
+       err = bt_mesh_model_send(gen_level_cli.model, &ctx, msg, NULL, NULL);
+       if (err) {
+               BT_ERR("model_send() failed (err %d)", err);
+               goto done;
+       }
+
+       err = cli_wait(&gen_level_cli, &param, OP_GEN_LEVEL_STATUS);
+done:
+       os_mbuf_free_chain(msg);
+       return err;
+}
+
+int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx,
+                         s16_t val, s16_t *state)
+{
+       struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 3 + 4);
+       struct bt_mesh_msg_ctx ctx = {
+               .net_idx = net_idx,
+               .app_idx = app_idx,
+               .addr = addr,
+               .send_ttl = BT_MESH_TTL_DEFAULT,
+       };
+       struct gen_level_param param = {
+               .level = state,
+       };
+       int err;
+
+       if (state) {
+               bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_SET);
+       } else {
+               bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_SET_UNACK);
+       }
+
+       net_buf_simple_add_le16(msg, val);
+       net_buf_simple_add_u8(msg, transaction_id);
+
+       err = bt_mesh_model_send(gen_level_cli.model, &ctx, msg, NULL, NULL);
+       if (err) {
+               BT_ERR("model_send() failed (err %d)", err);
+               goto done;
+       }
+
+       if (!state) {
+               goto done;
+       }
+
+       err = cli_wait(&gen_level_cli, &param, OP_GEN_LEVEL_STATUS);
+done:
+       os_mbuf_free_chain(msg);
+       return err;
+}
+
+int bt_mesh_gen_model_cli_init(struct bt_mesh_model *model, bool primary)
+{
+       struct bt_mesh_gen_model_cli *cli = model->user_data;
+
+       BT_DBG("primary %u", primary);
+
+       if (!cli) {
+               BT_ERR("No Generic Model Client context provided");
+               return -EINVAL;
+       }
+
+       cli->model = model;
+
+       k_sem_init(&cli->op_sync, 0, 1);
+
+       return 0;
+}
+
diff --git a/nimble/host/mesh/src/model_cli.h b/nimble/host/mesh/src/model_cli.h
new file mode 100644
index 000000000..972487649
--- /dev/null
+++ b/nimble/host/mesh/src/model_cli.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __MODEL_CLI_H__
+#define __MODEL_CLI_H__
+
+struct bt_mesh_gen_model_cli {
+    struct bt_mesh_model *model;
+
+    struct k_sem          op_sync;
+    u32_t                 op_pending;
+    void                 *op_param;
+};
+
+extern struct bt_mesh_gen_model_cli gen_onoff_cli;
+extern const struct bt_mesh_model_op gen_onoff_cli_op[];
+
+#define BT_MESH_MODEL_GEN_ONOFF_CLI()                  \
+       BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI,   \
+                     gen_onoff_cli_op, NULL, &gen_onoff_cli)
+
+extern struct bt_mesh_gen_model_cli gen_level_cli;
+extern const struct bt_mesh_model_op gen_level_cli_op[];
+
+#define BT_MESH_MODEL_GEN_LEVEL_CLI(pub)               \
+       BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_CLI,   \
+                     gen_level_cli_op, NULL, &gen_level_cli)
+
+
+int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx,
+                         u8_t *state);
+int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx,
+                         u8_t val, u8_t *state);
+int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx,
+                         s16_t *level);
+int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx,
+                         s16_t val, s16_t *state);
+int bt_mesh_gen_model_cli_init(struct bt_mesh_model *model, bool primary);
+
+#endif
diff --git a/nimble/host/mesh/src/model_srv.c b/nimble/host/mesh/src/model_srv.c
new file mode 100644
index 000000000..be727ce3f
--- /dev/null
+++ b/nimble/host/mesh/src/model_srv.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "mesh/mesh.h"
+
+#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_MODEL))
+
+#include "model_srv.h"
+#include "mesh_priv.h"
+
+static void gen_onoff_status(struct bt_mesh_model *model,
+                            struct bt_mesh_msg_ctx *ctx)
+{
+       struct bt_mesh_gen_onoff_srv_cb *cb = model->user_data;
+       struct os_mbuf *msg = NET_BUF_SIMPLE(3);
+       u8_t *state;
+
+       bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_STATUS);
+       state = net_buf_simple_add(msg, 1);
+       if (cb && cb->get) {
+               cb->get(model, state);
+       }
+
+       BT_DBG("state: %d", state);
+
+       if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+               BT_ERR("Send status failed");
+       }
+
+       os_mbuf_free_chain(msg);
+}
+
+static void gen_onoff_get(struct bt_mesh_model *model,
+                         struct bt_mesh_msg_ctx *ctx,
+                         struct os_mbuf *buf)
+{
+       BT_DBG("");
+
+       gen_onoff_status(model, ctx);
+}
+
+static void gen_onoff_set_unack(struct bt_mesh_model *model,
+                               struct bt_mesh_msg_ctx *ctx,
+                               struct os_mbuf *buf)
+{
+       struct bt_mesh_gen_onoff_srv_cb *cb = model->user_data;
+       u8_t state;
+
+       state = buf->om_data[0];
+
+       BT_DBG("state: %d", state);
+
+       if (cb && cb->set) {
+               cb->set(model, state);
+       }
+}
+
+static void gen_onoff_set(struct bt_mesh_model *model,
+                         struct bt_mesh_msg_ctx *ctx,
+                         struct os_mbuf *buf)
+{
+       BT_DBG("");
+
+       gen_onoff_set_unack(model, ctx, buf);
+       gen_onoff_status(model, ctx);
+}
+
+static void gen_level_status(struct bt_mesh_model *model,
+                            struct bt_mesh_msg_ctx *ctx)
+{
+       struct bt_mesh_gen_level_srv_cb *cb = model->user_data;
+       struct os_mbuf *msg = NET_BUF_SIMPLE(4);
+       s16_t *level;
+
+       bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_STATUS);
+       level = net_buf_simple_add(msg, 2);
+       if (cb && cb->get) {
+               cb->get(model, level);
+       }
+
+       BT_DBG("level: %d", level);
+
+       if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+               BT_ERR("Send status failed");
+       }
+
+       os_mbuf_free_chain(msg);
+}
+
+static void gen_level_get(struct bt_mesh_model *model,
+                         struct bt_mesh_msg_ctx *ctx,
+                         struct os_mbuf *buf)
+{
+       BT_DBG("");
+
+       gen_level_status(model, ctx);
+}
+
+static void gen_level_set_unack(struct bt_mesh_model *model,
+                               struct bt_mesh_msg_ctx *ctx,
+                               struct os_mbuf *buf) {
+       struct bt_mesh_gen_level_srv_cb *cb = model->user_data;
+       s16_t level;
+
+       level = (s16_t) net_buf_simple_pull_le16(buf);
+       BT_DBG("level: %d", level);
+
+       if (cb && cb->set) {
+               cb->set(model, level);
+       }
+}
+
+static void gen_level_set(struct bt_mesh_model *model,
+                         struct bt_mesh_msg_ctx *ctx,
+                         struct os_mbuf *buf)
+{
+       gen_level_set_unack(model, ctx, buf);
+       gen_level_status(model, ctx);
+}
+
+const struct bt_mesh_model_op gen_onoff_srv_op[] = {
+       { OP_GEN_ONOFF_GET,             0, gen_onoff_get },
+       { OP_GEN_ONOFF_SET,             2, gen_onoff_set },
+       { OP_GEN_ONOFF_SET_UNACK,       2, gen_onoff_set_unack },
+       BT_MESH_MODEL_OP_END,
+};
+
+const struct bt_mesh_model_op gen_level_srv_op[] = {
+       { OP_GEN_LEVEL_GET,             0, gen_level_get },
+       { OP_GEN_LEVEL_SET,             3, gen_level_set },
+       { OP_GEN_LEVEL_SET_UNACK,       3, gen_level_set_unack },
+       BT_MESH_MODEL_OP_END,
+};
diff --git a/nimble/host/mesh/src/model_srv.h b/nimble/host/mesh/src/model_srv.h
new file mode 100644
index 000000000..dc6dfdc9a
--- /dev/null
+++ b/nimble/host/mesh/src/model_srv.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __MODEL_SRV_H__
+#define __MODEL_SRV_H__
+
+struct bt_mesh_gen_onoff_srv_cb {
+    int (*get)(struct bt_mesh_model *model, u8_t *state);
+    int (*set)(struct bt_mesh_model *model, u8_t state);
+};
+
+extern const struct bt_mesh_model_op gen_onoff_srv_op[];
+
+#define BT_MESH_MODEL_GEN_ONOFF_SRV(srv, pub)          \
+       BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV,   \
+                     gen_onoff_srv_op, pub, srv)
+
+struct bt_mesh_gen_level_srv_cb {
+    int (*get)(struct bt_mesh_model *model, s16_t *level);
+    int (*set)(struct bt_mesh_model *model, s16_t level);
+};
+
+extern const struct bt_mesh_model_op gen_level_srv_op[];
+
+#define BT_MESH_MODEL_GEN_LEVEL_SRV(srv, pub)          \
+       BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_SRV,   \
+                     gen_level_srv_op, pub, srv)
+
+int pwm_init(void);
+
+#endif
diff --git a/nimble/host/mesh/src/shell.c b/nimble/host/mesh/src/shell.c
index 03ea6dd70..b5cf048c9 100644
--- a/nimble/host/mesh/src/shell.c
+++ b/nimble/host/mesh/src/shell.c
@@ -27,10 +27,16 @@
 #include "net.h"
 #include "access.h"
 #include "mesh_priv.h"
+#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
+#include "model_srv.h"
+#include "model_cli.h"
+#include "light_model.h"
+#endif
 #include "lpn.h"
 #include "transport.h"
 #include "foundation.h"
 #include "testing.h"
+#include "model_cli.h"
 
 /* This should be higher priority (lower value) than main task priority */
 #define BLE_MESH_SHELL_TASK_PRIO 126
@@ -172,10 +178,9 @@ static struct bt_mesh_model_pub health_pub;
 static void
 health_pub_init(void)
 {
-    health_pub.msg  = BT_MESH_HEALTH_FAULT_MSG(CUR_FAULTS_MAX);
+       health_pub.msg  = BT_MESH_HEALTH_FAULT_MSG(CUR_FAULTS_MAX);
 }
 
-
 static struct bt_mesh_cfg_cli cfg_cli = {
 };
 
@@ -209,18 +214,35 @@ static struct bt_mesh_health_cli health_cli = {
        .current_status = health_current_status,
 };
 
-static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
+#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
+static struct bt_mesh_model_pub gen_onoff_pub;
+static struct bt_mesh_model_pub gen_level_pub;
+static struct bt_mesh_gen_onoff_srv_cb gen_onoff_srv_cb = {
+       .get = light_model_gen_onoff_get,
+       .set = light_model_gen_onoff_set,
+};
+static struct bt_mesh_gen_level_srv_cb gen_level_srv_cb = {
+       .get = light_model_gen_level_get,
+       .set = light_model_gen_level_set,
+};
+#endif
 
 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_HEALTH_CLI(&health_cli),
+#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
+       BT_MESH_MODEL_GEN_ONOFF_SRV(&gen_onoff_srv_cb, &gen_onoff_pub),
+       BT_MESH_MODEL_GEN_ONOFF_CLI(),
+       BT_MESH_MODEL_GEN_LEVEL_SRV(&gen_level_srv_cb, &gen_level_pub),
+       BT_MESH_MODEL_GEN_LEVEL_CLI(),
+#endif
 };
 
 static struct bt_mesh_model vnd_models[] = {
-       BT_MESH_MODEL_VND(CID_VENDOR, VND_MODEL_ID_1, BT_MESH_MODEL_NO_OPS, 
NULL,
-                         NULL),
+       BT_MESH_MODEL_VND(CID_VENDOR, VND_MODEL_ID_1,
+                         BT_MESH_MODEL_NO_OPS, NULL, NULL),
 };
 
 static struct bt_mesh_elem elements[] = {
@@ -403,6 +425,8 @@ static void link_close(bt_mesh_prov_bearer_t bearer)
        printk("Provisioning link closed on %s\n", bearer2str(bearer));
 }
 
+static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
+
 static u8_t static_val[16];
 
 static struct bt_mesh_prov prov = {
@@ -2116,6 +2140,143 @@ struct shell_cmd_help cmd_del_fault_help = {
        NULL, "[Fault ID]", NULL
 };
 
+#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
+static int cmd_gen_onoff_get(int argc, char *argv[])
+{
+       u8_t state;
+       int err;
+
+       err = bt_mesh_gen_onoff_get(net.net_idx, net.dst, net.app_idx,
+                                   &state);
+       if (err) {
+               printk("Failed to send Generic OnOff Get (err %d)\n", err);
+       } else {
+               printk("Gen OnOff State %d\n", state);
+       }
+
+       return 0;
+}
+
+static int cmd_gen_onoff_set(int argc, char *argv[])
+{
+       u8_t state;
+       u8_t val;
+       int err;
+
+       if (argc < 2) {
+               return -EINVAL;
+       }
+
+       val = strtoul(argv[1], NULL, 0);
+
+       err = bt_mesh_gen_onoff_set(net.net_idx, net.dst, net.app_idx,
+                                   val, &state);
+       if (err) {
+               printk("Failed to send Generic OnOff Get (err %d)\n", err);
+       } else {
+               printk("Gen OnOff State %d\n", state);
+       }
+
+       return 0;
+}
+
+struct shell_cmd_help cmd_gen_onoff_set_help = {
+       NULL, "<0|1>", NULL
+};
+
+static int cmd_gen_onoff_set_unack(int argc, char *argv[])
+{
+       u8_t val;
+       int err;
+
+       if (argc < 2) {
+               return -EINVAL;
+       }
+
+       val = strtoul(argv[1], NULL, 0);
+
+       err = bt_mesh_gen_onoff_set(net.net_idx, net.dst, net.app_idx,
+                                   val, NULL);
+       if (err) {
+               printk("Failed to send Generic OnOff Get (err %d)\n", err);
+       }
+
+       return 0;
+}
+
+struct shell_cmd_help cmd_gen_onoff_set_unack_help = {
+       NULL, "<0|1>", NULL
+};
+
+static int cmd_gen_level_get(int argc, char *argv[])
+{
+       s16_t state;
+       int err;
+
+       err = bt_mesh_gen_level_get(net.net_idx, net.dst, net.app_idx,
+                                   &state);
+       if (err) {
+               printk("Failed to send Generic Level Get (err %d)\n", err);
+       } else {
+               printk("Gen Level State %d\n", state);
+       }
+
+       return 0;
+}
+
+static int cmd_gen_level_set(int argc, char *argv[])
+{
+       s16_t state;
+       s16_t val;
+       int err;
+
+       if (argc < 2) {
+               return -EINVAL;
+       }
+
+       val = (s16_t)strtoul(argv[1], NULL, 0);
+
+       err = bt_mesh_gen_level_set(net.net_idx, net.dst, net.app_idx,
+                                   val, &state);
+       if (err) {
+               printk("Failed to send Generic Level Get (err %d)\n", err);
+       } else {
+               printk("Gen Level State %d\n", state);
+       }
+
+       return 0;
+}
+
+struct shell_cmd_help cmd_gen_level_set_help = {
+       NULL, "<level>", NULL
+};
+
+static int cmd_gen_level_set_unack(int argc, char *argv[])
+{
+       s16_t val;
+       int err;
+
+       if (argc < 2) {
+               return -EINVAL;
+       }
+
+       val = (s16_t)strtoul(argv[1], NULL, 0);
+
+       err = bt_mesh_gen_level_set(net.net_idx, net.dst, net.app_idx,
+                                   val, NULL);
+       if (err) {
+               printk("Failed to send Generic Level Get (err %d)\n", err);
+       }
+
+       return 0;
+}
+
+struct shell_cmd_help cmd_gen_level_set_unack_help = {
+       NULL, "<level>", NULL
+};
+
+#endif /* MYNEWT_VAL(BLE_MESH_SHELL_MODELS) */
+
 static int cmd_print_credentials(int argc, char *argv[])
 {
        bt_test_print_credentials();
@@ -2239,6 +2400,16 @@ static const struct shell_cmd mesh_commands[] = {
        { "add-fault", cmd_add_fault, &cmd_add_fault_help },
        { "del-fault", cmd_del_fault, &cmd_del_fault_help },
 
+#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
+       /* Generic Client Model Operations */
+       { "gen-onoff-get", cmd_gen_onoff_get, NULL },
+       { "gen-onoff-set", cmd_gen_onoff_set, &cmd_gen_onoff_set_help },
+       { "gen-onoff-set-unack", cmd_gen_onoff_set_unack, 
&cmd_gen_onoff_set_unack_help },
+       { "gen-level-get", cmd_gen_level_get, NULL },
+       { "gen-level-set", cmd_gen_level_set, &cmd_gen_level_set_help },
+       { "gen-level-set-unack", cmd_gen_level_set_unack, 
&cmd_gen_level_set_unack_help },
+#endif
+
        { NULL, NULL, NULL}
 };
 
@@ -2271,5 +2442,10 @@ void ble_mesh_shell_init(void)
        bt_mesh_shell_task_init();
        shell_evq_set(&mesh_shell_queue);
        shell_register("mesh", mesh_commands);
+
+#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
+       light_model_init();
+#endif
+
 #endif
 }
diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml
index 59905f877..92494bd4d 100644
--- a/nimble/host/mesh/syscfg.yml
+++ b/nimble/host/mesh/syscfg.yml
@@ -382,6 +382,12 @@ syscfg.defs:
             Device UUID
         value: ((uint8_t[16]){0x11, 0x22, 0})
 
+    BLE_MESH_SHELL_MODELS:
+        description: >
+            Include implementation of some demo models.
+            This requires pwm0, pwm1, pwm2 and pwm3 devices.
+        value: 0
+
 syscfg.vals.BLE_MESH_SHELL:
     BLE_MESH_CFG_CLI: 1
     BLE_MESH_HEALTH_CLI: 1


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to