/*-------------------- Mgmt_Permit_Joining_req -------------------- IN: The package with the request information. OUT: The size in bytes of the request payload. */ zbSize_t Mgmt_Permit_Joining_req ( zbMgmtPermitJoiningRequest_t *pMessageComingIn, /*IN The package with the request information. */ zbNwkAddr_t aDestAddr /* IN: The destination address where to send the request. */ ) { zdoNlmeMessage_t * pZdoNlmeMsg; /* If the destiantion address is to all awake devices, first turn it on locally and then send it OTA. */ if(FLib_MemCmp((uint8_t *)gaBroadcastZCnZR, aDestAddr, sizeof(zbNwkAddr_t))) { /* Do the permit joinig locally as well. */ pZdoNlmeMsg = MSG_AllocType(zdoNlmeMessage_t); /* If we can not set this locally is highly probably that we are not able to send packets OTA. */ if(pZdoNlmeMsg == NULL) return 0; if (NlmeGetRequest(gDevType_c) != gEndDevice_c) { /* Build the NLME request using the incoming info. */ BeeUtilZeroMemory(pZdoNlmeMsg,sizeof(zdoNlmeMessage_t )); pZdoNlmeMsg->msgData.permitJoiningReq.permitDuration = pMessageComingIn->PermitDuration; pZdoNlmeMsg->msgType = gNlmePermitJoiningRequest_c; (void)ZDO_NLME_SapHandler(pZdoNlmeMsg); } } /* By returning the size ZDP send out the request. */ return sizeof(zbMgmtPermitJoiningRequest_t); }
/******************************************************************************* * State machine to send the next report. If it can't get the memory, tries * again later. * * This will concatinate all of the reportable attributes in a single cluster *******************************************************************************/ void ZCL_SendReport(void) { afDeviceDef_t *pDevice; uint8_t payloadLen; uint8_t reportLen; afToApsdeMessage_t *pMsg; /* a message for sending the report */ afAddrInfo_t addrInfo; afClusterDef_t *pCluster; zclFrame_t *pFrame; uint8_t i; zclReportAttr_t *pReportList; BeeUtilZeroMemory(&addrInfo, sizeof(addrInfo)); /* starting over? reset indexes */ if(gfZclReportRestart) { gZclReportDeviceIndex = gZclReportClusterIndex = gAsynchronousClusterIndex = 0; gfZclReportRestart = FALSE; } /* get a buffer to build the next report */ pMsg = AF_MsgAlloc(); if(!pMsg) { gfZclReportRestart = FALSE; ZLC_StartShortReportingTimer(); return; } /* walk through all devices */ while(gZclReportDeviceIndex < gNum_EndPoints_c) { /* make sure this app endpoint is a ZCL device */ pDevice = (afDeviceDef_t *) endPointList[gZclReportDeviceIndex].pDevice; /* report list */ pReportList = pDevice->pReportList; if(!pDevice || !pDevice->pfnZCL) { ++gZclReportDeviceIndex; continue; } /* Find if any attribute are a asynchronous, then update the attribute */ do { for(i=0; i<pDevice->reportCount; ++i) { zclAttrDef_t *pAttrDef; zclReportAttr_t *pCurrentReportList = &pReportList[i]; /* only looking for this one cluster, to see if it's in the reportinglist */ if(!IsEqual2Bytes(pCurrentReportList->aClusterId, pDevice->pClusterDef[gAsynchronousClusterIndex].aClusterId)) continue; // If the cluster is on the reporting list, find the reporting attribute pAttrDef = ZCL_FindAttr(&pDevice->pClusterDef[gAsynchronousClusterIndex], pCurrentReportList->attrId); if(pAttrDef) { /* It's a asynchronous attribute, update before reporting */ if(ZclAttrIsAsynchronous_c(pAttrDef->flags)) { ++gAsynchronousClusterIndex; BeeAppUpdateDevice(0, gZclUI_SendReportingAttributeRequest_c, pAttrDef->id, pCurrentReportList->aClusterId, NULL); //Free the message, because we return from here MSG_Free(pMsg); return; } } } ++gAsynchronousClusterIndex; }while(gAsynchronousClusterIndex < pDevice->clusterCount); /* check each cluster for reporting attributes */ while(gZclReportClusterIndex < pDevice->clusterCount) { pCluster = &pDevice->pClusterDef[gZclReportClusterIndex]; pFrame = (void *)(&((uint8_t *)pMsg)[ApsmeGetAsduOffset()]); /* build the report for the next cluster */ reportLen = ZCL_BuildAttrReport( (zclCmdReportAttr_t *)(pFrame + 1), /* ptr to report frame */ pDevice, /* ptr to device */ pCluster ); /* no reporting attributes this cluster */ if(!reportLen) { ++gZclReportClusterIndex; continue; } /* set up the address info */ addrInfo.dstAddrMode = gZbAddrModeIndirect_c; addrInfo.srcEndPoint = endPointList[gZclReportDeviceIndex].pEndpointDesc->pSimpleDesc->endPoint; addrInfo.txOptions = gZclTxOptions; addrInfo.radiusCounter = afDefaultRadius_c; /* determine which cluster to send it to */ Copy2Bytes(addrInfo.aClusterId, pCluster->aClusterId); /* set up frame */ pFrame->frameControl = gZclFrameControl_FrameTypeGeneral | gZclFrameControl_DisableDefaultRsp; pFrame->transactionId = gZclTransactionId++; pFrame->command = gZclCmdReportAttr_c; /* send the report */ payloadLen = sizeof(zclFrame_t) + reportLen; (void)ZCL_DataRequestNoCopy(&addrInfo, payloadLen, pMsg); ++gZclReportClusterIndex; /* start a short timer between reporting clusters */ gfZclReportRestart = FALSE; ZLC_StartShortReportingTimer(); return; } /* try next device */ ++gZclReportDeviceIndex; gZclReportClusterIndex=0; gAsynchronousClusterIndex=0; } /* end of while(gZclReportDeviceIndex < gNum_EndPoints_c) */ if(pMsg) MSG_Free(pMsg); /* start up a new timer if needed */ if(gZclReportingSetup.reportTimeout != 0 && gZclReportingSetup.reportTimeout != 0xFFFF) { gZclReportingSetup.reportCounter = gZclReportingSetup.reportTimeout; ZLC_StartReportingTimer(); } }
/************************************************************************************ * Generates a local Nlme Leave command to let the nwk layer know that WE as a device * are leaving the network, in other words, is a command to do a self-leave. Only called * from the ZDO state machine. * * NOTE: This function is meant to only be called byt the ZDO State machine on the * leaving state. * * Interface assumptions: * NONE. * * Return value: * NONE. * * Revison history: * Date Author Comments * ------ ------ -------- * 280208 MN Updated ************************************************************************************/ void ZdoNwkMng_GenerateNlmeLeaveRequest ( void /*IN: No Input Parameters*/ ) { /* Pointer to the buffer where the Nlme command will be filled. */ zdoNlmeMessage_t *pZdoNlmeMessage; /* The size for the curretn command to be passed down. */ uint8_t size = (sizeof(zbMsgId_t) + sizeof(nlmeLeaveReq_t)); /* Allocated the exact size memory for the Nlme command, remember this will passed down using a Sap hanlder, the memory will be freed by the next layer. */ pZdoNlmeMessage = MSG_AllocType(size); /* If for any reason the message was unable to be allocated, no further processing is done. */ if(!pZdoNlmeMessage) return; /* Most of the options are filled with a Zero value, lets fill the whole thing with Zeros, and just set the ones that are not Zero (less code). */ BeeUtilZeroMemory(pZdoNlmeMessage, size); /* Build the command. */ pZdoNlmeMessage->msgType = gNlmeLeaveRequest_c; #if gMgmt_Leave_rsp_d /* this would only occur if management leave command came from OTA */ if(zbMgmtOptionRemoveChildren_c & gMgmtSelfLeaveMask) { gMgmtSelfLeaveMask &= ~(zbMgmtOptionRemoveChildren_c); pZdoNlmeMessage->msgData.leaveReq.removeChildren = TRUE; } /* If the mgmt command was sent with the */ if(zbMgmtOptionReJoin_c & gMgmtSelfLeaveMask) { /* don't turn off bit yet in gMgmtSelfLeaveMask, it will be turned off later */ pZdoNlmeMessage->msgData.leaveReq.rejoin = TRUE; gMgmtSelfLeaveMask &= ~(zbMgmtOptionReJoin_c); } #endif /* check if the ZDO or the application needs to remove the children. */ if (gZdoStopMode & gZdoStopMode_RemoveChildren_c) { gZdoStopMode &= ~(gZdoStopMode_RemoveChildren_c); pZdoNlmeMessage->msgData.leaveReq.removeChildren = TRUE; } pZdoNlmeMessage->msgData.leaveReq.reuseAddress = mDefaultReuseAddressPolicy_c; if (ZDO_NLME_SapHandler( pZdoNlmeMessage )) { /* Catch the error message if needed. */ } }