You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2018/08/30 13:04:14 UTC
[GitHub] michal-narajowski closed pull request #151:
apps/blemesh_onoff_level_lighting_vnd: Add app with various models
michal-narajowski closed pull request #151: apps/blemesh_onoff_level_lighting_vnd: Add app with various models
URL: https://github.com/apache/mynewt-nimble/pull/151
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/apps/blemesh_models_example_2/README.md b/apps/blemesh_models_example_2/README.md
new file mode 100644
index 00000000..87de52ac
--- /dev/null
+++ b/apps/blemesh_models_example_2/README.md
@@ -0,0 +1,101 @@
+#### Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
+
+##### Overview
+********
+
+This is a application demonstrating a Bluetooth mesh node in
+which Root element has following models
+
+- Generic OnOff Server
+- Generic OnOff Client
+- Generic Level Server
+- Generic Level Client
+- Generic Power OnOff Server
+- Generic Power OnOff Setup Server
+- Generic Power OnOff Client
+- Light Lightness Server
+- Light Lightness Setup Server
+- Light Lightness Client
+- Light CTL Server
+- Light CTL Setup Server
+- Light CTL Client
+- Vendor Model
+
+And Secondary element has following models
+
+- Generic OnOff Server
+- Generic OnOff Client
+- Generic Level Server
+- Generic Level Client
+- Light CTL Temperature Server
+
+Prior to provisioning, an unprovisioned beacon is broadcast that contains
+a unique UUID. Each button controls the state of its
+corresponding LED and does not initiate any mesh activity
+
+##### Associations of Models with hardware
+************************************
+For the nRF52840-PDK board, these are the model associations:
+
+* LED1 is associated with generic OnOff Server's state which is part of Root element
+* LED2 is associated with Vendor Model which is part of Root element
+* LED3 is associated with generic Level (ROOT) / Light Lightness Actual value
+* LED4 is associated with generic Level (Secondary) / Light CTL Temperature value
+* Button1 and Button2 are associated with gen. OnOff Client or Vendor Model which is part of Root element
+* Button3 and Button4 are associated with gen. Level Client / Light Lightness Client / Light CTL Client which is part of Root element
+
+States of Servers are bounded as per Bluetooth SIG Mesh Model Specification v1.0
+
+After provisioning, the button clients must
+be configured to publish and the LED servers to subscribe.
+If a server is provided with a publish address, it will
+also publish its relevant status.
+
+##### Requirements
+************
+This sample has been tested on the Nordic nRF52840-PDK board, but would
+likely also run on the nrf52_pca10040 board.
+
+
+##### Running
+************
+
+Provisioning is done using the BlueZ meshctl utility. In this example, we'll use meshctl commands to bind:
+
+- Button1, Button2, and LED1 to application key 1. It then configures Button1 and Button2
+ to publish to group 0xC000 and LED1 to subscribe to that group.
+- Button3, Button4, and LED3 to application key 1. It then configures Button3 and Button4
+ to publish to group 0xC000 and LED3 to subscribe to that group.
+
+```
+discover-unprovisioned on
+provision <discovered UUID>
+menu config
+target 0100
+appkey-add 1
+bind 0 1 1000
+bind 0 1 1001
+bind 0 1 1002
+bind 0 1 1003
+sub-add 0100 c000 1000
+sub-add 0100 c000 1002
+pub-set 0100 c000 1 0 5 1001
+pub-set 0100 c000 1 0 5 1003
+```
+
+The meshctl utility maintains a persistent JSON database containing
+the mesh configuration. As additional nodes (boards) are provisioned, it
+assigns sequential unicast addresses based on the number of elements
+supported by the node. This example supports 2 elements per node.
+
+The meshctl target for configuration must be the root element's unicast
+address as it is the only one that has a configuration server model. If
+meshctl is gracefully exited, it can be restarted and reconnected to
+network 0x0.
+
+The meshctl utility also supports a onoff model client that can be used to
+change the state of any LED that is bound to application key 0x1.
+This is done by setting the target to the unicast address of the element
+that has that LED's model and issuing the onoff command.
+Group addresses are not supported.
+
diff --git a/apps/blemesh_models_example_2/pkg.yml b/apps/blemesh_models_example_2/pkg.yml
new file mode 100644
index 00000000..79f04e1e
--- /dev/null
+++ b/apps/blemesh_models_example_2/pkg.yml
@@ -0,0 +1,38 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+pkg.name: apps/blemesh_models_example_2
+pkg.type: app
+pkg.description: Sample application for BLE Mesh node with on/off, level, light and vendor models on nRF52840pdk
+pkg.author: "MichaĆ Narajowski <mi...@codecoup.pl>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+ - "@apache-mynewt-core/kernel/os"
+ - "@apache-mynewt-core/sys/console/full"
+ - "@apache-mynewt-core/sys/log/full"
+ - "@apache-mynewt-core/sys/stats/full"
+ - nimble/controller
+ - nimble/host
+ - nimble/host/services/gap
+ - nimble/host/services/gatt
+ - nimble/transport/ram
+
+pkg.lflags:
+ - -DFLOAT_SUPPORT
+ - -lm
diff --git a/apps/blemesh_models_example_2/src/ble_mesh.c b/apps/blemesh_models_example_2/src/ble_mesh.c
new file mode 100644
index 00000000..7145e083
--- /dev/null
+++ b/apps/blemesh_models_example_2/src/ble_mesh.c
@@ -0,0 +1,93 @@
+/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
+ *
+ * Copyright (c) 2018 Vikrant More
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "console/console.h"
+
+#include "ble_mesh.h"
+#include "device_composition.h"
+
+#define OOB_AUTH_ENABLE 1
+
+#ifdef OOB_AUTH_ENABLE
+
+static int output_number(bt_mesh_output_action_t action, u32_t number)
+{
+ printk("OOB Number: %lu\n", number);
+ return 0;
+}
+
+static int output_string(const char *str)
+{
+ printk("OOB String: %s\n", str);
+ return 0;
+}
+
+#endif
+
+static void prov_complete(u16_t net_idx, u16_t addr)
+{
+}
+
+static void prov_reset(void)
+{
+ bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
+}
+
+static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
+
+static const struct bt_mesh_prov prov = {
+ .uuid = dev_uuid,
+
+#ifdef OOB_AUTH_ENABLE
+
+ .output_size = 6,
+ .output_actions = BT_MESH_DISPLAY_NUMBER | BT_MESH_DISPLAY_STRING,
+ .output_number = output_number,
+ .output_string = output_string,
+
+#endif
+
+ .complete = prov_complete,
+ .reset = prov_reset,
+};
+
+void blemesh_on_reset(int reason)
+{
+ BLE_HS_LOG(ERROR, "Resetting state; reason=%d\n", reason);
+}
+
+void blemesh_on_sync(void)
+{
+ int err;
+ ble_addr_t addr;
+
+ console_printf("Bluetooth initialized\n");
+
+ /* Use NRPA */
+ err = ble_hs_id_gen_rnd(1, &addr);
+ assert(err == 0);
+ err = ble_hs_id_set_rnd(addr.val);
+ assert(err == 0);
+
+ err = bt_mesh_init(addr.type, &prov, &comp);
+ if (err) {
+ console_printf("Initializing mesh failed (err %d)\n", err);
+ return;
+ }
+
+ if (IS_ENABLED(CONFIG_SETTINGS)) {
+ settings_load();
+ }
+
+ if (bt_mesh_is_provisioned()) {
+ console_printf("Mesh network restored from flash\n");
+ }
+
+ bt_mesh_prov_enable(BT_MESH_PROV_GATT | BT_MESH_PROV_ADV);
+
+ console_printf("Mesh initialized\n");
+}
diff --git a/apps/blemesh_models_example_2/src/ble_mesh.h b/apps/blemesh_models_example_2/src/ble_mesh.h
new file mode 100644
index 00000000..fe43dff8
--- /dev/null
+++ b/apps/blemesh_models_example_2/src/ble_mesh.h
@@ -0,0 +1,34 @@
+/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
+ *
+ * Copyright (c) 2018 Vikrant More
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _BLE_MESH_H
+#define _BLE_MESH_H
+
+#include "mesh/mesh.h"
+#include "mesh/glue.h"
+
+/* 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 BT_MESH_MODEL_OP_GEN_LEVEL_GET BT_MESH_MODEL_OP_2(0x82, 0x05)
+#define BT_MESH_MODEL_OP_GEN_LEVEL_SET BT_MESH_MODEL_OP_2(0x82, 0x06)
+#define BT_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x07)
+#define BT_MESH_MODEL_OP_GEN_LEVEL_STATUS BT_MESH_MODEL_OP_2(0x82, 0x08)
+#define BT_MESH_MODEL_OP_GEN_DELTA_SET BT_MESH_MODEL_OP_2(0x82, 0x09)
+#define BT_MESH_MODEL_OP_GEN_DELTA_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x0A)
+#define BT_MESH_MODEL_OP_GEN_MOVE_SET BT_MESH_MODEL_OP_2(0x82, 0x0B)
+#define BT_MESH_MODEL_OP_GEN_MOVE_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x0C)
+
+void blemesh_on_reset(int reason);
+void blemesh_on_sync(void);
+void init_pub(void);
+
+#endif
+
diff --git a/apps/blemesh_models_example_2/src/common.h b/apps/blemesh_models_example_2/src/common.h
new file mode 100644
index 00000000..8a104012
--- /dev/null
+++ b/apps/blemesh_models_example_2/src/common.h
@@ -0,0 +1,16 @@
+/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
+ *
+ * Copyright (c) 2018 Vikrant More
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _COMMON_H
+#define _COMMON_H
+
+extern int button_device[];
+extern int led_device[];
+
+void update_light_state(void);
+
+#endif
diff --git a/apps/blemesh_models_example_2/src/device_composition.c b/apps/blemesh_models_example_2/src/device_composition.c
new file mode 100644
index 00000000..a19674d7
--- /dev/null
+++ b/apps/blemesh_models_example_2/src/device_composition.c
@@ -0,0 +1,1944 @@
+/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
+ *
+ * Copyright (c) 2018 Vikrant More
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "console/console.h"
+#include "hal/hal_gpio.h"
+
+#include "common.h"
+#include "ble_mesh.h"
+#include "device_composition.h"
+#include "state_binding.h"
+#include "transition.h"
+
+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 struct bt_mesh_health_srv health_srv = {
+};
+
+
+static struct bt_mesh_model_pub health_pub;
+
+static struct bt_mesh_model_pub gen_onoff_srv_pub_root;
+static struct bt_mesh_model_pub gen_onoff_cli_pub_root;
+static struct bt_mesh_model_pub gen_level_srv_pub_root;
+static struct bt_mesh_model_pub gen_level_cli_pub_root;
+static struct bt_mesh_model_pub gen_def_trans_time_srv_pub;
+static struct bt_mesh_model_pub gen_def_trans_time_cli_pub;
+static struct bt_mesh_model_pub gen_power_onoff_srv_pub;
+static struct bt_mesh_model_pub gen_power_onoff_cli_pub;
+static struct bt_mesh_model_pub light_lightness_srv_pub;
+static struct bt_mesh_model_pub light_lightness_cli_pub;
+static struct bt_mesh_model_pub light_ctl_srv_pub;
+static struct bt_mesh_model_pub light_ctl_cli_pub;
+static struct bt_mesh_model_pub vnd_pub;
+static struct bt_mesh_model_pub gen_onoff_srv_pub_s0;
+static struct bt_mesh_model_pub gen_onoff_cli_pub_s0;
+static struct bt_mesh_model_pub gen_level_srv_pub_s0;
+static struct bt_mesh_model_pub gen_level_cli_pub_s0;
+
+
+static struct os_mbuf *bt_mesh_pub_msg_health_pub;
+static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_srv_pub_root;
+static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_cli_pub_root;
+static struct os_mbuf *bt_mesh_pub_msg_gen_level_srv_pub_root;
+static struct os_mbuf *bt_mesh_pub_msg_gen_level_cli_pub_root;
+static struct os_mbuf *bt_mesh_pub_msg_gen_def_trans_time_srv_pub;
+static struct os_mbuf *bt_mesh_pub_msg_gen_def_trans_time_cli_pub;
+static struct os_mbuf *bt_mesh_pub_msg_gen_power_onoff_srv_pub;
+static struct os_mbuf *bt_mesh_pub_msg_gen_power_onoff_cli_pub;
+static struct os_mbuf *bt_mesh_pub_msg_light_lightness_srv_pub;
+static struct os_mbuf *bt_mesh_pub_msg_light_lightness_cli_pub;
+static struct os_mbuf *bt_mesh_pub_msg_light_ctl_srv_pub;
+static struct os_mbuf *bt_mesh_pub_msg_light_ctl_cli_pub;
+static struct os_mbuf *bt_mesh_pub_msg_vnd_pub;
+static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_srv_pub_s0;
+static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_cli_pub_s0;
+static struct os_mbuf *bt_mesh_pub_msg_gen_level_srv_pub_s0;
+static struct os_mbuf *bt_mesh_pub_msg_gen_level_cli_pub_s0;
+
+
+void init_pub(void)
+{
+ bt_mesh_pub_msg_health_pub = NET_BUF_SIMPLE(1 + 3 + 0);
+ bt_mesh_pub_msg_gen_onoff_srv_pub_root = NET_BUF_SIMPLE(2 + 3);
+ bt_mesh_pub_msg_gen_onoff_cli_pub_root = NET_BUF_SIMPLE(2 + 4);
+ bt_mesh_pub_msg_gen_level_srv_pub_root = NET_BUF_SIMPLE(2 + 5);
+ bt_mesh_pub_msg_gen_level_cli_pub_root = NET_BUF_SIMPLE(2 + 7);
+ bt_mesh_pub_msg_gen_power_onoff_srv_pub = NET_BUF_SIMPLE(2 + 1);
+ bt_mesh_pub_msg_gen_power_onoff_cli_pub = NET_BUF_SIMPLE(2 + 1);
+ bt_mesh_pub_msg_gen_def_trans_time_srv_pub = NET_BUF_SIMPLE(2 + 1);
+ bt_mesh_pub_msg_gen_def_trans_time_cli_pub = NET_BUF_SIMPLE(2 + 1);
+ bt_mesh_pub_msg_light_lightness_srv_pub = NET_BUF_SIMPLE(2 + 5);
+ bt_mesh_pub_msg_light_lightness_cli_pub = NET_BUF_SIMPLE(2 + 5);
+ bt_mesh_pub_msg_light_ctl_srv_pub = NET_BUF_SIMPLE(2 + 9);
+ bt_mesh_pub_msg_light_ctl_cli_pub = NET_BUF_SIMPLE(2 + 9);
+ bt_mesh_pub_msg_vnd_pub = NET_BUF_SIMPLE(3 + 6);
+ bt_mesh_pub_msg_gen_onoff_srv_pub_s0 = NET_BUF_SIMPLE(2 + 3);
+ bt_mesh_pub_msg_gen_onoff_cli_pub_s0 = NET_BUF_SIMPLE(2 + 4);
+ bt_mesh_pub_msg_gen_level_srv_pub_s0 = NET_BUF_SIMPLE(2 + 5);
+ bt_mesh_pub_msg_gen_level_cli_pub_s0 = NET_BUF_SIMPLE(2 + 7);
+
+
+ health_pub.msg = bt_mesh_pub_msg_health_pub;
+ gen_onoff_srv_pub_root.msg = bt_mesh_pub_msg_gen_onoff_srv_pub_root;
+ gen_onoff_cli_pub_root.msg = bt_mesh_pub_msg_gen_onoff_cli_pub_root;
+ gen_level_srv_pub_root.msg = bt_mesh_pub_msg_gen_level_srv_pub_root;
+ gen_level_cli_pub_root.msg = bt_mesh_pub_msg_gen_level_cli_pub_root;
+ gen_power_onoff_srv_pub.msg = bt_mesh_pub_msg_gen_power_onoff_srv_pub;
+ gen_power_onoff_cli_pub.msg = bt_mesh_pub_msg_gen_power_onoff_cli_pub;
+ gen_def_trans_time_srv_pub.msg = bt_mesh_pub_msg_gen_def_trans_time_srv_pub;
+ gen_def_trans_time_cli_pub.msg = bt_mesh_pub_msg_gen_def_trans_time_cli_pub;
+ light_lightness_srv_pub.msg = bt_mesh_pub_msg_light_lightness_srv_pub;
+ light_lightness_cli_pub.msg = bt_mesh_pub_msg_light_lightness_cli_pub;
+ light_ctl_srv_pub.msg = bt_mesh_pub_msg_light_ctl_srv_pub;
+ light_ctl_cli_pub.msg = bt_mesh_pub_msg_light_ctl_cli_pub;
+ vnd_pub.msg = bt_mesh_pub_msg_vnd_pub;
+ gen_onoff_srv_pub_s0.msg = bt_mesh_pub_msg_gen_onoff_srv_pub_s0;
+ gen_onoff_cli_pub_s0.msg = bt_mesh_pub_msg_gen_onoff_cli_pub_s0;
+ gen_level_srv_pub_s0.msg = bt_mesh_pub_msg_gen_level_srv_pub_s0;
+ gen_level_cli_pub_s0.msg = bt_mesh_pub_msg_gen_level_cli_pub_s0;
+}
+
+/* Definitions of models user data (Start) */
+struct generic_onoff_state gen_onoff_srv_root_user_data;
+
+struct generic_level_state gen_level_srv_root_user_data;
+
+struct gen_def_trans_time_state gen_def_trans_time_srv_user_data;
+
+struct generic_onpowerup_state gen_power_onoff_srv_user_data;
+
+struct light_lightness_state light_lightness_srv_user_data;
+
+struct light_ctl_state light_ctl_srv_user_data;
+
+struct vendor_state vnd_user_data;
+
+struct generic_onoff_state gen_onoff_srv_s0_user_data;
+
+struct generic_level_state gen_level_srv_s0_user_data;
+/* Definitions of models user data (End) */
+
+static struct bt_mesh_elem elements[];
+
+/* message handlers (Start) */
+
+/* Generic OnOff Server message handlers */
+static void gen_onoff_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 3 + 4);
+ struct generic_onoff_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_ONOFF_STATUS);
+ net_buf_simple_add_u8(msg, state->onoff);
+
+ if (state->is_optional_para_available) {
+ net_buf_simple_add_u8(msg, state->target_onoff);
+ net_buf_simple_add_u8(msg, state->tt);
+ }
+
+ state->is_optional_para_available = 0x00;
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send GEN_ONOFF_SRV Status response\n");
+ }
+}
+
+static bool gen_onoff_setunack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u8_t tid, onoff;
+ s64_t now;
+ struct os_mbuf *msg = model->pub->msg;
+ struct generic_onoff_state *state = model->user_data;
+
+ onoff = net_buf_simple_pull_u8(buf);
+ tid = net_buf_simple_pull_u8(buf);
+
+ if (onoff > STATE_ON) {
+ return false;
+ }
+
+ now = k_uptime_get();
+ if (state->last_tid == tid && state->last_tx_addr == ctx->addr &&
+ (now - state->last_msg_timestamp <= K_SECONDS(6))) {
+ return true;
+ }
+
+ state->is_optional_para_available = 0x01;
+
+ switch (buf->om_len) {
+ case 0x00: /* No optional fields are available */
+ state->tt = default_tt;
+ state->delay = 0;
+ state->is_optional_para_available = 0x00;
+ break;
+ case 0x02: /* Optional fields are available */
+ state->tt = net_buf_simple_pull_u8(buf);
+ state->delay = net_buf_simple_pull_u8(buf);
+ break;
+ default:
+ return false;
+ }
+
+ enable_transition = DISABLE_TRANSITION;
+
+ state->last_tid = tid;
+ state->last_tx_addr = ctx->addr;
+ state->last_msg_timestamp = now;
+ state->target_onoff = onoff;
+
+ onoff_tt_values(state);
+
+ if (state->tt_counter == 0) {
+ state->onoff = onoff;
+ }
+
+ if (bt_mesh_model_elem(model)->addr == elements[0].addr) {
+ /* Root element */
+ onoff_handler(state);
+ } else if (bt_mesh_model_elem(model)->addr == elements[1].addr) {
+ /* Secondary element */
+ printk("Hello World\n");
+ }
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_ONOFF_STATUS);
+ net_buf_simple_add_u8(msg, state->onoff);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+
+ return true;
+}
+
+static void gen_onoff_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ gen_onoff_setunack(model, ctx, buf);
+}
+
+static void gen_onoff_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ if (gen_onoff_setunack(model, ctx, buf) == true) {
+ gen_onoff_get(model, ctx, buf);
+ }
+}
+
+/* Generic OnOff Client message handlers */
+static void gen_onoff_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from GEN_ONOFF_SRV\n");
+ printk("Present OnOff = %02x\n", net_buf_simple_pull_u8(buf));
+
+ if (buf->om_len == 2) {
+ printk("Target OnOff = %02x\n", net_buf_simple_pull_u8(buf));
+ printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf));
+ }
+}
+
+/* Generic Level Server message handlers */
+static void gen_level_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 5 + 4);
+ struct generic_level_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_LEVEL_STATUS);
+ net_buf_simple_add_le16(msg, state->level);
+
+ if (state->is_optional_para_available == 0x01) {
+ net_buf_simple_add_le16(msg, state->target_level);
+ net_buf_simple_add_u8(msg, state->tt);
+ } else if (state->is_optional_para_available == 0x02) {
+
+ if (state->last_delta < 0) {
+ net_buf_simple_add_le16(msg, INT16_MIN);
+ } else if (state->last_delta > 0) {
+ net_buf_simple_add_le16(msg, INT16_MAX);
+ }
+
+ net_buf_simple_add_u8(msg, state->tt);
+ }
+
+ state->is_optional_para_available = 0x00;
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send GEN_LEVEL_SRV Status response\n");
+ }
+}
+
+static void gen_level_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u8_t tid;
+ s16_t level;
+ s64_t now;
+ struct os_mbuf *msg = model->pub->msg;
+ struct generic_level_state *state = model->user_data;
+
+ level = (s16_t) net_buf_simple_pull_le16(buf);
+ tid = net_buf_simple_pull_u8(buf);
+
+ now = k_uptime_get();
+ if (state->last_tid == tid && state->last_tx_addr == ctx->addr &&
+ (now - state->last_msg_timestamp <= K_SECONDS(6))) {
+ return;
+ }
+
+ state->is_optional_para_available = 0x01;
+
+ switch (buf->om_len) {
+ case 0x00: /* No optional fields are available */
+ state->tt = default_tt;
+ state->delay = 0;
+ state->is_optional_para_available = 0x00;
+ break;
+ case 0x02: /* Optional fields are available */
+ state->tt = net_buf_simple_pull_u8(buf);
+ state->delay = net_buf_simple_pull_u8(buf);
+ break;
+ default:
+ return;
+ }
+
+ enable_transition = DISABLE_TRANSITION;
+
+ state->last_tid = tid;
+ state->last_tx_addr = ctx->addr;
+ state->last_msg_timestamp = now;
+ state->target_level = level;
+
+ level_tt_values(state);
+
+ if (state->tt_counter == 0) {
+ state->level = level;
+ }
+
+ if (bt_mesh_model_elem(model)->addr == elements[0].addr) {
+ /* Root element */
+ enable_transition = LEVEL_TT;
+ level_lightness_handler(state);
+ } else if (bt_mesh_model_elem(model)->addr == elements[1].addr) {
+ /* Secondary element */
+ enable_transition = LEVEL_TEMP_TT;
+ level_temp_handler(state);
+ }
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_LEVEL_STATUS);
+ net_buf_simple_add_le16(msg, state->level);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+}
+
+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_get(model, ctx, buf);
+}
+
+static void gen_delta_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u8_t tid;
+ s32_t tmp32, delta;
+ s64_t now;
+ struct os_mbuf *msg = model->pub->msg;
+ struct generic_level_state *state = model->user_data;
+
+ delta = (s32_t) net_buf_simple_pull_le32(buf);
+ tid = net_buf_simple_pull_u8(buf);
+
+ now = k_uptime_get();
+ if (state->last_tid == tid && state->last_tx_addr == ctx->addr) {
+
+ if (now - state->last_msg_timestamp <= K_SECONDS(6)) {
+ if (state->last_delta == delta) {
+ return;
+ }
+ tmp32 = state->last_level + delta;
+ } else {
+ return;
+ }
+
+ } else {
+ state->last_level = state->level;
+ tmp32 = state->level + delta;
+ }
+
+ state->is_optional_para_available = 0x01;
+
+ switch (buf->om_len) {
+ case 0x00: /* No optional fields are available */
+ state->tt = default_tt;
+ state->delay = 0;
+ state->is_optional_para_available = 0x00;
+ break;
+ case 0x02: /* Optional fields are available */
+ state->tt = net_buf_simple_pull_u8(buf);
+ state->delay = net_buf_simple_pull_u8(buf);
+ break;
+ default:
+ return;
+ }
+
+ enable_transition = DISABLE_TRANSITION;
+
+ state->last_delta = delta;
+ state->last_tid = tid;
+ state->last_tx_addr = ctx->addr;
+ state->last_msg_timestamp = now;
+
+ if (tmp32 < INT16_MIN) {
+ tmp32 = INT16_MIN;
+ } else if (tmp32 > INT16_MAX) {
+ tmp32 = INT16_MAX;
+ }
+
+ state->target_level = tmp32;
+
+ delta_level_tt_values(state);
+
+ if (state->tt_counter_delta == 0) {
+ state->level = tmp32;
+ }
+
+ if (bt_mesh_model_elem(model)->addr == elements[0].addr) {
+ /* Root element */
+ enable_transition = LEVEL_TT_DELTA;
+ level_lightness_handler(state);
+ } else if (bt_mesh_model_elem(model)->addr == elements[1].addr) {
+ /* Secondary element */
+ enable_transition = LEVEL_TEMP_TT_DELTA;
+ level_temp_handler(state);
+ }
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_LEVEL_STATUS);
+ net_buf_simple_add_le16(msg, state->level);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+}
+
+static void gen_delta_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ gen_delta_set_unack(model, ctx, buf);
+ gen_level_get(model, ctx, buf);
+}
+
+static void gen_move_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u8_t tid;
+ s16_t delta;
+ s32_t tmp32;
+ s64_t now;
+ struct os_mbuf *msg = model->pub->msg;
+ struct generic_level_state *state = model->user_data;
+
+ delta = (s16_t) net_buf_simple_pull_le16(buf);
+ tid = net_buf_simple_pull_u8(buf);
+
+ now = k_uptime_get();
+ if (state->last_tid == tid && state->last_tx_addr == ctx->addr &&
+ (now - state->last_msg_timestamp <= K_SECONDS(6))) {
+ return;
+ }
+
+ state->is_optional_para_available = 0x02;
+
+ switch (buf->om_len) {
+ case 0x00: /* No optional fields are available */
+ state->tt = default_tt;
+ state->delay = 0;
+ state->is_optional_para_available = 0x00;
+ break;
+ case 0x02: /* Optional fields are available */
+ state->tt = net_buf_simple_pull_u8(buf);
+ state->delay = net_buf_simple_pull_u8(buf);
+ break;
+ default:
+ return;
+ }
+
+ enable_transition = DISABLE_TRANSITION;
+
+ state->last_delta = delta;
+ state->last_tid = tid;
+ state->last_tx_addr = ctx->addr;
+ state->last_msg_timestamp = now;
+
+ tmp32 = state->level + delta;
+ if (tmp32 < INT16_MIN) {
+ tmp32 = INT16_MIN;
+ } else if (tmp32 > INT16_MAX) {
+ tmp32 = INT16_MAX;
+ }
+
+ state->target_level = tmp32;
+
+ move_level_tt_values(state);
+
+ if (bt_mesh_model_elem(model)->addr == elements[0].addr) {
+ /* Root element */
+ if (delta == 0) {
+ ble_npl_callout_stop(&level_lightness_transition_timer);
+ } else {
+ enable_transition = LEVEL_TT_MOVE;
+ level_lightness_handler(state);
+ }
+ } else if (bt_mesh_model_elem(model)->addr == elements[1].addr) {
+ /* Secondary element */
+ if (delta == 0) {
+ ble_npl_callout_stop(&level_temp_transition_timer);
+ } else {
+ enable_transition = LEVEL_TEMP_TT_MOVE;
+ level_temp_handler(state);
+ }
+ }
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_LEVEL_STATUS);
+ net_buf_simple_add_le16(msg, state->level);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+}
+
+static void gen_move_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ gen_move_set_unack(model, ctx, buf);
+ gen_level_get(model, ctx, buf);
+}
+
+/* Generic Level Client message handlers */
+static void gen_level_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from GEN_LEVEL_SRV\n");
+ printk("Present Level = %04x\n", net_buf_simple_pull_le16(buf));
+
+ if (buf->om_len == 3) {
+ printk("Target Level = %04x\n", net_buf_simple_pull_le16(buf));
+ printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf));
+ }
+}
+
+/* Generic Default Transition Time Server message handlers */
+static void gen_def_trans_time_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
+ struct gen_def_trans_time_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x10));
+ net_buf_simple_add_u8(msg, state->tt);
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send GEN_DEF_TT_SRV Status response\n");
+ }
+}
+
+static bool gen_def_trans_time_setunack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u8_t tt;
+ struct os_mbuf *msg = model->pub->msg;
+ struct gen_def_trans_time_state *state = model->user_data;
+
+ tt = net_buf_simple_pull_u8(buf);
+
+ /* Here, Model specification is silent about tid implementation */
+
+ if ((tt & 0x3F) == 0x3F) {
+ return false;
+ }
+
+ state->tt = tt;
+ default_tt = tt;
+
+ /* Do some work here to save value of state->tt on SoC flash */
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x10));
+ net_buf_simple_add_u8(msg, state->tt);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+
+ return true;
+}
+
+static void gen_def_trans_time_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ gen_def_trans_time_setunack(model, ctx, buf);
+}
+
+static void gen_def_trans_time_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ if (gen_def_trans_time_setunack(model, ctx, buf) == true) {
+ gen_def_trans_time_get(model, ctx, buf);
+ }
+}
+
+/* Generic Default Transition Time Client message handlers */
+static void gen_def_trans_time_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from GEN_DEF_TT_SRV\n");
+ printk("Transition Time = %02x\n", net_buf_simple_pull_u8(buf));
+}
+
+/* Generic Power OnOff Server message handlers */
+static void gen_onpowerup_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4);
+ struct generic_onpowerup_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x12));
+ net_buf_simple_add_u8(msg, state->onpowerup);
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send GEN_POWER_ONOFF_SRV Status response\n");
+ }
+}
+
+/* Generic Power OnOff Client message handlers */
+static void gen_onpowerup_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from GEN_POWER_ONOFF_SRV\n");
+ printk("OnPowerUp = %02x\n", net_buf_simple_pull_u8(buf));
+}
+
+/* Generic Power OnOff Setup Server message handlers */
+static bool gen_onpowerup_setunack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u8_t onpowerup;
+ struct os_mbuf *msg = model->pub->msg;
+ struct generic_onpowerup_state *state = model->user_data;
+
+ onpowerup = net_buf_simple_pull_u8(buf);
+
+ /* Here, Model specification is silent about tid implementation */
+
+ if (onpowerup > STATE_RESTORE) {
+ return false;
+ }
+ state->onpowerup = onpowerup;
+
+ /* Do some work here to save value of state->onpowerup on SoC flash */
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x12));
+ net_buf_simple_add_u8(msg, state->onpowerup);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+
+ return true;
+}
+
+static void gen_onpowerup_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ gen_onpowerup_setunack(model, ctx, buf);
+}
+
+static void gen_onpowerup_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ if (gen_onpowerup_setunack(model, ctx, buf) == true) {
+ gen_onpowerup_get(model, ctx, buf);
+ }
+}
+
+/* Vendor Model message handlers*/
+static void vnd_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(3 + 6 + 4);
+ struct vendor_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_3(0x03, CID_RUNTIME));
+
+ net_buf_simple_add_le16(msg, state->current);
+ net_buf_simple_add_le32(msg, state->response);
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send VENDOR Status response\n");
+ }
+}
+
+static void vnd_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u8_t tid;
+ int current;
+ s64_t now;
+ struct vendor_state *state = model->user_data;
+
+ current = net_buf_simple_pull_le16(buf);
+ tid = net_buf_simple_pull_u8(buf);
+
+ now = k_uptime_get();
+ if (state->last_tid == tid && state->last_tx_addr == ctx->addr &&
+ (now - state->last_msg_timestamp <= 6000)) {
+ return;
+ }
+
+ state->last_tid = tid;
+ state->last_tx_addr = ctx->addr;
+ state->last_msg_timestamp = now;
+ state->current = current;
+
+ /* This is dummy response for demo purpose */
+ state->response = 0xA578FEB3;
+
+ printk("Vendor model message = %04x\n", state->current);
+
+ if (state->current == STATE_ON) {
+ /* LED2 On */
+ hal_gpio_write(led_device[1], 0);
+ } else {
+ /* LED2 Off */
+ hal_gpio_write(led_device[1], 1);
+ }
+}
+
+static void vnd_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ vnd_set_unack(model, ctx, buf);
+ vnd_get(model, ctx, buf);
+}
+
+static void vnd_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from Vendor\n");
+ printk("cmd = %04x\n", net_buf_simple_pull_le16(buf));
+ printk("response = %08lx\n", net_buf_simple_pull_le32(buf));
+}
+
+/* Light Lightness Server message handlers */
+static void light_lightness_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 5 + 4);
+ struct light_lightness_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x4E));
+ net_buf_simple_add_le16(msg, state->actual);
+
+ if (state->is_optional_para_available) {
+ net_buf_simple_add_le16(msg, state->target_actual);
+ net_buf_simple_add_u8(msg, state->tt);
+ }
+
+ state->is_optional_para_available = 0x00;
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send LightLightnessAct Status response\n");
+ }
+}
+
+static void light_lightness_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u8_t tid;
+ u16_t actual;
+ s64_t now;
+ struct os_mbuf *msg = model->pub->msg;
+ struct light_lightness_state *state = model->user_data;
+
+ actual = net_buf_simple_pull_le16(buf);
+ tid = net_buf_simple_pull_u8(buf);
+
+ now = k_uptime_get();
+ if (state->last_tid == tid && state->last_tx_addr == ctx->addr &&
+ (now - state->last_msg_timestamp <= K_SECONDS(6))) {
+ return;
+ }
+
+ state->is_optional_para_available = 0x01;
+
+ switch (buf->om_len) {
+ case 0x00: /* No optional fields are available */
+ state->tt = default_tt;
+ state->delay = 0;
+ state->is_optional_para_available = 0x00;
+ break;
+ case 0x02: /* Optional fields are available */
+ state->tt = net_buf_simple_pull_u8(buf);
+ state->delay = net_buf_simple_pull_u8(buf);
+ break;
+ default:
+ return;
+ }
+
+ enable_transition = DISABLE_TRANSITION;
+
+ state->last_tid = tid;
+ state->last_tx_addr = ctx->addr;
+ state->last_msg_timestamp = now;
+
+ if (actual > 0 && actual < state->light_range_min) {
+ actual = state->light_range_min;
+ } else if (actual > state->light_range_max) {
+ actual = state->light_range_max;
+ }
+
+ state->target_actual = actual;
+
+ light_lightnes_actual_tt_values(state);
+
+ if (state->tt_counter_actual == 0) {
+ state->actual = actual;
+ }
+
+ light_lightness_actual_handler(state);
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x4E));
+ net_buf_simple_add_le16(msg, state->actual);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+}
+
+static void light_lightness_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ light_lightness_set_unack(model, ctx, buf);
+ light_lightness_get(model, ctx, buf);
+}
+
+static void light_lightness_linear_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 5 + 4);
+ struct light_lightness_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x52));
+ net_buf_simple_add_le16(msg, state->linear);
+
+ if (state->is_optional_para_available) {
+ net_buf_simple_add_le16(msg, state->target_linear);
+ net_buf_simple_add_u8(msg, state->tt);
+ }
+
+ state->is_optional_para_available = 0x00;
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send LightLightnessLin Status response\n");
+ }
+}
+
+static void light_lightness_linear_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u8_t tid;
+ u16_t linear;
+ s64_t now;
+ struct os_mbuf *msg = model->pub->msg;
+ struct light_lightness_state *state = model->user_data;
+
+ linear = net_buf_simple_pull_le16(buf);
+ tid = net_buf_simple_pull_u8(buf);
+
+ now = k_uptime_get();
+ if (state->last_tid == tid && state->last_tx_addr == ctx->addr &&
+ (now - state->last_msg_timestamp <= K_SECONDS(6))) {
+ return;
+ }
+
+ state->is_optional_para_available = 0x01;
+
+ switch (buf->om_len) {
+ case 0x00: /* No optional fields are available */
+ state->tt = default_tt;
+ state->delay = 0;
+ state->is_optional_para_available = 0x00;
+ break;
+ case 0x02: /* Optional fields are available */
+ state->tt = net_buf_simple_pull_u8(buf);
+ state->delay = net_buf_simple_pull_u8(buf);
+ break;
+ default:
+ return;
+ }
+
+ enable_transition = DISABLE_TRANSITION;
+
+ state->last_tid = tid;
+ state->last_tx_addr = ctx->addr;
+ state->last_msg_timestamp = now;
+ state->target_linear = linear;
+
+ light_lightnes_linear_tt_values(state);
+
+ if (state->tt_counter_linear == 0) {
+ state->linear = linear;
+ }
+
+ light_lightness_linear_handler(state);
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x52));
+ net_buf_simple_add_le16(msg, state->linear);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+}
+
+static void light_lightness_linear_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ light_lightness_linear_set_unack(model, ctx, buf);
+ light_lightness_linear_get(model, ctx, buf);
+}
+
+static void light_lightness_last_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4);
+ struct light_lightness_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x54));
+
+ net_buf_simple_add_le16(msg, state->last);
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send LightLightnessLast Status response\n");
+ }
+}
+
+static void light_lightness_default_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4);
+ struct light_lightness_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x56));
+
+ net_buf_simple_add_le16(msg, state->def);
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send LightLightnessDef Status response\n");
+ }
+}
+
+static void light_lightness_range_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 5 + 4);
+ struct light_lightness_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x58));
+
+ net_buf_simple_add_u8(msg, state->status_code);
+ net_buf_simple_add_le16(msg, state->light_range_min);
+ net_buf_simple_add_le16(msg, state->light_range_max);
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send LightLightnessRange Status response\n");
+ }
+
+ state->status_code = RANGE_SUCCESSFULLY_UPDATED;
+}
+
+/* Light Lightness Setup Server message handlers */
+static void light_lightness_default_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = model->pub->msg;
+ struct light_lightness_state *state = model->user_data;
+
+ state->def = net_buf_simple_pull_le16(buf);
+
+ /* Here, Model specification is silent about tid implementation */
+
+ /* Do some work here to save value of state->def on SoC flash */
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x56));
+ net_buf_simple_add_le16(msg, state->def);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+}
+
+static void light_lightness_default_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ light_lightness_default_set_unack(model, ctx, buf);
+ light_lightness_default_get(model, ctx, buf);
+}
+
+static bool light_lightness_range_setunack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u16_t min, max;
+ struct os_mbuf *msg = model->pub->msg;
+ struct light_lightness_state *state = model->user_data;
+
+ min = net_buf_simple_pull_le16(buf);
+ max = net_buf_simple_pull_le16(buf);
+
+ /* Here, Model specification is silent about tid implementation */
+
+ if (min == 0 || max == 0) {
+ return false;
+ } else {
+ if (min <= max) {
+ state->status_code = RANGE_SUCCESSFULLY_UPDATED;
+
+ state->light_range_min = min;
+ state->light_range_max = max;
+
+ /* Do some work here to save values of
+ * state->light_range_min &
+ * state->light_range_max
+ * on SoC flash
+ */
+ } else {
+ /* The provided value for Range Max cannot be set */
+ state->status_code = CANNOT_SET_RANGE_MAX;
+ return false;
+ }
+ }
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x58));
+ net_buf_simple_add_u8(msg, state->status_code);
+ net_buf_simple_add_le16(msg, state->light_range_min);
+ net_buf_simple_add_le16(msg, state->light_range_max);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+
+ return true;
+}
+
+static void light_lightness_range_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ light_lightness_range_setunack(model, ctx, buf);
+}
+
+static void light_lightness_range_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ if (light_lightness_range_setunack(model, ctx, buf) == true) {
+ light_lightness_range_get(model, ctx, buf);
+ }
+}
+
+/* Light Lightness Client message handlers */
+static void light_lightness_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from LIGHT_LIGHTNESS_SRV (Actual)\n");
+ printk("Present Lightness = %04x\n", net_buf_simple_pull_le16(buf));
+
+ if (buf->om_len == 3) {
+ printk("Target Lightness = %04x\n",
+ net_buf_simple_pull_le16(buf));
+ printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf));
+ }
+}
+
+static void light_lightness_linear_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from LIGHT_LIGHTNESS_SRV (Linear)\n");
+ printk("Present Lightness = %04x\n", net_buf_simple_pull_le16(buf));
+
+ if (buf->om_len == 3) {
+ printk("Target Lightness = %04x\n",
+ net_buf_simple_pull_le16(buf));
+ printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf));
+ }
+}
+
+static void light_lightness_last_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from LIGHT_LIGHTNESS_SRV (Last)\n");
+ printk("Lightness = %04x\n", net_buf_simple_pull_le16(buf));
+}
+
+static void light_lightness_default_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from LIGHT_LIGHTNESS_SRV (Default)\n");
+ printk("Lightness = %04x\n", net_buf_simple_pull_le16(buf));
+}
+
+static void light_lightness_range_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from LIGHT_LIGHTNESS_SRV (Lightness Range)\n");
+ printk("Status Code = %02x\n", net_buf_simple_pull_u8(buf));
+ printk("Range Min = %04x\n", net_buf_simple_pull_le16(buf));
+ printk("Range Max = %04x\n", net_buf_simple_pull_le16(buf));
+}
+
+/* Light CTL Server message handlers */
+static void light_ctl_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 9 + 4);
+ struct light_ctl_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x60));
+ net_buf_simple_add_le16(msg, state->lightness);
+ net_buf_simple_add_le16(msg, state->temp);
+
+ if (state->is_optional_para_available) {
+ net_buf_simple_add_le16(msg, state->target_lightness);
+ net_buf_simple_add_le16(msg, state->target_temp);
+ net_buf_simple_add_u8(msg, state->tt);
+ }
+
+ state->is_optional_para_available = 0x00;
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send LightCTL Status response\n");
+ }
+}
+
+static bool light_ctl_setunack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u8_t tid;
+ s16_t delta_uv;
+ u16_t lightness, temp;
+ s64_t now;
+ struct os_mbuf *msg = model->pub->msg;
+ struct light_ctl_state *state = model->user_data;
+
+ lightness = net_buf_simple_pull_le16(buf);
+ temp = net_buf_simple_pull_le16(buf);
+ delta_uv = (s16_t) net_buf_simple_pull_le16(buf);
+ tid = net_buf_simple_pull_u8(buf);
+
+ if (temp < TEMP_MIN || temp > TEMP_MAX) {
+ return false;
+ }
+
+ now = k_uptime_get();
+ if (state->last_tid == tid && state->last_tx_addr == ctx->addr &&
+ (now - state->last_msg_timestamp <= K_SECONDS(6))) {
+ return true;
+ }
+
+ state->is_optional_para_available = 0x01;
+
+ switch (buf->om_len) {
+ case 0x00: /* No optional fields are available */
+ state->tt = default_tt;
+ state->delay = 0;
+ state->is_optional_para_available = 0x00;
+ break;
+ case 0x02: /* Optional fields are available */
+ state->tt = net_buf_simple_pull_u8(buf);
+ state->delay = net_buf_simple_pull_u8(buf);
+ break;
+ default:
+ return false;
+ }
+
+ enable_transition = DISABLE_TRANSITION;
+
+ state->last_tid = tid;
+ state->last_tx_addr = ctx->addr;
+ state->last_msg_timestamp = now;
+ state->target_lightness = lightness;
+
+ if (temp < state->temp_range_min) {
+ temp = state->temp_range_min;
+ } else if (temp > state->temp_range_max) {
+ temp = state->temp_range_max;
+ }
+
+ state->target_temp = temp;
+ state->target_delta_uv = delta_uv;
+
+ light_ctl_tt_values(state);
+
+ if (state->tt_counter == 0) {
+ state->lightness = lightness;
+ state->temp = temp;
+ state->delta_uv = delta_uv;
+ }
+
+ light_ctl_handler(state);
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x60));
+
+ /* Here, as per Model specification, status should be
+ * made up of lightness & temperature values only
+ */
+ net_buf_simple_add_le16(msg, state->lightness);
+ net_buf_simple_add_le16(msg, state->temp);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+
+ return true;
+}
+
+static void light_ctl_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ light_ctl_setunack(model, ctx, buf);
+}
+
+static void light_ctl_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ if (light_ctl_setunack(model, ctx, buf) == true) {
+ light_ctl_get(model, ctx, buf);
+ }
+}
+
+static void light_ctl_temp_range_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 5 + 4);
+ struct light_ctl_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x63));
+ net_buf_simple_add_u8(msg, state->status_code);
+ net_buf_simple_add_le16(msg, state->temp_range_min);
+ net_buf_simple_add_le16(msg, state->temp_range_max);
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send LightCTL Temp Range Status response\n");
+ }
+
+ state->status_code = RANGE_SUCCESSFULLY_UPDATED;
+}
+
+static void light_ctl_default_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 6 + 4);
+ struct light_ctl_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x68));
+ net_buf_simple_add_le16(msg, state->lightness_def);
+ net_buf_simple_add_le16(msg, state->temp_def);
+ net_buf_simple_add_le16(msg, state->delta_uv_def);
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send LightCTL Default Status response\n");
+ }
+}
+
+/* Light CTL Setup Server message handlers */
+static bool light_ctl_default_setunack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u16_t lightness, temp;
+ s16_t delta_uv;
+ struct os_mbuf *msg = model->pub->msg;
+ struct light_ctl_state *state = model->user_data;
+
+ lightness = net_buf_simple_pull_le16(buf);
+ temp = net_buf_simple_pull_le16(buf);
+ delta_uv = (s16_t) net_buf_simple_pull_le16(buf);
+
+ /* Here, Model specification is silent about tid implementation */
+
+ if (temp < TEMP_MIN || temp > TEMP_MAX) {
+ return false;
+ }
+
+ if (temp < state->temp_range_min) {
+ temp = state->temp_range_min;
+ } else if (temp > state->temp_range_max) {
+ temp = state->temp_range_max;
+ }
+
+ state->lightness_def = lightness;
+ state->temp_def = temp;
+ state->delta_uv_def = delta_uv;
+
+ /* Do some work here to save values of
+ * state->lightness_def, state->temp_Def & state->delta_uv_def
+ * on SoC flash
+ */
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x68));
+ net_buf_simple_add_le16(msg, state->lightness_def);
+ net_buf_simple_add_le16(msg, state->temp_def);
+ net_buf_simple_add_le16(msg, state->delta_uv_def);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+
+ return true;
+}
+
+static void light_ctl_default_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ light_ctl_default_setunack(model, ctx, buf);
+}
+
+static void light_ctl_default_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ if (light_ctl_default_setunack(model, ctx, buf) == true) {
+ light_ctl_default_get(model, ctx, buf);
+ }
+}
+
+static bool light_ctl_temp_range_setunack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u16_t min, max;
+ struct os_mbuf *msg = model->pub->msg;
+ struct light_ctl_state *state = model->user_data;
+
+ min = net_buf_simple_pull_le16(buf);
+ max = net_buf_simple_pull_le16(buf);
+
+ /* Here, Model specification is silent about tid implementation */
+
+ /* This is as per 6.1.3.1 in Mesh Model Specification */
+ if (min < TEMP_MIN || min > TEMP_MAX ||
+ max < TEMP_MIN || max > TEMP_MAX) {
+ return false;
+ }
+
+ if (min <= max) {
+ state->status_code = RANGE_SUCCESSFULLY_UPDATED;
+ state->temp_range_min = min;
+ state->temp_range_max = max;
+
+ /* Do some work here to save values of
+ * state->temp_range_min & state->temp_range_min
+ * on SoC flash
+ */
+ } else {
+ /* The provided value for Range Max cannot be set */
+ state->status_code = CANNOT_SET_RANGE_MAX;
+ return false;
+ }
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x63));
+ net_buf_simple_add_u8(msg, state->status_code);
+ net_buf_simple_add_le16(msg, state->temp_range_min);
+ net_buf_simple_add_le16(msg, state->temp_range_max);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+
+ return true;
+}
+
+static void light_ctl_temp_range_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ light_ctl_temp_range_setunack(model, ctx, buf);
+}
+
+static void light_ctl_temp_range_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ if (light_ctl_temp_range_setunack(model, ctx, buf) == true) {
+ light_ctl_temp_range_get(model, ctx, buf);
+ }
+}
+
+/* Light CTL Client message handlers */
+static void light_ctl_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from LIGHT_CTL_SRV\n");
+ printk("Present CTL Lightness = %04x\n", net_buf_simple_pull_le16(buf));
+ printk("Present CTL Temperature = %04x\n",
+ net_buf_simple_pull_le16(buf));
+
+ if (buf->om_len == 5) {
+ printk("Target CTL Lightness = %04x\n",
+ net_buf_simple_pull_le16(buf));
+ printk("Target CTL Temperature = %04x\n",
+ net_buf_simple_pull_le16(buf));
+ printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf));
+ }
+}
+
+static void light_ctl_temp_range_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from LIGHT_CTL_SRV (Temperature Range)\n");
+ printk("Status Code = %02x\n", net_buf_simple_pull_u8(buf));
+ printk("Range Min = %04x\n", net_buf_simple_pull_le16(buf));
+ printk("Range Max = %04x\n", net_buf_simple_pull_le16(buf));
+}
+
+static void light_ctl_temp_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from LIGHT_CTL_TEMP_SRV\n");
+ printk("Present CTL Temperature = %04x\n",
+ net_buf_simple_pull_le16(buf));
+ printk("Present CTL Delta UV = %04x\n",
+ net_buf_simple_pull_le16(buf));
+
+ if (buf->om_len == 5) {
+ printk("Target CTL Temperature = %04x\n",
+ net_buf_simple_pull_le16(buf));
+ printk("Target CTL Delta UV = %04x\n",
+ net_buf_simple_pull_le16(buf));
+ printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf));
+ }
+}
+
+static void light_ctl_default_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ printk("Acknownledgement from LIGHT_CTL_SRV (Default)\n");
+ printk("Lightness = %04x\n", net_buf_simple_pull_le16(buf));
+ printk("Temperature = %04x\n", net_buf_simple_pull_le16(buf));
+ printk("Delta UV = %04x\n", net_buf_simple_pull_le16(buf));
+}
+
+/* Light CTL Temp. Server message handlers */
+static void light_ctl_temp_get(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 9 + 4);
+ struct light_ctl_state *state = model->user_data;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x66));
+ net_buf_simple_add_le16(msg, state->temp);
+ net_buf_simple_add_le16(msg, state->delta_uv);
+
+ if (state->is_optional_para_available) {
+ net_buf_simple_add_le16(msg, state->target_temp);
+ net_buf_simple_add_le16(msg, state->target_delta_uv);
+ net_buf_simple_add_u8(msg, state->tt);
+ }
+
+ state->is_optional_para_available = 0x00;
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ printk("Unable to send LightCTL Temp. Status response\n");
+ }
+}
+
+static bool light_ctl_temp_setunack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ u8_t tid;
+ s16_t delta_uv;
+ u16_t temp;
+ s64_t now;
+
+ struct os_mbuf *msg = model->pub->msg;
+ struct light_ctl_state *state = model->user_data;
+
+ temp = net_buf_simple_pull_le16(buf);
+ delta_uv = (s16_t) net_buf_simple_pull_le16(buf);
+ tid = net_buf_simple_pull_u8(buf);
+
+ if (temp < TEMP_MIN || temp > TEMP_MAX) {
+ return false;
+ }
+
+ now = k_uptime_get();
+ if (state->last_tid == tid && state->last_tx_addr == ctx->addr &&
+ (now - state->last_msg_timestamp <= K_SECONDS(6))) {
+ return true;
+ }
+
+ state->is_optional_para_available = 0x01;
+
+ switch (buf->om_len) {
+ case 0x00: /* No optional fields are available */
+ state->tt = default_tt;
+ state->delay = 0;
+ state->is_optional_para_available = 0x00;
+ break;
+ case 0x02: /* Optional fields are available */
+ state->tt = net_buf_simple_pull_u8(buf);
+ state->delay = net_buf_simple_pull_u8(buf);
+ break;
+ default:
+ return false;
+ }
+
+ enable_transition = DISABLE_TRANSITION;
+
+ state->last_tid = tid;
+ state->last_tx_addr = ctx->addr;
+ state->last_msg_timestamp = now;
+
+ if (temp < state->temp_range_min) {
+ temp = state->temp_range_min;
+ } else if (temp > state->temp_range_max) {
+ temp = state->temp_range_max;
+ }
+
+ state->target_temp = temp;
+ state->target_delta_uv = delta_uv;
+
+ light_ctl_temp_tt_values(state);
+
+ if (state->tt_counter_temp == 0) {
+ state->temp = temp;
+ state->delta_uv = delta_uv;
+ }
+
+ light_ctl_temp_handler(state);
+
+ if (model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+ int err;
+
+ bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x66));
+ net_buf_simple_add_le16(msg, state->temp);
+ net_buf_simple_add_le16(msg, state->delta_uv);
+
+ err = bt_mesh_model_publish(model);
+ if (err) {
+ printk("bt_mesh_model_publish err %d\n", err);
+ }
+ }
+
+ return true;
+}
+
+static void light_ctl_temp_set_unack(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ light_ctl_temp_setunack(model, ctx, buf);
+}
+
+static void light_ctl_temp_set(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ if (light_ctl_temp_setunack(model, ctx, buf) == true) {
+ light_ctl_temp_get(model, ctx, buf);
+ }
+}
+
+/* message handlers (End) */
+
+/* Mapping of message handlers for Generic OnOff Server (0x1000) */
+static const struct bt_mesh_model_op gen_onoff_srv_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x01), 0, gen_onoff_get },
+ { BT_MESH_MODEL_OP_2(0x82, 0x02), 2, gen_onoff_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x03), 2, gen_onoff_set_unack },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Generic OnOff Client (0x1001) */
+static const struct bt_mesh_model_op gen_onoff_cli_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x04), 1, gen_onoff_status },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Generic Levl Server (0x1002) */
+static const struct bt_mesh_model_op gen_level_srv_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x05), 0, gen_level_get },
+ { BT_MESH_MODEL_OP_2(0x82, 0x06), 3, gen_level_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x07), 3, gen_level_set_unack },
+ { BT_MESH_MODEL_OP_2(0x82, 0x09), 5, gen_delta_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x0A), 5, gen_delta_set_unack },
+ { BT_MESH_MODEL_OP_2(0x82, 0x0B), 5, gen_move_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x0C), 5, gen_move_set_unack },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Generic Level Client (0x1003) */
+static const struct bt_mesh_model_op gen_level_cli_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x08), 2, gen_level_status },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Generic Default TT Server (0x1004) */
+static const struct bt_mesh_model_op gen_def_trans_time_srv_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x0D), 0, gen_def_trans_time_get },
+ { BT_MESH_MODEL_OP_2(0x82, 0x0E), 1, gen_def_trans_time_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x0F), 1, gen_def_trans_time_set_unack },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Generic Default TT Client (0x1005) */
+static const struct bt_mesh_model_op gen_def_trans_time_cli_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x10), 1, gen_def_trans_time_status },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Generic Power OnOff Server (0x1006) */
+static const struct bt_mesh_model_op gen_power_onoff_srv_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x11), 0, gen_onpowerup_get },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Generic Power OnOff Setup Server (0x1007) */
+static const struct bt_mesh_model_op gen_power_onoff_setup_srv_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x13), 1, gen_onpowerup_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x14), 1, gen_onpowerup_set_unack },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Generic Power OnOff Client (0x1008) */
+static const struct bt_mesh_model_op gen_power_onoff_cli_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x12), 1, gen_onpowerup_status },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Light Lightness Server (0x1300) */
+static const struct bt_mesh_model_op light_lightness_srv_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x4B), 0, light_lightness_get },
+ { BT_MESH_MODEL_OP_2(0x82, 0x4C), 3, light_lightness_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x4D), 3, light_lightness_set_unack },
+ { BT_MESH_MODEL_OP_2(0x82, 0x4F), 0, light_lightness_linear_get },
+ { BT_MESH_MODEL_OP_2(0x82, 0x50), 3, light_lightness_linear_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x51), 3,
+ light_lightness_linear_set_unack },
+ { BT_MESH_MODEL_OP_2(0x82, 0x53), 0, light_lightness_last_get },
+ { BT_MESH_MODEL_OP_2(0x82, 0x55), 0, light_lightness_default_get },
+ { BT_MESH_MODEL_OP_2(0x82, 0x57), 0, light_lightness_range_get },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Light Lightness Setup Server (0x1301) */
+static const struct bt_mesh_model_op light_lightness_setup_srv_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x59), 2, light_lightness_default_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x5A), 2,
+ light_lightness_default_set_unack },
+ { BT_MESH_MODEL_OP_2(0x82, 0x5B), 4, light_lightness_range_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x5C), 4, light_lightness_range_set_unack },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Light Lightness Client (0x1302) */
+static const struct bt_mesh_model_op light_lightness_cli_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x4E), 2, light_lightness_status },
+ { BT_MESH_MODEL_OP_2(0x82, 0x52), 2, light_lightness_linear_status },
+ { BT_MESH_MODEL_OP_2(0x82, 0x54), 2, light_lightness_last_status },
+ { BT_MESH_MODEL_OP_2(0x82, 0x56), 2, light_lightness_default_status },
+ { BT_MESH_MODEL_OP_2(0x82, 0x58), 5, light_lightness_range_status },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Light CTL Server (0x1303) */
+static const struct bt_mesh_model_op light_ctl_srv_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x5D), 0, light_ctl_get },
+ { BT_MESH_MODEL_OP_2(0x82, 0x5E), 5, light_ctl_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x5F), 5, light_ctl_set_unack },
+ { BT_MESH_MODEL_OP_2(0x82, 0x62), 0, light_ctl_temp_range_get },
+ { BT_MESH_MODEL_OP_2(0x82, 0x67), 0, light_ctl_default_get },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Light CTL Setup Server (0x1304) */
+static const struct bt_mesh_model_op light_ctl_setup_srv_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x69), 6, light_ctl_default_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x6A), 6, light_ctl_default_set_unack },
+ { BT_MESH_MODEL_OP_2(0x82, 0x6B), 4, light_ctl_temp_range_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x6C), 4, light_ctl_temp_range_set_unack },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Light CTL Client (0x1305) */
+static const struct bt_mesh_model_op light_ctl_cli_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x60), 4, light_ctl_status },
+ { BT_MESH_MODEL_OP_2(0x82, 0x63), 5, light_ctl_temp_range_status },
+ { BT_MESH_MODEL_OP_2(0x82, 0x66), 4, light_ctl_temp_status },
+ { BT_MESH_MODEL_OP_2(0x82, 0x68), 6, light_ctl_default_status },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Light CTL Temp. Server (0x1306) */
+static const struct bt_mesh_model_op light_ctl_temp_srv_op[] = {
+ { BT_MESH_MODEL_OP_2(0x82, 0x61), 0, light_ctl_temp_get },
+ { BT_MESH_MODEL_OP_2(0x82, 0x64), 5, light_ctl_temp_set },
+ { BT_MESH_MODEL_OP_2(0x82, 0x65), 5, light_ctl_temp_set_unack },
+ BT_MESH_MODEL_OP_END,
+};
+
+/* Mapping of message handlers for Vendor (0x4321) */
+static const struct bt_mesh_model_op vnd_ops[] = {
+ { BT_MESH_MODEL_OP_3(0x00, CID_RUNTIME), 0, vnd_get },
+ { BT_MESH_MODEL_OP_3(0x01, CID_RUNTIME), 3, vnd_set },
+ { BT_MESH_MODEL_OP_3(0x02, CID_RUNTIME), 3, vnd_set_unack },
+ { BT_MESH_MODEL_OP_3(0x03, CID_RUNTIME), 6, vnd_status },
+ BT_MESH_MODEL_OP_END,
+};
+
+struct bt_mesh_model root_models[] = {
+ BT_MESH_MODEL_CFG_SRV(&cfg_srv),
+ BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
+
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV,
+ gen_onoff_srv_op, &gen_onoff_srv_pub_root,
+ &gen_onoff_srv_root_user_data),
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI,
+ gen_onoff_cli_op, &gen_onoff_cli_pub_root,
+ NULL),
+
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_SRV,
+ gen_level_srv_op, &gen_level_srv_pub_root,
+ &gen_level_srv_root_user_data),
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_CLI,
+ gen_level_cli_op, &gen_level_cli_pub_root,
+ NULL),
+
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV,
+ gen_def_trans_time_srv_op,
+ &gen_def_trans_time_srv_pub,
+ &gen_def_trans_time_srv_user_data),
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_CLI,
+ gen_def_trans_time_cli_op,
+ &gen_def_trans_time_cli_pub,
+ NULL),
+
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV,
+ gen_power_onoff_srv_op, &gen_power_onoff_srv_pub,
+ &gen_power_onoff_srv_user_data),
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV,
+ gen_power_onoff_setup_srv_op,
+ &gen_power_onoff_srv_pub,
+ &gen_power_onoff_srv_user_data),
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_POWER_ONOFF_CLI,
+ gen_power_onoff_cli_op, &gen_power_onoff_cli_pub,
+ NULL),
+
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV,
+ light_lightness_srv_op, &light_lightness_srv_pub,
+ &light_lightness_srv_user_data),
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV,
+ light_lightness_setup_srv_op,
+ &light_lightness_srv_pub,
+ &light_lightness_srv_user_data),
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_CLI,
+ light_lightness_cli_op, &light_lightness_cli_pub,
+ NULL),
+
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_CTL_SRV,
+ light_ctl_srv_op, &light_ctl_srv_pub,
+ &light_ctl_srv_user_data),
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV,
+ light_ctl_setup_srv_op, &light_ctl_srv_pub,
+ &light_ctl_srv_user_data),
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_CTL_CLI,
+ light_ctl_cli_op, &light_ctl_cli_pub,
+ NULL),
+};
+
+struct bt_mesh_model vnd_models[] = {
+ BT_MESH_MODEL_VND(CID_RUNTIME, 0x4321, vnd_ops,
+ &vnd_pub, &vnd_user_data),
+};
+
+struct bt_mesh_model s0_models[] = {
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV,
+ gen_onoff_srv_op, &gen_onoff_srv_pub_s0,
+ &gen_onoff_srv_s0_user_data),
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI,
+ gen_onoff_cli_op, &gen_onoff_cli_pub_s0,
+ NULL),
+
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_SRV,
+ gen_level_srv_op, &gen_level_srv_pub_s0,
+ &gen_level_srv_s0_user_data),
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_CLI,
+ gen_level_cli_op, &gen_level_cli_pub_s0,
+ NULL),
+
+ BT_MESH_MODEL(BT_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV,
+ light_ctl_temp_srv_op, &light_ctl_srv_pub,
+ &light_ctl_srv_user_data),
+};
+
+static struct bt_mesh_elem elements[] = {
+ BT_MESH_ELEM(0, root_models, vnd_models),
+ BT_MESH_ELEM(0, s0_models, BT_MESH_MODEL_NONE),
+};
+
+const struct bt_mesh_comp comp = {
+ .cid = CID_RUNTIME,
+ .elem = elements,
+ .elem_count = ARRAY_SIZE(elements),
+};
diff --git a/apps/blemesh_models_example_2/src/device_composition.h b/apps/blemesh_models_example_2/src/device_composition.h
new file mode 100644
index 00000000..d91b3e52
--- /dev/null
+++ b/apps/blemesh_models_example_2/src/device_composition.h
@@ -0,0 +1,182 @@
+/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
+ *
+ * Copyright (c) 2018 Vikrant More
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _DEVICE_COMPOSITION_H
+#define _DEVICE_COMPOSITION_H
+
+#define CID_RUNTIME 0x05C3
+
+#define STATE_OFF 0x00
+#define STATE_ON 0x01
+#define STATE_DEFAULT 0x01
+#define STATE_RESTORE 0x02
+
+/* Following 4 values are as per Mesh Model specification */
+#define LIGHTNESS_MIN 0x0001
+#define LIGHTNESS_MAX 0xFFFF
+#define TEMP_MIN 0x0320
+#define TEMP_MAX 0x4E20
+
+/* Refer 7.2 of Mesh Model Specification */
+#define RANGE_SUCCESSFULLY_UPDATED 0x00
+#define CANNOT_SET_RANGE_MIN 0x01
+#define CANNOT_SET_RANGE_MAX 0x02
+
+enum lightness {
+ ONPOWERUP = 0x01,
+ ONOFF,
+ LEVEL,
+ DELTA_LEVEL,
+ ACTUAL,
+ LINEAR,
+ CTL,
+ IGNORE
+};
+
+enum temperature {
+ ONOFF_TEMP = 0x01,
+ LEVEL_TEMP,
+ CTL_TEMP,
+ IGNORE_TEMP
+};
+
+struct generic_onoff_state {
+ u8_t onoff;
+ u8_t target_onoff;
+
+ u8_t last_tid;
+ u16_t last_tx_addr;
+ s64_t last_msg_timestamp;
+
+ u8_t tt;
+ u32_t cal_tt;
+ u8_t delay;
+ u32_t tt_counter;
+
+ u8_t is_optional_para_available;
+};
+
+struct generic_level_state {
+ s16_t level;
+ s16_t target_level;
+
+ s16_t last_level;
+ s32_t last_delta;
+
+ u8_t last_tid;
+ u16_t last_tx_addr;
+ s64_t last_msg_timestamp;
+
+ s32_t tt_delta;
+ u8_t tt;
+ u32_t cal_tt;
+ u8_t delay;
+ u32_t tt_counter;
+ u32_t tt_counter_delta;
+ u32_t tt_counter_move;
+
+ u8_t is_optional_para_available;
+};
+
+struct generic_onpowerup_state {
+ u8_t onpowerup;
+ u8_t last_tid;
+ u16_t last_tx_addr;
+};
+
+struct gen_def_trans_time_state {
+ u8_t tt;
+};
+
+struct vendor_state {
+ int current;
+ u32_t response;
+ u8_t last_tid;
+ u16_t last_tx_addr;
+ s64_t last_msg_timestamp;
+};
+
+struct light_lightness_state {
+ u16_t linear;
+ u16_t target_linear;
+
+ u16_t actual;
+ u16_t target_actual;
+
+ u16_t last;
+ u16_t def;
+
+ u8_t status_code;
+ u16_t light_range_min;
+ u16_t light_range_max;
+
+ u8_t last_tid;
+ u16_t last_tx_addr;
+ s64_t last_msg_timestamp;
+
+ s32_t tt_delta_actual;
+ s32_t tt_delta_linear;
+ u8_t tt;
+ u32_t cal_tt;
+ u8_t delay;
+ u32_t tt_counter_actual;
+ u32_t tt_counter_linear;
+
+ u8_t is_optional_para_available;
+};
+
+struct light_ctl_state {
+ u16_t lightness;
+ u16_t target_lightness;
+
+ u16_t temp;
+ u16_t target_temp;
+
+ s16_t delta_uv;
+ s16_t target_delta_uv;
+
+ u8_t status_code;
+ u16_t temp_range_min;
+ u16_t temp_range_max;
+
+ u16_t lightness_def;
+ u16_t temp_def;
+ s16_t delta_uv_def;
+
+ u16_t temp_last;
+
+ u8_t last_tid;
+ u16_t last_tx_addr;
+ s64_t last_msg_timestamp;
+
+ s32_t tt_lightness_delta;
+ s32_t tt_temp_delta;
+ s32_t tt_duv_delta;
+ u8_t tt;
+ u32_t cal_tt;
+ u8_t delay;
+ u32_t tt_counter;
+ u32_t tt_counter_temp;
+
+ u8_t is_optional_para_available;
+};
+
+extern struct generic_onoff_state gen_onoff_srv_root_user_data;
+extern struct generic_level_state gen_level_srv_root_user_data;
+extern struct gen_def_trans_time_state gen_def_trans_time_srv_user_data;
+extern struct generic_onpowerup_state gen_power_onoff_srv_user_data;
+extern struct light_lightness_state light_lightness_srv_user_data;
+extern struct light_ctl_state light_ctl_srv_user_data;
+extern struct generic_level_state gen_level_srv_s0_user_data;
+
+extern struct bt_mesh_model root_models[];
+extern struct bt_mesh_model vnd_models[];
+extern struct bt_mesh_model s0_models[];
+
+extern const struct bt_mesh_comp comp;
+
+#endif
diff --git a/apps/blemesh_models_example_2/src/main.c b/apps/blemesh_models_example_2/src/main.c
new file mode 100644
index 00000000..10fc8dae
--- /dev/null
+++ b/apps/blemesh_models_example_2/src/main.c
@@ -0,0 +1,198 @@
+/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
+ *
+ * Copyright (c) 2018 Vikrant More
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "bsp/bsp.h"
+#include "console/console.h"
+#include "hal/hal_gpio.h"
+
+#include "common.h"
+#include "ble_mesh.h"
+#include "device_composition.h"
+#include "publisher.h"
+#include "state_binding.h"
+#include "transition.h"
+
+int button_device[] = {
+ BUTTON_1,
+ BUTTON_2,
+ BUTTON_3,
+ BUTTON_4,
+};
+
+int led_device[] = {
+ LED_1,
+ LED_2,
+ LED_3,
+ LED_4,
+};
+
+static struct ble_npl_callout button_work;
+
+static void button_pressed(struct os_event *ev)
+{
+ k_work_submit(&button_work);
+}
+
+static struct os_event button_event;
+
+static void
+gpio_irq_handler(void *arg)
+{
+ button_event.ev_arg = arg;
+ os_eventq_put(os_eventq_dflt_get(), &button_event);
+}
+
+static void gpio_init(void)
+{
+ /* LEDs configiuratin & setting */
+
+ hal_gpio_init_out(led_device[0], 1);
+ hal_gpio_init_out(led_device[1], 1);
+ hal_gpio_init_out(led_device[2], 1);
+ hal_gpio_init_out(led_device[3], 1);
+
+ /* Buttons configiuratin & setting */
+
+ k_work_init(&button_work, publish);
+
+ button_event.ev_cb = button_pressed;
+
+ hal_gpio_irq_init(button_device[0], gpio_irq_handler, NULL,
+ HAL_GPIO_TRIG_FALLING, HAL_GPIO_PULL_UP);
+ hal_gpio_irq_enable(button_device[0]);
+
+ hal_gpio_irq_init(button_device[1], gpio_irq_handler, NULL,
+ HAL_GPIO_TRIG_FALLING, HAL_GPIO_PULL_UP);
+ hal_gpio_irq_enable(button_device[1]);
+
+ hal_gpio_irq_init(button_device[2], gpio_irq_handler, NULL,
+ HAL_GPIO_TRIG_FALLING, HAL_GPIO_PULL_UP);
+ hal_gpio_irq_enable(button_device[2]);
+
+ hal_gpio_irq_init(button_device[3], gpio_irq_handler, NULL,
+ HAL_GPIO_TRIG_FALLING, HAL_GPIO_PULL_UP);
+ hal_gpio_irq_enable(button_device[3]);
+}
+
+void light_default_status_init(void)
+{
+ /* Assume vaules are retrived from Persistence Storage (Start).
+ * These had saved by respective Setup Servers.
+ */
+ gen_power_onoff_srv_user_data.onpowerup = STATE_DEFAULT;
+
+ light_lightness_srv_user_data.light_range_min = LIGHTNESS_MIN;
+ light_lightness_srv_user_data.light_range_max = LIGHTNESS_MAX;
+ light_lightness_srv_user_data.def = LIGHTNESS_MAX;
+
+ /* Following 2 values are as per specification */
+ light_ctl_srv_user_data.temp_range_min = TEMP_MIN;
+ light_ctl_srv_user_data.temp_range_max = TEMP_MAX;
+
+ light_ctl_srv_user_data.temp_def = TEMP_MIN;
+ /* (End) */
+
+ /* Assume following values are retrived from Persistence
+ * Storage (Start).
+ * These values had saved before power down.
+ */
+ light_lightness_srv_user_data.last = LIGHTNESS_MAX;
+ light_ctl_srv_user_data.temp_last = TEMP_MIN;
+ /* (End) */
+
+ light_ctl_srv_user_data.temp = light_ctl_srv_user_data.temp_def;
+
+ if (gen_power_onoff_srv_user_data.onpowerup == STATE_OFF) {
+ gen_onoff_srv_root_user_data.onoff = STATE_OFF;
+ state_binding(ONOFF, ONOFF_TEMP);
+ } else if (gen_power_onoff_srv_user_data.onpowerup == STATE_DEFAULT) {
+ gen_onoff_srv_root_user_data.onoff = STATE_ON;
+ state_binding(ONOFF, ONOFF_TEMP);
+ } else if (gen_power_onoff_srv_user_data.onpowerup == STATE_RESTORE) {
+ /* Assume following values is retrived from Persistence
+ * Storage (Start).
+ * This value had saved before power down.
+ */
+ gen_onoff_srv_root_user_data.onoff = STATE_ON;
+ /* (End) */
+
+ light_ctl_srv_user_data.temp =
+ light_ctl_srv_user_data.temp_last;
+
+ state_binding(ONPOWERUP, ONOFF_TEMP);
+ }
+}
+
+void update_light_state(void)
+{
+ u8_t power, color;
+
+ power = 100 * ((float) light_lightness_srv_user_data.actual / 65535);
+ color = 100 * ((float) (gen_level_srv_s0_user_data.level + 32768)
+ / 65535);
+
+ printk("power-> %d, color-> %d\n", power, color);
+
+ if (gen_onoff_srv_root_user_data.onoff == STATE_ON) {
+ /* LED1 On */
+ hal_gpio_write(led_device[0], 0);
+ } else {
+ /* LED1 Off */
+ hal_gpio_write(led_device[0], 1);
+ }
+
+ if (power < 50) {
+ /* LED3 On */
+ hal_gpio_write(led_device[2], 0);
+ } else {
+ /* LED3 Off */
+ hal_gpio_write(led_device[2], 1);
+ }
+
+ if (color < 50) {
+ /* LED4 On */
+ hal_gpio_write(led_device[3], 0);
+ } else {
+ /* LED4 Off */
+ hal_gpio_write(led_device[3], 1);
+ }
+}
+
+int main(void)
+{
+#ifdef ARCH_sim
+ mcu_sim_parse_args(argc, argv);
+#endif
+
+ /* Initialize OS */
+ sysinit();
+
+ light_default_status_init();
+
+ transition_timers_init();
+
+ gpio_init();
+
+ update_light_state();
+
+ init_pub();
+
+ printk("Initializing...\n");
+
+ /* Initialize the NimBLE host configuration. */
+ ble_hs_cfg.reset_cb = blemesh_on_reset;
+ ble_hs_cfg.sync_cb = blemesh_on_sync;
+ ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
+
+ randomize_publishers_TID();
+
+ while (1) {
+ os_eventq_run(os_eventq_dflt_get());
+ }
+
+ return 0;
+}
diff --git a/apps/blemesh_models_example_2/src/publisher.c b/apps/blemesh_models_example_2/src/publisher.c
new file mode 100644
index 00000000..9e0f4773
--- /dev/null
+++ b/apps/blemesh_models_example_2/src/publisher.c
@@ -0,0 +1,241 @@
+/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
+ *
+ * Copyright (c) 2018 Vikrant More
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "console/console.h"
+#include "hal/hal_gpio.h"
+
+#include "common.h"
+#include "ble_mesh.h"
+#include "publisher.h"
+#include "device_composition.h"
+
+#define ONOFF
+#define GENERIC_LEVEL
+/* #define LIGHT_CTL */
+/* #define LIGHT_CTL_TEMP */
+
+static bool is_randomization_of_TIDs_done;
+
+#if defined(ONOFF)
+static u8_t tid_onoff;
+#elif defined(VND_MODEL_TEST)
+static u8_t tid_vnd;
+#endif
+
+static u8_t tid_level;
+
+void randomize_publishers_TID(void)
+{
+#if defined(ONOFF)
+ bt_rand(&tid_onoff, sizeof(tid_onoff));
+#elif defined(VND_MODEL_TEST)
+ bt_rand(&tid_vnd, sizeof(tid_vnd));
+#endif
+
+ bt_rand(&tid_level, sizeof(tid_level));
+
+ is_randomization_of_TIDs_done = true;
+}
+
+static u32_t button_read(int button)
+{
+ return (uint32_t) hal_gpio_read(button);
+}
+
+void publish(struct ble_npl_event *work)
+{
+ int err = 0;
+
+ if (is_randomization_of_TIDs_done == false) {
+ return;
+ }
+
+ if (button_read(button_device[0]) == 0) {
+#if defined(ONOFF)
+ bt_mesh_model_msg_init(root_models[3].pub->msg,
+ BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK);
+ net_buf_simple_add_u8(root_models[3].pub->msg, 0x01);
+ net_buf_simple_add_u8(root_models[3].pub->msg, tid_onoff++);
+ err = bt_mesh_model_publish(&root_models[3]);
+#elif defined(ONOFF_TT)
+ bt_mesh_model_msg_init(root_models[3].pub->msg,
+ BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK);
+ net_buf_simple_add_u8(root_models[3].pub->msg, 0x01);
+ net_buf_simple_add_u8(root_models[3].pub->msg, tid_onoff++);
+ net_buf_simple_add_u8(root_models[3].pub->msg, 0x45);
+ net_buf_simple_add_u8(root_models[3].pub->msg, 0x28);
+ err = bt_mesh_model_publish(&root_models[3]);
+#elif defined(VND_MODEL_TEST)
+ bt_mesh_model_msg_init(vnd_models[0].pub->msg,
+ BT_MESH_MODEL_OP_3(0x02, CID_RUNTIME));
+ net_buf_simple_add_le16(vnd_models[0].pub->msg, 0x0001);
+ net_buf_simple_add_u8(vnd_models[0].pub->msg, tid_vnd++);
+ err = bt_mesh_model_publish(&vnd_models[0]);
+#endif
+
+ } else if (button_read(button_device[1]) == 0) {
+#if defined(ONOFF)
+ bt_mesh_model_msg_init(root_models[3].pub->msg,
+ BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK);
+ net_buf_simple_add_u8(root_models[3].pub->msg, 0x00);
+ net_buf_simple_add_u8(root_models[3].pub->msg, tid_onoff++);
+ err = bt_mesh_model_publish(&root_models[3]);
+#elif defined(ONOFF_TT)
+ bt_mesh_model_msg_init(root_models[3].pub->msg,
+ BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK);
+ net_buf_simple_add_u8(root_models[3].pub->msg, 0x00);
+ net_buf_simple_add_u8(root_models[3].pub->msg, tid_onoff++);
+ net_buf_simple_add_u8(root_models[3].pub->msg, 0x45);
+ net_buf_simple_add_u8(root_models[3].pub->msg, 0x28);
+ err = bt_mesh_model_publish(&root_models[3]);
+#elif defined(VND_MODEL_TEST)
+ bt_mesh_model_msg_init(vnd_models[0].pub->msg,
+ BT_MESH_MODEL_OP_3(0x02, CID_RUNTIME));
+ net_buf_simple_add_le16(vnd_models[0].pub->msg, 0x0000);
+ net_buf_simple_add_u8(vnd_models[0].pub->msg, tid_vnd++);
+ err = bt_mesh_model_publish(&vnd_models[0]);
+#endif
+
+ } else if (button_read(button_device[2]) == 0) {
+#if defined(GENERIC_LEVEL)
+ bt_mesh_model_msg_init(root_models[5].pub->msg,
+ BT_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK);
+ net_buf_simple_add_le16(root_models[5].pub->msg, LEVEL_S25);
+ net_buf_simple_add_u8(root_models[5].pub->msg, tid_level++);
+ err = bt_mesh_model_publish(&root_models[5]);
+#elif defined(GENERIC_DELTA_LEVEL)
+ bt_mesh_model_msg_init(root_models[5].pub->msg,
+ BT_MESH_MODEL_OP_GEN_DELTA_SET_UNACK);
+ net_buf_simple_add_le32(root_models[5].pub->msg, 100);
+ net_buf_simple_add_u8(root_models[5].pub->msg, tid_level++);
+ err = bt_mesh_model_publish(&root_models[5]);
+#elif defined(GENERIC_MOVE_LEVEL_TT)
+ bt_mesh_model_msg_init(root_models[5].pub->msg,
+ BT_MESH_MODEL_OP_GEN_MOVE_SET_UNACK);
+ net_buf_simple_add_le16(root_models[5].pub->msg, 13100);
+ net_buf_simple_add_u8(root_models[5].pub->msg, tid_level++);
+ net_buf_simple_add_u8(root_models[5].pub->msg, 0x45);
+ net_buf_simple_add_u8(root_models[5].pub->msg, 0x00);
+ err = bt_mesh_model_publish(&root_models[5]);
+#elif defined(LIGHT_LIGHTNESS_TT)
+ bt_mesh_model_msg_init(root_models[13].pub->msg,
+ BT_MESH_MODEL_OP_2(0x82, 0x4D));
+ net_buf_simple_add_le16(root_models[13].pub->msg, LEVEL_U25);
+ net_buf_simple_add_u8(root_models[13].pub->msg, tid_level++);
+ net_buf_simple_add_u8(root_models[13].pub->msg, 0x45);
+ net_buf_simple_add_u8(root_models[13].pub->msg, 0x28);
+ err = bt_mesh_model_publish(&root_models[13]);
+#elif defined(LIGHT_CTL)
+ bt_mesh_model_msg_init(root_models[16].pub->msg,
+ BT_MESH_MODEL_OP_2(0x82, 0x5F));
+ /* Lightness */
+ net_buf_simple_add_le16(root_models[16].pub->msg, LEVEL_U25);
+ /* Temperature (value should be from 0x0320 to 0x4E20 */
+ /* This is as per 6.1.3.1 in Mesh Model Specification */
+ net_buf_simple_add_le16(root_models[16].pub->msg, 0x0320);
+ /* Delta UV */
+ net_buf_simple_add_le16(root_models[16].pub->msg, 0x0000);
+ net_buf_simple_add_u8(root_models[16].pub->msg, tid_level++);
+ err = bt_mesh_model_publish(&root_models[16]);
+#elif defined(LIGHT_CTL_TT)
+ bt_mesh_model_msg_init(root_models[16].pub->msg,
+ BT_MESH_MODEL_OP_2(0x82, 0x5F));
+ /* Lightness */
+ net_buf_simple_add_le16(root_models[16].pub->msg, LEVEL_U25);
+ /* Temperature (value should be from 0x0320 to 0x4E20 */
+ /* This is as per 6.1.3.1 in Mesh Model Specification */
+ net_buf_simple_add_le16(root_models[16].pub->msg, 0x0320);
+ /* Delta UV */
+ net_buf_simple_add_le16(root_models[16].pub->msg, 0x0000);
+ net_buf_simple_add_u8(root_models[16].pub->msg, tid_level++);
+ net_buf_simple_add_u8(root_models[16].pub->msg, 0x45);
+ net_buf_simple_add_u8(root_models[16].pub->msg, 0x00);
+ err = bt_mesh_model_publish(&root_models[16]);
+#elif defined(LIGHT_CTL_TEMP)
+ bt_mesh_model_msg_init(root_models[16].pub->msg,
+ BT_MESH_MODEL_OP_2(0x82, 0x65));
+ /* Temperature (value should be from 0x0320 to 0x4E20 */
+ /* This is as per 6.1.3.1 in Mesh Model Specification */
+ net_buf_simple_add_le16(root_models[16].pub->msg, 0x0320);
+ /* Delta UV */
+ net_buf_simple_add_le16(root_models[16].pub->msg, 0x0000);
+ net_buf_simple_add_u8(root_models[16].pub->msg, tid_level++);
+ err = bt_mesh_model_publish(&root_models[16]);
+#endif
+
+ } else if (button_read(button_device[3]) == 0) {
+#if defined(GENERIC_LEVEL)
+ bt_mesh_model_msg_init(root_models[5].pub->msg,
+ BT_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK);
+ net_buf_simple_add_le16(root_models[5].pub->msg, LEVEL_S100);
+ net_buf_simple_add_u8(root_models[5].pub->msg, tid_level++);
+ err = bt_mesh_model_publish(&root_models[5]);
+#elif defined(GENERIC_DELTA_LEVEL)
+ bt_mesh_model_msg_init(root_models[5].pub->msg,
+ BT_MESH_MODEL_OP_GEN_DELTA_SET_UNACK);
+ net_buf_simple_add_le32(root_models[5].pub->msg, -100);
+ net_buf_simple_add_u8(root_models[5].pub->msg, tid_level++);
+ err = bt_mesh_model_publish(&root_models[5]);
+#elif defined(GENERIC_MOVE_LEVEL_TT)
+ bt_mesh_model_msg_init(root_models[5].pub->msg,
+ BT_MESH_MODEL_OP_GEN_MOVE_SET_UNACK);
+ net_buf_simple_add_le16(root_models[5].pub->msg, -13100);
+ net_buf_simple_add_u8(root_models[5].pub->msg, tid_level++);
+ net_buf_simple_add_u8(root_models[5].pub->msg, 0x45);
+ net_buf_simple_add_u8(root_models[5].pub->msg, 0x00);
+ err = bt_mesh_model_publish(&root_models[5]);
+#elif defined(LIGHT_LIGHTNESS_TT)
+ bt_mesh_model_msg_init(root_models[13].pub->msg,
+ BT_MESH_MODEL_OP_2(0x82, 0x4D));
+ net_buf_simple_add_le16(root_models[13].pub->msg, LEVEL_U100);
+ net_buf_simple_add_u8(root_models[13].pub->msg, tid_level++);
+ net_buf_simple_add_u8(root_models[13].pub->msg, 0x45);
+ net_buf_simple_add_u8(root_models[13].pub->msg, 0x28);
+ err = bt_mesh_model_publish(&root_models[13]);
+#elif defined(LIGHT_CTL)
+ bt_mesh_model_msg_init(root_models[16].pub->msg,
+ BT_MESH_MODEL_OP_2(0x82, 0x5F));
+ /* Lightness */
+ net_buf_simple_add_le16(root_models[16].pub->msg, LEVEL_U100);
+ /* Temperature (value should be from 0x0320 to 0x4E20 */
+ /* This is as per 6.1.3.1 in Mesh Model Specification */
+ net_buf_simple_add_le16(root_models[16].pub->msg, 0x4E20);
+ /* Delta UV */
+ net_buf_simple_add_le16(root_models[16].pub->msg, 0x0000);
+ net_buf_simple_add_u8(root_models[16].pub->msg, tid_level++);
+ err = bt_mesh_model_publish(&root_models[16]);
+#elif defined(LIGHT_CTL_TT)
+ bt_mesh_model_msg_init(root_models[16].pub->msg,
+ BT_MESH_MODEL_OP_2(0x82, 0x5F));
+ /* Lightness */
+ net_buf_simple_add_le16(root_models[16].pub->msg, LEVEL_U100);
+ /* Temperature (value should be from 0x0320 to 0x4E20 */
+ /* This is as per 6.1.3.1 in Mesh Model Specification */
+ net_buf_simple_add_le16(root_models[16].pub->msg, 0x4E20);
+ /* Delta UV */
+ net_buf_simple_add_le16(root_models[16].pub->msg, 0x0000);
+ net_buf_simple_add_u8(root_models[16].pub->msg, tid_level++);
+ net_buf_simple_add_u8(root_models[16].pub->msg, 0x45);
+ net_buf_simple_add_u8(root_models[16].pub->msg, 0x00);
+ err = bt_mesh_model_publish(&root_models[16]);
+#elif defined(LIGHT_CTL_TEMP)
+ bt_mesh_model_msg_init(root_models[16].pub->msg,
+ BT_MESH_MODEL_OP_2(0x82, 0x65));
+ /* Temperature (value should be from 0x0320 to 0x4E20 */
+ /* This is as per 6.1.3.1 in Mesh Model Specification */
+ net_buf_simple_add_le16(root_models[16].pub->msg, 0x4E20);
+ /* Delta UV */
+ net_buf_simple_add_le16(root_models[16].pub->msg, 0x0000);
+ net_buf_simple_add_u8(root_models[16].pub->msg, tid_level++);
+ err = bt_mesh_model_publish(&root_models[16]);
+#endif
+ }
+
+ if (err) {
+ printk("bt_mesh_model_publish: err: %d\n", err);
+ }
+}
diff --git a/apps/blemesh_models_example_2/src/publisher.h b/apps/blemesh_models_example_2/src/publisher.h
new file mode 100644
index 00000000..8ea169de
--- /dev/null
+++ b/apps/blemesh_models_example_2/src/publisher.h
@@ -0,0 +1,27 @@
+/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
+ *
+ * Copyright (c) 2018 Vikrant More
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _PUBLISHER_H
+#define _PUBLISHER_H
+
+/* Others */
+#define LEVEL_S0 -32768
+#define LEVEL_S25 -16384
+#define LEVEL_S50 0
+#define LEVEL_S75 16384
+#define LEVEL_S100 32767
+
+#define LEVEL_U0 0
+#define LEVEL_U25 16384
+#define LEVEL_U50 32768
+#define LEVEL_U75 49152
+#define LEVEL_U100 65535
+
+void randomize_publishers_TID(void);
+void publish(struct ble_npl_event *work);
+
+#endif
diff --git a/apps/blemesh_models_example_2/src/state_binding.c b/apps/blemesh_models_example_2/src/state_binding.c
new file mode 100644
index 00000000..bffe38ba
--- /dev/null
+++ b/apps/blemesh_models_example_2/src/state_binding.c
@@ -0,0 +1,183 @@
+/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
+ *
+ * Copyright (c) 2018 Vikrant More
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <math.h>
+
+#include "common.h"
+#include "ble_mesh.h"
+#include "device_composition.h"
+
+static s32_t ceiling(float num)
+{
+ s32_t inum;
+
+ inum = (s32_t) num;
+ if (num == (float) inum) {
+ return inum;
+ }
+
+ return inum + 1;
+}
+
+static bool constrain_light_actual_state(u16_t var)
+{
+ bool is_value_within_range;
+
+ is_value_within_range = false;
+
+ if (var > 0 &&
+ var < light_lightness_srv_user_data.light_range_min) {
+ var = light_lightness_srv_user_data.light_range_min;
+ } else if (var > light_lightness_srv_user_data.light_range_max) {
+ var = light_lightness_srv_user_data.light_range_max;
+ } else {
+ is_value_within_range = true;
+ }
+
+ light_lightness_srv_user_data.actual = var;
+
+ return is_value_within_range;
+}
+
+static void update_gen_onoff_state(void)
+{
+ if (light_lightness_srv_user_data.actual == 0) {
+ gen_onoff_srv_root_user_data.onoff = STATE_OFF;
+ } else {
+ gen_onoff_srv_root_user_data.onoff = STATE_ON;
+ }
+}
+
+void state_binding(u8_t lightness, u8_t temperature)
+{
+ bool is_value_within_range;
+ u16_t tmp16;
+ float tmp;
+
+ switch (temperature) {
+ case ONOFF_TEMP:/* Temp. update as per Light CTL temp. default state */
+ case CTL_TEMP: /* Temp. update as per Light CTL temp. state */
+ /* Mesh Model Specification 6.1.3.1.1 2nd formula start */
+ tmp = (light_ctl_srv_user_data.temp -
+ light_ctl_srv_user_data.temp_range_min) * 65535;
+ tmp = tmp / (light_ctl_srv_user_data.temp_range_max -
+ light_ctl_srv_user_data.temp_range_min);
+ gen_level_srv_s0_user_data.level = tmp - 32768;
+ /* 6.1.3.1.1 2nd formula end */
+ break;
+ case LEVEL_TEMP:/* Temp. update as per Generic Level (s0) state */
+ /* Mesh Model Specification 6.1.3.1.1 1st formula start */
+ tmp = (float) (light_ctl_srv_user_data.temp_range_max -
+ light_ctl_srv_user_data.temp_range_min) / 65535;
+ tmp = (gen_level_srv_s0_user_data.level + 32768) * tmp;
+ light_ctl_srv_user_data.temp =
+ light_ctl_srv_user_data.temp_range_min + tmp;
+ /* 6.1.3.1.1 1st formula end */
+ break;
+ default:
+ break;
+ }
+
+ tmp16 = 0;
+
+ switch (lightness) {
+ case ONPOWERUP: /* Lightness update as per Generic OnPowerUp state */
+ if (gen_onoff_srv_root_user_data.onoff == STATE_OFF) {
+ light_lightness_srv_user_data.actual = 0;
+ light_lightness_srv_user_data.linear = 0;
+ gen_level_srv_root_user_data.level = -32768;
+ light_ctl_srv_user_data.lightness = 0;
+ return;
+ } else if (gen_onoff_srv_root_user_data.onoff == STATE_ON) {
+ light_lightness_srv_user_data.actual =
+ light_lightness_srv_user_data.last;
+ }
+
+ break;
+ case ONOFF: /* Lightness update as per Generic OnOff (root) state */
+ if (gen_onoff_srv_root_user_data.onoff == STATE_OFF) {
+ light_lightness_srv_user_data.actual = 0;
+ light_lightness_srv_user_data.linear = 0;
+ gen_level_srv_root_user_data.level = -32768;
+ light_ctl_srv_user_data.lightness = 0;
+ return;
+ } else if (gen_onoff_srv_root_user_data.onoff == STATE_ON) {
+ if (light_lightness_srv_user_data.def == 0) {
+ light_lightness_srv_user_data.actual =
+ light_lightness_srv_user_data.last;
+ } else {
+ light_lightness_srv_user_data.actual =
+ light_lightness_srv_user_data.def;
+ }
+ }
+
+ break;
+ case LEVEL: /* Lightness update as per Generic Level (root) state */
+ tmp16 = gen_level_srv_root_user_data.level + 32768;
+ constrain_light_actual_state(tmp16);
+ update_gen_onoff_state();
+ break;
+ case DELTA_LEVEL: /* Lightness update as per Gen. Level (root) state */
+ /* This is as per Mesh Model Specification 3.3.2.2.3 */
+ tmp16 = gen_level_srv_root_user_data.level + 32768;
+ if (tmp16 > 0 &&
+ tmp16 < light_lightness_srv_user_data.light_range_min) {
+ if (gen_level_srv_root_user_data.last_delta < 0) {
+ tmp16 = 0;
+ } else {
+ tmp16 =
+ light_lightness_srv_user_data.light_range_min;
+ }
+ } else if (tmp16 >
+ light_lightness_srv_user_data.light_range_max) {
+ tmp16 =
+ light_lightness_srv_user_data.light_range_max;
+ }
+
+ light_lightness_srv_user_data.actual = tmp16;
+
+ update_gen_onoff_state();
+ break;
+ case ACTUAL: /* Lightness update as per Light Lightness Actual state */
+ update_gen_onoff_state();
+ break;
+ case LINEAR: /* Lightness update as per Light Lightness Linear state */
+ tmp16 = (u16_t) 65535 *
+ sqrt(((float) light_lightness_srv_user_data.linear /
+ 65535));
+
+ is_value_within_range = constrain_light_actual_state(tmp16);
+ update_gen_onoff_state();
+
+ if (is_value_within_range) {
+ goto ignore_linear_update_others;
+ }
+
+ break;
+ case CTL: /* Lightness update as per Light CTL Lightness state */
+ constrain_light_actual_state(light_ctl_srv_user_data.lightness);
+ update_gen_onoff_state();
+ break;
+ default:
+ return;
+ }
+
+ tmp = ((float) light_lightness_srv_user_data.actual / 65535);
+ light_lightness_srv_user_data.linear = ceiling(65535 * tmp * tmp);
+
+ignore_linear_update_others:
+ if (light_lightness_srv_user_data.actual != 0) {
+ light_lightness_srv_user_data.last =
+ light_lightness_srv_user_data.actual;
+ }
+
+ gen_level_srv_root_user_data.level =
+ light_lightness_srv_user_data.actual - 32768;
+
+ light_ctl_srv_user_data.lightness =
+ light_lightness_srv_user_data.actual;
+}
diff --git a/apps/blemesh_models_example_2/src/state_binding.h b/apps/blemesh_models_example_2/src/state_binding.h
new file mode 100644
index 00000000..e7dd1087
--- /dev/null
+++ b/apps/blemesh_models_example_2/src/state_binding.h
@@ -0,0 +1,13 @@
+/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
+ *
+ * Copyright (c) 2018 Vikrant More
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _STATE_BINDING_H
+#define _STATE_BINDING_H
+
+void state_binding(u8_t lightness, u8_t temperature);
+
+#endif
diff --git a/apps/blemesh_models_example_2/src/transition.c b/apps/blemesh_models_example_2/src/transition.c
new file mode 100644
index 00000000..3edbce2f
--- /dev/null
+++ b/apps/blemesh_models_example_2/src/transition.c
@@ -0,0 +1,678 @@
+/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
+ *
+ * Copyright (c) 2018 Vikrant More
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "common.h"
+#include "ble_mesh.h"
+#include "device_composition.h"
+#include "state_binding.h"
+#include "transition.h"
+
+u8_t enable_transition;
+u8_t default_tt;
+
+struct ble_npl_callout onoff_work;
+struct ble_npl_callout level_lightness_work;
+struct ble_npl_callout level_temp_work;
+struct ble_npl_callout light_lightness_actual_work;
+struct ble_npl_callout light_lightness_linear_work;
+struct ble_npl_callout light_ctl_work;
+struct ble_npl_callout light_ctl_temp_work;
+
+struct ble_npl_callout onoff_transition_timer;
+struct ble_npl_callout level_lightness_transition_timer;
+struct ble_npl_callout level_temp_transition_timer;
+struct ble_npl_callout light_lightness_actual_transition_timer;
+struct ble_npl_callout light_lightness_linear_transition_timer;
+struct ble_npl_callout light_ctl_transition_timer;
+struct ble_npl_callout light_ctl_temp_transition_timer;
+
+static u32_t tt_counter_calculator(u8_t *tt, u32_t *cal_tt)
+{
+ u8_t steps_multiplier, resolution;
+ u32_t tt_counter;
+
+ resolution = ((*tt) >> 6);
+ steps_multiplier = (*tt) & 0x3F;
+
+ switch (resolution) {
+ case 0: /* 100ms */
+ *cal_tt = steps_multiplier * 100;
+ break;
+ case 1: /* 1 second */
+ *cal_tt = steps_multiplier * 1000;
+ break;
+ case 2: /* 10 seconds */
+ *cal_tt = steps_multiplier * 10000;
+ break;
+ case 3: /* 10 minutes */
+ *cal_tt = steps_multiplier * 600000;
+ break;
+ }
+
+ tt_counter = ((float) *cal_tt / 100);
+
+ if (tt_counter > DEVICE_SPECIFIC_RESOLUTION) {
+ tt_counter = DEVICE_SPECIFIC_RESOLUTION;
+ }
+
+ if (tt_counter != 0) {
+ *cal_tt = *cal_tt / tt_counter;
+ }
+
+ return tt_counter;
+}
+
+void onoff_tt_values(struct generic_onoff_state *state)
+{
+ state->tt_counter = tt_counter_calculator(&state->tt, &state->cal_tt);
+}
+
+void level_tt_values(struct generic_level_state *state)
+{
+ u32_t tt_counter;
+
+ tt_counter = tt_counter_calculator(&state->tt, &state->cal_tt);
+ state->tt_counter = tt_counter;
+
+ if (tt_counter == 0) {
+ tt_counter = 1;
+ }
+
+ state->tt_delta = ((float) (state->level - state->target_level) /
+ tt_counter);
+}
+
+void delta_level_tt_values(struct generic_level_state *state)
+{
+ u32_t tt_counter;
+
+ tt_counter = tt_counter_calculator(&state->tt, &state->cal_tt);
+ state->tt_counter_delta = tt_counter;
+
+ if (tt_counter == 0) {
+ tt_counter = 1;
+ }
+
+ state->tt_delta = ((float) state->last_delta / tt_counter);
+
+ state->tt_delta *= -1;
+}
+
+void move_level_tt_values(struct generic_level_state *state)
+{
+ u32_t tt_counter;
+
+ tt_counter = tt_counter_calculator(&state->tt, &state->cal_tt);
+ state->tt_counter_move = tt_counter;
+
+ if (tt_counter == 0) {
+ tt_counter = 1;
+ }
+
+ state->tt_delta = ((float) state->last_delta / tt_counter);
+
+ state->tt_delta *= -1;
+}
+
+void light_lightnes_actual_tt_values(struct light_lightness_state *state)
+{
+ u32_t tt_counter;
+
+ tt_counter = tt_counter_calculator(&state->tt, &state->cal_tt);
+ state->tt_counter_actual = tt_counter;
+
+ if (tt_counter == 0) {
+ tt_counter = 1;
+ }
+
+ state->tt_delta_actual =
+ ((float) (state->actual - state->target_actual) /
+ tt_counter);
+}
+
+void light_lightnes_linear_tt_values(struct light_lightness_state *state)
+{
+ u32_t tt_counter;
+
+ tt_counter = tt_counter_calculator(&state->tt, &state->cal_tt);
+ state->tt_counter_linear = tt_counter;
+
+ if (tt_counter == 0) {
+ tt_counter = 1;
+ }
+
+ state->tt_delta_linear =
+ ((float) (state->linear - state->target_linear) /
+ tt_counter);
+}
+
+void light_ctl_tt_values(struct light_ctl_state *state)
+{
+ u32_t tt_counter;
+
+ tt_counter = tt_counter_calculator(&state->tt, &state->cal_tt);
+ state->tt_counter = tt_counter;
+
+ if (tt_counter == 0) {
+ tt_counter = 1;
+ }
+
+ state->tt_lightness_delta =
+ ((float) (state->lightness - state->target_lightness) /
+ tt_counter);
+
+ state->tt_temp_delta =
+ ((float) (state->temp - state->target_temp) /
+ tt_counter);
+
+ state->tt_duv_delta =
+ ((float) (state->delta_uv - state->target_delta_uv) /
+ tt_counter);
+}
+
+void light_ctl_temp_tt_values(struct light_ctl_state *state)
+{
+ u32_t tt_counter;
+
+ tt_counter = tt_counter_calculator(&state->tt, &state->cal_tt);
+ state->tt_counter_temp = tt_counter;
+
+ if (tt_counter == 0) {
+ tt_counter = 1;
+ }
+
+ state->tt_temp_delta = ((float) (state->temp - state->target_temp) /
+ tt_counter);
+
+ state->tt_duv_delta =
+ ((float) (state->delta_uv - state->target_delta_uv) /
+ tt_counter);
+}
+
+/* Timers related handlers & threads (Start) */
+static void onoff_work_handler(struct ble_npl_event *work)
+{
+ struct generic_onoff_state *state = &gen_onoff_srv_root_user_data;
+
+ if (enable_transition != ONOFF_TT) {
+ ble_npl_callout_stop(&onoff_transition_timer);
+ return;
+ }
+
+ if (state->tt_counter != 0) {
+ state->tt_counter--;
+
+ if (state->target_onoff == STATE_ON) {
+ state->onoff = STATE_ON;
+
+ state_binding(ONOFF, IGNORE_TEMP);
+ update_light_state();
+
+ enable_transition = DISABLE_TRANSITION;
+ }
+ }
+
+ if (state->tt_counter == 0) {
+ state->onoff = state->target_onoff;
+
+ state_binding(ONOFF, IGNORE_TEMP);
+ update_light_state();
+
+ ble_npl_callout_stop(&onoff_transition_timer);
+ }
+}
+
+static void level_lightness_work_handler(struct ble_npl_event *work)
+{
+ u32_t *tt_counter;
+ struct generic_level_state *state = &gen_level_srv_root_user_data;
+
+ tt_counter = NULL;
+
+ switch (enable_transition) {
+ case LEVEL_TT:
+ tt_counter = &state->tt_counter;
+ break;
+ case LEVEL_TT_DELTA:
+ tt_counter = &state->tt_counter_delta;
+ break;
+ case LEVEL_TT_MOVE:
+ tt_counter = &state->tt_counter_move;
+ break;
+ default:
+ ble_npl_callout_stop(&level_lightness_transition_timer);
+ return;
+ }
+
+ if (*tt_counter != 0) {
+ s32_t lightness;
+
+ (*tt_counter)--;
+
+ lightness = state->level - state->tt_delta;
+
+ if (lightness > INT16_MAX) {
+ lightness = INT16_MAX;
+ } else if (lightness < INT16_MIN) {
+ lightness = INT16_MIN;
+ }
+
+ if (state->level != lightness) {
+ state->level = lightness;
+
+ state_binding(LEVEL, IGNORE_TEMP);
+ update_light_state();
+ } else {
+ enable_transition = DISABLE_TRANSITION;
+ }
+ }
+
+ if (*tt_counter == 0) {
+ state->level = state->target_level;
+
+ state_binding(LEVEL, IGNORE_TEMP);
+ update_light_state();
+
+ ble_npl_callout_stop(&level_lightness_transition_timer);
+ }
+}
+
+static void level_temp_work_handler(struct ble_npl_event *work)
+{
+ u32_t *tt_counter;
+ struct generic_level_state *state = &gen_level_srv_s0_user_data;
+
+ tt_counter = NULL;
+
+ switch (enable_transition) {
+ case LEVEL_TT:
+ tt_counter = &state->tt_counter;
+ break;
+ case LEVEL_TT_DELTA:
+ tt_counter = &state->tt_counter_delta;
+ break;
+ case LEVEL_TT_MOVE:
+ tt_counter = &state->tt_counter_move;
+ break;
+ default:
+ ble_npl_callout_stop(&level_temp_transition_timer);
+ return;
+ }
+
+ if (*tt_counter != 0) {
+ s32_t temp;
+
+ (*tt_counter)--;
+
+ temp = state->level - state->tt_delta;
+
+ if (temp > INT16_MAX) {
+ temp = INT16_MAX;
+ } else if (temp < INT16_MIN) {
+ temp = INT16_MIN;
+ }
+
+ if (state->level != temp) {
+ state->level = temp;
+
+ state_binding(IGNORE, LEVEL_TEMP);
+ update_light_state();
+ } else {
+ enable_transition = DISABLE_TRANSITION;
+ }
+ }
+
+ if (*tt_counter == 0) {
+ state->level = state->target_level;
+
+ state_binding(IGNORE, LEVEL_TEMP);
+ update_light_state();
+
+ ble_npl_callout_stop(&level_temp_transition_timer);
+ }
+}
+
+static void light_lightness_actual_work_handler(struct ble_npl_event *work)
+{
+ struct light_lightness_state *state = &light_lightness_srv_user_data;
+
+ if (enable_transition != LIGTH_LIGHTNESS_ACTUAL_TT) {
+ ble_npl_callout_stop(&light_lightness_actual_transition_timer);
+ return;
+ }
+
+ if (state->tt_counter_actual != 0) {
+ u32_t actual;
+
+ state->tt_counter_actual--;
+
+ actual = state->actual - state->tt_delta_actual;
+
+ if (state->actual != actual) {
+ state->actual = actual;
+
+ state_binding(ACTUAL, IGNORE_TEMP);
+ update_light_state();
+ } else {
+ enable_transition = DISABLE_TRANSITION;
+ }
+ }
+
+ if (state->tt_counter_actual == 0) {
+ state->actual = state->target_actual;
+
+ state_binding(ACTUAL, IGNORE_TEMP);
+ update_light_state();
+
+ ble_npl_callout_stop(&light_lightness_actual_transition_timer);
+ }
+}
+
+static void light_lightness_linear_work_handler(struct ble_npl_event *work)
+{
+ struct light_lightness_state *state = &light_lightness_srv_user_data;
+
+ if (enable_transition != LIGTH_LIGHTNESS_LINEAR_TT) {
+ ble_npl_callout_stop(&light_lightness_linear_transition_timer);
+ return;
+ }
+
+ if (state->tt_counter_linear != 0) {
+ u32_t linear;
+
+ state->tt_counter_linear--;
+
+ linear = state->linear - state->tt_delta_linear;
+
+ if (state->linear != linear) {
+ state->linear = linear;
+
+ state_binding(LINEAR, IGNORE_TEMP);
+ update_light_state();
+ } else {
+ enable_transition = DISABLE_TRANSITION;
+ }
+ }
+
+ if (state->tt_counter_linear == 0) {
+ state->linear = state->target_linear;
+
+ state_binding(LINEAR, IGNORE_TEMP);
+ update_light_state();
+
+ ble_npl_callout_stop(&light_lightness_linear_transition_timer);
+ }
+}
+
+static void light_ctl_work_handler(struct ble_npl_event *work)
+{
+ struct light_ctl_state *state = &light_ctl_srv_user_data;
+
+ if (enable_transition != LIGTH_CTL_TT) {
+ ble_npl_callout_stop(&light_ctl_transition_timer);
+ return;
+ }
+
+ if (state->tt_counter != 0) {
+ u32_t lightness, temp;
+ s32_t delta_uv;
+
+ state->tt_counter--;
+
+ /* Lightness */
+ lightness = state->lightness - state->tt_lightness_delta;
+
+ /* Temperature */
+ temp = state->temp - state->tt_temp_delta;
+
+ /* Delta_UV */
+ delta_uv = state->delta_uv - state->tt_duv_delta;
+
+ if (delta_uv > INT16_MAX) {
+ delta_uv = INT16_MAX;
+ } else if (delta_uv < INT16_MIN) {
+ delta_uv = INT16_MIN;
+ }
+
+ if (state->lightness != lightness || state->temp != temp ||
+ state->delta_uv != delta_uv) {
+ state->lightness = lightness;
+ state->temp = temp;
+ state->delta_uv = delta_uv;
+
+ state_binding(CTL, CTL_TEMP);
+ update_light_state();
+ } else {
+ enable_transition = DISABLE_TRANSITION;
+ }
+ }
+
+ if (state->tt_counter == 0) {
+ state->lightness = state->target_lightness;
+ state->temp = state->target_temp;
+ state->delta_uv = state->target_delta_uv;
+
+ state_binding(CTL, CTL_TEMP);
+ update_light_state();
+
+ ble_npl_callout_stop(&light_ctl_transition_timer);
+ }
+}
+
+static void light_ctl_temp_work_handler(struct ble_npl_event *work)
+{
+ struct light_ctl_state *state = &light_ctl_srv_user_data;
+
+ if (enable_transition != LIGHT_CTL_TEMP_TT) {
+ ble_npl_callout_stop(&light_ctl_temp_transition_timer);
+ return;
+ }
+
+ if (state->tt_counter_temp != 0) {
+ s32_t delta_uv;
+ u32_t temp;
+
+ state->tt_counter_temp--;
+
+ /* Temperature */
+ temp = state->temp - state->tt_temp_delta;
+
+ /* Delta UV */
+ delta_uv = state->delta_uv - state->tt_duv_delta;
+
+ if (delta_uv > INT16_MAX) {
+ delta_uv = INT16_MAX;
+ } else if (delta_uv < INT16_MIN) {
+ delta_uv = INT16_MIN;
+ }
+
+ if (state->temp != temp || state->delta_uv != delta_uv) {
+ state->temp = temp;
+ state->delta_uv = delta_uv;
+
+ state_binding(IGNORE, CTL_TEMP);
+ update_light_state();
+ } else {
+ enable_transition = DISABLE_TRANSITION;
+ }
+ }
+
+ if (state->tt_counter_temp == 0) {
+ state->temp = state->target_temp;
+ state->delta_uv = state->target_delta_uv;
+
+ state_binding(IGNORE, CTL_TEMP);
+ update_light_state();
+
+ ble_npl_callout_stop(&light_ctl_temp_transition_timer);
+ }
+}
+
+static void onoff_tt_handler(struct ble_npl_event *ev)
+{
+ struct generic_onoff_state *state = ble_npl_event_get_arg(ev);
+
+ assert(state != NULL);
+ ble_npl_callout_reset(&onoff_work, 0);
+ ble_npl_callout_reset(&onoff_transition_timer, K_MSEC(state->cal_tt));
+}
+
+static void level_lightness_tt_handler(struct ble_npl_event *ev)
+{
+ struct generic_level_state *state = ble_npl_event_get_arg(ev);
+
+ assert(state != NULL);
+ ble_npl_callout_reset(&level_lightness_work, 0);
+ ble_npl_callout_reset(&level_lightness_transition_timer, K_MSEC(state->cal_tt));
+}
+
+static void level_temp_tt_handler(struct ble_npl_event *ev)
+{
+ struct generic_level_state *state = ble_npl_event_get_arg(ev);
+
+ assert(state != NULL);
+ ble_npl_callout_reset(&level_temp_work, 0);
+ ble_npl_callout_reset(&level_temp_transition_timer, K_MSEC(state->cal_tt));
+}
+
+static void light_lightness_actual_tt_handler(struct ble_npl_event *ev)
+{
+ struct light_lightness_state *state = ble_npl_event_get_arg(ev);
+
+ assert(state != NULL);
+ ble_npl_callout_reset(&light_lightness_actual_work, 0);
+ ble_npl_callout_reset(&light_lightness_actual_transition_timer, K_MSEC(state->cal_tt));
+}
+
+static void light_lightness_linear_tt_handler(struct ble_npl_event *ev)
+{
+ struct light_lightness_state *state = ble_npl_event_get_arg(ev);
+
+ assert(state != NULL);
+ ble_npl_callout_reset(&light_lightness_linear_work, 0);
+ ble_npl_callout_reset(&light_lightness_linear_transition_timer, K_MSEC(state->cal_tt));
+}
+
+static void light_ctl_tt_handler(struct ble_npl_event *ev)
+{
+ struct light_ctl_state *state = ble_npl_event_get_arg(ev);
+
+ assert(state != NULL);
+ ble_npl_callout_reset(&light_ctl_work, 0);
+ ble_npl_callout_reset(&light_ctl_transition_timer, K_MSEC(state->cal_tt));
+}
+
+static void light_ctl_temp_tt_handler(struct ble_npl_event *ev)
+{
+ struct light_ctl_state *state = ble_npl_event_get_arg(ev);
+
+ assert(state != NULL);
+ ble_npl_callout_reset(&light_ctl_temp_work, 0);
+ ble_npl_callout_reset(&light_ctl_temp_transition_timer, K_MSEC(state->cal_tt));
+}
+/* Timers related handlers & threads (End) */
+
+/* Messages handlers (Start) */
+void onoff_handler(struct generic_onoff_state *state)
+{
+ enable_transition = ONOFF_TT;
+
+ ble_npl_callout_set_arg(&onoff_transition_timer, state);
+ ble_npl_callout_reset(&onoff_transition_timer, K_MSEC(5 * state->delay));
+}
+
+void level_lightness_handler(struct generic_level_state *state)
+{
+ ble_npl_callout_set_arg(&level_lightness_transition_timer, state);
+ ble_npl_callout_reset(&level_lightness_transition_timer,
+ K_MSEC(5 * state->delay));
+}
+
+void level_temp_handler(struct generic_level_state *state)
+{
+ ble_npl_callout_set_arg(&level_temp_transition_timer, state);
+ ble_npl_callout_reset(&level_temp_transition_timer, K_MSEC(5 * state->delay));
+}
+
+void light_lightness_actual_handler(struct light_lightness_state *state)
+{
+ enable_transition = LIGTH_LIGHTNESS_ACTUAL_TT;
+
+ ble_npl_callout_set_arg(&light_lightness_actual_transition_timer, state);
+ ble_npl_callout_reset(&light_lightness_actual_transition_timer,
+ K_MSEC(5 * state->delay));
+}
+
+void light_lightness_linear_handler(struct light_lightness_state *state)
+{
+ enable_transition = LIGTH_LIGHTNESS_LINEAR_TT;
+
+ ble_npl_callout_set_arg(&light_lightness_linear_transition_timer, state);
+ ble_npl_callout_reset(&light_lightness_linear_transition_timer,
+ K_MSEC(5 * state->delay));
+}
+
+void light_ctl_handler(struct light_ctl_state *state)
+{
+ enable_transition = LIGTH_CTL_TT;
+
+ ble_npl_callout_set_arg(&light_ctl_transition_timer, state);
+ ble_npl_callout_reset(&light_ctl_transition_timer, K_MSEC(5 * state->delay));
+}
+
+void light_ctl_temp_handler(struct light_ctl_state *state)
+{
+ enable_transition = LIGHT_CTL_TEMP_TT;
+
+ ble_npl_callout_set_arg(&light_ctl_temp_transition_timer, state);
+ ble_npl_callout_reset(&light_ctl_temp_transition_timer,
+ K_MSEC(5 * state->delay));
+}
+/* Messages handlers (End) */
+
+void transition_timers_init(void)
+{
+ ble_npl_callout_init(&onoff_work, ble_npl_eventq_dflt_get(),
+ onoff_work_handler, NULL);
+
+ ble_npl_callout_init(&level_lightness_work, ble_npl_eventq_dflt_get(),
+ level_lightness_work_handler, NULL);
+ ble_npl_callout_init(&level_temp_work, ble_npl_eventq_dflt_get(),
+ level_temp_work_handler, NULL);
+
+ ble_npl_callout_init(&light_lightness_actual_work, ble_npl_eventq_dflt_get(),
+ light_lightness_actual_work_handler, NULL);
+ ble_npl_callout_init(&light_lightness_linear_work, ble_npl_eventq_dflt_get(),
+ light_lightness_linear_work_handler, NULL);
+
+ ble_npl_callout_init(&light_ctl_work, ble_npl_eventq_dflt_get(),
+ light_ctl_work_handler, NULL);
+ ble_npl_callout_init(&light_ctl_temp_work, ble_npl_eventq_dflt_get(),
+ light_ctl_temp_work_handler, NULL);
+
+ ble_npl_callout_init(&onoff_transition_timer, ble_npl_eventq_dflt_get(),
+ onoff_tt_handler, NULL);
+
+ ble_npl_callout_init(&level_lightness_transition_timer, ble_npl_eventq_dflt_get(),
+ level_lightness_tt_handler, NULL);
+ ble_npl_callout_init(&level_temp_transition_timer, ble_npl_eventq_dflt_get(),
+ level_temp_tt_handler, NULL);
+
+ ble_npl_callout_init(&light_lightness_actual_transition_timer, ble_npl_eventq_dflt_get(),
+ light_lightness_actual_tt_handler, NULL);
+ ble_npl_callout_init(&light_lightness_linear_transition_timer, ble_npl_eventq_dflt_get(),
+ light_lightness_linear_tt_handler, NULL);
+
+ ble_npl_callout_init(&light_ctl_transition_timer, ble_npl_eventq_dflt_get(),
+ light_ctl_tt_handler, NULL);
+ ble_npl_callout_init(&light_ctl_temp_transition_timer, ble_npl_eventq_dflt_get(),
+ light_ctl_temp_tt_handler, NULL);
+
+ ble_npl_callout_init(&light_ctl_temp_transition_timer, ble_npl_eventq_dflt_get(),
+ light_ctl_temp_tt_handler, NULL);
+
+}
\ No newline at end of file
diff --git a/apps/blemesh_models_example_2/src/transition.h b/apps/blemesh_models_example_2/src/transition.h
new file mode 100644
index 00000000..f399005f
--- /dev/null
+++ b/apps/blemesh_models_example_2/src/transition.h
@@ -0,0 +1,58 @@
+/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
+ *
+ * Copyright (c) 2018 Vikrant More
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _TRANSITION_H
+#define _TRANSITION_H
+
+#define DEVICE_SPECIFIC_RESOLUTION 10
+
+enum transition_time {
+ DISABLE_TRANSITION = 0x00,
+ ONOFF_TT = 0x01,
+ LEVEL_TT,
+ LEVEL_TT_DELTA,
+ LEVEL_TT_MOVE,
+ LIGTH_LIGHTNESS_ACTUAL_TT,
+ LIGTH_LIGHTNESS_LINEAR_TT,
+ LIGTH_CTL_TT,
+ LEVEL_TEMP_TT,
+ LEVEL_TEMP_TT_DELTA,
+ LEVEL_TEMP_TT_MOVE,
+ LIGHT_CTL_TEMP_TT
+};
+
+extern u8_t enable_transition;
+extern u8_t default_tt;
+
+extern struct ble_npl_callout onoff_transition_timer;
+extern struct ble_npl_callout level_lightness_transition_timer;
+extern struct ble_npl_callout level_temp_transition_timer;
+extern struct ble_npl_callout light_lightness_actual_transition_timer;
+extern struct ble_npl_callout light_lightness_linear_transition_timer;
+extern struct ble_npl_callout light_ctl_transition_timer;
+extern struct ble_npl_callout light_ctl_temp_transition_timer;
+
+void onoff_tt_values(struct generic_onoff_state *state);
+void level_tt_values(struct generic_level_state *state);
+void delta_level_tt_values(struct generic_level_state *state);
+void move_level_tt_values(struct generic_level_state *state);
+void light_lightnes_actual_tt_values(struct light_lightness_state *state);
+void light_lightnes_linear_tt_values(struct light_lightness_state *state);
+void light_ctl_tt_values(struct light_ctl_state *state);
+void light_ctl_temp_tt_values(struct light_ctl_state *state);
+
+void onoff_handler(struct generic_onoff_state *state);
+void level_lightness_handler(struct generic_level_state *state);
+void level_temp_handler(struct generic_level_state *state);
+void light_lightness_actual_handler(struct light_lightness_state *state);
+void light_lightness_linear_handler(struct light_lightness_state *state);
+void light_ctl_handler(struct light_ctl_state *state);
+void light_ctl_temp_handler(struct light_ctl_state *state);
+
+void transition_timers_init(void);
+
+#endif
diff --git a/apps/blemesh_models_example_2/syscfg.yml b/apps/blemesh_models_example_2/syscfg.yml
new file mode 100644
index 00000000..68ec0746
--- /dev/null
+++ b/apps/blemesh_models_example_2/syscfg.yml
@@ -0,0 +1,56 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Package: apps/blemesh
+
+syscfg.vals:
+ # Set log level to info (disable debug logging).
+ LOG_LEVEL: 1
+
+ # Default task settings
+ OS_MAIN_STACK_SIZE: 768
+
+ # Newtmgr is not supported in this app, so disable newtmgr-over-shell.
+ SHELL_NEWTMGR: 0
+
+ MSYS_1_BLOCK_COUNT: 48
+
+ FLOAT_USER: 1
+ HARD_FLOAT: 1
+
+ BLE_MESH_ADV_BUF_COUNT: 20
+ BLE_MESH_TX_SEG_MAX: 9
+
+ BLE_MESH: 1
+ BLE_MESH_CFG_CLI: 1
+ BLE_MESH_DEV_UUID: "((uint8_t[16]){0xdd, 0xdd, 0})"
+ BLE_MESH_SETTINGS: 0
+ CONFIG_NFFS: 0
+
+ BLE_MESH_DEBUG: 0
+ BLE_MESH_DEBUG_NET: 0
+ BLE_MESH_DEBUG_TRANS: 0
+ BLE_MESH_DEBUG_BEACON: 0
+ BLE_MESH_DEBUG_CRYPTO: 0
+ BLE_MESH_DEBUG_PROV: 0
+ BLE_MESH_DEBUG_ACCESS: 0
+ BLE_MESH_DEBUG_MODEL: 0
+ BLE_MESH_DEBUG_ADV: 0
+ BLE_MESH_DEBUG_LOW_POWER: 0
+ BLE_MESH_DEBUG_FRIEND: 0
+ BLE_MESH_DEBUG_PROXY: 0
----------------------------------------------------------------
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:
users@infra.apache.org
With regards,
Apache Git Services