OVMS3-idf/components/bt/esp_ble_mesh/mesh_models/server/server_common.c
lly 7cd08b5824 ble_mesh: Miscellaneous modifications
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
2020-02-26 17:37:44 +08:00

258 lines
8.8 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 "mesh.h"
#include "access.h"
#include "mesh_common.h"
#include "generic_server.h"
#include "lighting_server.h"
/**
* According to Mesh Model Spec:
* If the Transition Time field is not present and the Generic Default Transition
* Time state is supported, the Generic Default Transition Time state shall be
* used. Otherwise the transition shall be instantaneous.
*/
#define INSTANTANEOUS_TRANS_TIME 0
u8_t bt_mesh_get_default_trans_time(struct bt_mesh_model *model)
{
/**
* 1. If a Generic Default Transition Time Server model is present on the
* main element of the model, that model instance shall be used.
* 2. If a Generic Default Transition Time Server model is not present on
* the main element of the model, then the Generic Default Transition
* Time Server model instance that is present on the element with the
* largest address that is smaller than the address of the main element
* of the node shall be used; if no model instance is present on any
* element with an address smaller than the address of the main element,
* then the Generic Default Transition Time Server is not supported.
*/
struct bt_mesh_elem *element = bt_mesh_model_elem(model);
struct bt_mesh_gen_def_trans_time_srv *state = NULL;
u16_t primary_addr = bt_mesh_primary_addr();
struct bt_mesh_model *srv = NULL;
for (u16_t addr = element->addr; addr >= primary_addr; addr--) {
element = bt_mesh_elem_find(addr);
if (element) {
srv = bt_mesh_model_find(element, BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV);
if (srv) {
state = (struct bt_mesh_gen_def_trans_time_srv *)srv->user_data;
if (state) {
return state->state.trans_time;
}
}
}
}
return INSTANTANEOUS_TRANS_TIME;
}
int bt_mesh_get_light_lc_trans_time(struct bt_mesh_model *model, u8_t *trans_time)
{
struct bt_mesh_light_lc_srv *srv = NULL;
u32_t value = 0U;
if (model == NULL || trans_time == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
if (model->id != BLE_MESH_MODEL_ID_LIGHT_LC_SRV) {
BT_ERR("%s, Not a Light LC Server", __func__);
return -EINVAL;
}
srv = (struct bt_mesh_light_lc_srv *)model->user_data;
if (srv == NULL) {
BT_ERR("%s, Invalid Light LC Server user_data", __func__);
return -EINVAL;
}
/**
* 1. Set transition time to 0x54 for BQB test case MESH/SR/LLC/BV-04-C.
* Light LC Property Set: 0x3C, 0x004E20 -> Light LC Time Run On
* Light LC Property Set: 0x37, 0x004E20 -> Light LC Time Fade On
* Light LC Property Set: 0x39, 0x004E20 -> Light LC Time Fade Standby Manual
*
* 2. Set transition time to 0x0 for BQB test case MESH/SR/LLC/BV-08-C.
*
* TODO: Based on Light LC state and choose property property value as the
* transition time. Currently directly use Light LC Time Run On property value.
* Unit: Millisecond, range: [0, 16777214(0xFFFFFE)]
*/
value = srv->lc->prop_state.time_run_on & 0xFFFFFF;
/**
* Convert value into Default Transition Time state format.
* 0b00: 0 ~ 6.2s, 100 millisecond step resolution
* 0b01: 0 ~ 62s, 1 second step resolution
* 0b10: 0 ~ 620s, 10 seconds step resolution
* 0b11: 0 ~ 620m, 10 minutes step resolution
*/
if (value <= 6200) {
*trans_time = (0 << 6) | (value / 100);
} else if (value <= 62000) {
*trans_time = (1 << 6) | (value / 1000);
} else if (value <= 620000) {
*trans_time = (2 << 6) | (value / 10000);
} else {
*trans_time = (3 << 6) | (value / 600000);
}
return 0;
}
int bt_mesh_server_get_optional(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf,
u8_t *trans_time, u8_t *delay,
bool *optional)
{
if (model == NULL || buf == NULL || trans_time == NULL ||
delay == NULL || optional == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
if (buf->len != 0x00 && buf->len != 0x02) {
BT_ERR("%s, Invalid optional message length %d", __func__, buf->len);
return -EINVAL;
}
/* Currently we only get optional msg info which dst is set to a unicast address */
if (!BLE_MESH_ADDR_IS_UNICAST(ctx->recv_dst)) {
*trans_time = 0U;
*delay = 0U;
*optional = false;
return 0;
}
/* No optional fields are available */
if (buf->len == 0x00) {
if (model->id == BLE_MESH_MODEL_ID_LIGHT_LC_SRV) {
/**
* Both messages(i.e. Light LC OnOff Set/Set Unack) may optionally include
* a Transition Time field indicating the transition time to the target state.
* If the Transition Time is not included, the Light LC Server shall use
* its appropriate transition times defined by the Light LC Property states.
*/
if (bt_mesh_get_light_lc_trans_time(model, trans_time)) {
BT_ERR("%s, Failed to get Light LC transition time", __func__);
return -EIO;
}
} else {
*trans_time = bt_mesh_get_default_trans_time(model);
}
*delay = 0U;
*optional = false;
return 0;
}
/* Optional fields are available */
*trans_time = net_buf_simple_pull_u8(buf);
if ((*trans_time & 0x3F) == 0x3F) {
BT_ERR("%s, Invalid Transaction Number of Steps 0x3F", __func__);
return -EINVAL;
}
*delay = net_buf_simple_pull_u8(buf);
*optional = true;
return 0;
}
void bt_mesh_server_alloc_ctx(struct k_work *work)
{
/**
* This function is used to allocate memory for storing "struct bt_mesh_msg_ctx"
* of the received messages, because some server models will callback the "struct
* bt_mesh_msg_ctx" info to the application layer after a certain delay.
* Here we use the allocated heap memory to store the "struct bt_mesh_msg_ctx".
*/
__ASSERT(work, "%s, Invalid parameter", __func__);
if (!work->_reserved) {
work->_reserved = bt_mesh_calloc(sizeof(struct bt_mesh_msg_ctx));
__ASSERT(work->_reserved, "%s, Failed to allocate memory", __func__);
}
}
void bt_mesh_server_free_ctx(struct k_work *work)
{
__ASSERT(work, "%s, Invalid parameter", __func__);
if (work->_reserved) {
bt_mesh_free(work->_reserved);
work->_reserved = NULL;
}
}
bool bt_mesh_is_server_recv_last_msg(struct bt_mesh_last_msg_info *last,
u8_t tid, u16_t src, u16_t dst, s64_t *now)
{
*now = k_uptime_get();
/* Currently we only compare msg info which dst is set to a unicast address */
if (!BLE_MESH_ADDR_IS_UNICAST(dst)) {
return false;
}
if (last->tid == tid && last->src == src && last->dst == dst &&
(*now - last->timestamp <= K_SECONDS(6))) {
return true;
}
return false;
}
void bt_mesh_server_update_last_msg(struct bt_mesh_last_msg_info *last,
u8_t tid, u16_t src, u16_t dst, s64_t *now)
{
/* Currently we only update msg info which dst is set to a unicast address */
if (!BLE_MESH_ADDR_IS_UNICAST(dst)) {
return;
}
last->tid = tid;
last->src = src;
last->dst = dst;
last->timestamp = *now;
return;
}
struct net_buf_simple *bt_mesh_server_get_pub_msg(struct bt_mesh_model *model, u16_t msg_len)
{
struct net_buf_simple *buf = NULL;
if (model == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return NULL;
}
if (model->pub == NULL || model->pub->msg == NULL ||
model->pub->addr == BLE_MESH_ADDR_UNASSIGNED) {
BT_DBG("%s, Model 0x%04x has no publication support", __func__, model->id);
return NULL;
}
buf = model->pub->msg;
if (buf->size < msg_len) {
BT_ERR("%s, Too small publication msg size %d, model 0x%04x",
__func__, buf->size, model->id);
return NULL;
}
return buf;
}