CH582 Mesh采用self_provisioner_vendor和adv_vendor例程進(jìn)行多節(jié)點(diǎn)通信的相關(guān)問(wèn)題

實(shí)驗(yàn)所用文件:

CH582官方例程Mesh中的self_provisioner_vendor和adv_vendor。

配網(wǎng)者節(jié)點(diǎn):self_provisioner_vendor

普通入網(wǎng)節(jié)點(diǎn):adv_vendor

代碼修改調(diào)整部分:配網(wǎng)者節(jié)點(diǎn):

1、App_Init函數(shù)中注釋掉測(cè)試任務(wù),利用按鍵回調(diào)函數(shù)進(jìn)行測(cè)試(按下按鍵進(jìn)行數(shù)據(jù)發(fā)送,從而開(kāi)始節(jié)點(diǎn)間數(shù)據(jù)傳輸)

?void App_Init(void)
?{
? ? ?// 注冊(cè)事件處理函數(shù)到TMOS任務(wù)系統(tǒng)
? ? ?App_TaskID = TMOS_ProcessEventRegister(App_ProcessEvent);
?
? ? ?// 初始化自定義廠商模型客戶端
? ? ?vendor_model_cli_init(vnd_models);
? ? ?// 同步BLE Mesh功能和參數(shù)
? ? ?blemesh_on_sync();
?
? ? ?// 初始化按鍵硬件
? ? ?HAL_KeyInit();
? ? ?// 配置按鍵回調(diào)函數(shù)
? ? ?HalKeyConfig(keyPress);
?
? ? ?// 添加一個(gè)測(cè)試任務(wù),定時(shí)向第一個(gè)配網(wǎng)設(shè)備發(fā)送透?jìng)鲾?shù)據(jù),定時(shí)時(shí)長(zhǎng)為4800ms
?// ? ?tmos_start_task(App_TaskID, APP_NODE_TEST_EVT, 4800);
?}

對(duì)keyPress函數(shù)進(jìn)行修改,通過(guò)按鍵控制數(shù)據(jù)發(fā)送,從而開(kāi)啟節(jié)點(diǎn)間數(shù)據(jù)傳輸

?void keyPress(uint8_t keys)
?{
? ? ?APP_DBG("%d", keys); // 打印按鍵的值,用于調(diào)試。
?
? ? ?switch(keys) // 根據(jù)按鍵的值執(zhí)行不同的操作。
? ? ?{
? ? ? ? ?default: // 默認(rèn)情況下(未指定特殊鍵的處理邏輯時(shí)),執(zhí)行以下代碼:
? ? ? ? ?{
? ? ? ? ? ? ?if(3) // 如果按鍵為3,即評(píng)估版的S4-KEY
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 向所有入網(wǎng)節(jié)點(diǎn)廣播數(shù)據(jù),從而開(kāi)始節(jié)點(diǎn)間數(shù)據(jù)傳輸
? ? ? ? ? ? ? ? ?uint8_t status;
? ? ? ? ? ? ? ? ?uint8_t data[4] = {0, 1, 2, 3}; // 準(zhǔn)備要發(fā)送的測(cè)試數(shù)據(jù)
? ? ? ? ? ? ? ? ?status = vendor_model_cli_send(0xFFFF, data, sizeof(data));
? ? ? ? ? ? ? ? ?if(status) // 如果發(fā)送失敗,打印錯(cuò)誤狀態(tài)
? ? ? ? ? ? ? ? ? ? ?APP_DBG("trans failed %d", status);
? ? ? ? ? ? ?}
?
?
? ? ? ? ? ? ?if(1) // 如果條件為true(這里只是示例,實(shí)際情況中會(huì)替換為具體的條件判斷。)
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 刪除節(jié)點(diǎn)操作
? ? ? ? ? ? ? ? ?if(app_nodes[1].node_addr) // 如果第二個(gè)節(jié)點(diǎn)的地址存在。
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?uint8_t status; // 定義刪除狀態(tài)變量。
? ? ? ? ? ? ? ? ? ? ?APP_DBG("node1_addr %x", app_nodes[1].node_addr); // 打印節(jié)點(diǎn)地址,用于調(diào)試。
? ? ? ? ? ? ? ? ? ? ?if(0) // 如果條件為false(這里只是示例,實(shí)際情況中會(huì)替換為具體的條件判斷。)
? ? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? ?// 通過(guò)藍(lán)牙Mesh協(xié)議棧提供的命令來(lái)刪除節(jié)點(diǎn)
? ? ? ? ? ? ? ? ? ? ? ? ?status = bt_mesh_cfg_node_reset(self_prov_net_idx, app_nodes[1].node_addr);
? ? ? ? ? ? ? ? ? ? ? ? ?if(status) // 如果刪除失敗
? ? ? ? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?APP_DBG("reset failed %d", status); // 打印刪除失敗的狀態(tài)碼。
? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ? ?else
? ? ? ? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?reset_node_addr = app_nodes[1].node_addr; // 保存被刪除節(jié)點(diǎn)的地址。
? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ?if(1) // 如果條件為true(這里只是示例,實(shí)際情況中會(huì)替換為具體的條件判斷。)
? ? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? ?// 通過(guò)應(yīng)用層自定義協(xié)議來(lái)刪除節(jié)點(diǎn)。
? ? ? ? ? ? ? ? ? ? ? ? ?app_mesh_manage.delete_node.cmd = CMD_DELETE_NODE; // 設(shè)置刪除命令。
? ? ? ? ? ? ? ? ? ? ? ? ?// 設(shè)置節(jié)點(diǎn)地址,低字節(jié)和高字節(jié)。
? ? ? ? ? ? ? ? ? ? ? ? ?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;
? ? ? ? ? ? ? ? ? ? ? ? ?// 使用廠商自定義模型發(fā)送刪除節(jié)點(diǎn)的命令,并保存返回的狀態(tài)值。
? ? ? ? ? ? ? ? ? ? ? ? ?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); // 打印刪除失敗的狀態(tài)碼。
? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ? ?else
? ? ? ? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 啟動(dòng)一個(gè)定時(shí)任務(wù),3秒后沒(méi)有收到應(yīng)答則認(rèn)為超時(shí)。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tmos_start_task(App_TaskID, APP_DELETE_NODE_TIMEOUT_EVT, 4800);
? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ?}
? ? ? ? ? ? ?break; // 結(jié)束switch語(yǔ)句
? ? ? ? ?}
? ? ?}
?}

2、修改vendor_model_cli_status_t結(jié)構(gòu)體的內(nèi)容,增加一項(xiàng)mydata數(shù)據(jù),用于記錄addr、rssi、ttl等信息

?typedef struct
?{
? ? ?struct vendor_model_cli_EventHdr vendor_model_cli_Hdr;
? ? ?union vendor_model_cli_Event_t ? vendor_model_cli_Event;
? ? ?void* mydata;
?} vendor_model_cli_status_t;

利用上述修改后的結(jié)構(gòu)體中增加的mydata變量,在vendor_message_cli_trans函數(shù)中修改廠商模型客戶端狀態(tài)參數(shù)

?static void vendor_message_cli_trans(struct bt_mesh_model ? *model,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf)
?{
? ? ?vendor_model_cli_status_t vendor_model_cli_status; // 定義廠商模型客戶端狀態(tài)結(jié)構(gòu)體
? ? ?uint8_t ? ? ? ? ? ? ? ? ?*pData = buf->data; // 數(shù)據(jù)指針指向緩存的數(shù)據(jù)部分
? ? ?uint16_t ? ? ? ? ? ? ? ? ?len = buf->len; // 數(shù)據(jù)長(zhǎng)度
?
? ? ?// 檢查收到的TID和地址是否與期望的一致
? ? ?if((pData[0] != vendor_model_cli->cli_tid.trans_tid) ||
? ? ? ? (ctx->addr != vendor_model_cli->cli_tid.trans_addr))
? ? ?{
? ? ? ? ?// 更新期望的TID和地址
? ? ? ? ?vendor_model_cli->cli_tid.trans_tid = pData[0];
? ? ? ? ?vendor_model_cli->cli_tid.trans_addr = ctx->addr;
? ? ? ? ?// pData指針指向真正的數(shù)據(jù),跳過(guò)TID
? ? ? ? ?pData++;
? ? ? ? ?len--;
?
? ? ? ? ?// 設(shè)置廠商模型客戶端狀態(tài)參數(shù)
? ? ? ? ?vendor_model_cli_status.vendor_model_cli_Hdr.opcode =
? ? ? ? ? ? ?OP_VENDOR_MESSAGE_TRANSPARENT_MSG;
? ? ? ? ?vendor_model_cli_status.vendor_model_cli_Hdr.status = 0;
? ? ? ? ?vendor_model_cli_status.vendor_model_cli_Event.trans.pdata = pData;
? ? ? ? ?vendor_model_cli_status.vendor_model_cli_Event.trans.len = len;
? ? ? ? ?vendor_model_cli_status.vendor_model_cli_Event.trans.addr = ctx->addr;
? ? ? ? ?vendor_model_cli_status.mydata = (void*)ctx; // 新增的mydata變量記錄ctx
?
? ? ? ? ?// 如果設(shè)置了處理函數(shù),調(diào)用之
? ? ? ? ?if(vendor_model_cli->handler)
? ? ? ? ?{
? ? ? ? ? ? ?vendor_model_cli->handler(&vendor_model_cli_status);
? ? ? ? ?}
? ? ?}
?}

修改vendor_model_cli_rsp_handler函數(shù),在接收到消息后,打印上述獲得的ctx的具體內(nèi)容,即addr、rssi、ttl等,然后定義一個(gè)數(shù)據(jù)data廣播給0xFFFF,即所有節(jié)點(diǎn),這樣在配網(wǎng)器節(jié)點(diǎn)接收到數(shù)據(jù)后就會(huì)向所有入網(wǎng)節(jié)點(diǎn)廣播信息,從而獲得配網(wǎng)器節(jié)點(diǎn)和各個(gè)入網(wǎng)節(jié)點(diǎn)間的rssi等信息

