/
pvvx
/
TLB2Z
Обзор
Документация
Войти
/
pvvx
/
TLB2Z
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/SDK/stack/zigbee/aps/aps_group.c
365 строк
9 KB
Victor
add SDK, new cfg tb03f, add zg-807z
19 фев 2026, 08:55
19 фев 2026, 08:55
627d0d5
Код
Авторство
О чём код?
/******************************************************************************************************** * @file aps_group.c * * @brief This is the source file for aps_group * * @author Zigbee Group * @date 2021 * * @par Copyright (c) 2021, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK") * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************************************/ #include "../common/includes/zb_common.h" #define APS_GROUP_EP_INVALID 0xff #define APS_INVALID_GRP_ADDR 0xffff static u8 aps_group_entry_num = 0; //number of group entry items in group table _CODE_APS_ void aps_groupTblSave2Flash(void *arg){ #if NV_ENABLE nv_flashWriteNew(1, NV_MODULE_APS, NV_ITEM_APS_GROUP_TABLE, APS_GROUP_TABLE_SIZE * sizeof(aps_group_tbl_ent_t), (u8*)aps_group_tbl); #endif } _CODE_APS_ u8 aps_groupTblNvInit(void){ u8 ret = NV_ITEM_NOT_FOUND; #if NV_ENABLE nv_itemLengthCheckAdd(NV_ITEM_APS_GROUP_TABLE, APS_GROUP_TABLE_SIZE * sizeof(aps_group_tbl_ent_t)); ret = nv_flashReadNew(1, NV_MODULE_APS, NV_ITEM_APS_GROUP_TABLE, sizeof(aps_group_tbl_ent_t), (u8*)aps_group_tbl); #endif return ret; } static void aps_groupEntryDel(aps_group_tbl_ent_t *p){ aps_group_tbl_ent_t *p0 = &aps_group_tbl[0]; u8 sn = p - p0; u8 num = aps_group_entry_num; if(p){ p->group_addr = APS_INVALID_GRP_ADDR; aps_group_entry_num--; #if 1 //fill the invalid entry with the valid one if(sn < (num - 1)){ memcpy((u8 *)p, (u8 *)(p+1), (num - 1 - sn) * sizeof(aps_group_tbl_ent_t)); } p0 += (num - 1); p0->group_addr = APS_INVALID_GRP_ADDR; #endif } } _CODE_APS_ aps_group_tbl_ent_t *aps_group_search_by_addr(u16 group_addr) { u8 i = 0; u8 index = 0; u8 findEmpty = FALSE; if (group_addr == APS_INVALID_GRP_ADDR) { findEmpty = TRUE; } while(i < aps_group_entry_num){ if (aps_group_tbl[index].group_addr == APS_INVALID_GRP_ADDR){ if(findEmpty){ return &aps_group_tbl[index]; }else{ index++; continue; } } if(aps_group_tbl[index].group_addr == group_addr) { return &aps_group_tbl[index]; } i++; index++; } if(findEmpty) { while(index < APS_GROUP_TABLE_SIZE) { if (aps_group_tbl[index].group_addr == APS_INVALID_GRP_ADDR) { return &aps_group_tbl[index]; } index++; } } return NULL; } _CODE_APS_ u8 *aps_group_ep_info_get(u16 group_addr, u8 *epNum){ aps_group_tbl_ent_t *ent = aps_group_search_by_addr(group_addr); if(ent){ *epNum = ent->n_endpoints; return (&ent->endpoints[0]); } return NULL; } _CODE_APS_ u8 *aps_group_ep_find(aps_group_tbl_ent_t *entry, u8 endpoint) { u8 i = 0; u8 index = 0; u8 findEmpty = FALSE; if (endpoint == APS_GROUP_EP_INVALID) { findEmpty = TRUE; } while (i < entry->n_endpoints) { if (entry->endpoints[index] == APS_GROUP_EP_INVALID) { if (findEmpty) { return &entry->endpoints[index]; } else { index++; continue; } } if (entry->endpoints[index] == endpoint) { return &entry->endpoints[index]; } i++; index++; } if(findEmpty) { while(index < APS_EP_NUM_IN_GROUP_TBL) { if(entry->endpoints[index] == APS_GROUP_EP_INVALID){ return &entry->endpoints[index]; } index++; } } return NULL; } _CODE_APS_ aps_group_tbl_ent_t *aps_group_search(u16 groupAddr, u8 endpoint) { aps_group_tbl_ent_t *pEntry; u8* pEndpoint; pEntry = aps_group_search_by_addr(groupAddr); if (pEntry == NULL) { return NULL; } pEndpoint = aps_group_ep_find(pEntry, endpoint); if (pEndpoint == NULL) { return NULL; } return pEntry; } /******************************************************************************************************************* * @brief This primitive is generated by the next higher layer when it wants to add membership in a particular group to an endpoint, so that frames addressed to the group will be delivered to that endpoint in the future. * @param req: aps_add_group_req_t struct */ _CODE_APS_ aps_status_t aps_me_group_add_req(aps_add_group_req_t *req) { aps_status_t status = APS_STATUS_SUCCESS; aps_group_tbl_ent_t *pEntry; u8 *pEndpoint; if((req->ep < 0x01) || (req->ep > 0xfe)){ status = APS_STATUS_INVALID_PARAMETER; return status; } pEntry = aps_group_search_by_addr(req->group_addr); if(pEntry){//Group entry found //Add or update endpoint pEndpoint = aps_group_ep_find(pEntry, req->ep); if(pEndpoint == NULL) {//Endpoint not found pEndpoint = aps_group_ep_find(pEntry, APS_GROUP_EP_INVALID); if(pEndpoint == NULL) { return APS_STATUS_TABLE_FULL; }else{ *pEndpoint = req->ep; pEntry->n_endpoints++; } }else{ return APS_STATUS_DUPLICATE_ENTRY; } }else{// Group entry not found pEntry = aps_group_search_by_addr(APS_INVALID_GRP_ADDR); if (pEntry == NULL) { return APS_STATUS_TABLE_FULL; } //clear previous info for(u8 j=0;j<APS_EP_NUM_IN_GROUP_TBL;j++){ pEntry->endpoints[j] = APS_GROUP_EP_INVALID; } memset(pEntry->group_name, 0, APS_GROUP_NAME_LEN); pEntry->group_addr = req->group_addr; pEntry->endpoints[0] = req->ep; pEntry->n_endpoints = 1; aps_group_entry_num++; }//end if(pEntry) if(APS_STATUS_SUCCESS == status){ TL_SCHEDULE_TASK(aps_groupTblSave2Flash,NULL); } return status; } _CODE_APS_ aps_status_t aps_me_group_delete_req(aps_delete_group_req_t *req){ aps_status_t status = APS_STATUS_SUCCESS; aps_group_tbl_ent_t *pEntry; u8 *pEndpoint; if((req->ep < 0x01) || (req->ep > 0xfe)){ status = APS_STATUS_INVALID_PARAMETER; return status; } pEntry = aps_group_search_by_addr(req->group_addr); if(pEntry == NULL){//Group address not found return APS_STATUS_INVALID_GROUP; } pEndpoint = aps_group_ep_find(pEntry, req->ep); if(pEndpoint == NULL){//Endpoint not found return APS_STATUS_INVALID_GROUP; } *pEndpoint = APS_GROUP_EP_INVALID; pEntry->n_endpoints--; if (pEntry->n_endpoints == 0) { //TODO: No endpoint in the group, delete the group aps_groupEntryDel(pEntry); //pEntry->group_addr = APS_INVALID_GRP_ADDR; }else{ //move the valid data to the first positions u8 validEp[APS_EP_NUM_IN_GROUP_TBL]; memset(validEp, APS_GROUP_EP_INVALID, APS_EP_NUM_IN_GROUP_TBL); u8 validCnt = 0; for(u8 m = 0; m < APS_EP_NUM_IN_GROUP_TBL; m++){ if(pEntry->endpoints[m] != APS_GROUP_EP_INVALID){ validEp[validCnt++] = pEntry->endpoints[m]; } } memcpy(pEntry->endpoints, validEp, APS_EP_NUM_IN_GROUP_TBL); } if(APS_STATUS_SUCCESS == status){ TL_SCHEDULE_TASK(aps_groupTblSave2Flash,NULL); } return status; } _CODE_APS_ void aps_groupTblReset(void){ aps_group_entry_num = 0; for (u8 i = 0; i < APS_GROUP_TABLE_SIZE; i++) { aps_group_tbl[i].group_addr = APS_INVALID_GRP_ADDR; aps_group_tbl[i].n_endpoints = 0; for(u8 j=0;j<APS_EP_NUM_IN_GROUP_TBL;j++){ aps_group_tbl[i].endpoints[j] = APS_GROUP_EP_INVALID; } } } _CODE_APS_ aps_status_t aps_me_group_delete_all_req(u8 ep){ aps_status_t status = APS_STATUS_SUCCESS; aps_group_tbl_ent_t *pEntry; u8 *pEndpoint; u8 i = 0; u8 index = 0; if((ep < 0x01) || (ep > 0xfe)){ status = APS_STATUS_INVALID_PARAMETER; return status; } while(i <= aps_group_entry_num){ //skip the empty group if(aps_group_tbl[index].group_addr == APS_INVALID_GRP_ADDR){ index++; if (index >= APS_GROUP_TABLE_SIZE){ i++; index = 0; } continue; } pEntry = &aps_group_tbl[index]; pEndpoint = aps_group_ep_find(pEntry,ep); if(pEndpoint){ *pEndpoint = APS_GROUP_EP_INVALID; pEntry->n_endpoints--; } //If the endpoints already empty, clear the group entry if(pEntry->n_endpoints == 0){ //todo Before deleting a group, remove all associated scene entries. //zcl_scene_removeScenesWithGroup(pEntry->group_addr); aps_groupEntryDel(pEntry); //pEntry->group_addr = APS_INVALID_GRP_ADDR; }else{ //move the valid data to the first positions u8 validEp[APS_EP_NUM_IN_GROUP_TBL]; memset(validEp, APS_GROUP_EP_INVALID, APS_EP_NUM_IN_GROUP_TBL); u8 validCnt = 0; for(u8 m = 0; m < APS_EP_NUM_IN_GROUP_TBL; m++){ if(pEntry->endpoints[m] != APS_GROUP_EP_INVALID){ validEp[validCnt++] = pEntry->endpoints[m]; } } memcpy(pEntry->endpoints, validEp, APS_EP_NUM_IN_GROUP_TBL); } //search next group index++; i++; }//end while aps_groupTblReset(); TL_SCHEDULE_TASK(aps_groupTblSave2Flash, NULL); return status; } _CODE_APS_ u8 aps_group_entry_num_get(void){ return aps_group_entry_num; } _CODE_APS_ void aps_group_list_get(u8 *counter, u16 *group_list) { u8 i = 0; if(!counter || !group_list){ return; } *counter = 0; while (i < APS_GROUP_TABLE_SIZE) { if(aps_group_tbl[i].group_addr != APS_INVALID_GRP_ADDR){ group_list[(*counter)++] = aps_group_tbl[i].group_addr; } i++; } } _CODE_APS_ void aps_init_group_num_set(void){ for(u8 i=0; i<APS_GROUP_TABLE_SIZE; i++){ if(aps_group_tbl[i].group_addr != APS_INVALID_GRP_ADDR){ aps_group_entry_num++; } } }