1. Add an API to set Provisioner static oob value 2. Add an API to deinit BLE Mesh stack 3. Add an API to set Provisioner unicast address 4. Add an API to provision devices with fixed address 5. Add an API to store node composition data 6. Add an API to get node with device uuid 7. Add an API to get node with unicast address 8. Add an API to delete node with device uuid 9. Add an API to delete node with unicast address 10. Add an API for Provisioner to update local AppKey 11. Add an API for Provisioner to update local NetKey 12. Support Provisioner persistent functionality 13. Fix Provisioner entering IV Update procedure 14. Fix an issue which may cause client failing to send msg 15. Use bt_mesh.flags to indicate device role 16. Remove several useless macros 17. Callback RSSI of received mesh provisioning packets 18. Modify the Provisioner disable function 19. Change some log level from debug to info 20. Add parameters to Provisioner bind AppKey completion event 21. Fix node ignoring relay messages issue 22. Support using a specific partition for BLE Mesh 23. Fix compile warning when proxy related macros are disabled 24. Clean up BLE Mesh stack included header files 25. NULL can be input if client message needs no parameters 26. Fix compile warning when BT log is disabled 27. Initilize BLE Mesh stack local variables 28. Support using PSRAM for BLE Mesh mutex, queue and task 29. Add a menuconfig option to enable using memory from PSRAM 30. Clean up sdkconfig.defaults of BLE Mesh examples
1500 lines
56 KiB
C
1500 lines
56 KiB
C
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
|
|
//
|
|
// Licensed 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.
|
|
|
|
#include <errno.h>
|
|
|
|
#include "access.h"
|
|
#include "transport.h"
|
|
#include "model_opcode.h"
|
|
#include "state_transition.h"
|
|
|
|
#include "btc_ble_mesh_time_scene_model.h"
|
|
|
|
static bt_mesh_mutex_t time_scene_server_lock;
|
|
|
|
static void bt_mesh_time_scene_server_mutex_new(void)
|
|
{
|
|
if (!time_scene_server_lock.mutex) {
|
|
bt_mesh_mutex_create(&time_scene_server_lock);
|
|
}
|
|
}
|
|
|
|
static void bt_mesh_time_scene_server_mutex_free(void)
|
|
{
|
|
bt_mesh_mutex_free(&time_scene_server_lock);
|
|
}
|
|
|
|
void bt_mesh_time_scene_server_lock(void)
|
|
{
|
|
bt_mesh_mutex_lock(&time_scene_server_lock);
|
|
}
|
|
|
|
void bt_mesh_time_scene_server_unlock(void)
|
|
{
|
|
bt_mesh_mutex_unlock(&time_scene_server_lock);
|
|
}
|
|
|
|
/* message handlers (Start) */
|
|
|
|
/* Time Server & Time Setup Server message handlers */
|
|
static void send_time_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
bool publish, u16_t opcode)
|
|
{
|
|
struct net_buf_simple *msg = NULL;
|
|
u8_t zero[5] = {0};
|
|
u8_t length = 1 + 10;
|
|
|
|
if (ctx == NULL && publish == false) {
|
|
BT_ERR("%s, Invalid parameter", __func__);
|
|
return;
|
|
}
|
|
|
|
if (publish == false) {
|
|
msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
|
|
if (msg == NULL) {
|
|
BT_ERR("%s, Failed to allocate memory", __func__);
|
|
return;
|
|
}
|
|
} else {
|
|
msg = bt_mesh_server_get_pub_msg(model, length);
|
|
if (msg == NULL) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
bt_mesh_model_msg_init(msg, opcode);
|
|
switch (opcode) {
|
|
case BLE_MESH_MODEL_OP_TIME_STATUS:
|
|
if (model->id == BLE_MESH_MODEL_ID_TIME_SRV) {
|
|
struct bt_mesh_time_srv *srv = model->user_data;
|
|
net_buf_simple_add_mem(msg, srv->state->time.tai_seconds, TAI_SECONDS_LEN);
|
|
if (memcmp(srv->state->time.tai_seconds, zero, TAI_SECONDS_LEN)) {
|
|
net_buf_simple_add_u8(msg, srv->state->time.subsecond);
|
|
/**
|
|
* Set the Uncertainty field to a value that is a sum of the value of
|
|
* the Uncertainty state and an estimated time it will take the message
|
|
* to be processed before being sent on the radio interface.
|
|
*
|
|
* TODO: how to estimate the processing time?
|
|
*/
|
|
net_buf_simple_add_u8(msg, srv->state->time.uncertainty);
|
|
net_buf_simple_add_le16(msg,
|
|
(srv->state->time.tai_utc_delta_curr << 1) | srv->state->time.time_authority);
|
|
net_buf_simple_add_u8(msg, srv->state->time.time_zone_offset_curr);
|
|
}
|
|
} else if (model->id == BLE_MESH_MODEL_ID_TIME_SETUP_SRV) {
|
|
struct bt_mesh_time_setup_srv *srv = model->user_data;
|
|
net_buf_simple_add_mem(msg, srv->state->time.tai_seconds, TAI_SECONDS_LEN);
|
|
if (memcmp(srv->state->time.tai_seconds, zero, TAI_SECONDS_LEN)) {
|
|
net_buf_simple_add_u8(msg, srv->state->time.subsecond);
|
|
net_buf_simple_add_u8(msg, srv->state->time.uncertainty);
|
|
net_buf_simple_add_le16(msg,
|
|
(srv->state->time.tai_utc_delta_curr << 1) | srv->state->time.time_authority);
|
|
net_buf_simple_add_u8(msg, srv->state->time.time_zone_offset_curr);
|
|
}
|
|
}
|
|
break;
|
|
case BLE_MESH_MODEL_OP_TIME_ZONE_STATUS:
|
|
if (model->id == BLE_MESH_MODEL_ID_TIME_SRV) {
|
|
struct bt_mesh_time_srv *srv = model->user_data;
|
|
net_buf_simple_add_u8(msg, srv->state->time.time_zone_offset_curr);
|
|
net_buf_simple_add_u8(msg, srv->state->time.time_zone_offset_new);
|
|
net_buf_simple_add_mem(msg, srv->state->time.tai_zone_change, TAI_OF_ZONE_CHANGE_LEN);
|
|
} else if (model->id == BLE_MESH_MODEL_ID_TIME_SETUP_SRV) {
|
|
struct bt_mesh_time_setup_srv *srv = model->user_data;
|
|
net_buf_simple_add_u8(msg, srv->state->time.time_zone_offset_curr);
|
|
net_buf_simple_add_u8(msg, srv->state->time.time_zone_offset_new);
|
|
net_buf_simple_add_mem(msg, srv->state->time.tai_zone_change, TAI_OF_ZONE_CHANGE_LEN);
|
|
}
|
|
break;
|
|
case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS:
|
|
if (model->id == BLE_MESH_MODEL_ID_TIME_SRV) {
|
|
struct bt_mesh_time_srv *srv = model->user_data;
|
|
net_buf_simple_add_le16(msg, srv->state->time.tai_utc_delta_curr);
|
|
net_buf_simple_add_le16(msg, srv->state->time.tai_utc_delta_new);
|
|
net_buf_simple_add_mem(msg, srv->state->time.tai_delta_change, TAI_OF_DELTA_CHANGE_LEN);
|
|
} else if (model->id == BLE_MESH_MODEL_ID_TIME_SETUP_SRV) {
|
|
struct bt_mesh_time_setup_srv *srv = model->user_data;
|
|
net_buf_simple_add_le16(msg, srv->state->time.tai_utc_delta_curr);
|
|
net_buf_simple_add_le16(msg, srv->state->time.tai_utc_delta_new);
|
|
net_buf_simple_add_mem(msg, srv->state->time.tai_delta_change, TAI_OF_DELTA_CHANGE_LEN);
|
|
}
|
|
break;
|
|
case BLE_MESH_MODEL_OP_TIME_ROLE_STATUS: {
|
|
struct bt_mesh_time_setup_srv *srv = model->user_data;
|
|
net_buf_simple_add_u8(msg, srv->state->time_role);
|
|
break;
|
|
}
|
|
default:
|
|
BT_WARN("%s, Unknown Time status opcode 0x%04x", __func__, opcode);
|
|
if (publish == false) {
|
|
bt_mesh_free_buf(msg);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (publish == false) {
|
|
BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
|
|
bt_mesh_free_buf(msg);
|
|
} else {
|
|
BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void time_get(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct bt_mesh_server_rsp_ctrl *rsp_ctrl = NULL;
|
|
u8_t zero[5] = {0};
|
|
u16_t opcode = 0U, val = 0U;
|
|
u8_t prev_ttl = 0U;
|
|
|
|
if (model->user_data == NULL) {
|
|
BT_ERR("%s, Invalid model user_data", __func__);
|
|
return;
|
|
}
|
|
|
|
switch (model->id) {
|
|
case BLE_MESH_MODEL_ID_TIME_SRV: {
|
|
struct bt_mesh_time_srv *srv = model->user_data;
|
|
if (srv->state == NULL) {
|
|
BT_ERR("%s, Invalid Time Server state", __func__);
|
|
return;
|
|
}
|
|
rsp_ctrl = &srv->rsp_ctrl;
|
|
break;
|
|
}
|
|
case BLE_MESH_MODEL_ID_TIME_SETUP_SRV: {
|
|
struct bt_mesh_time_setup_srv *srv = model->user_data;
|
|
if (srv->state == NULL) {
|
|
BT_ERR("%s, Invalid Time Setup Server state", __func__);
|
|
return;
|
|
}
|
|
rsp_ctrl = &srv->rsp_ctrl;
|
|
break;
|
|
}
|
|
default:
|
|
BT_ERR("%s, Invalid Time Server 0x%04x", __func__, model->id);
|
|
return;
|
|
}
|
|
|
|
if (rsp_ctrl->get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
|
|
if (ctx->recv_op != BLE_MESH_MODEL_OP_TIME_STATUS) {
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_GET_MSG, model, ctx, NULL, 0);
|
|
return;
|
|
}
|
|
}
|
|
|
|
switch (ctx->recv_op) {
|
|
case BLE_MESH_MODEL_OP_TIME_GET:
|
|
opcode = BLE_MESH_MODEL_OP_TIME_STATUS;
|
|
break;
|
|
case BLE_MESH_MODEL_OP_TIME_STATUS: {
|
|
struct bt_mesh_time_srv *srv = model->user_data;
|
|
if (srv->state == NULL) {
|
|
BT_ERR("%s, Invalid Time Server state", __func__);
|
|
return;
|
|
}
|
|
if (srv->state->time_role != TIME_RELAY &&
|
|
srv->state->time_role != TIME_CLINET) {
|
|
/**
|
|
* If the value of the Time Role state of the element is 0x00 (None) or
|
|
* 0x01 (Time Authority), the message shall be ignored.
|
|
*/
|
|
return;
|
|
}
|
|
if (rsp_ctrl->status_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
|
|
bt_mesh_time_scene_server_recv_status_msg_t status = {0};
|
|
memcpy(status.time_status.tai_seconds, buf->data, TAI_SECONDS_LEN);
|
|
net_buf_simple_pull(buf, TAI_SECONDS_LEN);
|
|
if (memcmp(status.time_status.tai_seconds, zero, TAI_SECONDS_LEN)) {
|
|
if (buf->len != TAI_SECONDS_LEN) {
|
|
BT_ERR("%s, Invalid Time Status length %d", __func__, buf->len + TAI_SECONDS_LEN);
|
|
return;
|
|
}
|
|
status.time_status.subsecond = net_buf_simple_pull_u8(buf);
|
|
status.time_status.uncertainty = net_buf_simple_pull_u8(buf);
|
|
val = net_buf_simple_pull_le16(buf);
|
|
status.time_status.time_authority = val & BIT(0);
|
|
status.time_status.tai_utc_delta = (val >> 1) & BIT_MASK(15);
|
|
status.time_status.time_zone_offset = net_buf_simple_pull_u8(buf);
|
|
}
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_STATUS_MSG, model, ctx, (const u8_t *)&status, sizeof(status));
|
|
return;
|
|
}
|
|
memcpy(srv->state->time.tai_seconds, buf->data, TAI_SECONDS_LEN);
|
|
net_buf_simple_pull(buf, TAI_SECONDS_LEN);
|
|
/**
|
|
* If the TAI Seconds field is 0x0000000000 the Subsecond, Uncertainty,
|
|
* Time Authority, TAI-UTC Delta and Time Zone Offset fields shall be
|
|
* omitted; otherwise these fields shall be present.
|
|
*/
|
|
if (memcmp(srv->state->time.tai_seconds, zero, TAI_SECONDS_LEN)) {
|
|
if (buf->len != TAI_SECONDS_LEN) {
|
|
BT_ERR("%s, Invalid Time Status length %d", __func__, buf->len + TAI_SECONDS_LEN);
|
|
return;
|
|
}
|
|
srv->state->time.subsecond = net_buf_simple_pull_u8(buf);
|
|
srv->state->time.uncertainty = net_buf_simple_pull_u8(buf);
|
|
val = net_buf_simple_pull_le16(buf);
|
|
srv->state->time.tai_utc_delta_curr = (val >> 1) & BIT_MASK(15);
|
|
srv->state->time.time_zone_offset_curr = net_buf_simple_pull_u8(buf);
|
|
}
|
|
|
|
bt_mesh_time_scene_server_state_change_t change = {0};
|
|
memcpy(change.time_status.tai_seconds, srv->state->time.tai_seconds, TAI_SECONDS_LEN);
|
|
change.time_status.subsecond = srv->state->time.subsecond;
|
|
change.time_status.uncertainty = srv->state->time.uncertainty;
|
|
change.time_status.time_authority = srv->state->time.time_authority;
|
|
change.time_status.tai_utc_delta_curr = srv->state->time.subsecond;
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change));
|
|
|
|
if (model->pub == NULL || model->pub->msg == NULL ||
|
|
model->pub->addr == BLE_MESH_ADDR_UNASSIGNED) {
|
|
return;
|
|
}
|
|
prev_ttl = model->pub->ttl;
|
|
if (srv->state->time_role == TIME_RELAY) {
|
|
/**
|
|
* Shall publish a Time Status message using TTL = 0 if the value of the
|
|
* Time Role state is 0x02 (Time Relay) and the Publish Address for the
|
|
* Time Server model is not set to unassigned address.
|
|
*/
|
|
model->pub->ttl = 0U;
|
|
}
|
|
send_time_status(model, NULL, true, BLE_MESH_MODEL_OP_TIME_STATUS);
|
|
/* Restore model publication ttl value */
|
|
model->pub->ttl = prev_ttl;
|
|
return;
|
|
}
|
|
case BLE_MESH_MODEL_OP_TIME_ZONE_GET:
|
|
opcode = BLE_MESH_MODEL_OP_TIME_ZONE_STATUS;
|
|
break;
|
|
case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_GET:
|
|
opcode = BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS;
|
|
break;
|
|
case BLE_MESH_MODEL_OP_TIME_ROLE_GET:
|
|
opcode = BLE_MESH_MODEL_OP_TIME_ROLE_STATUS;
|
|
break;
|
|
default:
|
|
BT_WARN("%s, Unknown Time Get opcode 0x%04x", __func__, ctx->recv_op);
|
|
return;
|
|
}
|
|
|
|
send_time_status(model, ctx, false, opcode);
|
|
return;
|
|
}
|
|
|
|
static void time_set(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct bt_mesh_time_setup_srv *srv = model->user_data;
|
|
bt_mesh_time_scene_server_state_change_t change = {0};
|
|
u16_t opcode = 0U, val = 0U;
|
|
u8_t role = 0U;
|
|
|
|
if (srv == NULL || srv->state == NULL) {
|
|
BT_ERR("%s, Invalid model user_data", __func__);
|
|
return;
|
|
}
|
|
|
|
switch (ctx->recv_op) {
|
|
case BLE_MESH_MODEL_OP_TIME_SET:
|
|
if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
|
|
bt_mesh_time_scene_server_recv_set_msg_t set = {0};
|
|
memcpy(set.time_set.tai_seconds, buf->data, TAI_SECONDS_LEN);
|
|
net_buf_simple_pull(buf, TAI_SECONDS_LEN);
|
|
set.time_set.subsecond = net_buf_simple_pull_u8(buf);
|
|
set.time_set.uncertainty = net_buf_simple_pull_u8(buf);
|
|
val = net_buf_simple_pull_le16(buf);
|
|
set.time_set.time_authority = val & BIT(0);
|
|
set.time_set.tai_utc_delta = (val >> 1) & BIT_MASK(15);
|
|
set.time_set.time_zone_offset = net_buf_simple_pull_u8(buf);
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set));
|
|
return;
|
|
}
|
|
memcpy(srv->state->time.tai_seconds, buf->data, TAI_SECONDS_LEN);
|
|
net_buf_simple_pull(buf, TAI_SECONDS_LEN);
|
|
srv->state->time.subsecond = net_buf_simple_pull_u8(buf);
|
|
srv->state->time.uncertainty = net_buf_simple_pull_u8(buf);
|
|
val = net_buf_simple_pull_le16(buf);
|
|
srv->state->time.time_authority = val & BIT(0);
|
|
srv->state->time.tai_utc_delta_curr = (val >> 1) & BIT_MASK(15);
|
|
srv->state->time.time_zone_offset_curr = net_buf_simple_pull_u8(buf);
|
|
opcode = BLE_MESH_MODEL_OP_TIME_STATUS;
|
|
break;
|
|
case BLE_MESH_MODEL_OP_TIME_ZONE_SET:
|
|
if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
|
|
bt_mesh_time_scene_server_recv_set_msg_t set = {0};
|
|
set.time_zone_set.time_zone_offset_new = net_buf_simple_pull_u8(buf);
|
|
memcpy(set.time_zone_set.tai_zone_change, buf->data, TAI_OF_ZONE_CHANGE_LEN);
|
|
net_buf_simple_pull(buf, TAI_OF_ZONE_CHANGE_LEN);
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set));
|
|
return;
|
|
}
|
|
srv->state->time.time_zone_offset_new = net_buf_simple_pull_u8(buf);
|
|
memcpy(srv->state->time.tai_zone_change, buf->data, TAI_OF_ZONE_CHANGE_LEN);
|
|
net_buf_simple_pull(buf, TAI_OF_ZONE_CHANGE_LEN);
|
|
opcode = BLE_MESH_MODEL_OP_TIME_ZONE_STATUS;
|
|
break;
|
|
case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET:
|
|
val = net_buf_simple_pull_le16(buf);
|
|
if ((val >> 15) & BIT(0)) {
|
|
BT_ERR("%s, Invalid Padding value 1", __func__);
|
|
return;
|
|
}
|
|
if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
|
|
bt_mesh_time_scene_server_recv_set_msg_t set = {0};
|
|
set.tai_utc_delta_set.tai_utc_delta_new = val & BIT_MASK(15);
|
|
memcpy(set.tai_utc_delta_set.tai_delta_change, buf->data, TAI_OF_DELTA_CHANGE_LEN);
|
|
net_buf_simple_pull(buf, TAI_OF_DELTA_CHANGE_LEN);
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set));
|
|
return;
|
|
}
|
|
srv->state->time.tai_utc_delta_new = val & BIT_MASK(15);
|
|
memcpy(srv->state->time.tai_delta_change, buf->data, TAI_OF_DELTA_CHANGE_LEN);
|
|
net_buf_simple_pull(buf, TAI_OF_DELTA_CHANGE_LEN);
|
|
opcode = BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS;
|
|
break;
|
|
case BLE_MESH_MODEL_OP_TIME_ROLE_SET:
|
|
role = net_buf_simple_pull_u8(buf);
|
|
if (role > TIME_CLINET) {
|
|
BT_ERR("%s, Invalid Time Role 0x%02x", __func__, role);
|
|
return;
|
|
}
|
|
if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
|
|
bt_mesh_time_scene_server_recv_set_msg_t set = {
|
|
.time_role_set.time_role = role,
|
|
};
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set));
|
|
return;
|
|
}
|
|
srv->state->time_role = role;
|
|
opcode = BLE_MESH_MODEL_OP_TIME_ROLE_STATUS;
|
|
break;
|
|
default:
|
|
BT_ERR("%s, Unknown Time Set opcode 0x%04x", __func__, ctx->recv_op);
|
|
return;
|
|
}
|
|
|
|
switch (ctx->recv_op) {
|
|
case BLE_MESH_MODEL_OP_TIME_SET:
|
|
memcpy(change.time_set.tai_seconds, srv->state->time.tai_seconds, TAI_SECONDS_LEN);
|
|
change.time_set.subsecond = srv->state->time.subsecond;
|
|
change.time_set.uncertainty = srv->state->time.uncertainty;
|
|
change.time_set.time_authority = srv->state->time.time_authority;
|
|
change.time_set.tai_utc_delta_curr = srv->state->time.subsecond;
|
|
break;
|
|
case BLE_MESH_MODEL_OP_TIME_ZONE_SET:
|
|
change.time_zone_set.time_zone_offset_new = srv->state->time.time_zone_offset_new;
|
|
memcpy(change.time_zone_set.tai_zone_change, srv->state->time.tai_zone_change, TAI_OF_ZONE_CHANGE_LEN);
|
|
break;
|
|
case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET:
|
|
change.tai_utc_delta_set.tai_utc_delta_new = srv->state->time.tai_utc_delta_new;
|
|
memcpy(change.tai_utc_delta_set.tai_delta_change, srv->state->time.tai_delta_change, TAI_OF_DELTA_CHANGE_LEN);
|
|
break;
|
|
case BLE_MESH_MODEL_OP_TIME_ROLE_SET:
|
|
change.time_role_set.role = srv->state->time_role;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change));
|
|
|
|
/* Send corresponding time status message */
|
|
send_time_status(model, ctx, false, opcode);
|
|
return;
|
|
}
|
|
|
|
/* Scene Server & Scene Setup Server message handlers */
|
|
static void send_scene_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
bool publish)
|
|
{
|
|
struct bt_mesh_scene_srv *srv = model->user_data;
|
|
struct net_buf_simple *msg = NULL;
|
|
u8_t length = 1 + 6;
|
|
|
|
if (publish == false) {
|
|
msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
|
|
if (msg == NULL) {
|
|
BT_ERR("%s, Failed to allocate memory", __func__);
|
|
return;
|
|
}
|
|
} else {
|
|
msg = bt_mesh_server_get_pub_msg(model, length);
|
|
if (msg == NULL) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_SCENE_STATUS);
|
|
/**
|
|
* If the message is sent as a reply to the Scene Recall message, the
|
|
* Status Code field identifies the result of the related operation;
|
|
* otherwise, the Status Code field shall be set to Success.
|
|
*/
|
|
if (ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_GET) {
|
|
net_buf_simple_add_u8(msg, SCENE_SUCCESS);
|
|
} else {
|
|
net_buf_simple_add_u8(msg, srv->state->status_code);
|
|
}
|
|
net_buf_simple_add_le16(msg, srv->state->current_scene);
|
|
/**
|
|
* When an element is in the process of changing the Scene state, the
|
|
* Target Scene field identifies the target Scene Number of the target
|
|
* Scene state the element is to reach.
|
|
* When an element is not in the process of changing the Scene state,
|
|
* the Target Scene field shall be omitted.
|
|
*/
|
|
if (srv->transition.counter) {
|
|
bt_mesh_server_calc_remain_time(&srv->transition);
|
|
net_buf_simple_add_le16(msg, srv->state->target_scene);
|
|
net_buf_simple_add_u8(msg, srv->transition.remain_time);
|
|
}
|
|
|
|
if (publish == false) {
|
|
BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
|
|
bt_mesh_free_buf(msg);
|
|
} else {
|
|
BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void send_scene_register_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
u8_t status_code, bool publish)
|
|
{
|
|
struct bt_mesh_scene_setup_srv *srv = model->user_data;
|
|
struct scene_register *scene = NULL;
|
|
struct net_buf_simple *msg = NULL;
|
|
u16_t total_len = 9U;
|
|
int i;
|
|
|
|
if (ctx == NULL && publish == false) {
|
|
BT_ERR("%s, Invalid parameter", __func__);
|
|
return;
|
|
}
|
|
|
|
if (publish == false) {
|
|
msg = bt_mesh_alloc_buf(MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN));
|
|
if (msg == NULL) {
|
|
BT_ERR("%s, Failed to allocate memory", __func__);
|
|
return;
|
|
}
|
|
} else {
|
|
msg = bt_mesh_server_get_pub_msg(model, 5);
|
|
if (msg == NULL) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS);
|
|
net_buf_simple_add_u8(msg, status_code);
|
|
net_buf_simple_add_le16(msg, srv->state->current_scene);
|
|
|
|
for (i = 0; i < srv->state->scene_count; i++) {
|
|
scene = &srv->state->scenes[i];
|
|
if (scene->scene_number != INVALID_SCENE_NUMBER) {
|
|
total_len += SCENE_NUMBER_LEN;
|
|
if ((publish == false && total_len > MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN)) ||
|
|
(publish == true && total_len > msg->size + BLE_MESH_SERVER_TRANS_MIC_SIZE)) {
|
|
/* Add this in case the message is too long */
|
|
break;
|
|
}
|
|
net_buf_simple_add_le16(msg, scene->scene_number);
|
|
}
|
|
}
|
|
|
|
if (publish == false) {
|
|
BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
|
|
bt_mesh_free_buf(msg);
|
|
} else {
|
|
BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void scene_get(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct bt_mesh_scene_srv *srv = model->user_data;
|
|
|
|
if (srv == NULL || srv->state == NULL) {
|
|
BT_ERR("%s, Invalid model user_data", __func__);
|
|
return;
|
|
}
|
|
|
|
if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_GET_MSG, model, ctx, NULL, 0);
|
|
return;
|
|
}
|
|
|
|
switch (ctx->recv_op) {
|
|
case BLE_MESH_MODEL_OP_SCENE_GET:
|
|
send_scene_status(model, ctx, false);
|
|
return;
|
|
case BLE_MESH_MODEL_OP_SCENE_REGISTER_GET:
|
|
/**
|
|
* When a Scene Server receives a Scene Register Get message, it shall
|
|
* respond with a Scene Register Status message, setting the Status
|
|
* Code field to Success.
|
|
*/
|
|
send_scene_register_status(model, ctx, SCENE_SUCCESS, false);
|
|
return;
|
|
default:
|
|
BT_WARN("%s, Unknown Scene Get opcode 0x%04x", __func__, ctx->recv_op);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void scene_publish(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, u16_t opcode)
|
|
{
|
|
struct bt_mesh_scene_srv *srv = model->user_data;
|
|
|
|
if (srv == NULL || srv->state == NULL) {
|
|
BT_ERR("%s, Invalid model user_data", __func__);
|
|
return;
|
|
}
|
|
|
|
send_scene_status(model, ctx, true);
|
|
return;
|
|
}
|
|
|
|
static void scene_recall(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct bt_mesh_scene_srv *srv = model->user_data;
|
|
struct scene_register *scene = NULL;
|
|
u8_t tid = 0U, trans_time = 0U, delay = 0U;
|
|
u16_t scene_number = 0U;
|
|
bool optional = false;
|
|
s64_t now = 0;
|
|
int i;
|
|
|
|
if (srv == NULL || srv->state == NULL) {
|
|
BT_ERR("%s, Invalid model user_data", __func__);
|
|
return;
|
|
}
|
|
|
|
scene_number = net_buf_simple_pull_le16(buf);
|
|
if (scene_number == INVALID_SCENE_NUMBER) {
|
|
BT_ERR("%s, Invalid Scene Number 0x0000", __func__);
|
|
return;
|
|
}
|
|
tid = net_buf_simple_pull_u8(buf);
|
|
|
|
if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
|
|
return;
|
|
}
|
|
|
|
if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
|
|
bt_mesh_time_scene_server_recv_set_msg_t set = {
|
|
.scene_recall.op_en = optional,
|
|
.scene_recall.scene_number = scene_number,
|
|
.scene_recall.tid = tid,
|
|
.scene_recall.trans_time = trans_time,
|
|
.scene_recall.delay = delay,
|
|
};
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set));
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < srv->state->scene_count; i++) {
|
|
scene = &srv->state->scenes[i];
|
|
if (scene->scene_number == scene_number) {
|
|
break;
|
|
}
|
|
}
|
|
if (i == srv->state->scene_count) {
|
|
BT_WARN("%s, Scene Number 0x%04x not exist", __func__, scene_number);
|
|
srv->state->status_code = SCENE_NOT_FOUND;
|
|
if (ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_RECALL) {
|
|
send_scene_status(model, ctx, false);
|
|
}
|
|
send_scene_status(model, ctx, true);
|
|
return;
|
|
}
|
|
srv->state->status_code = SCENE_SUCCESS;
|
|
|
|
/* Mesh Model Spec doesn't mention about this operation. */
|
|
if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
|
|
if (ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_RECALL) {
|
|
send_scene_status(model, ctx, false);
|
|
}
|
|
send_scene_status(model, ctx, true);
|
|
/* In this condition, no event will be callback to application layer */
|
|
return;
|
|
}
|
|
|
|
bt_mesh_time_scene_server_lock();
|
|
|
|
bt_mesh_server_stop_transition(&srv->transition);
|
|
bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
|
|
|
|
srv->state->in_progress = false;
|
|
/**
|
|
* When the scene transition is not in progress, the value of the Target
|
|
* Scene state shall be set to 0x0000.
|
|
*/
|
|
srv->state->target_scene = INVALID_SCENE_NUMBER;
|
|
|
|
/**
|
|
* If the target state is equal to the current state, the transition
|
|
* shall not be started and is considered complete.
|
|
*/
|
|
if (srv->state->current_scene != scene_number) {
|
|
scene_tt_values(srv, trans_time, delay);
|
|
} else {
|
|
if (ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_RECALL) {
|
|
send_scene_status(model, ctx, false);
|
|
}
|
|
send_scene_status(model, ctx, true);
|
|
|
|
bt_mesh_time_scene_server_state_change_t change = {
|
|
.scene_recall.scene_number = scene_number,
|
|
};
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change));
|
|
|
|
bt_mesh_time_scene_server_unlock();
|
|
return;
|
|
}
|
|
|
|
/* Copy the ctx of the received message */
|
|
if (srv->transition.timer.work._reserved) {
|
|
memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx));
|
|
}
|
|
|
|
/* For Instantaneous Transition */
|
|
if (srv->transition.counter == 0U) {
|
|
srv->state->current_scene = scene_number;
|
|
} else {
|
|
/**
|
|
* When a scene transition is in progress, the value of the Current
|
|
* Scene state shall be set to 0x0000.
|
|
*/
|
|
srv->state->in_progress = true;
|
|
srv->state->current_scene = INVALID_SCENE_NUMBER;
|
|
srv->state->target_scene = scene_number;
|
|
}
|
|
|
|
srv->transition.just_started = true;
|
|
if (ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_RECALL) {
|
|
send_scene_status(model, ctx, false);
|
|
}
|
|
send_scene_status(model, ctx, true);
|
|
|
|
bt_mesh_time_scene_server_unlock();
|
|
|
|
bt_mesh_server_start_transition(&srv->transition);
|
|
return;
|
|
}
|
|
|
|
static void scene_action(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct bt_mesh_scene_setup_srv *srv = model->user_data;
|
|
struct scene_register *scene = NULL;
|
|
u16_t scene_number = 0U;
|
|
int i;
|
|
|
|
if (srv == NULL || srv->state == NULL) {
|
|
BT_ERR("%s, Invalid model user_data", __func__);
|
|
return;
|
|
}
|
|
|
|
scene_number = net_buf_simple_pull_le16(buf);
|
|
if (scene_number == INVALID_SCENE_NUMBER) {
|
|
BT_ERR("%s, Invalid Scene number 0x0000", __func__);
|
|
return;
|
|
}
|
|
|
|
switch (ctx->recv_op) {
|
|
case BLE_MESH_MODEL_OP_SCENE_STORE:
|
|
case BLE_MESH_MODEL_OP_SCENE_STORE_UNACK: {
|
|
if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
|
|
bt_mesh_time_scene_server_recv_set_msg_t set = {
|
|
.scene_store.scene_number = scene_number,
|
|
};
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set));
|
|
return;
|
|
}
|
|
/* Try to find a matching Scene Number */
|
|
for (i = 0; i < srv->state->scene_count; i++) {
|
|
scene = &srv->state->scenes[i];
|
|
if (scene->scene_number == scene_number) {
|
|
srv->state->status_code = SCENE_SUCCESS;
|
|
srv->state->current_scene = scene_number;
|
|
break;
|
|
}
|
|
}
|
|
/* Try to find a unset entry if no matching Scene Number is found */
|
|
if (i == srv->state->scene_count) {
|
|
BT_DBG("%s, No matching Scene Number 0x%04x found", __func__, scene_number);
|
|
for (i = 0; i < srv->state->scene_count; i++) {
|
|
scene = &srv->state->scenes[i];
|
|
if (scene->scene_number == INVALID_SCENE_NUMBER) {
|
|
scene->scene_number = scene_number;
|
|
srv->state->status_code = SCENE_SUCCESS;
|
|
srv->state->current_scene = scene_number;
|
|
break;
|
|
}
|
|
}
|
|
if (i == srv->state->scene_count) {
|
|
BT_WARN("%s, Scene Register full", __func__);
|
|
srv->state->status_code = SCENE_REG_FULL;
|
|
/* Get the Scene Number of the currently active scene */
|
|
for (i = 0; i < srv->state->scene_count; i++) {
|
|
scene = &srv->state->scenes[i];
|
|
if (scene->scene_number != INVALID_SCENE_NUMBER) {
|
|
srv->state->current_scene = scene->scene_number;
|
|
break;
|
|
}
|
|
}
|
|
if (i == srv->state->scene_count) {
|
|
/* A value of 0x0000 when no scene is active */
|
|
srv->state->current_scene = INVALID_SCENE_NUMBER;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (srv->state->in_progress == true) {
|
|
/**
|
|
* When the scene transition is in progress and a new Scene Number is
|
|
* stored in the Scene Register as a result of Scene Store operation,
|
|
* the Target Scene state shall be set to the new Scene Number.
|
|
*/
|
|
srv->state->target_scene = scene_number;
|
|
}
|
|
if (srv->state->status_code == SCENE_SUCCESS) {
|
|
bt_mesh_time_scene_server_state_change_t change = {
|
|
.scene_store.scene_number = scene_number,
|
|
};
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change));
|
|
}
|
|
break;
|
|
}
|
|
case BLE_MESH_MODEL_OP_SCENE_DELETE:
|
|
case BLE_MESH_MODEL_OP_SCENE_DELETE_UNACK: {
|
|
if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
|
|
bt_mesh_time_scene_server_recv_set_msg_t set = {
|
|
.scene_delete.scene_number = scene_number,
|
|
};
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set));
|
|
return;
|
|
}
|
|
for (i = 0; i < srv->state->scene_count; i++) {
|
|
scene = &srv->state->scenes[i];
|
|
if (scene->scene_number == scene_number) {
|
|
scene->scene_number = INVALID_SCENE_NUMBER;
|
|
break;
|
|
}
|
|
}
|
|
if (i == srv->state->scene_count) {
|
|
BT_WARN("%s, Scene Number 0x%04x not exist", __func__, scene_number);
|
|
/**
|
|
* When a Scene Server receives a Scene Delete message with the Scene
|
|
* Number value that does not match a Scene Number stored within the
|
|
* Scene Register state, it shall respond with the Scene Register
|
|
* Status message, setting the Status Code field to Success.
|
|
*/
|
|
}
|
|
srv->state->status_code = SCENE_SUCCESS;
|
|
if (srv->state->current_scene == scene_number) {
|
|
/**
|
|
* When the Current Scene Number is deleted from a Scene Register state
|
|
* as a result of Scene Delete operation, the Current Scene state shall
|
|
* be set to 0x0000.
|
|
*/
|
|
srv->state->current_scene = INVALID_SCENE_NUMBER;
|
|
} else {
|
|
/**
|
|
* MMDL/SR/SCES/BV-02-C requires response with Current Scene set to the
|
|
* latest Scene Number, but this is not mentioned in the spec.
|
|
*
|
|
* TODO: Do we need a timestamp for each newly added scene?
|
|
*/
|
|
for (i = srv->state->scene_count; i > 0; i--) {
|
|
scene = &srv->state->scenes[i - 1];
|
|
if (scene->scene_number != INVALID_SCENE_NUMBER) {
|
|
srv->state->current_scene = scene->scene_number;
|
|
break;
|
|
}
|
|
}
|
|
if (i == 0) {
|
|
/* A value of 0x0000 when no scene is active */
|
|
srv->state->current_scene = INVALID_SCENE_NUMBER;
|
|
}
|
|
}
|
|
|
|
if (srv->state->target_scene == scene_number &&
|
|
srv->state->in_progress == true) {
|
|
/**
|
|
* When the scene transition is in progress and the target Scene Number
|
|
* is deleted from a Scene Register state as a result of Scene Delete
|
|
* operation, the Target Scene state shall be set to 0x0000.
|
|
*/
|
|
srv->state->target_scene = INVALID_SCENE_NUMBER;
|
|
|
|
/**
|
|
* When a scene is deleted when a scene transition to the deleted Scene
|
|
* Number is in progress, the scene transition shall be terminated, but
|
|
* individual model transitions shall not be terminated.
|
|
*/
|
|
struct bt_mesh_scene_srv *scene_srv = NULL;
|
|
struct bt_mesh_model *scene_model = NULL;
|
|
|
|
scene_model = bt_mesh_model_find(bt_mesh_model_elem(model), BLE_MESH_MODEL_ID_SCENE_SRV);
|
|
if (scene_model == NULL) {
|
|
BT_ERR("%s, Scene Server is not present in the element", __func__);
|
|
break;
|
|
}
|
|
|
|
scene_srv = scene_model->user_data;
|
|
if (scene_srv == NULL || scene_srv->state == NULL) {
|
|
BT_ERR("%s, Invalid Scene Server parameter", __func__);
|
|
break;
|
|
}
|
|
|
|
if (srv->state != scene_srv->state) {
|
|
/**
|
|
* Add this in case the Scene Setup Server is extending the Scene
|
|
* Server in another element.
|
|
*/
|
|
BT_WARN("%s, Different Scene state in Scene Server & Scene Setup Server", __func__);
|
|
break;
|
|
}
|
|
|
|
scene_srv->state->in_progress = false;
|
|
bt_mesh_server_stop_transition(&scene_srv->transition);
|
|
}
|
|
|
|
bt_mesh_time_scene_server_state_change_t change = {
|
|
.scene_delete.scene_number = scene_number,
|
|
};
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change));
|
|
break;
|
|
}
|
|
default:
|
|
BT_ERR("%s, Unknown Scene setup action opcode 0x%04x", __func__, ctx->recv_op);
|
|
return;
|
|
}
|
|
|
|
if (ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_STORE ||
|
|
ctx->recv_op == BLE_MESH_MODEL_OP_SCENE_DELETE) {
|
|
send_scene_register_status(model, ctx, srv->state->status_code, false);
|
|
}
|
|
send_scene_register_status(model, NULL, srv->state->status_code, true);
|
|
|
|
return;
|
|
}
|
|
|
|
static u16_t get_schedule_reg_bit(struct bt_mesh_scheduler_state *state)
|
|
{
|
|
u16_t val = 0U;
|
|
int i;
|
|
|
|
for (i = 0; i < state->schedule_count; i++) {
|
|
if (state->schedules[i].in_use) {
|
|
val |= (1 << i);
|
|
}
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
static u64_t get_schedule_reg_state(struct bt_mesh_scheduler_state *state, u8_t index)
|
|
{
|
|
struct schedule_register *reg = &state->schedules[index];
|
|
u64_t val = 0U;
|
|
|
|
val = ((u64_t)(reg->year) << 4) | index;
|
|
val |= ((u64_t)(reg->day) << 23) | ((u64_t)(reg->month) << 11);
|
|
val |= ((u64_t)(reg->minute) << 33) | ((u64_t)(reg->hour) << 28);
|
|
val |= ((u64_t)(reg->day_of_week) << 45) | ((u64_t)(reg->second) << 39);
|
|
val |= ((u64_t)(reg->trans_time) << 56) | ((u64_t)(reg->action) << 52);
|
|
|
|
return val;
|
|
}
|
|
|
|
static void send_scheduler_act_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
u8_t index)
|
|
{
|
|
NET_BUF_SIMPLE_DEFINE(msg, 1 + 10 + BLE_MESH_SERVER_TRANS_MIC_SIZE);
|
|
u64_t value = 0U;
|
|
|
|
bt_mesh_model_msg_init(&msg, BLE_MESH_MODEL_OP_SCHEDULER_ACT_STATUS);
|
|
switch (model->id) {
|
|
case BLE_MESH_MODEL_ID_SCHEDULER_SRV: {
|
|
struct bt_mesh_scheduler_srv *srv = model->user_data;
|
|
value = get_schedule_reg_state(srv->state, index);
|
|
net_buf_simple_add_le32(&msg, (u32_t)value);
|
|
net_buf_simple_add_le32(&msg, (u32_t)(value >> 32));
|
|
net_buf_simple_add_le16(&msg, srv->state->schedules[index].scene_number);
|
|
break;
|
|
}
|
|
case BLE_MESH_MODEL_ID_SCHEDULER_SETUP_SRV: {
|
|
struct bt_mesh_scheduler_setup_srv *srv = model->user_data;
|
|
value = get_schedule_reg_state(srv->state, index);
|
|
net_buf_simple_add_le32(&msg, (u32_t)value);
|
|
net_buf_simple_add_le32(&msg, (u32_t)(value >> 32));
|
|
net_buf_simple_add_le16(&msg, srv->state->schedules[index].scene_number);
|
|
break;
|
|
}
|
|
default:
|
|
BT_ERR("%s, Invalid Scheduler Server 0x%04x", __func__, model->id);
|
|
return;
|
|
}
|
|
|
|
BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, &msg, NULL, NULL));
|
|
return;
|
|
}
|
|
|
|
static void scheduler_get(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
struct bt_mesh_scheduler_srv *srv = model->user_data;
|
|
NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + BLE_MESH_SERVER_TRANS_MIC_SIZE);
|
|
|
|
if (srv == NULL || srv->state == NULL) {
|
|
BT_ERR("%s, Invalid model user_data", __func__);
|
|
return;
|
|
}
|
|
|
|
switch (ctx->recv_op) {
|
|
case BLE_MESH_MODEL_OP_SCHEDULER_GET: {
|
|
if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_GET_MSG, model, ctx, NULL, 0);
|
|
return;
|
|
}
|
|
|
|
bt_mesh_model_msg_init(&msg, BLE_MESH_MODEL_OP_SCHEDULER_STATUS);
|
|
net_buf_simple_add_le16(&msg, get_schedule_reg_bit(srv->state));
|
|
BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, &msg, NULL, NULL));
|
|
return;
|
|
}
|
|
case BLE_MESH_MODEL_OP_SCHEDULER_ACT_GET: {
|
|
u8_t index = net_buf_simple_pull_u8(buf);
|
|
if (index > SCHEDULE_ENTRY_MAX_INDEX) {
|
|
BT_ERR("%s, Invalid Scheduler Register Entry index 0x%02x", __func__, index);
|
|
return;
|
|
}
|
|
|
|
if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
|
|
bt_mesh_time_scene_server_recv_get_msg_t get = {
|
|
.scheduler_act_get.index = index,
|
|
};
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_GET_MSG, model, ctx, (const u8_t *)&get, sizeof(get));
|
|
return;
|
|
}
|
|
|
|
send_scheduler_act_status(model, ctx, index);
|
|
return;
|
|
}
|
|
default:
|
|
BT_WARN("%s, Unknown Scheduler Get opcode 0x%04x", __func__, ctx->recv_op);
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void scheduler_act_set(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
/**
|
|
* A recommended implementation of the Scheduler should calculate the value
|
|
* of the TAI Seconds of the next scheduled event and put it in a queue of
|
|
* scheduled events sorted by time. Every second, the first event in the
|
|
* queue is compared with the value of the Time state. The first event is
|
|
* executed if it is less than or equal to the Time state and then removed
|
|
* from the queue. After execution, the Repeat Flag shall be checked, and
|
|
* the next occurrence of the scheduled event is calculated and put in the
|
|
* queue.
|
|
*/
|
|
struct bt_mesh_scheduler_setup_srv *srv = model->user_data;
|
|
u8_t index = 0U, year = 0U, day = 0U, hour = 0U, minute = 0U,
|
|
second = 0U, day_of_week = 0U, action = 0U, trans_time = 0U;
|
|
u16_t month = 0U, scene_number = 0U;
|
|
u64_t value = 0U;
|
|
|
|
if (srv == NULL || srv->state == NULL) {
|
|
BT_ERR("%s, Invalid model user_data", __func__);
|
|
return;
|
|
}
|
|
|
|
value = net_buf_simple_pull_le32(buf);
|
|
value |= ((u64_t)net_buf_simple_pull_le32(buf) << 32);
|
|
|
|
index = value & BIT_MASK(4);
|
|
year = (value >> 4) & BIT_MASK(7);
|
|
month = (value >> 11) & BIT_MASK(12);
|
|
day = (value >> 23) & BIT_MASK(5);
|
|
hour = (value >> 28) & BIT_MASK(5);
|
|
minute = (value >> 33) & BIT_MASK(6);
|
|
second = (value >> 39) & BIT_MASK(6);
|
|
day_of_week = (value >> 45) & BIT_MASK(7);
|
|
action = (value >> 52) & BIT_MASK(4);
|
|
trans_time = (value >> 56) & BIT_MASK(8);
|
|
|
|
if (index > SCHEDULE_ENTRY_MAX_INDEX) {
|
|
BT_ERR("%s, Invalid Scheduler Register Entry index 0x%02x", __func__, index);
|
|
return;
|
|
}
|
|
|
|
if (year > SCHEDULE_YEAR_ANY_YEAR) {
|
|
BT_ERR("%s, Invalid Scheduler Register year 0x%02x", __func__, year);
|
|
return;
|
|
}
|
|
|
|
if (hour > SCHEDULE_HOUR_ONCE_A_DAY) {
|
|
BT_ERR("%s, Invalid Scheduler Register hour 0x%02x", __func__, hour);
|
|
return;
|
|
}
|
|
|
|
if (action > SCHEDULE_ACT_SCENE_RECALL && action != SCHEDULE_ACT_NO_ACTION) {
|
|
BT_ERR("%s, Invalid Scheduler Register action 0x%02x", __func__, action);
|
|
return;
|
|
}
|
|
|
|
scene_number = net_buf_simple_pull_le16(buf);
|
|
|
|
if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
|
|
bt_mesh_time_scene_server_recv_set_msg_t set = {
|
|
.scheduler_act_set.index = index,
|
|
.scheduler_act_set.year = year,
|
|
.scheduler_act_set.month = month,
|
|
.scheduler_act_set.day = day,
|
|
.scheduler_act_set.hour = hour,
|
|
.scheduler_act_set.minute = minute,
|
|
.scheduler_act_set.second = second,
|
|
.scheduler_act_set.day_of_week = day_of_week,
|
|
.scheduler_act_set.action = action,
|
|
.scheduler_act_set.trans_time = trans_time,
|
|
.scheduler_act_set.scene_number = scene_number,
|
|
};
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_RECV_SET_MSG, model, ctx, (const u8_t *)&set, sizeof(set));
|
|
return;
|
|
}
|
|
|
|
srv->state->schedules[index].in_use = true;
|
|
srv->state->schedules[index].year = year;
|
|
srv->state->schedules[index].month = month;
|
|
srv->state->schedules[index].day = day;
|
|
srv->state->schedules[index].hour = hour;
|
|
srv->state->schedules[index].minute = minute;
|
|
srv->state->schedules[index].second = second;
|
|
srv->state->schedules[index].day_of_week = day_of_week;
|
|
srv->state->schedules[index].action = action;
|
|
srv->state->schedules[index].trans_time = trans_time;
|
|
srv->state->schedules[index].scene_number = scene_number;
|
|
|
|
bt_mesh_time_scene_server_state_change_t change = {
|
|
.scheduler_act_set.index = index,
|
|
.scheduler_act_set.year = year,
|
|
.scheduler_act_set.month = month,
|
|
.scheduler_act_set.day = day,
|
|
.scheduler_act_set.hour = hour,
|
|
.scheduler_act_set.minute = minute,
|
|
.scheduler_act_set.second = second,
|
|
.scheduler_act_set.day_of_week = day_of_week,
|
|
.scheduler_act_set.action = action,
|
|
.scheduler_act_set.trans_time = trans_time,
|
|
.scheduler_act_set.scene_number = scene_number,
|
|
};
|
|
bt_mesh_time_scene_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const u8_t *)&change, sizeof(change));
|
|
|
|
if (ctx->recv_op == BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET) {
|
|
send_scheduler_act_status(model, ctx, index);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* message handlers (End) */
|
|
|
|
/* Mapping of message handlers for Time Server (0x1200) */
|
|
const struct bt_mesh_model_op time_srv_op[] = {
|
|
{ BLE_MESH_MODEL_OP_TIME_GET, 0, time_get },
|
|
{ BLE_MESH_MODEL_OP_TIME_STATUS, 5, time_get },
|
|
{ BLE_MESH_MODEL_OP_TIME_ZONE_GET, 0, time_get },
|
|
{ BLE_MESH_MODEL_OP_TAI_UTC_DELTA_GET, 0, time_get },
|
|
BLE_MESH_MODEL_OP_END,
|
|
};
|
|
|
|
/* Mapping of message handlers for Time Setup Server (0x1201) */
|
|
const struct bt_mesh_model_op time_setup_srv_op[] = {
|
|
{ BLE_MESH_MODEL_OP_TIME_SET, 10, time_set },
|
|
{ BLE_MESH_MODEL_OP_TIME_ZONE_SET, 6, time_set },
|
|
{ BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET, 7, time_set },
|
|
{ BLE_MESH_MODEL_OP_TIME_ROLE_GET, 0, time_get },
|
|
{ BLE_MESH_MODEL_OP_TIME_ROLE_SET, 1, time_set },
|
|
BLE_MESH_MODEL_OP_END,
|
|
};
|
|
|
|
/* Mapping of message handlers for Scene Server (0x1203) */
|
|
const struct bt_mesh_model_op scene_srv_op[] = {
|
|
{ BLE_MESH_MODEL_OP_SCENE_GET, 0, scene_get },
|
|
{ BLE_MESH_MODEL_OP_SCENE_RECALL, 3, scene_recall },
|
|
{ BLE_MESH_MODEL_OP_SCENE_RECALL_UNACK, 3, scene_recall },
|
|
{ BLE_MESH_MODEL_OP_SCENE_REGISTER_GET, 0, scene_get },
|
|
BLE_MESH_MODEL_OP_END,
|
|
};
|
|
|
|
/* Mapping of message handlers for Scene Setup Server (0x1204) */
|
|
const struct bt_mesh_model_op scene_setup_srv_op[] = {
|
|
{ BLE_MESH_MODEL_OP_SCENE_STORE, 2, scene_action },
|
|
{ BLE_MESH_MODEL_OP_SCENE_STORE_UNACK, 2, scene_action },
|
|
{ BLE_MESH_MODEL_OP_SCENE_DELETE, 2, scene_action },
|
|
{ BLE_MESH_MODEL_OP_SCENE_DELETE_UNACK, 2, scene_action },
|
|
BLE_MESH_MODEL_OP_END,
|
|
};
|
|
|
|
/* Mapping of message handlers for Scheduler Server (0x1206) */
|
|
const struct bt_mesh_model_op scheduler_srv_op[] = {
|
|
{ BLE_MESH_MODEL_OP_SCHEDULER_GET, 0, scheduler_get },
|
|
{ BLE_MESH_MODEL_OP_SCHEDULER_ACT_GET, 1, scheduler_get },
|
|
BLE_MESH_MODEL_OP_END,
|
|
};
|
|
|
|
/* Mapping of message handlers for Scheduler Setup Server (0x1207) */
|
|
const struct bt_mesh_model_op scheduler_setup_srv_op[] = {
|
|
{ BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET, 10, scheduler_act_set },
|
|
{ BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET_UNACK, 10, scheduler_act_set },
|
|
BLE_MESH_MODEL_OP_END,
|
|
};
|
|
|
|
static int check_scene_server_init(struct bt_mesh_scenes_state *state)
|
|
{
|
|
int i;
|
|
|
|
if (state->scene_count == 0U || state->scenes == NULL) {
|
|
BT_ERR("%s, Invalid Scene state", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (i = 0; i < state->scene_count; i++) {
|
|
if (state->scenes[i].scene_value == NULL) {
|
|
BT_ERR("%s, Invalid Scene value, index %d", __func__, i);
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int time_scene_server_init(struct bt_mesh_model *model)
|
|
{
|
|
if (model->user_data == NULL) {
|
|
BT_ERR("%s, No Time Scene Server context provided, model_id 0x%04x", __func__, model->id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch (model->id) {
|
|
case BLE_MESH_MODEL_ID_TIME_SRV: {
|
|
struct bt_mesh_time_srv *srv = model->user_data;
|
|
if (srv->state == NULL) {
|
|
BT_ERR("%s, NULL Time State", __func__);
|
|
return -EINVAL;
|
|
}
|
|
srv->model = model;
|
|
break;
|
|
}
|
|
case BLE_MESH_MODEL_ID_TIME_SETUP_SRV: {
|
|
struct bt_mesh_time_setup_srv *srv = model->user_data;
|
|
if (srv->state == NULL) {
|
|
BT_ERR("%s, NULL Time State", __func__);
|
|
return -EINVAL;
|
|
}
|
|
srv->model = model;
|
|
break;
|
|
}
|
|
case BLE_MESH_MODEL_ID_SCENE_SRV: {
|
|
struct bt_mesh_scene_srv *srv = model->user_data;
|
|
if (srv->state == NULL) {
|
|
BT_ERR("%s, NULL Scene State", __func__);
|
|
return -EINVAL;
|
|
}
|
|
if (check_scene_server_init(srv->state)) {
|
|
return -EINVAL;
|
|
}
|
|
if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
|
|
bt_mesh_server_alloc_ctx(&srv->transition.timer.work);
|
|
k_delayed_work_init(&srv->transition.timer, scene_recall_work_handler);
|
|
}
|
|
srv->model = model;
|
|
break;
|
|
}
|
|
case BLE_MESH_MODEL_ID_SCENE_SETUP_SRV: {
|
|
struct bt_mesh_scene_setup_srv *srv = model->user_data;
|
|
if (srv->state == NULL) {
|
|
BT_ERR("%s, NULL Scene State", __func__);
|
|
return -EINVAL;
|
|
}
|
|
if (check_scene_server_init(srv->state)) {
|
|
return -EINVAL;
|
|
}
|
|
srv->model = model;
|
|
break;
|
|
}
|
|
case BLE_MESH_MODEL_ID_SCHEDULER_SRV: {
|
|
struct bt_mesh_scheduler_srv *srv = model->user_data;
|
|
if (srv->state == NULL) {
|
|
BT_ERR("%s, NULL Scheduler State", __func__);
|
|
return -EINVAL;
|
|
}
|
|
if (srv->state->schedule_count == 0U || srv->state->schedules == NULL) {
|
|
BT_ERR("%s, NULL Register Schedule", __func__);
|
|
return -EINVAL;
|
|
}
|
|
srv->model = model;
|
|
break;
|
|
}
|
|
case BLE_MESH_MODEL_ID_SCHEDULER_SETUP_SRV: {
|
|
struct bt_mesh_scheduler_setup_srv *srv = model->user_data;
|
|
if (srv->state == NULL) {
|
|
BT_ERR("%s, NULL Scheduler State", __func__);
|
|
return -EINVAL;
|
|
}
|
|
if (srv->state->schedule_count == 0U || srv->state->schedules == NULL) {
|
|
BT_ERR("%s, NULL Register Schedule", __func__);
|
|
return -EINVAL;
|
|
}
|
|
srv->model = model;
|
|
break;
|
|
}
|
|
default:
|
|
BT_WARN("%s, Unknown Time Scene Server Model, model_id 0x%04x", __func__, model->id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
bt_mesh_time_scene_server_mutex_new();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int bt_mesh_time_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Time Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
/**
|
|
* When this model is present on an Element, the corresponding Time Setup
|
|
* Server model shall also be present.
|
|
*/
|
|
struct bt_mesh_elem *element = bt_mesh_model_elem(model);
|
|
if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_TIME_SETUP_SRV) == NULL) {
|
|
BT_WARN("%s, Time Setup Server is not present", __func__);
|
|
/* Just give a warning here, continue with the initialization */
|
|
}
|
|
return time_scene_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_time_setup_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
/* This model does not support subscribing nor publishing */
|
|
if (model->pub) {
|
|
BT_ERR("%s, Time Setup Server shall not support publication", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return time_scene_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_scene_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Scene Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* The model may be present only on the Primary element of a node. */
|
|
if (primary == false) {
|
|
BT_WARN("%s, Scene Server is not on the Primary element", __func__);
|
|
/* Just give a warning here, continue with the initialization */
|
|
}
|
|
/**
|
|
* When this model is present on an Element, the corresponding Scene Setup
|
|
* Server model shall also be present.
|
|
*/
|
|
struct bt_mesh_elem *element = bt_mesh_model_elem(model);
|
|
if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_SCENE_SETUP_SRV) == NULL) {
|
|
BT_WARN("%s, Scene Setup Server is not present", __func__);
|
|
/* Just give a warning here, continue with the initialization */
|
|
}
|
|
return time_scene_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_scene_setup_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
/* The model may be present only on the Primary element of a node. */
|
|
if (primary == false) {
|
|
BT_WARN("%s, Scene Setup Server is not on the Primary element", __func__);
|
|
/* Just give a warning here, continue with the initialization */
|
|
}
|
|
return time_scene_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_scheduler_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Scheduler Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* The model may be present only on the Primary element of a node. */
|
|
if (primary == false) {
|
|
BT_WARN("%s, Scheduler Server is not on the Primary element", __func__);
|
|
/* Just give a warning here, continue with the initialization */
|
|
}
|
|
/**
|
|
* When this model is present on an Element, the corresponding Scheduler
|
|
* Setup Server model shall also be present. The model requires the Time
|
|
* Server model shall be present on the element.
|
|
*/
|
|
struct bt_mesh_elem *element = bt_mesh_model_elem(model);
|
|
if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_SCHEDULER_SETUP_SRV) == NULL) {
|
|
BT_WARN("%s, Scheduler Setup Server is not present", __func__);
|
|
/* Just give a warning here, continue with the initialization */
|
|
}
|
|
if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_TIME_SRV) == NULL) {
|
|
BT_WARN("%s, Time Server is not present", __func__);
|
|
/* Just give a warning here, continue with the initialization */
|
|
}
|
|
return time_scene_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_scheduler_setup_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
/* The model may be present only on the Primary element of a node. */
|
|
if (primary == false) {
|
|
BT_WARN("%s, Scheduler Setup Server is not on the Primary element", __func__);
|
|
/* Just give a warning here, continue with the initialization */
|
|
}
|
|
return time_scene_server_init(model);
|
|
}
|
|
|
|
static int time_scene_server_deinit(struct bt_mesh_model *model)
|
|
{
|
|
if (model->user_data == NULL) {
|
|
BT_ERR("%s, No Time Scene Server context provided, model_id 0x%04x", __func__, model->id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch (model->id) {
|
|
case BLE_MESH_MODEL_ID_SCENE_SRV: {
|
|
struct bt_mesh_scene_srv *srv = model->user_data;
|
|
if (srv->state == NULL) {
|
|
BT_ERR("%s, NULL Scene State", __func__);
|
|
return -EINVAL;
|
|
}
|
|
if (check_scene_server_init(srv->state)) {
|
|
return -EINVAL;
|
|
}
|
|
if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
|
|
bt_mesh_server_free_ctx(&srv->transition.timer.work);
|
|
k_delayed_work_free(&srv->transition.timer);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
BT_WARN("%s, Unknown Time Scene Server Model, model_id 0x%04x", __func__, model->id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
bt_mesh_time_scene_server_mutex_free();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int bt_mesh_time_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Time Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return time_scene_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_time_setup_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub) {
|
|
BT_ERR("%s, Time Setup Server shall not support publication", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return time_scene_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_scene_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Scene Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return time_scene_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_scene_setup_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
return time_scene_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_scheduler_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Scheduler Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return time_scene_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_scheduler_setup_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
return time_scene_server_deinit(model);
|
|
}
|