?static void vendor_model_cli_rsp_handler(const vendor_model_cli_status_t *val)
?{
? ? ?// 如果狀態(tài)碼非0,說(shuō)明存在錯(cuò)誤或者超時(shí)未收到應(yīng)答
? ? ?if(val->vendor_model_cli_Hdr.status)
? ? ?{
? ? ? ? ?APP_DBG("Timeout opcode 0x%02x", val->vendor_model_cli_Hdr.opcode); // 打印超時(shí)信息及操作碼
? ? ? ? ?return; // 函數(shù)返回,不處理后續(xù)內(nèi)容
? ? ?}
?
? ? ?// 根據(jù)收到的操作碼執(zhí)行對(duì)應(yīng)的處理
? ? ?if(val->vendor_model_cli_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_MSG)
? ? ?{
? ? ? ? ?// 接收數(shù)據(jù)
? ? ? ? ?struct bt_mesh_msg_ctx *ctx = (struct bt_mesh_msg_ctx *)val->mydata;
? ? ? ? ?if(ctx->addr==0x0001)
? ? ? ? ? ? ?return;
? ? ? ? ?APP_DBG("MYDATA_CLI---src:0x%04x dst:0x%04x rssi:%d app_idx:0x%x recv_ttl:%d send_ttl:%d", ctx->addr, ctx->recv_dst, ctx->recv_rssi, ctx->app_idx, ctx->recv_ttl, ctx->send_ttl);
? ? ? ? ?// 發(fā)送數(shù)據(jù)
? ? ? ? ?uint8_t status;
? ? ? ? ?uint8_t data[4] = {0, 1, 2, 3}; // 準(zhǔn)備要發(fā)送的測(cè)試數(shù)據(jù)
? ? ? ? ?status=vendor_model_cli_send(0xFFFF,data,sizeof(data));
? ? ? ? ?if(status) // 如果發(fā)送失敗,打印錯(cuò)誤狀態(tài)
? ? ? ? ? ? ?APP_DBG("trans failed %d", status);
?
? ? ? ? ?// 將透?jìng)鲾?shù)據(jù)復(fù)制到app_mesh_manage結(jié)構(gòu)中
? ? ? ? ?tmos_memcpy(&app_mesh_manage, val->vendor_model_cli_Event.trans.pdata, val->vendor_model_cli_Event.trans.len);
?
? ? ? ? ?// 根據(jù)透?jìng)鲾?shù)據(jù)的首個(gè)字節(jié)判斷處理邏輯
? ? ? ? ?switch(app_mesh_manage.data.buf[0])
? ? ? ? ?{
? ? ? ? ? ? ?case CMD_DELETE_NODE_ACK: // 應(yīng)用層自定義刪除命令應(yīng)答
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 如果接收到的數(shù)據(jù)長(zhǎng)度不正確,打印錯(cuò)誤信息后返回
? ? ? ? ? ? ? ? ?if(val->vendor_model_cli_Event.trans.len != DELETE_NODE_ACK_DATA_LEN)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("Delete node ack data err!");
? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ? ?}
?
? ? ? ? ? ? ? ? ?// 定義節(jié)點(diǎn)指針,處理刪除節(jié)點(diǎn)的應(yīng)答邏輯
? ? ? ? ? ? ? ? ?node_t *node;
? ? ? ? ? ? ? ? ?// 停止刪除節(jié)點(diǎn)的超時(shí)任務(wù)
? ? ? ? ? ? ? ? ?tmos_stop_task(App_TaskID, APP_DELETE_NODE_TIMEOUT_EVT);
? ? ? ? ? ? ? ? ?// 按地址刪除節(jié)點(diǎn)
? ? ? ? ? ? ? ? ?bt_mesh_node_del_by_addr(val->vendor_model_cli_Event.trans.addr);
? ? ? ? ? ? ? ? ?// 獲取相應(yīng)地址的節(jié)點(diǎn)
? ? ? ? ? ? ? ? ?node = node_get(val->vendor_model_cli_Event.trans.addr);
? ? ? ? ? ? ? ? ?// 設(shè)置節(jié)點(diǎn)為初始化狀態(tài)
? ? ? ? ? ? ? ? ?node->stage.node = NODE_INIT;
? ? ? ? ? ? ? ? ?// 設(shè)置節(jié)點(diǎn)地址為未分配
? ? ? ? ? ? ? ? ?node->node_addr = BLE_MESH_ADDR_UNASSIGNED;
? ? ? ? ? ? ? ? ?// 設(shè)置false,表示節(jié)點(diǎn)不固定(未配網(wǎng)狀態(tài))
? ? ? ? ? ? ? ? ?APP_DBG("Delete node complete"); // 打印節(jié)點(diǎn)刪除成功的信息
? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ?}
? ? ? ? ? ? ?// 可以添加更多的case處理其他消息類(lèi)型
? ? ? ? ?}
? ? ?}
? ? ?else if(val->vendor_model_cli_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_IND)
? ? ?{
?
? ? ?}
? ? ?else if(val->vendor_model_cli_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_WRT)
? ? ?{
? ? ? ? ?// 如果是write類(lèi)型的響應(yīng),這里沒(méi)有做特殊處理
? ? ?}
? ? ?else
? ? ?{
? ? ? ? ?// 未知的操作碼類(lèi)型,打印操作碼信息
? ? ? ? ?APP_DBG("Unknow opcode 0x%02x", val->vendor_model_cli_Hdr.opcode);
? ? ?}
?}

普通入網(wǎng)節(jié)點(diǎn):

1、和配網(wǎng)者節(jié)點(diǎn)類(lèi)似,修改vendor_model_srv_status_t結(jié)構(gòu)體的內(nèi)容,增加一項(xiàng)mydata數(shù)據(jù),用于記錄addr、rssi、ttl等信息

?typedef struct
?{
? ? ?struct vendor_model_srv_EventHdr vendor_model_srv_Hdr;
? ? ?union vendor_model_srv_Event_t ? vendor_model_srv_Event;
? ? ?void* mydata;
?} vendor_model_srv_status_t;

2、利用上述修改后的結(jié)構(gòu)體中增加的mydata變量,在vendor_message_srv_trans函數(shù)中修改廠商模型服務(wù)端狀態(tài)參數(shù)

?static void vendor_message_srv_trans(struct bt_mesh_model ? *model,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf)
?{
? ? ?// 定義Vendor Model服務(wù)狀態(tài)結(jié)構(gòu)體
? ? ?vendor_model_srv_status_t vendor_model_srv_status;
? ? ?uint8_t ? ? ? ? ? ? ? ? ?*pData = buf->data; ?// 指向接收數(shù)據(jù)內(nèi)容的指針
? ? ?uint16_t ? ? ? ? ? ? ? ? ?len = buf->len; ? ? // 接收數(shù)據(jù)的長(zhǎng)度
?
? ? ?// 如果接收到的消息的事務(wù)ID或地址與期望的不同,則記錄并處理該消息
? ? ?if((pData[0] != vendor_model_srv->srv_tid.trans_tid) ||
? ? ? ? (ctx->addr != vendor_model_srv->srv_tid.trans_addr))
? ? ?{
? ? ? ? ?// 更新期望的事務(wù)ID和來(lái)源地址
? ? ? ? ?vendor_model_srv->srv_tid.trans_tid = pData[0];
? ? ? ? ?vendor_model_srv->srv_tid.trans_addr = ctx->addr;
? ? ? ? ?// 跳過(guò)事務(wù)ID
? ? ? ? ?pData++;
? ? ? ? ?len--;
? ? ? ? ?// 設(shè)置狀態(tài)結(jié)構(gòu)體的操作碼和狀態(tài)
? ? ? ? ?vendor_model_srv_status.vendor_model_srv_Hdr.opcode =
? ? ? ? ? ? ?OP_VENDOR_MESSAGE_TRANSPARENT_MSG;
? ? ? ? ?vendor_model_srv_status.vendor_model_srv_Hdr.status = 0;
? ? ? ? ?// 設(shè)置狀態(tài)結(jié)構(gòu)體的事件參數(shù),包括數(shù)據(jù)內(nèi)容、長(zhǎng)度和來(lái)源地址
? ? ? ? ?vendor_model_srv_status.vendor_model_srv_Event.trans.pdata = pData;
? ? ? ? ?vendor_model_srv_status.vendor_model_srv_Event.trans.len = len;
? ? ? ? ?vendor_model_srv_status.vendor_model_srv_Event.trans.addr = ctx->addr;
? ? ? ? ?vendor_model_srv_status.mydata=ctx; // 新增的mydata變量記錄ctx
? ? ? ? ?// 如果存在處理函數(shù),調(diào)用該函數(shù)
? ? ? ? ?if(vendor_model_srv->handler)
? ? ? ? ?{
? ? ? ? ? ? ?vendor_model_srv->handler(&vendor_model_srv_status);
? ? ? ? ?}
? ? ?}
?}

3、修改vendor_model_srv_rsp_handler函數(shù),在接收到消息后,打印上述獲得的ctx的具體內(nèi)容,即addr、rssi、ttl等,然后定義一個(gè)數(shù)據(jù)data廣播給0xFFFF,即所有節(jié)點(diǎn),這樣在入網(wǎng)節(jié)點(diǎn)接收到數(shù)據(jù)后就會(huì)向所有節(jié)點(diǎn)(包括配網(wǎng)器節(jié)點(diǎn)和其他入網(wǎng)節(jié)點(diǎn))廣播信息,從而獲得當(dāng)前入網(wǎng)節(jié)點(diǎn)和其他節(jié)點(diǎn)間的rssi等信息

