/********************************** (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 ******************************/