1176 lines
33 KiB
C
1176 lines
33 KiB
C
/********************************** (C) COPYRIGHT *******************************
|
|
* File Name : app.c
|
|
* Author : WCH
|
|
* Version : V1.1
|
|
* Date : 2022/01/18
|
|
* Description :
|
|
*********************************************************************************
|
|
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
|
* Attention: This software (modified or not) and binary are used for
|
|
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
|
*******************************************************************************/
|
|
|
|
/******************************************************************************/
|
|
#include "CONFIG.h"
|
|
#include "MESH_LIB.h"
|
|
#include "app_vendor_model_srv.h"
|
|
#include "app_vendor_model_cli.h"
|
|
#include "app.h"
|
|
#include "HAL.h"
|
|
|
|
/*********************************************************************
|
|
* GLOBAL TYPEDEFS
|
|
*/
|
|
#define ADV_TIMEOUT K_MINUTES(10)
|
|
|
|
#define SELENCE_ADV_ON 0x01
|
|
#define SELENCE_ADV_OF 0x00
|
|
|
|
/*********************************************************************
|
|
* GLOBAL TYPEDEFS
|
|
*/
|
|
|
|
static uint8_t MESH_MEM[1024 * 2 + 30 * CONFIG_MESH_PROV_NODE_COUNT_DEF] = {0};
|
|
|
|
extern const ble_mesh_cfg_t app_mesh_cfg;
|
|
extern const struct device app_dev;
|
|
|
|
static uint8_t App_TaskID = 0; // Task ID for internal task/event processing
|
|
|
|
static uint16_t App_ProcessEvent(uint8_t task_id, uint16_t events);
|
|
|
|
static uint8_t dev_uuid[16] = {0}; // 此设备的UUID
|
|
|
|
static const uint8_t self_prov_net_key[16] = {
|
|
0x00, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
|
|
0x00, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
|
|
};
|
|
|
|
static const uint8_t self_prov_dev_key[16] = {
|
|
0x00, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
|
|
0x00, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
|
|
};
|
|
|
|
static const uint8_t self_prov_app_key[16] = {
|
|
0x00, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
|
|
0x00, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
|
|
};
|
|
|
|
/* The key indexes are 12-bit values ranging from 0x000 to 0xFFF
|
|
inclusive. A network key at index 0x000 is called the primary NetKey*/
|
|
const uint16_t self_prov_net_idx = 0x0000; // 自配网所用的net key
|
|
const uint16_t self_prov_app_idx = 0x0001; // 自配网所用的app key
|
|
const uint32_t self_prov_iv_index = 0x00000000; // 自配网的iv_index
|
|
const uint16_t self_prov_addr = 0x0001; // 自配网的自身主元素地址
|
|
const uint8_t self_prov_flags = 0x00; // 是否处于key更新状态,默认为否
|
|
const uint16_t vendor_sub_addr = 0xC000; // 配置自定义模型的订阅group地址
|
|
|
|
#if(!CONFIG_BLE_MESH_PB_GATT)
|
|
NET_BUF_SIMPLE_DEFINE_STATIC(rx_buf, 65);
|
|
#endif /* !PB_GATT */
|
|
|
|
/*********************************************************************
|
|
* LOCAL FUNCION
|
|
*/
|
|
|
|
static void link_open(bt_mesh_prov_bearer_t bearer);
|
|
static void link_close(bt_mesh_prov_bearer_t bearer, uint8_t reason);
|
|
static void prov_complete(uint16_t net_idx, uint16_t addr, uint8_t flags, uint32_t iv_index);
|
|
static void unprov_recv(bt_mesh_prov_bearer_t bearer,
|
|
const uint8_t uuid[16], bt_mesh_prov_oob_info_t oob_info,
|
|
const unprivison_info_t *info);
|
|
static void node_added(uint16_t net_idx, uint16_t addr, uint8_t num_elem);
|
|
static node_t *node_get(uint16_t node_addr);
|
|
static void cfg_cli_rsp_handler(const cfg_cli_status_t *val);
|
|
static void vendor_model_cli_rsp_handler(const vendor_model_cli_status_t *val);
|
|
static int vendor_model_cli_send(uint16_t addr, uint8_t *pData, uint16_t len);
|
|
static void node_init(void);
|
|
|
|
static struct bt_mesh_cfg_srv cfg_srv = {
|
|
#if(CONFIG_BLE_MESH_RELAY)
|
|
.relay = BLE_MESH_RELAY_ENABLED,
|
|
#endif
|
|
.beacon = BLE_MESH_BEACON_ENABLED,
|
|
#if(CONFIG_BLE_MESH_FRIEND)
|
|
.frnd = BLE_MESH_FRIEND_ENABLED,
|
|
#endif
|
|
#if(CONFIG_BLE_MESH_PROXY)
|
|
.gatt_proxy = BLE_MESH_GATT_PROXY_ENABLED,
|
|
#endif
|
|
/* 默认TTL为3 */
|
|
.default_ttl = 3,
|
|
/* 底层发送数据重试7次,每次间隔10ms(不含内部随机数) */
|
|
.net_transmit = BLE_MESH_TRANSMIT(7, 10),
|
|
/* 底层转发数据重试7次,每次间隔10ms(不含内部随机数) */
|
|
.relay_retransmit = BLE_MESH_TRANSMIT(7, 10),
|
|
};
|
|
|
|
static struct bt_mesh_health_srv health_srv;
|
|
|
|
BLE_MESH_HEALTH_PUB_DEFINE(health_pub, 8);
|
|
|
|
struct bt_mesh_cfg_cli cfg_cli = {
|
|
.handler = cfg_cli_rsp_handler,
|
|
};
|
|
|
|
uint16_t cfg_srv_keys[CONFIG_MESH_MOD_KEY_COUNT_DEF] = {BLE_MESH_KEY_UNUSED};
|
|
uint16_t cfg_srv_groups[CONFIG_MESH_MOD_GROUP_COUNT_DEF] = {BLE_MESH_ADDR_UNASSIGNED};
|
|
|
|
uint16_t cfg_cli_keys[CONFIG_MESH_MOD_KEY_COUNT_DEF] = {BLE_MESH_KEY_UNUSED};
|
|
uint16_t cfg_cli_groups[CONFIG_MESH_MOD_GROUP_COUNT_DEF] = {BLE_MESH_ADDR_UNASSIGNED};
|
|
|
|
uint16_t health_srv_keys[CONFIG_MESH_MOD_KEY_COUNT_DEF] = {BLE_MESH_KEY_UNUSED};
|
|
uint16_t health_srv_groups[CONFIG_MESH_MOD_GROUP_COUNT_DEF] = {BLE_MESH_ADDR_UNASSIGNED};
|
|
|
|
// root模型加载
|
|
static struct bt_mesh_model root_models[] = {
|
|
BLE_MESH_MODEL_CFG_SRV(cfg_srv_keys, cfg_srv_groups, &cfg_srv),
|
|
BLE_MESH_MODEL_CFG_CLI(cfg_cli_keys, cfg_cli_groups, &cfg_cli),
|
|
BLE_MESH_MODEL_HEALTH_SRV(health_srv_keys, health_srv_groups, &health_srv, &health_pub),
|
|
};
|
|
|
|
struct bt_mesh_vendor_model_cli vendor_model_cli = {
|
|
.cli_tid.trans_tid = 0xFF,
|
|
.cli_tid.ind_tid = 0xFF,
|
|
.handler = vendor_model_cli_rsp_handler,
|
|
};
|
|
|
|
uint16_t vnd_model_cli_keys[CONFIG_MESH_MOD_KEY_COUNT_DEF] = {BLE_MESH_KEY_UNUSED};
|
|
uint16_t vnd_model_cli_groups[CONFIG_MESH_MOD_GROUP_COUNT_DEF] = {BLE_MESH_ADDR_UNASSIGNED};
|
|
|
|
// 自定义模型加载
|
|
struct bt_mesh_model vnd_models[] = {
|
|
BLE_MESH_MODEL_VND_CB(CID_WCH, BLE_MESH_MODEL_ID_WCH_CLI, vnd_model_cli_op, NULL, vnd_model_cli_keys,
|
|
vnd_model_cli_groups, &vendor_model_cli, NULL),
|
|
};
|
|
|
|
// 模型组成 elements
|
|
static struct bt_mesh_elem elements[] = {
|
|
{
|
|
/* Location Descriptor (GATT Bluetooth Namespace Descriptors) */
|
|
.loc = (0),
|
|
.model_count = ARRAY_SIZE(root_models),
|
|
.models = (root_models),
|
|
.vnd_model_count = ARRAY_SIZE(vnd_models),
|
|
.vnd_models = (vnd_models),
|
|
}
|
|
};
|
|
|
|
// elements 构成 Node Composition
|
|
const struct bt_mesh_comp app_comp = {
|
|
.cid = 0x07D7, // WCH 公司id
|
|
.elem = elements,
|
|
.elem_count = ARRAY_SIZE(elements),
|
|
};
|
|
|
|
// 配网参数和回调
|
|
static const struct bt_mesh_prov app_prov = {
|
|
.uuid = dev_uuid,
|
|
.link_open = link_open,
|
|
.link_close = link_close,
|
|
.complete = prov_complete,
|
|
.unprovisioned_beacon = unprov_recv,
|
|
.node_added = node_added,
|
|
};
|
|
|
|
// 配网者管理的节点,第0个为自己,第1,2依次为配网顺序的节点
|
|
node_t app_nodes[1 + CONFIG_MESH_PROV_NODE_COUNT_DEF] = {0};
|
|
|
|
app_mesh_manage_t app_mesh_manage;
|
|
|
|
uint16_t reset_node_addr = BLE_MESH_ADDR_UNASSIGNED;
|
|
uint8_t settings_load_over = FALSE;
|
|
/*********************************************************************
|
|
* GLOBAL TYPEDEFS
|
|
*/
|
|
|
|
/*********************************************************************
|
|
* @fn link_open
|
|
*
|
|
* @brief 配网时后的link打开回调
|
|
*
|
|
* @param bearer - 当前link是PB_ADV还是PB_GATT
|
|
*
|
|
* @return none
|
|
*/
|
|
static void link_open(bt_mesh_prov_bearer_t bearer)
|
|
{
|
|
APP_DBG("");
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn link_close
|
|
*
|
|
* @brief 配网后的link关闭回调
|
|
*
|
|
* @param bearer - 当前link是PB_ADV还是PB_GATT
|
|
* @param reason - link关闭原因
|
|
*
|
|
* @return none
|
|
*/
|
|
static void link_close(bt_mesh_prov_bearer_t bearer, uint8_t reason)
|
|
{
|
|
APP_DBG("reason %x", reason);
|
|
if(reason == CLOSE_REASON_RESOURCES)
|
|
{
|
|
// 存储的节点已满,可选择 停止发起配网 或 清除全部节点 或 按地址清除节点(注意应用层管理的节点也需要对应清除)
|
|
bt_mesh_provisioner_disable(BLE_MESH_PROV_ADV, TRUE);
|
|
//bt_mesh_node_clear();node_init();
|
|
//bt_mesh_node_del_by_addr(app_nodes[1].node_addr);
|
|
}
|
|
else
|
|
{
|
|
bt_mesh_provisioner_enable(BLE_MESH_PROV_ADV);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn node_unblock_get
|
|
*
|
|
* @brief 获取 一个未阻塞的 node
|
|
*
|
|
* @return node_t / NULL
|
|
*/
|
|
static node_t *node_unblock_get(void)
|
|
{
|
|
for(int i = 0; i < ARRAY_SIZE(app_nodes); i++)
|
|
{
|
|
if(app_nodes[i].node_addr != BLE_MESH_ADDR_UNASSIGNED &&
|
|
app_nodes[i].fixed != TRUE &&
|
|
app_nodes[i].blocked == FALSE)
|
|
{
|
|
return &app_nodes[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn node_block_get
|
|
*
|
|
* @brief 获取一个正在阻塞的 node
|
|
*
|
|
* @return node_t / NULL
|
|
*/
|
|
static node_t *node_block_get(void)
|
|
{
|
|
for(int i = 0; i < ARRAY_SIZE(app_nodes); i++)
|
|
{
|
|
if(app_nodes[i].node_addr != BLE_MESH_ADDR_UNASSIGNED &&
|
|
app_nodes[i].fixed != TRUE &&
|
|
app_nodes[i].blocked == TRUE)
|
|
{
|
|
return &app_nodes[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn node_work_handler
|
|
*
|
|
* @brief node 任务到期执行,判断是否还有未配置完成的节点,调用节点配置函数
|
|
*
|
|
* @return TRUE 继续执行配置节点
|
|
* FALSE 节点配置完成,停止任务
|
|
*/
|
|
static BOOL node_work_handler(void)
|
|
{
|
|
node_t *node;
|
|
|
|
node = node_unblock_get();
|
|
if(!node)
|
|
{
|
|
APP_DBG("Unable find Unblocked Node");
|
|
return FALSE;
|
|
}
|
|
|
|
if(node->retry_cnt-- == 0)
|
|
{
|
|
APP_DBG("Ran Out of Retransmit");
|
|
// 如果配置失败则删除节点
|
|
bt_mesh_node_del_by_addr(node->node_addr);
|
|
node = node_get(node->node_addr);
|
|
node->stage.node = NODE_INIT;
|
|
node->node_addr = BLE_MESH_ADDR_UNASSIGNED;
|
|
node->fixed = FALSE;
|
|
APP_DBG("Delete node complete");
|
|
goto unblock;
|
|
}
|
|
|
|
if(!node->cb->stage(node))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
node->fixed = TRUE;
|
|
|
|
unblock:
|
|
|
|
node = node_block_get();
|
|
if(node)
|
|
{
|
|
node->blocked = FALSE;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn node_init
|
|
*
|
|
* @brief node 初始化
|
|
*
|
|
* @return none
|
|
*/
|
|
static void node_init(void)
|
|
{
|
|
int i;
|
|
|
|
for(i = 0; i < ARRAY_SIZE(app_nodes); i++)
|
|
{
|
|
app_nodes[i].stage.node = NODE_INIT;
|
|
app_nodes[i].node_addr = BLE_MESH_ADDR_UNASSIGNED;
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn free_node_get
|
|
*
|
|
* @brief 获取一个空的node
|
|
*
|
|
* @return node_t / NULL
|
|
*/
|
|
static node_t *free_node_get(void)
|
|
{
|
|
for(int i = 0; i < ARRAY_SIZE(app_nodes); i++)
|
|
{
|
|
if(app_nodes[i].node_addr == BLE_MESH_ADDR_UNASSIGNED)
|
|
{
|
|
return &app_nodes[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn node_get
|
|
*
|
|
* @brief 获取匹配的node
|
|
*
|
|
* @param node_addr - node网络地址
|
|
*
|
|
* @return node_t / NULL
|
|
*/
|
|
static node_t *node_get(uint16_t node_addr)
|
|
{
|
|
for(int i = 0; i < ARRAY_SIZE(app_nodes); i++)
|
|
{
|
|
if(app_nodes[i].node_addr == node_addr)
|
|
{
|
|
return &app_nodes[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn node_should_blocked
|
|
*
|
|
* @brief 判断此node配置流程是否阻塞
|
|
*
|
|
* @param node_addr - node网络地址
|
|
*
|
|
* @return TRUE node未完成配置
|
|
* FALSE node已经完成配置或不需要配置
|
|
*/
|
|
static BOOL node_should_blocked(uint16_t node_addr)
|
|
{
|
|
for(int i = 0; i < ARRAY_SIZE(app_nodes); i++)
|
|
{
|
|
if(app_nodes[i].node_addr != BLE_MESH_ADDR_UNASSIGNED &&
|
|
app_nodes[i].node_addr != node_addr &&
|
|
app_nodes[i].fixed != TRUE &&
|
|
app_nodes[i].blocked == FALSE)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn node_cfg_process
|
|
*
|
|
* @brief 找一个空闲的节点,执行配置流程
|
|
*
|
|
* @param node - 空节点指针
|
|
* @param net_idx - 网络key编号
|
|
* @param addr - 网络地址
|
|
* @param num_elem - 元素数量
|
|
*
|
|
* @return node_t / NULL
|
|
*/
|
|
static node_t *node_cfg_process(node_t *node, uint16_t net_idx, uint16_t addr, uint8_t num_elem)
|
|
{
|
|
if(!node)
|
|
{
|
|
node = free_node_get();
|
|
if(!node)
|
|
{
|
|
APP_DBG("No Free Node Object Available");
|
|
return NULL;
|
|
}
|
|
node->net_idx = net_idx;
|
|
node->node_addr = addr;
|
|
node->elem_count = num_elem;
|
|
}
|
|
|
|
node->blocked = node_should_blocked(addr);
|
|
|
|
if(!node->blocked)
|
|
{
|
|
tmos_start_task(App_TaskID, APP_NODE_EVT, 1600);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn node_stage_set
|
|
*
|
|
* @brief 设置远端node配置的下一个阶段
|
|
*
|
|
* @param node - 要配置的节点
|
|
* @param new_stage - 下一个阶段
|
|
*
|
|
* @return none
|
|
*/
|
|
static void node_stage_set(node_t *node, node_stage_t new_stage)
|
|
{
|
|
node->retry_cnt = 5;
|
|
node->stage.node = new_stage;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn local_stage_set
|
|
*
|
|
* @brief 设置本地node配置的下一个阶段(即配置自身)
|
|
*
|
|
* @param node - 要配置的节点
|
|
* @param new_stage - 下一个阶段
|
|
*
|
|
* @return none
|
|
*/
|
|
static void local_stage_set(node_t *node, local_stage_t new_stage)
|
|
{
|
|
node->retry_cnt = 1;
|
|
node->stage.local = new_stage;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn node_rsp
|
|
*
|
|
* @brief 每执行一个远端节点配置流程的回调,设置下一个配置阶段
|
|
*
|
|
* @param p1 - 要配置的远端node
|
|
* @param p2 - 当前的状态
|
|
*
|
|
* @return none
|
|
*/
|
|
static void node_rsp(void *p1, const void *p2)
|
|
{
|
|
node_t *node = p1;
|
|
const cfg_cli_status_t *val = p2;
|
|
|
|
switch(val->cfgHdr.opcode)
|
|
{
|
|
case OP_APP_KEY_ADD:
|
|
APP_DBG("node Application Key Added");
|
|
node_stage_set(node, NODE_MOD_BIND_SET);
|
|
break;
|
|
case OP_MOD_APP_BIND:
|
|
APP_DBG("node vendor Model Binded");
|
|
node_stage_set(node, NODE_MOD_SUB_SET);
|
|
break;
|
|
case OP_MOD_SUB_ADD:
|
|
APP_DBG("node vendor Model Subscription Set");
|
|
node_stage_set(node, NODE_CONFIGURATIONED);
|
|
break;
|
|
default:
|
|
APP_DBG("Unknown Opcode (0x%04x)", val->cfgHdr.opcode);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn local_rsp
|
|
*
|
|
* @brief 每执行一个本地节点配置流程的回调,设置下一个配置阶段
|
|
*
|
|
* @param p1 - 要配置的本地node
|
|
* @param p2 - 当前的状态
|
|
*
|
|
* @return none
|
|
*/
|
|
static void local_rsp(void *p1, const void *p2)
|
|
{
|
|
node_t *node = p1;
|
|
const cfg_cli_status_t *val = p2;
|
|
|
|
switch(val->cfgHdr.opcode)
|
|
{
|
|
case OP_APP_KEY_ADD:
|
|
APP_DBG("local Application Key Added");
|
|
local_stage_set(node, LOCAL_MOD_BIND_SET);
|
|
break;
|
|
case OP_MOD_APP_BIND:
|
|
APP_DBG("local vendor Model Binded");
|
|
local_stage_set(node, LOCAL_CONFIGURATIONED);
|
|
break;
|
|
default:
|
|
APP_DBG("Unknown Opcode (0x%04x)", val->cfgHdr.opcode);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn node_stage
|
|
*
|
|
* @brief 远端节点配置,添加app key,并为自定义服务绑定app key,设置模型订阅
|
|
*
|
|
* @param p1 - 要配置的本地node
|
|
*
|
|
* @return TRUE 配置发送失败
|
|
* FALSE 配置发送正常
|
|
*/
|
|
static BOOL node_stage(void *p1)
|
|
{
|
|
int err;
|
|
BOOL ret = FALSE;
|
|
node_t *node = p1;
|
|
|
|
switch(node->stage.node)
|
|
{
|
|
case NODE_APPKEY_ADD:
|
|
err = bt_mesh_cfg_app_key_add(node->net_idx, node->node_addr, self_prov_net_idx, self_prov_app_idx, self_prov_app_key);
|
|
if(err)
|
|
{
|
|
APP_DBG("Unable to adding Application key (err %d)", err);
|
|
ret = TRUE;
|
|
}
|
|
break;
|
|
|
|
case NODE_MOD_BIND_SET:
|
|
err = bt_mesh_cfg_mod_app_bind_vnd(node->net_idx, node->node_addr, node->node_addr, self_prov_app_idx, BLE_MESH_MODEL_ID_WCH_SRV, CID_WCH);
|
|
if(err)
|
|
{
|
|
APP_DBG("Unable to Binding vendor Model (err %d)", err);
|
|
ret = TRUE;
|
|
}
|
|
break;
|
|
|
|
// 设置模型订阅
|
|
case NODE_MOD_SUB_SET:
|
|
err = bt_mesh_cfg_mod_sub_add_vnd(node->net_idx, node->node_addr, node->node_addr, vendor_sub_addr, BLE_MESH_MODEL_ID_WCH_SRV, CID_WCH);
|
|
if(err)
|
|
{
|
|
APP_DBG("Unable to Set vendor Model Subscription (err %d)", err);
|
|
ret = TRUE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ret = TRUE;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn local_stage
|
|
*
|
|
* @brief 本地节点配置,添加app key,并为自定义客户端绑定app key
|
|
*
|
|
* @param p1 - 要配置的本地node
|
|
*
|
|
* @return TRUE 配置发送失败
|
|
* FALSE 配置发送正常
|
|
*/
|
|
static BOOL local_stage(void *p1)
|
|
{
|
|
int err;
|
|
BOOL ret = FALSE;
|
|
node_t *node = p1;
|
|
|
|
switch(node->stage.local)
|
|
{
|
|
case LOCAL_APPKEY_ADD:
|
|
err = bt_mesh_cfg_app_key_add(node->net_idx, node->node_addr, self_prov_net_idx, self_prov_app_idx, self_prov_app_key);
|
|
if(err)
|
|
{
|
|
APP_DBG("Unable to adding Application key (err %d)", err);
|
|
ret = 1;
|
|
}
|
|
break;
|
|
|
|
case LOCAL_MOD_BIND_SET:
|
|
err = bt_mesh_cfg_mod_app_bind_vnd(node->net_idx, node->node_addr, node->node_addr, self_prov_app_idx, BLE_MESH_MODEL_ID_WCH_CLI, CID_WCH);
|
|
if(err)
|
|
{
|
|
APP_DBG("Unable to Binding vendor Model (err %d)", err);
|
|
ret = 1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ret = 1;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static const cfg_cb_t node_cfg_cb = {
|
|
node_rsp,
|
|
node_stage,
|
|
};
|
|
|
|
static const cfg_cb_t local_cfg_cb = {
|
|
local_rsp,
|
|
local_stage,
|
|
};
|
|
|
|
/*********************************************************************
|
|
* @fn prov_complete
|
|
*
|
|
* @brief 配网完成回调,重新开始广播
|
|
*
|
|
* @param net_idx - 网络key的index
|
|
* @param addr - link关闭原因网络地址
|
|
* @param flags - 是否处于key refresh状态
|
|
* @param iv_index - 当前网络iv的index
|
|
*
|
|
* @return none
|
|
*/
|
|
static void prov_complete(uint16_t net_idx, uint16_t addr, uint8_t flags, uint32_t iv_index)
|
|
{
|
|
int err;
|
|
node_t *node;
|
|
|
|
APP_DBG("");
|
|
|
|
err = bt_mesh_provisioner_enable(BLE_MESH_PROV_ADV);
|
|
if(err)
|
|
{
|
|
APP_DBG("Unabled Enable Provisoner (err:%d)", err);
|
|
}
|
|
|
|
node = node_get(addr);
|
|
if(!node || !node->fixed)
|
|
{
|
|
node = node_cfg_process(node, net_idx, addr, ARRAY_SIZE(elements));
|
|
if(!node)
|
|
{
|
|
APP_DBG("Unable allocate node object");
|
|
return;
|
|
}
|
|
|
|
node->cb = &local_cfg_cb;
|
|
// 判断当前是否已加载完成,如果还在加载中则说明上次运行已配置,直接认为已完成
|
|
if( settings_load_over )
|
|
{
|
|
local_stage_set(node, LOCAL_APPKEY_ADD);
|
|
}
|
|
else
|
|
{
|
|
local_stage_set(node, LOCAL_CONFIGURATIONED);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn unprov_recv
|
|
*
|
|
* @brief 收到未配网广播,发起配网
|
|
*
|
|
* @param bearer - 在PB_ADV/PB_GATT收到未配网广播
|
|
* @param uuid - 未配网广播数据中包含的UUID,通过此数据判断设备信息
|
|
* @param oob_info - 带外数据信息
|
|
* @param info - 其他未配网信息
|
|
*
|
|
* @return none
|
|
*/
|
|
static void unprov_recv(bt_mesh_prov_bearer_t bearer,
|
|
const uint8_t uuid[16], bt_mesh_prov_oob_info_t oob_info,
|
|
const unprivison_info_t *info)
|
|
{
|
|
APP_DBG("");
|
|
int err;
|
|
|
|
if(bearer & BLE_MESH_PROV_ADV)
|
|
{
|
|
err = bt_mesh_provision_adv(uuid, self_prov_net_idx, BLE_MESH_ADDR_UNASSIGNED, 5);
|
|
if(err)
|
|
{
|
|
APP_DBG("Unable Open PB-ADV Session (err:%d)", err);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn node_added
|
|
*
|
|
* @brief 远端节点配网成功,添加到本地节点管理,并开始远端节点配置流程
|
|
*
|
|
* @param net_idx - 节点使用的网络key编号
|
|
* @param addr - 节点的网络地址
|
|
* @param num_elem - 节点包含的元素数量
|
|
*
|
|
* @return none
|
|
*/
|
|
static void node_added(uint16_t net_idx, uint16_t addr, uint8_t num_elem)
|
|
{
|
|
node_t *node;
|
|
APP_DBG("");
|
|
|
|
node = node_get(addr);
|
|
if(!node || !node->fixed)
|
|
{
|
|
node = node_cfg_process(node, net_idx, addr, num_elem);
|
|
if(!node)
|
|
{
|
|
APP_DBG("Unable allocate node object");
|
|
return;
|
|
}
|
|
|
|
node->cb = &node_cfg_cb;
|
|
// 判断当前是否已加载完成,如果还在加载中则说明上次运行已配置,直接认为已完成
|
|
if( settings_load_over )
|
|
{
|
|
node_stage_set(node, NODE_APPKEY_ADD);
|
|
}
|
|
else
|
|
{
|
|
node_stage_set(node, NODE_CONFIGURATIONED);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn cfg_cli_rsp_handler
|
|
*
|
|
* @brief 收到cfg命令的应答回调,此处例程只处理配置节点命令应答,
|
|
* 如果超时则延迟1秒后再次执行配置节点流程
|
|
*
|
|
* @param val - 回调参数,包含命令类型和返回数据
|
|
*
|
|
* @return none
|
|
*/
|
|
static void cfg_cli_rsp_handler(const cfg_cli_status_t *val)
|
|
{
|
|
node_t *node;
|
|
APP_DBG("");
|
|
|
|
// 通过协议栈删除节点的应答,由于有可能节点已被删除所以收不到应答,所以不管是否应答一律算成功。注意如果节点未在线则节点自身不会收到删除命令
|
|
if(val->cfgHdr.opcode == OP_NODE_RESET)
|
|
{
|
|
if(reset_node_addr != BLE_MESH_ADDR_UNASSIGNED)
|
|
{
|
|
bt_mesh_node_del_by_addr(reset_node_addr);
|
|
node = node_get(reset_node_addr);
|
|
node->stage.node = NODE_INIT;
|
|
node->node_addr = BLE_MESH_ADDR_UNASSIGNED;
|
|
node->fixed = FALSE;
|
|
APP_DBG("node reset complete");
|
|
}
|
|
return;
|
|
}
|
|
|
|
node = node_unblock_get();
|
|
if(!node)
|
|
{
|
|
APP_DBG("Unable find Unblocked Node");
|
|
return;
|
|
}
|
|
|
|
if(val->cfgHdr.status == 0xFF)
|
|
{
|
|
APP_DBG("Opcode 0x%04x, timeout", val->cfgHdr.opcode);
|
|
goto end;
|
|
}
|
|
|
|
node->cb->rsp(node, val);
|
|
|
|
end:
|
|
tmos_start_task(App_TaskID, APP_NODE_EVT, K_SECONDS(1));
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn vendor_model_cli_rsp_handler
|
|
*
|
|
* @brief 收到厂商模型数据的回调,
|
|
*
|
|
* @param val - 回调参数,包含命令类型和返回数据内容,长度和来源地址
|
|
*
|
|
* @return none
|
|
*/
|
|
static void vendor_model_cli_rsp_handler(const vendor_model_cli_status_t *val)
|
|
{
|
|
if(val->vendor_model_cli_Hdr.status)
|
|
{
|
|
// 有应答数据传输 超时未收到应答
|
|
APP_DBG("Timeout opcode 0x%02x", val->vendor_model_cli_Hdr.opcode);
|
|
return;
|
|
}
|
|
if(val->vendor_model_cli_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_MSG)
|
|
{
|
|
// 收到透传数据
|
|
APP_DBG("trans len %d, data 0x%02x from 0x%04x", val->vendor_model_cli_Event.trans.len,
|
|
val->vendor_model_cli_Event.trans.pdata[0],
|
|
val->vendor_model_cli_Event.trans.addr);
|
|
tmos_memcpy(&app_mesh_manage, val->vendor_model_cli_Event.trans.pdata, val->vendor_model_cli_Event.trans.len);
|
|
switch(app_mesh_manage.data.buf[0])
|
|
{
|
|
// 判断是否为应用层自定义删除命令应答
|
|
case CMD_DELETE_NODE_ACK:
|
|
{
|
|
if(val->vendor_model_cli_Event.trans.len != DELETE_NODE_ACK_DATA_LEN)
|
|
{
|
|
APP_DBG("Delete node ack data err!");
|
|
return;
|
|
}
|
|
node_t *node;
|
|
tmos_stop_task(App_TaskID, APP_DELETE_NODE_TIMEOUT_EVT);
|
|
bt_mesh_node_del_by_addr(val->vendor_model_cli_Event.trans.addr);
|
|
node = node_get(val->vendor_model_cli_Event.trans.addr);
|
|
node->stage.node = NODE_INIT;
|
|
node->node_addr = BLE_MESH_ADDR_UNASSIGNED;
|
|
node->fixed = FALSE;
|
|
APP_DBG("Delete node complete");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if(val->vendor_model_cli_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_IND)
|
|
{
|
|
// 收到indicate数据
|
|
APP_DBG("ind len %d, data 0x%02x from 0x%04x", val->vendor_model_cli_Event.ind.len,
|
|
val->vendor_model_cli_Event.ind.pdata[0],
|
|
val->vendor_model_cli_Event.ind.addr);
|
|
}
|
|
else if(val->vendor_model_cli_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_WRT)
|
|
{
|
|
// 收到write的应答
|
|
}
|
|
else
|
|
{
|
|
APP_DBG("Unknow opcode 0x%02x", val->vendor_model_cli_Hdr.opcode);
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn vendor_model_cli_send
|
|
*
|
|
* @brief 通过厂商自定义模型发送数据
|
|
*
|
|
* @param addr - 需要发送的目的地址
|
|
* pData - 需要发送的数据指针
|
|
* len - 需要发送的数据长度
|
|
*
|
|
* @return 参考Global_Error_Code
|
|
*/
|
|
static int vendor_model_cli_send(uint16_t addr, uint8_t *pData, uint16_t len)
|
|
{
|
|
struct send_param param = {
|
|
.app_idx = self_prov_app_idx, // 此消息使用的app key
|
|
.addr = addr, // 此消息发往的目的地地址,此处为第1个配网的节点
|
|
.trans_cnt = 0x01, // 此消息的用户层发送次数
|
|
.period = K_MSEC(400), // 此消息重传的间隔,建议不小于(200+50*TTL)ms,若数据较大则建议加长
|
|
.rand = (0), // 此消息发送的随机延迟
|
|
.tid = vendor_cli_tid_get(), // tid,每个独立消息递增循环,cli使用0~127
|
|
.send_ttl = BLE_MESH_TTL_DEFAULT, // ttl,无特定则使用默认值
|
|
};
|
|
// return vendor_message_cli_write(¶m, pData, len); // 调用自定义模型客户端的有应答写函数发送数据,默认超时2s
|
|
return vendor_message_cli_send_trans(¶m, pData, len); // 或者调用自定义模型服务的透传函数发送数据,只发送,无应答机制
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn keyPress
|
|
*
|
|
* @brief 按键回调
|
|
*
|
|
* @param keys - 按键类型
|
|
*
|
|
* @return none
|
|
*/
|
|
void keyPress(uint8_t keys)
|
|
{
|
|
APP_DBG("%d", keys);
|
|
|
|
switch(keys)
|
|
{
|
|
default:
|
|
{
|
|
if(0)
|
|
{
|
|
// 发送数据
|
|
if(app_nodes[1].node_addr)
|
|
{
|
|
uint8_t status;
|
|
APP_DBG("node1_addr %x", app_nodes[1].node_addr);
|
|
uint8_t data[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16};
|
|
status = vendor_model_cli_send(app_nodes[1].node_addr, data, 16);
|
|
if(status)
|
|
{
|
|
APP_DBG("write failed %d", status);
|
|
}
|
|
}
|
|
}
|
|
if(1)
|
|
{
|
|
// 删除节点,可以通过协议栈写好的命令删除,也可以通过应用层自定协议删除
|
|
if(app_nodes[1].node_addr)
|
|
{
|
|
uint8_t status;
|
|
APP_DBG("node1_addr %x", app_nodes[1].node_addr);
|
|
if(0)
|
|
{
|
|
// 通过协议栈写好的命令删除
|
|
status = bt_mesh_cfg_node_reset(self_prov_net_idx, app_nodes[1].node_addr);
|
|
if(status)
|
|
{
|
|
APP_DBG("reset failed %d", status);
|
|
}
|
|
else
|
|
{
|
|
reset_node_addr = app_nodes[1].node_addr;
|
|
}
|
|
}
|
|
if(1)
|
|
{
|
|
// 通过应用层自定协议删除
|
|
app_mesh_manage.delete_node.cmd = CMD_DELETE_NODE;
|
|
app_mesh_manage.delete_node.addr[0] = app_nodes[1].node_addr&0xFF;
|
|
app_mesh_manage.delete_node.addr[1] = (app_nodes[1].node_addr>>8)&0xFF;
|
|
status = vendor_model_cli_send(app_nodes[1].node_addr, app_mesh_manage.data.buf, DELETE_NODE_DATA_LEN);
|
|
if(status)
|
|
{
|
|
APP_DBG("delete failed %d", status);
|
|
}
|
|
else
|
|
{
|
|
// 定时三秒,未收到应答就超时
|
|
tmos_start_task(App_TaskID, APP_DELETE_NODE_TIMEOUT_EVT, 4800);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn blemesh_on_sync
|
|
*
|
|
* @brief 同步mesh参数,启用对应功能,不建议修改
|
|
*
|
|
* @param none
|
|
*
|
|
* @return none
|
|
*/
|
|
void blemesh_on_sync(void)
|
|
{
|
|
int err;
|
|
mem_info_t info;
|
|
|
|
if(tmos_memcmp(VER_MESH_LIB, VER_MESH_FILE, strlen(VER_MESH_FILE)) == FALSE)
|
|
{
|
|
PRINT("head file error...\n");
|
|
while(1);
|
|
}
|
|
|
|
info.base_addr = MESH_MEM;
|
|
info.mem_len = ARRAY_SIZE(MESH_MEM);
|
|
#if(CONFIG_BLE_MESH_FRIEND)
|
|
friend_init_register(bt_mesh_friend_init);
|
|
#endif /* FRIEND */
|
|
#if(CONFIG_BLE_MESH_LOW_POWER)
|
|
lpn_init_register(bt_mesh_lpn_init);
|
|
#endif /* LPN */
|
|
#if(defined(BLE_MAC)) && (BLE_MAC == TRUE)
|
|
tmos_memcpy(dev_uuid, MacAddr, 6);
|
|
err = bt_mesh_cfg_set(&app_mesh_cfg, &app_dev, MacAddr, &info);
|
|
#else
|
|
{
|
|
uint8_t MacAddr[6];
|
|
FLASH_GetMACAddress(MacAddr);
|
|
tmos_memcpy(dev_uuid, MacAddr, 6);
|
|
// 使用芯片mac地址
|
|
err = bt_mesh_cfg_set(&app_mesh_cfg, &app_dev, MacAddr, &info);
|
|
}
|
|
#endif
|
|
if(err)
|
|
{
|
|
APP_DBG("Unable set configuration (err:%d)", err);
|
|
return;
|
|
}
|
|
hal_rf_init();
|
|
err = bt_mesh_comp_register(&app_comp);
|
|
node_init();
|
|
|
|
#if(CONFIG_BLE_MESH_RELAY)
|
|
bt_mesh_relay_init();
|
|
#endif /* RELAY */
|
|
#if(CONFIG_BLE_MESH_PROXY || CONFIG_BLE_MESH_PB_GATT)
|
|
#if(CONFIG_BLE_MESH_PROXY)
|
|
bt_mesh_proxy_beacon_init_register((void *)bt_mesh_proxy_beacon_init);
|
|
gatts_notify_register(bt_mesh_gatts_notify);
|
|
proxy_gatt_enable_register(bt_mesh_proxy_gatt_enable);
|
|
#endif /* PROXY */
|
|
#if(CONFIG_BLE_MESH_PB_GATT)
|
|
proxy_prov_enable_register(bt_mesh_proxy_prov_enable);
|
|
#endif /* PB_GATT */
|
|
bt_mesh_proxy_init();
|
|
#endif /* PROXY || PB-GATT */
|
|
|
|
#if(CONFIG_BLE_MESH_PROXY_CLI)
|
|
bt_mesh_proxy_client_init(cli); //待添加
|
|
#endif /* PROXY_CLI */
|
|
|
|
bt_mesh_prov_retransmit_init();
|
|
|
|
#if(!CONFIG_BLE_MESH_PB_GATT)
|
|
adv_link_rx_buf_register(&rx_buf);
|
|
#endif /* !PB_GATT */
|
|
err = bt_mesh_prov_init(&app_prov);
|
|
|
|
bt_mesh_mod_init();
|
|
bt_mesh_net_init();
|
|
bt_mesh_trans_init();
|
|
bt_mesh_beacon_init();
|
|
bt_mesh_adv_init();
|
|
|
|
#if((CONFIG_BLE_MESH_PB_GATT) || (CONFIG_BLE_MESH_PROXY) || (CONFIG_BLE_MESH_OTA))
|
|
bt_mesh_conn_adv_init();
|
|
#endif /* PROXY || PB-GATT || OTA */
|
|
|
|
#if(CONFIG_BLE_MESH_SETTINGS)
|
|
bt_mesh_settings_init();
|
|
#endif /* SETTINGS */
|
|
|
|
#if(CONFIG_BLE_MESH_PROXY_CLI)
|
|
bt_mesh_proxy_cli_adapt_init();
|
|
#endif /* PROXY_CLI */
|
|
|
|
#if((CONFIG_BLE_MESH_PROXY) || (CONFIG_BLE_MESH_PB_GATT) || \
|
|
(CONFIG_BLE_MESH_PROXY_CLI) || (CONFIG_BLE_MESH_OTA))
|
|
bt_mesh_adapt_init();
|
|
#endif /* PROXY || PB-GATT || PROXY_CLI || OTA */
|
|
|
|
#if(CONFIG_BLE_MESH_LOW_POWER)
|
|
bt_mesh_lpn_set(TRUE);
|
|
#endif /* LPN */
|
|
|
|
if(err)
|
|
{
|
|
APP_DBG("Initializing mesh failed (err %d)", err);
|
|
return;
|
|
}
|
|
APP_DBG("Bluetooth initialized");
|
|
|
|
#if(CONFIG_BLE_MESH_SETTINGS)
|
|
settings_load();
|
|
settings_load_over = TRUE;
|
|
#endif /* SETTINGS */
|
|
|
|
if(bt_mesh_is_provisioned())
|
|
{
|
|
APP_DBG("Mesh network restored from flash");
|
|
}
|
|
else
|
|
{
|
|
err = bt_mesh_provision(self_prov_net_key, self_prov_net_idx, self_prov_flags,
|
|
self_prov_iv_index, self_prov_addr, self_prov_dev_key);
|
|
if(err)
|
|
{
|
|
APP_DBG("Self Privisioning (err %d)", err);
|
|
return;
|
|
}
|
|
}
|
|
APP_DBG("Mesh initialized");
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn App_Init
|
|
*
|
|
* @brief 应用层初始化
|
|
*
|
|
* @return none
|
|
*/
|
|
void App_Init(void)
|
|
{
|
|
App_TaskID = TMOS_ProcessEventRegister(App_ProcessEvent);
|
|
|
|
vendor_model_cli_init(vnd_models);
|
|
blemesh_on_sync();
|
|
|
|
HAL_KeyInit();
|
|
HalKeyConfig(keyPress);
|
|
|
|
// 添加一个测试任务,定时向第一个配网的设备发送透传数据
|
|
tmos_start_task(App_TaskID, APP_NODE_TEST_EVT, 4800);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* @fn App_ProcessEvent
|
|
*
|
|
* @brief 应用层事件处理函数
|
|
*
|
|
* @param task_id - The TMOS assigned task ID.
|
|
* @param events - events to process. This is a bit map and can
|
|
* contain more than one event.
|
|
*
|
|
* @return events not processed
|
|
*/
|
|
static uint16_t App_ProcessEvent(uint8_t task_id, uint16_t events)
|
|
{
|
|
// 节点配置任务事件处理
|
|
if(events & APP_NODE_EVT)
|
|
{
|
|
if(node_work_handler())
|
|
return (events);
|
|
else
|
|
return (events ^ APP_NODE_EVT);
|
|
}
|
|
|
|
// 测试任务事件处理
|
|
if(events & APP_NODE_TEST_EVT)
|
|
{
|
|
if(app_nodes[1].node_addr)
|
|
{
|
|
uint8_t status;
|
|
APP_DBG("app_nodes[1] ADDR %x", app_nodes[1].node_addr);
|
|
uint8_t data[4] = {0, 1, 2, 3};
|
|
status = vendor_model_cli_send(app_nodes[1].node_addr, data, 4); // 调用自定义模型客户端的透传函数发送数据
|
|
if(status)
|
|
APP_DBG("trans failed %d", status);
|
|
}
|
|
tmos_start_task(App_TaskID, APP_NODE_TEST_EVT, 6400);
|
|
return (events ^ APP_NODE_TEST_EVT);
|
|
}
|
|
|
|
if(events & APP_DELETE_NODE_TIMEOUT_EVT)
|
|
{
|
|
// 通过应用层自定协议删除超时,可添加其他流程
|
|
APP_DBG("Delete node failed ");
|
|
return (events ^ APP_DELETE_NODE_TIMEOUT_EVT);
|
|
}
|
|
|
|
// Discard unknown events
|
|
return 0;
|
|
}
|
|
|
|
/******************************** endfile @ main ******************************/
|