?static void vendor_model_srv_rsp_handler(const vendor_model_srv_status_t *val)
?{
? ? ?// 如果收到的消息表明有錯(cuò)誤或狀態(tài)不正確
? ? ?if(val->vendor_model_srv_Hdr.status)
? ? ?{
? ? ? ? ?// 如果是因?yàn)閼?yīng)答回復(fù)超時(shí)未收到
? ? ? ? ?APP_DBG("Timeout opcode 0x%02x", val->vendor_model_srv_Hdr.opcode);
? ? ? ? ?return;
? ? ?}
? ? ?// 如果操作碼表示是透?jìng)飨?/span>
? ? ?if(val->vendor_model_srv_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_MSG)
? ? ?{
? ? ? ? ?// 接收
? ? ? ? ?struct bt_mesh_msg_ctx *ctx = (struct bt_mesh_msg_ctx *)val->mydata;
? ? ? ? ?if(ctx->addr==my_addr)
? ? ? ? ? ? ?return;
? ? ? ? ?APP_DBG("MYDATA_SRV---src:0x%04x dst:0x%04x rssi:%d app_idx:0x%x recv_ttl:%d send_ttl:%d", ctx->addr, ctx->recv_dst, ctx->recv_rssi, ctx->app_idx, ctx->recv_ttl, ctx->send_ttl);
?
? ? ? ? ?// 發(fā)送
? ? ? ? ?uint8_t status;
? ? ? ? ?uint8_t data[4] = {0, 1, 2, 3}; // 準(zhǔn)備要發(fā)送的測(cè)試數(shù)據(jù)
? ? ? ? ?status=vendor_model_srv_send(0xFFFF,data,sizeof(data));
? ? ? ? ?if(status) // 如果發(fā)送失敗,打印錯(cuò)誤狀態(tài)
? ? ? ? ? ? ?APP_DBG("trans failed %d", status);
?
? ? ? ? ?// 將收到的數(shù)據(jù)復(fù)制到app_mesh_manage中
? ? ? ? ?tmos_memcpy(&app_mesh_manage, val->vendor_model_srv_Event.trans.pdata, val->vendor_model_srv_Event.trans.len);
? ? ? ? ?// 根據(jù)消息內(nèi)容的第一個(gè)字節(jié)判斷消息類(lèi)型
? ? ? ? ?switch(app_mesh_manage.data.buf[0])
? ? ? ? ?{
? ? ? ? ? ? ?// 如果是刪除節(jié)點(diǎn)的命令
? ? ? ? ? ? ?case CMD_DELETE_NODE:
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 檢查接收到的數(shù)據(jù)長(zhǎng)度是否合理
? ? ? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len != DELETE_NODE_DATA_LEN)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("Delete node data err!");
? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?uint8_t status;
? ? ? ? ? ? ? ? ?// 收到刪除命令,打印信息并發(fā)送ack回信,然后啟動(dòng)延時(shí)以刪除本節(jié)點(diǎn)
? ? ? ? ? ? ? ? ?APP_DBG("receive delete cmd, send ack and start delete node delay");
? ? ? ? ? ? ? ? ?app_mesh_manage.delete_node_ack.cmd = CMD_DELETE_NODE_ACK;
? ? ? ? ? ? ? ? ?status = vendor_model_srv_send(val->vendor_model_srv_Event.trans.addr,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?app_mesh_manage.data.buf, DELETE_NODE_ACK_DATA_LEN);
? ? ? ? ? ? ? ? ?// 如果發(fā)送ack失敗,打印錯(cuò)誤信息
? ? ? ? ? ? ? ? ?if(status)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("send ack failed %d", status);
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?// 向所有節(jié)點(diǎn)發(fā)送命令,告知它們刪除存儲(chǔ)的相關(guān)信息
? ? ? ? ? ? ? ? ?APP_DBG("send to all node to let them delete stored info ");
? ? ? ? ? ? ? ? ?app_mesh_manage.delete_node_info.cmd = CMD_DELETE_NODE_INFO;
? ? ? ? ? ? ? ? ?status = vendor_model_srv_send(BLE_MESH_ADDR_ALL_NODES,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?app_mesh_manage.data.buf, DELETE_NODE_INFO_DATA_LEN);
? ? ? ? ? ? ? ? ?// 如果發(fā)送失敗,則打印錯(cuò)誤信息
? ? ? ? ? ? ? ? ?if(status)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("send ack failed %d", status);
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?// 啟動(dòng)一個(gè)任務(wù),延時(shí)刪除本節(jié)點(diǎn)
? ? ? ? ? ? ? ? ?tmos_start_task(App_TaskID, APP_DELETE_LOCAL_NODE_EVT, APP_DELETE_LOCAL_NODE_DELAY);
? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ?}
? ? ? ? ? ? ?// 如果是有節(jié)點(diǎn)被刪除的命令,需要?jiǎng)h除存儲(chǔ)的該節(jié)點(diǎn)信息
? ? ? ? ? ? ?case CMD_DELETE_NODE_INFO:
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 檢查接收到的數(shù)據(jù)長(zhǎng)度是否合理
? ? ? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len != DELETE_NODE_INFO_DATA_LEN)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("Delete node info data err!");
? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?// 記錄要?jiǎng)h除信息的地址,并啟動(dòng)一個(gè)任務(wù),延時(shí)執(zhí)行刪除操作
? ? ? ? ? ? ? ? ?delete_node_info_address = val->vendor_model_srv_Event.trans.addr;
? ? ? ? ? ? ? ? ?tmos_start_task(App_TaskID, APP_DELETE_NODE_INFO_EVT, APP_DELETE_NODE_INFO_DELAY);
? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ?}
? ? ? ? ? ? ?// 其他情況,不是已知的命令類(lèi)型
? ? ? ? ? ? ?default:
? ? ? ? ? ? ? ? ?APP_DBG("Unknow opcode 0x%02x", val->vendor_model_srv_Hdr.opcode);
? ? ? ? ? ? ? ? ?break;
? ? ? ? ?}
? ? ?}
? ? ?// 如果操作碼表示是寫(xiě)入消息
? ? ?else if(val->vendor_model_srv_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_WRT)
? ? ?{
?
? ? ? ? ?// 收到write數(shù)據(jù),打印長(zhǎng)度和來(lái)源地址
? ? ? ? ?APP_DBG("len %d, from 0x%04x", val->vendor_model_srv_Event.write.len, val->vendor_model_srv_Event.write.addr);
?
? ? ? ? ?// 新增:循環(huán)打印完整的數(shù)據(jù)內(nèi)容
? ? ? ? ?for(int i = 0; i < val->vendor_model_srv_Event.write.len; i++) {
? ? ? ? ? ? ?APP_DBG("data[%d] = 0x%02x", i, val->vendor_model_srv_Event.write.pdata[i]);
? ? ? ? ?}
?
? ? ?}
? ? ?// 如果操作碼表示是確認(rèn)消息
? ? ?else if(val->vendor_model_srv_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_IND)
? ? ?{
? ? ? ? ?// 發(fā)送的indicate已收到應(yīng)答
? ? ?}
? ? ?// 如果操作碼未知
? ? ?else
? ? ?{
? ? ? ? ?// 打印未知的操作碼信息
? ? ? ? ?APP_DBG("Unknow opcode 0x%02x", val->vendor_model_srv_Hdr.opcode);
? ? ?}
?}


實(shí)驗(yàn)流程及現(xiàn)象:

①燒錄程序到配網(wǎng)器節(jié)點(diǎn)和多個(gè)入網(wǎng)節(jié)點(diǎn)(實(shí)驗(yàn)采用4個(gè)普通節(jié)點(diǎn))中,并將所有節(jié)點(diǎn)連接串口,在串口調(diào)試助手中可以看到入網(wǎng)節(jié)點(diǎn)依次分配地址為2、3、4、5。

image-20240327164520717.png

image-20240327164622909.png

。。。

image-20240327164747904.png

②評(píng)估版按下按鍵S4(對(duì)應(yīng)keyPress為3),實(shí)現(xiàn)配網(wǎng)者節(jié)點(diǎn)向0xFFFF地址的所有入網(wǎng)節(jié)點(diǎn)廣播消息,從而開(kāi)啟各節(jié)點(diǎn)信息傳輸功能。此時(shí)可以在配網(wǎng)者節(jié)點(diǎn)對(duì)應(yīng)的串口調(diào)試助手中看到來(lái)自各個(gè)普通節(jié)點(diǎn)的信息以及彼此之間的RSSI值。同時(shí),在各個(gè)普通節(jié)點(diǎn)對(duì)應(yīng)的串口調(diào)試助手中也可以看到和其他節(jié)點(diǎn)間的數(shù)據(jù)傳輸過(guò)程以及彼此之間的RSSI值。

配網(wǎng)器的串口調(diào)試助手:

image-20240327165403690.png

入網(wǎng)節(jié)點(diǎn)2的串口調(diào)試助手:

image-20240327165615974.png

。。。

入網(wǎng)節(jié)點(diǎn)5的串口調(diào)試助手:

image-20240327165916320.png



疑問(wèn):

問(wèn)題①:存在一個(gè)問(wèn)題,當(dāng)按下按鍵開(kāi)始節(jié)點(diǎn)間通信時(shí),剛開(kāi)始的一段時(shí)間內(nèi)可以看到所有節(jié)點(diǎn)彼此之間都可以通信,但是一段時(shí)間后,入網(wǎng)節(jié)點(diǎn)2會(huì)刪除自身節(jié)點(diǎn),其他節(jié)點(diǎn)間正常通信,請(qǐng)問(wèn)該問(wèn)題是什么原因?qū)е碌?,怎么解決?現(xiàn)象如下所示:

image-20240327170406838.png

image-20240327193247443.png

問(wèn)題②:目前是通過(guò)串口調(diào)試助手觀察信息接收情況和RSSI值,且針對(duì)配網(wǎng)者和所有入網(wǎng)節(jié)點(diǎn),每一個(gè)節(jié)點(diǎn)的串口調(diào)試助手中都能看到當(dāng)前節(jié)點(diǎn)和其余節(jié)點(diǎn)間通信的RSSI值,我需要將所有節(jié)點(diǎn)的串口調(diào)試助手中的數(shù)據(jù)傳輸給電腦,在電腦中進(jìn)行后續(xù)處理,已知的方法是通過(guò)串口調(diào)試助手的日志打印成txt文本,然后在電腦中就可以讀取。但是如果不用串口調(diào)試助手,如何把串口中的這些打印數(shù)據(jù)傳給電腦,可以利用wifi模塊么?如果可以,怎么實(shí)現(xiàn)?



熱門(mén)產(chǎn)品 : USB3.0 HUB控制器:CH634

您好,問(wèn)題①中,測(cè)試收發(fā)的數(shù)據(jù)包的內(nèi)容是怎樣的??创诖蛴。鞘盏搅藙h除節(jié)點(diǎn)指令后刪除節(jié)點(diǎn)本身的,可能是數(shù)據(jù)包內(nèi)容恰好是刪除指令。正常運(yùn)行不會(huì)自動(dòng)觸發(fā)刪除節(jié)點(diǎn)命令。

image.png

問(wèn)題②中,是希望無(wú)線傳輸日志到電腦上嗎?

用wifi是可以的,不過(guò)電腦端的上位機(jī)需要自行編寫(xiě),PCB板子上需要增加wifi模塊的成本。如果不用wifi,可以利用2.4G RF射頻信號(hào)來(lái)實(shí)現(xiàn)。mesh節(jié)點(diǎn)是支持2.4G RF射頻+mesh組網(wǎng)在同一套代碼里運(yùn)行的,需要上傳給電腦的信息可以通過(guò)2.4G射頻信號(hào)發(fā)出去;在電腦端插接一個(gè)接收頭,2.4G收到的信號(hào)再通過(guò)USB模擬串口來(lái)輸出給上位機(jī)軟件。

如果有線模式也能接受,是不希望使用USB轉(zhuǎn)串口模塊,MCU上的USB接口是支持模擬COM口,直接給串口助手上位機(jī)發(fā)包的。


感謝您的回復(fù),相關(guān)問(wèn)題已解決?,F(xiàn)在我想在現(xiàn)有實(shí)現(xiàn)節(jié)點(diǎn)間通信的基礎(chǔ)上考慮低功耗休眠問(wèn)題,請(qǐng)問(wèn)是要用到adv_vendor_friend朋友節(jié)點(diǎn)例程和adv_vendor_power例程么,因?yàn)槲椰F(xiàn)在實(shí)現(xiàn)的節(jié)點(diǎn)間相互通信是一直在廣播,節(jié)點(diǎn)接收到其他節(jié)點(diǎn)發(fā)送的數(shù)據(jù)后再發(fā)送,我想設(shè)置成特定時(shí)間間隔廣播一段時(shí)間,然后進(jìn)入休眠模式,從而降低功耗,請(qǐng)問(wèn)應(yīng)該怎么實(shí)現(xiàn)?


