#if defined(SAPP_ZSTACK) #include "SAPP_FrameWork.h" #include /********************************************************************* * FUNCTIONS *********************************************************************/ static void createEndPoint(struct ep_info_t *epInfo, uint8 *task_id, uint8 ep); #if defined(ZDO_COORDINATOR) static uint8 uartMsgProcesser(uint8 *msg); #endif /********************************************************************* * Local Variables *********************************************************************/ //uint8 ctrlBuffer[sizeof(TOPOINFO) + sizeof(FUNCTABLE) + FUNC_NUM * sizeof(FUNCINFO)]; static TOPOINFO topoBuffer = { 0x02 }; FUNCTABLE *funcTableBuffer;// = (FUNCTABLE *)(&ctrlBuffer[sizeof(TOPOINFO)]); static devStates_t curNwkState; static uint8 controlTaskId; static uint8 functionTaskId; static struct ep_info_t controlEndPointInfo; static uint8 isUserTimerRunning = 0; void sapp_taskInitProcess(void) { #if defined ( BUILD_ALL_DEVICES ) // The "Demo" target is setup to have BUILD_ALL_DEVICES and HOLD_AUTO_START // We are looking at a jumper (defined in SampleAppHw.c) to be jumpered // together - if they are - we will start up a coordinator. Otherwise, // the device will start as a router. if ( readCoordinatorJumper() ) zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR; else zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER; #endif // BUILD_ALL_DEVICES #if defined ( HOLD_AUTO_START ) // HOLD_AUTO_START is a compile option that will surpress ZDApp // from starting the device and wait for the application to // start the device. ZDOInitDevice(0); #endif // 构造功能列表 funcTableBuffer = createFuncTable(funcCount); funcTableBuffer->ft_type = 0x01; funcTableBuffer->ft_count = funcCount; int i; for(i = 0; i < funcCount; i++) { funcTableBuffer->ft_list[i].type = funcList[i].function.type; funcTableBuffer->ft_list[i].id = funcList[i].function.id; funcTableBuffer->ft_list[i].cycle = funcList[i].function.cycle; } controlTaskId = tasksCnt - 2; functionTaskId = tasksCnt - 1; HalIOInit(functionTaskId); createEndPoint(&controlEndPointInfo, &controlTaskId, CONTROL_ENDPOINT); for(i = 0; i < funcCount; i++) { struct ep_info_t *ep = &funcList[i]; createEndPoint(ep, &functionTaskId, i + 1); if(ep->res_available) (*ep->res_available)(ep, ResInit, NULL); } #if defined(ZDO_COORDINATOR)// || defined(RTR_NWK) // RegisterForKeys( SampleApp_TaskID ); MT_UartRegisterTaskID(controlTaskId); #endif } /********************************************************************* * LOCAL FUNCTIONS */ static void createEndPoint(struct ep_info_t *epInfo, uint8 *task_id, uint8 ep) { static cId_t commonClusterId = SAPP_PERIODIC_CLUSTERID; // Fill out the endpoint description. epInfo->task_id = *task_id; epInfo->ep = ep; epInfo->timerTick = epInfo->function.cycle; epInfo->userTimer = 0; epInfo->simpleDesc.EndPoint = ep; epInfo->simpleDesc.AppProfId = SAPP_PROFID; epInfo->simpleDesc.AppDeviceId = SAPP_DEVICEID; epInfo->simpleDesc.AppDevVer = SAPP_DEVICE_VERSION; epInfo->simpleDesc.Reserved = 0; epInfo->simpleDesc.AppNumInClusters = 1; epInfo->simpleDesc.pAppInClusterList = &commonClusterId; epInfo->simpleDesc.AppNumOutClusters = 1; epInfo->simpleDesc.pAppOutClusterList = &commonClusterId; epInfo->SampleApp_epDesc.endPoint = ep; epInfo->SampleApp_epDesc.task_id = task_id; epInfo->SampleApp_epDesc.simpleDesc = &epInfo->simpleDesc; epInfo->SampleApp_epDesc.latencyReq = noLatencyReqs; // Register the endpoint description with the AF afRegister(&epInfo->SampleApp_epDesc); } uint16 sapp_controlEpProcess(uint8 task_id, uint16 events) { afIncomingMSGPacket_t *MSGpkt; if ( events & SYS_EVENT_MSG ) { MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(task_id); while ( MSGpkt ) { switch ( MSGpkt->hdr.event ) { #if defined(ZDO_COORDINATOR) case CMD_SERIAL_MSG: // SampleApp_UartMessage((uint8 *)MSGpkt); uartMsgProcesser((uint8 *)MSGpkt); HalLedBlink( HAL_LED_1, 2, 50, 90 ); break; #endif // Received when a messages is received (OTA) for this endpoint case AF_INCOMING_MSG_CMD: { // TODO: QueryProfile or QueryTopo switch(MSGpkt->clusterId) { case SAPP_PERIODIC_CLUSTERID: switch(MSGpkt->cmd.Data[0]) { case 0x01: // CtrlQueryProfile // 获取到数据包的来源地址来当做发送数据的目标 SendData(CONTROL_ENDPOINT, funcTableBuffer->ft_data, MSGpkt->srcAddr.addr.shortAddr, MSGpkt->srcAddr.endPoint, sizeof(FUNCTABLE) + funcCount * sizeof(FUNCINFO)); break; case 0x02: // CtrlQueryTopo // 获取到数据包的来源地址来当做发送数据的目标 SendData(CONTROL_ENDPOINT, (unsigned char *)&topoBuffer, MSGpkt->srcAddr.addr.shortAddr, MSGpkt->srcAddr.endPoint, sizeof(TOPOINFO)); break; case 0x03: // CtrlQuerySpecialFunction // cmd.Data[0] = 3, cmd.Data[1] = funcCode, cmd.Data[2] = funcID { uint8 i; for(i = 0; i < funcTableBuffer->ft_count; i++) { if((funcTableBuffer->ft_list[i].type == MSGpkt->cmd.Data[1]) && (funcTableBuffer->ft_list[i].id == MSGpkt->cmd.Data[2])) { // 0x03, EndPoint, rCycle uint8 specialFunc[3] = { 0x03, i + 1, funcTableBuffer->ft_list[i].cycle }; SendData(CONTROL_ENDPOINT, specialFunc, MSGpkt->srcAddr.addr.shortAddr, MSGpkt->srcAddr.endPoint, sizeof(specialFunc)); break; } } } break; default: { int i; for(i = 0; i < funcCount; i++) { struct ep_info_t *ep = &funcList[i]; if(ep->res_available) (*ep->res_available)(ep, ResControlPkg, MSGpkt); } } break; } HalLedBlink( HAL_LED_2, 1, 50, 250 ); break; } break; } // Received whenever the device changes state in the network case ZDO_STATE_CHANGE: { devStates_t st = (devStates_t)(MSGpkt->hdr.status); if ( (st == DEV_ZB_COORD) || (st == DEV_ROUTER) || (st == DEV_END_DEVICE) ) { // topoBuffer->type = 0x02; memcpy(topoBuffer.IEEE, NLME_GetExtAddr(), 8); #if !defined(ZDO_COORDINATOR) topoBuffer.PAddr = NLME_GetCoordShortAddr(); #else topoBuffer.PAddr = 0xFFFF; #endif osal_memcpy(&topoBuffer.panid, &_NIB.nwkPanId, sizeof(uint16)); osal_memcpy(&topoBuffer.channel, &_NIB.nwkLogicalChannel, sizeof(uint8)); //向协调器发送拓扑信息 SendData(CONTROL_ENDPOINT, (unsigned char *)&topoBuffer, 0x0000, TRANSFER_ENDPOINT, sizeof(TOPOINFO)); HalLedBlink( HAL_LED_2, 4, 50, 250 ); } } break; default: break; } // Release the memory osal_msg_deallocate( (uint8 *)MSGpkt ); // Next - if one is available MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( task_id ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } // 定时器时间到, 遍历所有端点看是否有userTimer if(events & SAPP_SEND_PERIODIC_MSG_EVT) { int i; uint8 hasUserTimer = 0; for(i = 0; i < funcCount; i++) { struct ep_info_t *ep = &funcList[i]; if(ep->userTimer && ep->res_available) { hasUserTimer = 1; ep->userTimer = ep->userTimer - 1; if(ep->userTimer <= 1) { ep->userTimer = 0; (*ep->res_available)(ep, ResUserTimer, NULL); } } } if(hasUserTimer) { // 重新启动定时器 osal_start_timerEx(task_id, SAPP_SEND_PERIODIC_MSG_EVT, 1000); } else { isUserTimerRunning = 0; osal_stop_timerEx(task_id, SAPP_SEND_PERIODIC_MSG_EVT); } // return unprocessed events return (events ^ SAPP_SEND_PERIODIC_MSG_EVT); } // Discard unknown events return 0; } uint16 sapp_functionEpProcess(uint8 task_id, uint16 events) { afIncomingMSGPacket_t *MSGpkt; if(events & SYS_EVENT_MSG) { MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( task_id ); while ( MSGpkt ) { switch ( MSGpkt->hdr.event ) { // 接收到数据包 case AF_INCOMING_MSG_CMD: { switch ( MSGpkt->clusterId ) { case SAPP_PERIODIC_CLUSTERID: if(MSGpkt->endPoint <= funcCount) { struct ep_info_t *ep = &funcList[MSGpkt->endPoint - 1]; if(ep->incoming_data) (*ep->incoming_data)(ep, MSGpkt->srcAddr.addr.shortAddr, MSGpkt->srcAddr.endPoint, &MSGpkt->cmd); } HalLedBlink( HAL_LED_2, 1, 50, 250 ); break; } } break; case ZDO_STATE_CHANGE: { curNwkState = (devStates_t)(MSGpkt->hdr.status); if ( (curNwkState == DEV_ZB_COORD) || (curNwkState == DEV_ROUTER) || (curNwkState == DEV_END_DEVICE) ) { int i; int hasTimeOut = 0; for(i = 0; i < funcCount; i++) { struct ep_info_t *ep = &funcList[i]; if(ep->nwk_stat_change) (*ep->nwk_stat_change)(ep); // 重置端点计数器 if(ep->time_out && ep->function.cycle) { ep->timerTick = ep->function.cycle; hasTimeOut = 1; } } if(hasTimeOut) { // 加入网络成功,启动定时器,为各个端点提供定时 osal_start_timerEx(task_id, SAPP_SEND_PERIODIC_MSG_EVT, 1000); } } else osal_stop_timerEx(task_id, SAPP_SEND_PERIODIC_MSG_EVT); } break; case IOPORT_INT_EVENT: { OSALIOIntData_t* IOIntData; IOIntData =(OSALIOIntData_t*)MSGpkt; if(IOIntData->endPoint <= funcCount) { struct ep_info_t *ep = &funcList[IOIntData->endPoint - 1]; if(ep->res_available) (*ep->res_available)(ep, ResIOInt, IOIntData->arg); } } break; #if defined(HAL_IRDEC) && (HAL_IRDEC == TRUE) case IRDEC_INT_EVENT: // { OSALIRDecIntData_t* TimerIntData = (OSALIRDecIntData_t*)MSGpkt; if(TimerIntData->endPoint <= funcCount) { struct ep_info_t *ep = &funcList[TimerIntData->endPoint - 1]; if(ep->res_available) (*ep->res_available)(ep, ResTimerInt, TimerIntData->data); } } break; #endif default: break; } // Release the memory osal_msg_deallocate( (uint8 *)MSGpkt ); // Next - if one is available MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( task_id ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } // 定时器时间到, 遍历所有端点看是否有需要调用time_out if(events & SAPP_SEND_PERIODIC_MSG_EVT) { int i; for(i = 0; i < funcCount; i++) { struct ep_info_t *ep = &funcList[i]; if(ep->time_out && ep->function.cycle) { // 端点需要周期执行 ep->timerTick = ep->timerTick - 1; if(ep->timerTick == 0) { // 定时时间到,执行time_out函数 (*ep->time_out)(ep); ep->timerTick = ep->function.cycle; } } #if 0 if(ep->userTimer && ep->res_available) { ep->userTimer = ep->userTimer - 1; if(ep->userTimer <= 1) { (*ep->res_available)(ep, ResUserTimer, NULL); ep->userTimer = 0; } } #endif } // 重新启动定时器 osal_start_timerEx(task_id, SAPP_SEND_PERIODIC_MSG_EVT, 1000); // return unprocessed events return (events ^ SAPP_SEND_PERIODIC_MSG_EVT); } // Discard unknown events return 0; } #if defined(ZDO_COORDINATOR) static uint8 uartMsgProcesser(uint8 *msg) { mtOSALSerialData_t *pMsg = (mtOSALSerialData_t *)msg; mtUserSerialMsg_t *pMsgBody = (mtUserSerialMsg_t *)pMsg->msg; if ( (curNwkState != DEV_ZB_COORD) && (curNwkState != DEV_ROUTER) && (curNwkState != DEV_END_DEVICE) ) return 1; switch(pMsgBody->cmd) { case 0x0018: { switch(pMsgBody->cmdEndPoint) { case 0xF1: { // 转发数据 SendData(TRANSFER_ENDPOINT, pMsgBody->data, pMsgBody->addr, pMsgBody->endPoint, pMsgBody->len - 6); } break; } } break; } return 1; } #endif uint8 SendData(uint8 srcEP, const void *buf, uint16 addr, uint8 dstEP, uint8 Len) { static uint8 transID = 0; afAddrType_t SendDataAddr; struct ep_info_t *epInfo; if(srcEP <= funcCount) epInfo = &funcList[srcEP - 1]; else epInfo = &controlEndPointInfo; SendDataAddr.addrMode = (afAddrMode_t)Addr16Bit; //短地址发送 SendDataAddr.endPoint = dstEP; SendDataAddr.addr.shortAddr = addr; if ( AF_DataRequest( &SendDataAddr, //发送的地址和模式 // TODO: &epInfo->SampleApp_epDesc, //终端(比如操作系统中任务ID等) SAPP_PERIODIC_CLUSTERID,//发送串ID Len, (uint8*)buf, &transID, //信息ID(操作系统参数) AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) { HalLedBlink( HAL_LED_1, 1, 50, 250 ); return 1; } else { return 0; } } void CreateUserTimer(struct ep_info_t *ep, uint8 seconds) { if(ep == NULL) return; if(ep->res_available == NULL) return; ep->userTimer = seconds; if(isUserTimerRunning == 0) { osal_start_timerEx(controlTaskId, SAPP_SEND_PERIODIC_MSG_EVT, 1000); isUserTimerRunning = 1; } } void DeleteUserTimer(struct ep_info_t *ep) { if(ep == NULL) return; ep->userTimer = 0; } void ModifyRefreshCycle(struct ep_info_t *ep, uint8 seconds) { if(ep == NULL) return; if(ep->time_out == NULL) return; ep->function.cycle = seconds; if(ep->timerTick > seconds) ep->timerTick = seconds; } #if ! defined(ZDO_COORDINATOR) && defined(RTR_NWK) void RouterTimeoutRoutine(struct ep_info_t *ep) { SendData(ep->ep, (unsigned char *)&topoBuffer, 0x0000, TRANSFER_ENDPOINT, sizeof(TOPOINFO)); //节点向协调器发送采集数据 } #endif #if defined(ZDO_COORDINATOR) void CoordinatorIncomingRoutine(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg) { //msg->Data[], msg->DataLength, msg->TransSeqNumber // 转发数据到串口 if(msg->DataLength > 0) { mtUserSerialMsg_t *pMsg = osal_mem_alloc(sizeof(mtUserSerialMsg_t) + msg->DataLength - 1); pMsg->sop = MT_UART_SOF; pMsg->len = msg->DataLength + 6; pMsg->cmd = 0x0018; pMsg->cmdEndPoint = 0xF1; pMsg->addr = addr; pMsg->endPoint = endPoint; memcpy(pMsg->data, msg->Data, msg->DataLength); pMsg->fsc = MT_UartCalcFCS(0, &pMsg->len, 1); pMsg->fsc = MT_UartCalcFCS(pMsg->fsc, pMsg->dataBody, pMsg->len); HalUARTWrite(HAL_UART_PORT_0, &pMsg->sop, sizeof(mtUserSerialMsg_t) - 2 + msg->DataLength); HalUARTWrite(HAL_UART_PORT_0, &pMsg->fsc, 1); osal_mem_free(pMsg); } } #endif #endif//SAPP_ZSTACK