您好,adv_vendor_friend和adv_vendor_low_power代碼配合使用,是走的mesh的朋友節(jié)點(diǎn)-低功耗節(jié)點(diǎn)方案,做雙向通信時(shí)可以這樣用。建議在長(zhǎng)供電節(jié)點(diǎn)比較多的場(chǎng)景下使用,比如說(shuō)智能樓宇內(nèi)添置低功耗的溫濕度傳感器。低功耗節(jié)點(diǎn)例程,在配好網(wǎng)后會(huì)按搜索朋友節(jié)點(diǎn)的間隔喚醒;建立朋友關(guān)系后,MCU會(huì)按向朋友節(jié)點(diǎn)拉取消息的間隔喚醒,其他時(shí)間內(nèi)沒(méi)有TMOS事件即可自動(dòng)休眠。

我想設(shè)置成特定時(shí)間間隔廣播一段時(shí)間,然后進(jìn)入休眠模式,從而降低功耗”這個(gè)需求,本身可以通過(guò)adv_vendor開(kāi)HAL_SLEEP去實(shí)現(xiàn),不過(guò)由于休眠期間收不到包,收包沒(méi)有保障,所以只建議在只往外發(fā)包,單向發(fā)包的場(chǎng)景下使用;另外該場(chǎng)景下需要每隔24h打開(kāi)至少持續(xù)10s的接收掃描,用于同步網(wǎng)絡(luò)。


基礎(chǔ)實(shí)驗(yàn):

本節(jié)實(shí)驗(yàn)內(nèi)容采用自配網(wǎng)例程adv_vendor_self_provision進(jìn)行實(shí)驗(yàn)。

使用官方提供的例程,利用Mesh組網(wǎng)實(shí)現(xiàn)通信(3個(gè)節(jié)點(diǎn),從節(jié)點(diǎn)1發(fā)送一個(gè)自定義數(shù)據(jù)給節(jié)點(diǎn)2,節(jié)點(diǎn)2收到數(shù)據(jù)后獲取節(jié)點(diǎn)1和節(jié)點(diǎn)2的RSSI值,并結(jié)合節(jié)點(diǎn)1和節(jié)點(diǎn)2的地址,打包成一個(gè)數(shù)據(jù)包data,并將該數(shù)據(jù)包發(fā)送給節(jié)點(diǎn)3,節(jié)點(diǎn)3收到數(shù)據(jù)data后將該數(shù)據(jù)解析并打印,然后再次打包該數(shù)據(jù)data傳輸給節(jié)點(diǎn)2,節(jié)點(diǎn)2收到來(lái)自節(jié)點(diǎn)3發(fā)送的數(shù)據(jù)data后同樣進(jìn)行解析打印和再次打包,然后發(fā)送給節(jié)點(diǎn)1,最終在節(jié)點(diǎn)1處接收到該數(shù)據(jù)包,解析并打?。ㄔ诠?jié)點(diǎn)1的串口調(diào)試助手中看到數(shù)據(jù)包的具體內(nèi)容)。

實(shí)驗(yàn)芯片連接如下所示,其中節(jié)點(diǎn)1連接一個(gè)功耗分析儀,用于觀察電流:

1.png

實(shí)驗(yàn)所用文件:

CH582官方例程Mesh中的自配網(wǎng)例程adv_vendor_self_provision。

代碼修改部分:代碼通用修改:

1)節(jié)點(diǎn)自配網(wǎng)時(shí)設(shè)置自身地址self_prov_addr。

?// 下面這些常量定義了自配網(wǎng)所需的一些索引和地址信息
?const uint16_t self_prov_net_idx = 0x0000; ? ? ?// 自配網(wǎng)所用的net key索引
?const uint16_t self_prov_app_idx = 0x0001; ? ? ?// 自配網(wǎng)所用的app key索引
?const uint32_t self_prov_iv_index = 0x00000000; // 自配網(wǎng)的IV索引
?const uint16_t self_prov_addr = 0x0001; ? ? ? ? // 自配網(wǎng)的自身主元素地址-----不同節(jié)點(diǎn)要定義不同的節(jié)點(diǎn)地址,比如:節(jié)點(diǎn)3---0x0003
?const uint8_t ?self_prov_flags = 0x00; ? ? ? ? ?// 自配網(wǎng)期間的Key更新標(biāo)志,0表示不在更新?tīng)顟B(tài)
?const uint16_t vendor_sub_addr = 0xC001; ? ? ? ?// 自定義模型的訂閱組地址

2)節(jié)點(diǎn)入網(wǎng)時(shí)添加一段打印函數(shù),用于幫助查看節(jié)點(diǎn)入網(wǎng)情況。

?/*********************************************************************
? * @fn ? ? ?node_cfg_process
? *
? * @brief ? 尋找一個(gè)空閑節(jié)點(diǎn),并且執(zhí)行配置流程
? *
? * @param ? node ? ? ? ?- 空的節(jié)點(diǎn)指針
? * @param ? net_idx ? ? - 網(wǎng)絡(luò)鍵索引
? * @param ? addr ? ? ? ?- 設(shè)備在網(wǎng)絡(luò)中的地址
? * @param ? num_elem ? ?- 元素的數(shù)量
? *
? * @return ?返回節(jié)點(diǎn)類(lèi)型指針,如果失敗則返回NULL
? */
?static node_t *node_cfg_process(node_t *node, uint16_t net_idx, uint16_t addr, uint8_t num_elem)
?{
? ? ?// 此處假定 app_nodes 指向了一個(gè)足夠大的節(jié)點(diǎn)數(shù)組
? ? ?node = app_nodes;
?
? ? ?// 初始化節(jié)點(diǎn)配置
? ? ?node->net_idx = net_idx; ? ?// 設(shè)置網(wǎng)絡(luò)鍵索引
? ? ?node->node_addr = addr; ? ? // 設(shè)置網(wǎng)絡(luò)地址
? ? ?node->elem_count = num_elem; // 設(shè)置元素?cái)?shù)量
?
? ? ?// 以下內(nèi)容為增加的打印函數(shù)
? ? ?APP_DBG("節(jié)點(diǎn)已添加到NVS");
? ? ?APP_DBG("節(jié)點(diǎn)序號(hào)%:d",net_idx);
? ? ?APP_DBG("節(jié)點(diǎn)地址:%d",addr);
? ? ?APP_DBG("節(jié)點(diǎn)元素?cái)?shù)量:%d",num_elem);
?
? ? ?return node; ? ? ? ? ? ? ? ?// 返回節(jié)點(diǎn)指針
?}


首端節(jié)點(diǎn)(節(jié)點(diǎn)1)代碼修改:

1)節(jié)點(diǎn)需要發(fā)送一個(gè)自定義數(shù)據(jù)包,用于開(kāi)啟數(shù)據(jù)發(fā)送功能,這里選擇在APP_Init函數(shù)中加一個(gè)測(cè)試時(shí)間來(lái)實(shí)現(xiàn),代碼如下:

?/*********************************************************************
? * @fn ? ? ?App_Init
? *
? * @brief ? 實(shí)現(xiàn)應(yīng)用層初始化
? *
? * @return ?無(wú)返回值
? */
?void App_Init()
?{
? ? ?// 注冊(cè)處理事件的任務(wù)ID
? ? ?App_TaskID = TMOS_ProcessEventRegister(App_ProcessEvent);
?
? ? ?// 初始化自定義模型服務(wù)器
? ? ?vendor_model_srv_init(vnd_models);
? ? ?// 同步BLE Mesh狀態(tài)并啟用功能
? ? ?blemesh_on_sync();
? ? ?// 初始化按鍵處理器
?// ? ?HAL_KeyInit();
? ? ?// 配置按鍵回調(diào)
?// ? ?HalKeyConfig(keyPress);
?// ? ? 添加一個(gè)測(cè)試任務(wù),定時(shí)向第一個(gè)配網(wǎng)設(shè)備發(fā)送透?jìng)鲾?shù)據(jù),定時(shí)時(shí)長(zhǎng)為4800ms
? ? ?tmos_start_task(App_TaskID, APP_NODE_TEST_EVT, 4800);
?}
?
?/*********************************************************************
? * @fn ? ? ?App_ProcessEvent
? *
? * @brief ? 處理由TMOS來(lái)的應(yīng)用層事件
? *
? * @param ? task_id ?- TMOS分配的任務(wù)ID
? * @param ? events ? - 要處理的事件,這是一個(gè)位圖,可能包含一個(gè)以上的事件
? *
? * @return ?返回未處理的事件
? */
?static uint16_t App_ProcessEvent(uint8_t task_id, uint16_t events)
?{
? ? ?// 處理節(jié)點(diǎn)配置相關(guān)的任務(wù)事件
? ? ?if(events & APP_NODE_EVT)
? ? ?{
? ? ? ? ?// 配置本地網(wǎng)絡(luò)信息
? ? ? ? ?cfg_local_net_info();
? ? ? ? ?// 將事件標(biāo)記為已處理
? ? ? ? ?return (events ^ APP_NODE_EVT);
? ? ?}
?
? ? ?// 處理測(cè)試任務(wù)事件
? ? ?if(events & APP_NODE_TEST_EVT)
? ? ?{
? ? ? ? ?uint8_t status;
? ? ? ? ?uint8_t data[4] = {0, 1, 2, 3}; // 準(zhǔn)備要發(fā)送的測(cè)試數(shù)據(jù)
? ? ? ? ?status = vendor_model_srv_send(vendor_sub_addr, data, sizeof(data));
? ? ? ? ?if(status) // 如果發(fā)送失敗,打印錯(cuò)誤狀態(tài)
? ? ? ? ? ? ?APP_DBG("trans failed %d", status);
?
? ? ? ? ?tmos_start_task(App_TaskID, APP_NODE_TEST_EVT, 3000);
?
? ? ? ? ?return (events ^ APP_NODE_TEST_EVT);
? ? ?}
?
? ? ?// 如果設(shè)定刪除節(jié)點(diǎn)的超時(shí)事件已到,則處理超時(shí)邏輯
? ? ?if(events & APP_DELETE_NODE_TIMEOUT_EVT)
? ? ?{
? ? ? ? ?// 通過(guò)應(yīng)用層自定義協(xié)議未能刪除節(jié)點(diǎn)的超時(shí)處理,可以在此添加更多的處理邏輯
? ? ? ? ?APP_DBG("Delete node failed");
? ? ? ? ?// 將事件標(biāo)記為已處理
? ? ? ? ?return (events ^ APP_DELETE_NODE_TIMEOUT_EVT);
? ? ?}
?
? ? ?// 如果收到刪除本地節(jié)點(diǎn)的命令則執(zhí)行刪除流程
? ? ?if(events & APP_DELETE_LOCAL_NODE_EVT)
? ? ?{
? ? ? ? ?// 收到刪除命令,開(kāi)始刪除本地網(wǎng)絡(luò)信息
? ? ? ? ?APP_DBG("Delete local node");
? ? ? ? ?// 重置本地的網(wǎng)絡(luò)狀態(tài)
? ? ? ? ?bt_mesh_reset();
? ? ? ? ?// 將事件標(biāo)記為已處理
? ? ? ? ?return (events ^ APP_DELETE_LOCAL_NODE_EVT);
? ? ?}
?
? ? ?// 如果設(shè)定了刪除存儲(chǔ)的節(jié)點(diǎn)信息事件,則執(zhí)行刪除流程
? ? ?if(events & APP_DELETE_NODE_INFO_EVT)
? ? ?{
? ? ? ? ?// 刪除已存儲(chǔ)的被刪除節(jié)點(diǎn)的信息
? ? ? ? ?bt_mesh_delete_node_info(delete_node_info_address, app_comp.elem_count);
? ? ? ? ?APP_DBG("Delete stored node info complete");
? ? ? ? ?// 將事件標(biāo)記為已處理
? ? ? ? ?return (events ^ APP_DELETE_NODE_INFO_EVT);
? ? ?}
?
? ? ?// 丟棄未能識(shí)別的事件
? ? ?return 0;
?}

2)節(jié)點(diǎn)1作為首端節(jié)點(diǎn),除了通開(kāi)啟發(fā)送數(shù)據(jù)功能,還要設(shè)置接收數(shù)據(jù)時(shí)的相應(yīng)處理:當(dāng)接收到來(lái)自節(jié)點(diǎn)2的信息pdata時(shí),解析數(shù)據(jù)包pdata,并打印數(shù)據(jù)包內(nèi)容。

?/*********************************************************************
? * @fn ? ? ?vendor_model_srv_rsp_handler
? *
? * @brief ? 處理自定義模型服務(wù)的回調(diào)事件
? *
? * @param ? val ? ? - 回調(diào)參數(shù),包含消息類(lèi)型、數(shù)據(jù)內(nèi)容、長(zhǎng)度、來(lái)源地址
? *
? * @return ?無(wú)返回值
? */
?static void vendor_model_srv_rsp_handler(const vendor_model_srv_status_t *val)
?{
? ? ?// 檢查命令執(zhí)行狀態(tài),如果超時(shí)未收到應(yīng)答則打印提示信息
? ? ?if(val->vendor_model_srv_Hdr.status)
? ? ?{
? ? ? ? ?APP_DBG("Timeout opcode 0x%02x", val->vendor_model_srv_Hdr.opcode);
? ? ? ? ?return;
? ? ?}
? ? ?// 根據(jù)操作碼執(zhí)行相應(yīng)的操作
? ? ?if(val->vendor_model_srv_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_MSG)
? ? ?{
? ? ? ? ?// 接收
? ? ? ? ?struct bt_mesh_msg_ctx *ctx = (struct bt_mesh_msg_ctx *)val->mydata;
?
? ? ? ? ?if(ctx->addr==0x0002)
? ? ? ? ?{
? ? ? ? ? ? ?// 確保接收到的數(shù)據(jù)長(zhǎng)度至少為5個(gè)字節(jié)
? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len >= 5) {
? ? ? ? ? ? ? ? ?// 解析數(shù)據(jù)
? ? ? ? ? ? ? ? ?uint16_t src_addr = val->vendor_model_srv_Event.trans.pdata[0] + (val->vendor_model_srv_Event.trans.pdata[1] << 8);
? ? ? ? ? ? ? ? ?uint16_t my_addr = val->vendor_model_srv_Event.trans.pdata[2] + (val->vendor_model_srv_Event.trans.pdata[3] << 8);
? ? ? ? ? ? ? ? ?int8_t rssi = val->vendor_model_srv_Event.trans.pdata[4];
?
? ? ? ? ? ? ? ? ?// 打印解析后的數(shù)據(jù)
? ? ? ? ? ? ? ? ?APP_DBG("src: 0x%04x, my_addr: 0x%04x, rssi: %d", src_addr, my_addr, rssi);
? ? ? ? ? ? ?} else {
? ? ? ? ? ? ? ? ?APP_DBG("Received data is too short.");
? ? ? ? ? ? ?}
? ? ? ? ?}
?
? ? ? ? ?// 根據(jù)收到的消息內(nèi)容進(jìn)行處理
? ? ? ? ?tmos_memcpy(&app_mesh_manage, val->vendor_model_srv_Event.trans.pdata, val->vendor_model_srv_Event.trans.len);
? ? ? ? ?// 判斷消息類(lèi)型并執(zhí)行相應(yīng)的邏輯
? ? ? ? ?switch(app_mesh_manage.data.buf[0])
? ? ? ? ?{
? ? ? ? ? ? ?// 處理節(jié)點(diǎn)刪除命令
? ? ? ? ? ? ?case CMD_DELETE_NODE:
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 校驗(yàn)數(shù)據(jù)長(zhǎng)度
? ? ? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len != DELETE_NODE_DATA_LEN)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("Delete node data err!");
? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?uint8_t status;
? ? ? ? ? ? ? ? ?APP_DBG("receive delete cmd, send ack and start delete node delay");
? ? ? ? ? ? ? ? ?// 設(shè)置回復(fù)命令并發(fā)送應(yīng)答
? ? ? ? ? ? ? ? ?app_mesh_manage.delete_node_ack.cmd = CMD_DELETE_NODE_ACK;
? ? ? ? ? ? ? ? ?status = vendor_model_srv_send(val->vendor_model_srv_Event.trans.addr,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? app_mesh_manage.data.buf, DELETE_NODE_ACK_DATA_LEN);
? ? ? ? ? ? ? ? ?if(status)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("send ack failed %d", status);
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?// 發(fā)送全網(wǎng)命令以刪除存儲(chǔ)信息,并設(shè)置刪除延遲
? ? ? ? ? ? ? ? ?APP_DBG("send to all nodes to let them delete stored info ");
? ? ? ? ? ? ? ? ?app_mesh_manage.delete_node_info.cmd = CMD_DELETE_NODE_INFO;
? ? ? ? ? ? ? ? ?status = vendor_model_srv_send(BLE_MESH_ADDR_ALL_NODES,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? app_mesh_manage.data.buf, DELETE_NODE_INFO_DATA_LEN);
? ? ? ? ? ? ? ? ?if(status)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("send failed %d", status);
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?tmos_start_task(App_TaskID, APP_DELETE_LOCAL_NODE_EVT, APP_DELETE_LOCAL_NODE_DELAY);
? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ?}
?
? ? ? ? ? ? ?// 處理節(jié)點(diǎn)刪除的應(yīng)答命令
? ? ? ? ? ? ?case CMD_DELETE_NODE_ACK:
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 檢查數(shù)據(jù)長(zhǎng)度
? ? ? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len != DELETE_NODE_ACK_DATA_LEN)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("Delete node ack data err!");
? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?// 刪除完畢,取消刪除超時(shí)定時(shí)器
? ? ? ? ? ? ? ? ?tmos_stop_task(App_TaskID, APP_DELETE_NODE_TIMEOUT_EVT);
? ? ? ? ? ? ? ? ?APP_DBG("Delete node complete");
? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ?}
?
? ? ? ? ? ? ?// 處理命令以刪除存儲(chǔ)的節(jié)點(diǎn)信息
? ? ? ? ? ? ?case CMD_DELETE_NODE_INFO:
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 檢查數(shù)據(jù)長(zhǎng)度
? ? ? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len != DELETE_NODE_INFO_DATA_LEN)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("Delete node info data err!");
? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?// 記錄刪除的節(jié)點(diǎn)地址并設(shè)置刪除信息事件
? ? ? ? ? ? ? ? ?delete_node_info_address = val->vendor_model_srv_Event.trans.addr;
? ? ? ? ? ? ? ? ?tmos_start_task(App_TaskID, APP_DELETE_NODE_INFO_EVT, APP_DELETE_NODE_INFO_DELAY);
? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ?}
? ? ? ? ?}
? ? ?}
? ? ?else if(val->vendor_model_srv_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_WRT)
? ? ?{
? ? ? ? ?// 收到write請(qǐng)求時(shí)的相關(guān)處理,暫時(shí)未定義
? ? ?}
? ? ?else if(val->vendor_model_srv_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_IND)
? ? ?{
? ? ? ? ?// 當(dāng)indicate消息得到確認(rèn)時(shí)的相關(guān)處理,暫時(shí)未定義
? ? ?}
? ? ?else
? ? ?{
? ? ? ? ?// 打印未知操作碼的信息
? ? ? ? ?APP_DBG("Unknown opcode 0x%02x", val->vendor_model_srv_Hdr.opcode);
? ? ?}
?}

中間節(jié)點(diǎn)(節(jié)點(diǎn)2)代碼修改:

?/*********************************************************************
? * @fn ? ? ?vendor_model_srv_rsp_handler
? *
? * @brief ? 處理自定義模型服務(wù)的回調(diào)事件
? *
? * @param ? val ? ? - 回調(diào)參數(shù),包含消息類(lèi)型、數(shù)據(jù)內(nèi)容、長(zhǎng)度、來(lái)源地址
? *
? * @return ?無(wú)返回值
? */
?static void vendor_model_srv_rsp_handler(const vendor_model_srv_status_t *val)
?{
? ? ?// 檢查命令執(zhí)行狀態(tài),如果超時(shí)未收到應(yīng)答則打印提示信息
? ? ?if(val->vendor_model_srv_Hdr.status)
? ? ?{
? ? ? ? ?APP_DBG("Timeout opcode 0x%02x", val->vendor_model_srv_Hdr.opcode);
? ? ? ? ?return;
? ? ?}
? ? ?// 根據(jù)操作碼執(zhí)行相應(yīng)的操作
? ? ?if(val->vendor_model_srv_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_MSG)
? ? ?{
? ? ? ? ?// 接收
? ? ? ? ?struct bt_mesh_msg_ctx *ctx = (struct bt_mesh_msg_ctx *)val->mydata;
? ? ? ? ?// 當(dāng)接收到來(lái)自0x0001節(jié)點(diǎn)的信息后,會(huì)向0x0003節(jié)點(diǎn)發(fā)送信息
? ? ? ? ?if(ctx->addr==0x0001)
? ? ? ? ?{
? ? ? ? ? ? ?// 發(fā)送
? ? ? ? ? ? ?uint8_t status;
? ? ? ? ? ? ?// 準(zhǔn)備要發(fā)送的數(shù)據(jù)
? ? ? ? ? ? ?uint8_t sendData[5]; // 2 bytes for ctx->addr, 2 bytes for my_addr, and 1 byte for ctx->recv_rssi
? ? ? ? ? ? ?// 打包數(shù)據(jù)
? ? ? ? ? ? ?// 注意: 這里假設(shè)系統(tǒng)為小端字節(jié)序,如果是大端字節(jié)序需要調(diào)整
? ? ? ? ? ? ?memcpy(sendData, &ctx->addr, 2); // 復(fù)制ctx->addr
? ? ? ? ? ? ?memcpy(sendData + 2, &self_prov_addr, 2); // 復(fù)制my_addr
? ? ? ? ? ? ?// 由于rssi是int8_t,直接將其值賦給數(shù)組的相應(yīng)位置
? ? ? ? ? ? ?sendData[4] = ctx->recv_rssi; // 復(fù)制ctx->recv_rssi
? ? ? ? ? ? ?status=vendor_model_srv_send(0x0003,sendData,sizeof(sendData));
? ? ? ? ? ? ?if(status) // 如果發(fā)送失敗,打印錯(cuò)誤狀態(tài)
? ? ? ? ? ? ? ? ?APP_DBG("trans failed %d", status);
? ? ? ? ?}
?
? ? ? ? ?// 當(dāng)接收到來(lái)自0x0003節(jié)點(diǎn)的信息pdata后,會(huì)向0x0001節(jié)點(diǎn)發(fā)送該pdata信息
? ? ? ? ?if(ctx->addr==0x0003)
? ? ? ? ?{
? ? ? ? ? ? ?// 確保接收到的數(shù)據(jù)長(zhǎng)度至少為5個(gè)字節(jié)
? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len >= 5) {
? ? ? ? ? ? ? ? ?// 解析數(shù)據(jù)
? ? ? ? ? ? ? ? ?uint16_t src_addr = val->vendor_model_srv_Event.trans.pdata[0] + (val->vendor_model_srv_Event.trans.pdata[1] << 8);
? ? ? ? ? ? ? ? ?uint16_t my_addr = val->vendor_model_srv_Event.trans.pdata[2] + (val->vendor_model_srv_Event.trans.pdata[3] << 8);
? ? ? ? ? ? ? ? ?int8_t rssi = val->vendor_model_srv_Event.trans.pdata[4];
?
? ? ? ? ? ? ? ? ?// 打印解析后的數(shù)據(jù)
? ? ? ? ? ? ? ? ?APP_DBG("src: 0x%04x, my_addr: 0x%04x, rssi: %d", src_addr, my_addr, rssi);
?
? ? ? ? ? ? ? ? ?// 將該解析數(shù)據(jù)pdata發(fā)送給0x0001
? ? ? ? ? ? ? ? ?uint8_t status;
? ? ? ? ? ? ? ? ?// 準(zhǔn)備要發(fā)送的數(shù)據(jù)
? ? ? ? ? ? ? ? ?uint8_t sendData[5]; // 2 bytes for src_addr, 2 bytes for my_addr, and 1 byte for rssi
? ? ? ? ? ? ? ? ?// 打包數(shù)據(jù)
? ? ? ? ? ? ? ? ?// 注意: 這里假設(shè)系統(tǒng)為小端字節(jié)序,如果是大端字節(jié)序需要調(diào)整
? ? ? ? ? ? ? ? ?memcpy(sendData, &src_addr, 2); // 復(fù)制ctx->addr
? ? ? ? ? ? ? ? ?memcpy(sendData + 2, &my_addr, 2); // 復(fù)制my_addr
? ? ? ? ? ? ? ? ?// 由于rssi是int8_t,直接將其值賦給數(shù)組的相應(yīng)位置
? ? ? ? ? ? ? ? ?sendData[4] = rssi; // 復(fù)制ctx->recv_rssi
? ? ? ? ? ? ? ? ?status=vendor_model_srv_send(0x0001,sendData,sizeof(sendData));
? ? ? ? ? ? ? ? ?if(status) // 如果發(fā)送失敗,打印錯(cuò)誤狀態(tài)
? ? ? ? ? ? ? ? ? ? ?APP_DBG("trans failed %d", status);
?
? ? ? ? ? ? ?} else {
? ? ? ? ? ? ? ? ?APP_DBG("Received data is too short.");
? ? ? ? ? ? ?}
? ? ? ? ?}
? ? ? ? ?// 根據(jù)收到的消息內(nèi)容進(jìn)行處理
? ? ? ? ?tmos_memcpy(&app_mesh_manage, val->vendor_model_srv_Event.trans.pdata, val->vendor_model_srv_Event.trans.len);
? ? ? ? ?// 判斷消息類(lèi)型并執(zhí)行相應(yīng)的邏輯
? ? ? ? ?switch(app_mesh_manage.data.buf[0])
? ? ? ? ?{
? ? ? ? ? ? ?// 處理節(jié)點(diǎn)刪除命令
? ? ? ? ? ? ?case CMD_DELETE_NODE:
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 校驗(yàn)數(shù)據(jù)長(zhǎng)度
? ? ? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len != DELETE_NODE_DATA_LEN)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("Delete node data err!");
? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?uint8_t status;
? ? ? ? ? ? ? ? ?APP_DBG("receive delete cmd, send ack and start delete node delay");
? ? ? ? ? ? ? ? ?// 設(shè)置回復(fù)命令并發(fā)送應(yīng)答
? ? ? ? ? ? ? ? ?app_mesh_manage.delete_node_ack.cmd = CMD_DELETE_NODE_ACK;
? ? ? ? ? ? ? ? ?status = vendor_model_srv_send(val->vendor_model_srv_Event.trans.addr,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? app_mesh_manage.data.buf, DELETE_NODE_ACK_DATA_LEN);
? ? ? ? ? ? ? ? ?if(status)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("send ack failed %d", status);
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?// 發(fā)送全網(wǎng)命令以刪除存儲(chǔ)信息,并設(shè)置刪除延遲
? ? ? ? ? ? ? ? ?APP_DBG("send to all nodes to let them delete stored info ");
? ? ? ? ? ? ? ? ?app_mesh_manage.delete_node_info.cmd = CMD_DELETE_NODE_INFO;
? ? ? ? ? ? ? ? ?status = vendor_model_srv_send(BLE_MESH_ADDR_ALL_NODES,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? app_mesh_manage.data.buf, DELETE_NODE_INFO_DATA_LEN);
? ? ? ? ? ? ? ? ?if(status)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("send failed %d", status);
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?tmos_start_task(App_TaskID, APP_DELETE_LOCAL_NODE_EVT, APP_DELETE_LOCAL_NODE_DELAY);
? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ?}
?
? ? ? ? ? ? ?// 處理節(jié)點(diǎn)刪除的應(yīng)答命令
? ? ? ? ? ? ?case CMD_DELETE_NODE_ACK:
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 檢查數(shù)據(jù)長(zhǎng)度
? ? ? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len != DELETE_NODE_ACK_DATA_LEN)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("Delete node ack data err!");
? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?// 刪除完畢,取消刪除超時(shí)定時(shí)器
? ? ? ? ? ? ? ? ?tmos_stop_task(App_TaskID, APP_DELETE_NODE_TIMEOUT_EVT);
? ? ? ? ? ? ? ? ?APP_DBG("Delete node complete");
? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ?}
?
? ? ? ? ? ? ?// 處理命令以刪除存儲(chǔ)的節(jié)點(diǎn)信息
? ? ? ? ? ? ?case CMD_DELETE_NODE_INFO:
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 檢查數(shù)據(jù)長(zhǎng)度
? ? ? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len != DELETE_NODE_INFO_DATA_LEN)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("Delete node info data err!");
? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?// 記錄刪除的節(jié)點(diǎn)地址并設(shè)置刪除信息事件
? ? ? ? ? ? ? ? ?delete_node_info_address = val->vendor_model_srv_Event.trans.addr;
? ? ? ? ? ? ? ? ?tmos_start_task(App_TaskID, APP_DELETE_NODE_INFO_EVT, APP_DELETE_NODE_INFO_DELAY);
? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ?}
? ? ? ? ?}
? ? ?}
? ? ?else if(val->vendor_model_srv_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_WRT)
? ? ?{
? ? ? ? ?// 收到write請(qǐng)求時(shí)的相關(guān)處理,暫時(shí)未定義
? ? ?}
? ? ?else if(val->vendor_model_srv_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_IND)
? ? ?{
? ? ? ? ?// 當(dāng)indicate消息得到確認(rèn)時(shí)的相關(guān)處理,暫時(shí)未定義
? ? ?}
? ? ?else
? ? ?{
? ? ? ? ?// 打印未知操作碼的信息
? ? ? ? ?APP_DBG("Unknown opcode 0x%02x", val->vendor_model_srv_Hdr.opcode);
? ? ?}
?}

尾端節(jié)點(diǎn)(節(jié)點(diǎn)3)代碼修改:

?/*********************************************************************
? * @fn ? ? ?vendor_model_srv_rsp_handler
? *
? * @brief ? 處理自定義模型服務(wù)的回調(diào)事件
? *
? * @param ? val ? ? - 回調(diào)參數(shù),包含消息類(lèi)型、數(shù)據(jù)內(nèi)容、長(zhǎng)度、來(lái)源地址
? *
? * @return ?無(wú)返回值
? */
?static void vendor_model_srv_rsp_handler(const vendor_model_srv_status_t *val)
?{
? ? ?// 檢查命令執(zhí)行狀態(tài),如果超時(shí)未收到應(yīng)答則打印提示信息
? ? ?if(val->vendor_model_srv_Hdr.status)
? ? ?{
? ? ? ? ?APP_DBG("Timeout opcode 0x%02x", val->vendor_model_srv_Hdr.opcode);
? ? ? ? ?return;
? ? ?}
? ? ?// 根據(jù)操作碼執(zhí)行相應(yīng)的操作
? ? ?if(val->vendor_model_srv_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_MSG)
? ? ?{
? ? ? ? ?// 接收
? ? ? ? ?struct bt_mesh_msg_ctx *ctx = (struct bt_mesh_msg_ctx *)val->mydata;
?
? ? ? ? ?// 當(dāng)接收到來(lái)自0x0002節(jié)點(diǎn)的信息后,會(huì)向0x0002節(jié)點(diǎn)發(fā)送信息
? ? ? ? ?if(ctx->addr==0x0002)
? ? ? ? ?{
? ? ? ? ? ? ?// 確保接收到的數(shù)據(jù)長(zhǎng)度至少為5個(gè)字節(jié)
? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len >= 5) {
? ? ? ? ? ? ? ? ?// 解析數(shù)據(jù)
? ? ? ? ? ? ? ? ?uint16_t src_addr = val->vendor_model_srv_Event.trans.pdata[0] + (val->vendor_model_srv_Event.trans.pdata[1] << 8);
? ? ? ? ? ? ? ? ?uint16_t my_addr = val->vendor_model_srv_Event.trans.pdata[2] + (val->vendor_model_srv_Event.trans.pdata[3] << 8);
? ? ? ? ? ? ? ? ?int8_t rssi = val->vendor_model_srv_Event.trans.pdata[4];
?
? ? ? ? ? ? ? ? ?// 打印解析后的數(shù)據(jù)
? ? ? ? ? ? ? ? ?APP_DBG("src: 0x%04x, my_addr: 0x%04x, rssi: %d", src_addr, my_addr, rssi);
?
? ? ? ? ? ? ? ? ?// 將該解析數(shù)據(jù)pdata發(fā)送給0x0002
? ? ? ? ? ? ? ? ?uint8_t status;
? ? ? ? ? ? ? ? ?// 準(zhǔn)備要發(fā)送的數(shù)據(jù)
? ? ? ? ? ? ? ? ?uint8_t sendData[5]; // 2 bytes for src_addr, 2 bytes for my_addr, and 1 byte for rssi
? ? ? ? ? ? ? ? ?// 打包數(shù)據(jù)
? ? ? ? ? ? ? ? ?// 注意: 這里假設(shè)系統(tǒng)為小端字節(jié)序,如果是大端字節(jié)序需要調(diào)整
? ? ? ? ? ? ? ? ?memcpy(sendData, &src_addr, 2); // 復(fù)制ctx->addr
? ? ? ? ? ? ? ? ?memcpy(sendData + 2, &my_addr, 2); // 復(fù)制my_addr
? ? ? ? ? ? ? ? ?// 由于rssi是int8_t,直接將其值賦給數(shù)組的相應(yīng)位置
? ? ? ? ? ? ? ? ?sendData[4] = rssi; // 復(fù)制ctx->recv_rssi
? ? ? ? ? ? ? ? ?status=vendor_model_srv_send(0x0002,sendData,sizeof(sendData));
? ? ? ? ? ? ? ? ?if(status) // 如果發(fā)送失敗,打印錯(cuò)誤狀態(tài)
? ? ? ? ? ? ? ? ? ? ?APP_DBG("trans failed %d", status);
?
? ? ? ? ? ? ?} else {
? ? ? ? ? ? ? ? ?APP_DBG("Received data is too short.");
? ? ? ? ? ? ?}
? ? ? ? ?}
?
? ? ? ? ?// 根據(jù)收到的消息內(nèi)容進(jìn)行處理
? ? ? ? ?tmos_memcpy(&app_mesh_manage, val->vendor_model_srv_Event.trans.pdata, val->vendor_model_srv_Event.trans.len);
? ? ? ? ?// 判斷消息類(lèi)型并執(zhí)行相應(yīng)的邏輯
? ? ? ? ?switch(app_mesh_manage.data.buf[0])
? ? ? ? ?{
? ? ? ? ? ? ?// 處理節(jié)點(diǎn)刪除命令
? ? ? ? ? ? ?case CMD_DELETE_NODE:
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 校驗(yàn)數(shù)據(jù)長(zhǎng)度
? ? ? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len != DELETE_NODE_DATA_LEN)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("Delete node data err!");
? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?uint8_t status;
? ? ? ? ? ? ? ? ?APP_DBG("receive delete cmd, send ack and start delete node delay");
? ? ? ? ? ? ? ? ?// 設(shè)置回復(fù)命令并發(fā)送應(yīng)答
? ? ? ? ? ? ? ? ?app_mesh_manage.delete_node_ack.cmd = CMD_DELETE_NODE_ACK;
? ? ? ? ? ? ? ? ?status = vendor_model_srv_send(val->vendor_model_srv_Event.trans.addr,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? app_mesh_manage.data.buf, DELETE_NODE_ACK_DATA_LEN);
? ? ? ? ? ? ? ? ?if(status)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("send ack failed %d", status);
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?// 發(fā)送全網(wǎng)命令以刪除存儲(chǔ)信息,并設(shè)置刪除延遲
? ? ? ? ? ? ? ? ?APP_DBG("send to all nodes to let them delete stored info ");
? ? ? ? ? ? ? ? ?app_mesh_manage.delete_node_info.cmd = CMD_DELETE_NODE_INFO;
? ? ? ? ? ? ? ? ?status = vendor_model_srv_send(BLE_MESH_ADDR_ALL_NODES,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? app_mesh_manage.data.buf, DELETE_NODE_INFO_DATA_LEN);
? ? ? ? ? ? ? ? ?if(status)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("send failed %d", status);
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?tmos_start_task(App_TaskID, APP_DELETE_LOCAL_NODE_EVT, APP_DELETE_LOCAL_NODE_DELAY);
? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ?}
?
? ? ? ? ? ? ?// 處理節(jié)點(diǎn)刪除的應(yīng)答命令
? ? ? ? ? ? ?case CMD_DELETE_NODE_ACK:
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 檢查數(shù)據(jù)長(zhǎng)度
? ? ? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len != DELETE_NODE_ACK_DATA_LEN)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("Delete node ack data err!");
? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?// 刪除完畢,取消刪除超時(shí)定時(shí)器
? ? ? ? ? ? ? ? ?tmos_stop_task(App_TaskID, APP_DELETE_NODE_TIMEOUT_EVT);
? ? ? ? ? ? ? ? ?APP_DBG("Delete node complete");
? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ?}
?
? ? ? ? ? ? ?// 處理命令以刪除存儲(chǔ)的節(jié)點(diǎn)信息
? ? ? ? ? ? ?case CMD_DELETE_NODE_INFO:
? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ?// 檢查數(shù)據(jù)長(zhǎng)度
? ? ? ? ? ? ? ? ?if(val->vendor_model_srv_Event.trans.len != DELETE_NODE_INFO_DATA_LEN)
? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?APP_DBG("Delete node info data err!");
? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?// 記錄刪除的節(jié)點(diǎn)地址并設(shè)置刪除信息事件
? ? ? ? ? ? ? ? ?delete_node_info_address = val->vendor_model_srv_Event.trans.addr;
? ? ? ? ? ? ? ? ?tmos_start_task(App_TaskID, APP_DELETE_NODE_INFO_EVT, APP_DELETE_NODE_INFO_DELAY);
? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ?}
? ? ? ? ?}
? ? ?}
? ? ?else if(val->vendor_model_srv_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_WRT)
? ? ?{
? ? ? ? ?// 收到write請(qǐng)求時(shí)的相關(guān)處理,暫時(shí)未定義
? ? ?}
? ? ?else if(val->vendor_model_srv_Hdr.opcode == OP_VENDOR_MESSAGE_TRANSPARENT_IND)
? ? ?{
? ? ? ? ?// 當(dāng)indicate消息得到確認(rèn)時(shí)的相關(guān)處理,暫時(shí)未定義
? ? ?}
? ? ?else
? ? ?{
? ? ? ? ?// 打印未知操作碼的信息
? ? ? ? ?APP_DBG("Unknown opcode 0x%02x", val->vendor_model_srv_Hdr.opcode);
? ? ?}
?}


基礎(chǔ)實(shí)驗(yàn)的實(shí)驗(yàn)現(xiàn)象:

節(jié)點(diǎn)1所連功耗分析儀顯示如下:

12ms時(shí)間顯示比例下:

2.png

120ms時(shí)間顯示比例下:

3.png

節(jié)點(diǎn)2串口調(diào)試助手:

4.png

節(jié)點(diǎn)3串口調(diào)試助手:

5.png

問(wèn)題:

在實(shí)現(xiàn)上述業(yè)務(wù)的基礎(chǔ)上,我想降低節(jié)點(diǎn)的功耗,考慮的是參考文章在TMOS系統(tǒng)中手動(dòng)管理休眠 和文章CH582開(kāi)啟睡眠模式下低功耗測(cè)試來(lái)實(shí)現(xiàn),嘗試在節(jié)點(diǎn)1的測(cè)試事件APP_NODE_TEST_EVT中發(fā)送測(cè)試數(shù)據(jù)后添加一段相關(guān)代碼,具體如下:

? ? ?// 處理測(cè)試任務(wù)事件
? ? ?if(events & APP_NODE_TEST_EVT)
? ? ?{
? ? ? ? ?uint8_t status;
? ? ? ? ?uint8_t data[4] = {0, 1, 2, 3}; // 準(zhǔn)備要發(fā)送的測(cè)試數(shù)據(jù)
? ? ? ? ?status = vendor_model_srv_send(vendor_sub_addr, data, sizeof(data));
? ? ? ? ?if(status) // 如果發(fā)送失敗,打印錯(cuò)誤狀態(tài)
? ? ? ? ? ? ?APP_DBG("trans failed %d", status);
?
? ? ? ? ?tmos_start_task(App_TaskID, APP_NODE_TEST_EVT, 3000);
?
? ? ? ? ?PRINT("sleep mode sleep \n");
?
? ? ? ? ?DelayMs(5);
?
? ? ? ? ?RTC_TMRFunCfg(Period_2_S);/* 定時(shí)1s的RTC鬧鐘 */
? ? ? ? ?PWR_PeriphWakeUpCfg( ENABLE, RB_SLP_RTC_WAKE, Short_Delay );/* 使能RTC中斷喚醒源 */
?
? ? ? ? ?PFIC_EnableIRQ(RTC_IRQn);/* 使能RTC中斷 */
? ? ? ? ?/* 注意當(dāng)主頻為80M時(shí),Sleep睡眠喚醒中斷不可調(diào)用flash內(nèi)代碼 */
? ? ? ? ?LowPower_Sleep(RB_PWR_RAM30K | RB_PWR_RAM2K); /* 只保留30+2K SRAM 供電 */
? ? ? ? ?HSECFG_Current(HSE_RCur_100); ? ? ? ? ? ? ? ? /* 降為額定電流(低功耗函數(shù)中提升了HSE偏置電流) */
? ? ? ? ?PFIC_DisableIRQ(RTC_IRQn);
?
? ? ? ? ?DelayMs(5);
? ? ? ? ?PRINT("wake.. \n");
? ? ? ? ?DelayMs(20);
?
? ? ? ? ?// 清除測(cè)試任務(wù)事件標(biāo)志
? ? ? ? ?return (events ^ APP_NODE_TEST_EVT);
? ? ?}

RTC中斷處理函數(shù)修改如下:

?/*******************************************************************************
? * @fn ? ? ?RTC_IRQHandler
? *
? * @brief ? RTC中斷處理
? *
? * @param ? None.
? *
? * @return ?None.
? */
?__INTERRUPT
?__HIGH_CODE
?void RTC_IRQHandler(void)
?{
?// ? ?R8_RTC_FLAG_CTRL = (RB_RTC_TMR_CLR | RB_RTC_TRIG_CLR);
?// ? ?RTCTigFlag = 1;
?
? ? ?if (RTC_GetITFlag(RTC_TMR_EVENT))
? ? ?{
? ? ? ? ?RTC_ClearITFlag(RTC_TMR_EVENT);
? ? ?}
?}

然后重新燒錄程序,觀察現(xiàn)象如下:

6.png

串口調(diào)試助手中觀察到節(jié)點(diǎn)1休眠后會(huì)復(fù)位,代碼PRINT("wake.. \n");打印的wake提示也沒(méi)有,同時(shí)在功耗儀上觀察電流如下所示:

7.png

請(qǐng)問(wèn)這是什么原因,如何解決,從而實(shí)現(xiàn)我所提業(yè)務(wù)的低功耗處理?



您好,如果您使用的是今年1月更新的CH583EVT,注意下方代碼涉及到休眠:

image.png


對(duì)節(jié)點(diǎn)1加入休眠處理(GPIO引腳,PB4低電平喚醒):

代碼添加如下:

app.c文件末尾處加入GPIOA_IRQHandler中斷函數(shù):

?/*********************************************************************
? * @fn ? ? ?GPIOA_IRQHandler
? *
? * @brief ? GPIOA中斷函數(shù)
? *
? * @return ?none
? */
?__INTERRUPT
?__HIGH_CODE
?void GPIOB_IRQHandler(void)
?{
? ? ?GPIOB_ClearITFlagBit(GPIO_Pin_4);
?
?}

并對(duì)App_ProcessEvent函數(shù)修改如下:參考文章在TMOS系統(tǒng)中手動(dòng)管理休眠加入如下代碼

? ? ?// 處理測(cè)試任務(wù)事件
? ? ?if(events & APP_NODE_TEST_EVT)
? ? ?{
? ? ? ? ?uint8_t status;
? ? ? ? ?uint8_t data[4] = {0, 1, 2, 3}; // 準(zhǔn)備要發(fā)送的測(cè)試數(shù)據(jù)
? ? ? ? ?status = vendor_model_srv_send(vendor_sub_addr, data, sizeof(data));
? ? ? ? ?if(status) // 如果發(fā)送失敗,打印錯(cuò)誤狀態(tài)
? ? ? ? ? ? ?APP_DBG("trans failed %d", status);
?
? ? ? ? ?// 下列代碼為參考文章添加的代碼
? ? ? ? ?PRINT("sleep mode sleep \n");
? ? ? ? ?DelayMs(5);
? ? ? ? ?tmos_stop_task(halTaskID, HAL_REG_INIT_EVENT); ?//默認(rèn)2分鐘一次的校準(zhǔn)先暫停
? ? ? ? ?sys_safe_access_enable();
? ? ? ? ?R8_CK32K_CONFIG &= ~(RB_CLK_INT32K_PON | RB_CLK_XT32K_PON); //關(guān)閉32K晶振電源,更省電
? ? ? ? ?sys_safe_access_disable();
? ? ? ? ?LowPower_Sleep(RB_PWR_RAM2K | RB_PWR_RAM30K | RB_PWR_EXTEND); //保留24+2K的SRAM的供電
? ? ? ? ?sys_safe_access_enable();
? ? ? ? ?R8_CK32K_CONFIG |= RB_CLK_INT32K_PON; ? ? ? //32K電源打開(kāi),供TMOS系統(tǒng)使用
? ? ? ? ?sys_safe_access_disable();
? ? ? ? ?HSECFG_Current(HSE_RCur_100); ? ? ? ? ? ? ? ? // 降為額定電流(低功耗函數(shù)中提升了HSE偏置電流)
? ? ? ? ?DelayMs(5); ? ? //這里建議給一定的延時(shí),延時(shí)足夠到下方的打印能正常就好
? ? ? ? ?PRINT("wake.. \n");
? ? ? ? ?tmos_set_event(halTaskID, HAL_REG_INIT_EVENT); ? ? ?//先校準(zhǔn)RF,再開(kāi)廣播
?
? ? ? ? ?
? ? ? ? ?// 重新添加測(cè)試任務(wù)事件,下次執(zhí)行時(shí)間間隔為6400ms
? ? ? ? ?tmos_start_task(App_TaskID, APP_NODE_TEST_EVT, 3200);
? ? ? ? ?// 清除測(cè)試任務(wù)事件標(biāo)志
? ? ? ? ?return (events ^ APP_NODE_TEST_EVT);
? ? ?}

app_main.c文件中代碼修改如下:在主函數(shù)中加入GPIO喚醒的代碼

?int main(void)
?{
?#if(defined(DCDC_ENABLE)) && (DCDC_ENABLE == TRUE)
? ? ?PWR_DCDCCfg(ENABLE);
?#endif
?
?/********GPIO喚醒的配置,加在主函數(shù)初始化中********/
? ? ?GPIOB_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_PU);
? ? ?GPIOB_ITModeCfg(GPIO_Pin_4, GPIO_ITMode_FallEdge); // 下降沿喚醒
? ? ?PFIC_EnableIRQ(GPIO_B_IRQn);
? ? ?PWR_PeriphWakeUpCfg(ENABLE, RB_SLP_GPIO_WAKE, Long_Delay);
?/******************************************/
?
?
?
? ? ?SetSysClock(CLK_SOURCE_PLL_60MHz);
?
?#if CONFIG_BLE_MESH_LOW_POWER ? //或者判斷HAL_SLEEP是否啟用,都行。使能低功耗節(jié)點(diǎn)功能時(shí),需要一并啟用HAL_SLEEP
? ? ?GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
? ? ?GPIOB_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
?#endif
?
?#ifdef DEBUG
? ? ?GPIOA_SetBits(bTXD1);
? ? ?GPIOA_ModeCfg(bTXD1, GPIO_ModeOut_PP_5mA);
? ? ?UART1_DefInit();
?#endif
? ? ?PRINT("%s\n", VER_LIB);
? ? ?PRINT("%s\n", VER_MESH_LIB);
? ? ?CH58X_BLEInit();
? ? ?HAL_Init();
? ? ?bt_mesh_lib_init();
? ? ?App_Init();
? ? ?Main_Circulation();
?}

當(dāng)節(jié)點(diǎn)1加入到網(wǎng)絡(luò)后,進(jìn)入休眠狀態(tài),當(dāng)PB4引腳接地后,產(chǎn)生一個(gè)下降沿,喚醒節(jié)點(diǎn)1,節(jié)點(diǎn)1收到來(lái)自節(jié)點(diǎn)2發(fā)送的數(shù)據(jù)包并打印其內(nèi)容,然后進(jìn)入休眠狀態(tài)。當(dāng)再次將PB4引腳接地后,會(huì)重復(fù)上述過(guò)程,如下圖所示。10.png此時(shí)可以在功耗分析中觀察到電流變化如下圖所示:

11.png

現(xiàn)在我想用RTC喚醒,而不是GPIO喚醒,我根據(jù)您給出的建議注釋了MCU.c文件中的那一行代碼,然后在上述app.c代碼基礎(chǔ)上添加一段RTC喚醒的代碼,并注釋掉app_main.c中GPIO喚醒的代碼:

? ? ?// 處理測(cè)試任務(wù)事件
? ? ?if(events & APP_NODE_TEST_EVT)
? ? ?{
? ? ? ? ?uint8_t status;
? ? ? ? ?uint8_t data[4] = {0, 1, 2, 3}; // 準(zhǔn)備要發(fā)送的測(cè)試數(shù)據(jù)
? ? ? ? ?status = vendor_model_srv_send(vendor_sub_addr, data, sizeof(data));
? ? ? ? ?if(status) // 如果發(fā)送失敗,打印錯(cuò)誤狀態(tài)
? ? ? ? ? ? ?APP_DBG("trans failed %d", status);
?
? ? ? ? ?// RTC喚醒添加的代碼
? ? ? ? ?RTC_TMRFunCfg(Period_1_S); ? /* 定時(shí)1s的RTC鬧鐘 */
? ? ? ? ?PFIC_EnableIRQ(RTC_IRQn); ? /* 使能RTC中斷 */
? ? ? ? ?PWR_PeriphWakeUpCfg( ENABLE, RB_SLP_RTC_WAKE, Long_Delay ); ? /* 使能RTC中斷喚醒源 */
? ? ? ? ?
? ? ? ? ?// 下列代碼為參考文章添加的代碼
? ? ? ? ?PRINT("sleep mode sleep \n");
? ? ? ? ?DelayMs(5);
? ? ? ? ?tmos_stop_task(halTaskID, HAL_REG_INIT_EVENT); ?//默認(rèn)2分鐘一次的校準(zhǔn)先暫停
? ? ? ? ?sys_safe_access_enable();
? ? ? ? ?R8_CK32K_CONFIG &= ~(RB_CLK_INT32K_PON | RB_CLK_XT32K_PON); //關(guān)閉32K晶振電源,更省電
? ? ? ? ?sys_safe_access_disable();
? ? ? ? ?LowPower_Sleep(RB_PWR_RAM2K | RB_PWR_RAM30K | RB_PWR_EXTEND); //保留24+2K的SRAM的供電
? ? ? ? ?sys_safe_access_enable();
? ? ? ? ?R8_CK32K_CONFIG |= RB_CLK_INT32K_PON; ? ? ? //32K電源打開(kāi),供TMOS系統(tǒng)使用
? ? ? ? ?sys_safe_access_disable();
? ? ? ? ?HSECFG_Current(HSE_RCur_100); ? ? ? ? ? ? ? ? // 降為額定電流(低功耗函數(shù)中提升了HSE偏置電流)
? ? ? ? ?DelayMs(5); ? ? //這里建議給一定的延時(shí),延時(shí)足夠到下方的打印能正常就好
? ? ? ? ?PRINT("wake.. \n");
? ? ? ? ?tmos_set_event(halTaskID, HAL_REG_INIT_EVENT); ? ? ?//先校準(zhǔn)RF,再開(kāi)廣播
?
? ? ? ? ?
? ? ? ? ?// 重新添加測(cè)試任務(wù)事件,下次執(zhí)行時(shí)間間隔為6400ms
? ? ? ? ?tmos_start_task(App_TaskID, APP_NODE_TEST_EVT, 3200);
? ? ? ? ?// 清除測(cè)試任務(wù)事件標(biāo)志
? ? ? ? ?return (events ^ APP_NODE_TEST_EVT);
? ? ?}

重新跑例程后,發(fā)現(xiàn)雖然休眠后不會(huì)復(fù)位,但是休眠后也不會(huì)喚醒,節(jié)點(diǎn)1串口顯示如下:13.png功耗儀也顯示后面一直在休眠,如下所示:

12.png

請(qǐng)問(wèn)這個(gè)問(wèn)題可能是什么原因?qū)е碌?,?yīng)該如何處理,另外文章在TMOS系統(tǒng)中手動(dòng)管理休眠只有GPIO喚醒方式,RTC定時(shí)喚醒怎么實(shí)現(xiàn),我想?yún)⒖家幌拢?/span>



您好,博客中的場(chǎng)景是僅用GPIO喚醒的場(chǎng)景,使用RTC喚醒就不要關(guān)閉32K的電源了,不關(guān)閉一直跑那下面重新打開(kāi)32K電源的代碼塊也不用了。

RTC只能由32K時(shí)鐘提供,喚醒MCU也是需要32K時(shí)鐘的。

image.png


只有登錄才能回復(fù),可以選擇微信賬號(hào)登錄

国产91精品新入口,国产成人综合网在线播放,九热这里只有精品,本道在线观看,美女视频a美女视频,韩国美女激情视频,日本美女pvp视频