/****************************************************************************** * @fn zb_StartRequest * * @brief The zb_StartRequest function starts the ZigBee stack. When the * ZigBee stack starts, the device reads configuration parameters * from Nonvolatile memory and the device joins its network. The * ZigBee stack calls the zb_StartConrifm callback function when * the startup process completes. * * @param none * * @return none */ void zb_StartRequest() { uint8 logicalType; zb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType ); // Check for bad combinations of compile flag definitions and device type setting. if ((logicalType > ZG_DEVICETYPE_ENDDEVICE) || #if !ZG_BUILD_ENDDEVICE_TYPE // Only RTR or Coord possible. (logicalType == ZG_DEVICETYPE_ENDDEVICE) || #endif #if !ZG_BUILD_RTR_TYPE // Only End Device possible. (logicalType == ZG_DEVICETYPE_ROUTER) || (logicalType == ZG_DEVICETYPE_COORDINATOR) || #elif ZG_BUILD_RTRONLY_TYPE // Only RTR possible. (logicalType == ZG_DEVICETYPE_COORDINATOR) || #elif !ZG_BUILD_JOINING_TYPE // Only Coord possible. (logicalType == ZG_DEVICETYPE_ROUTER) || #endif (0)) { logicalType = ZB_INVALID_PARAMETER; SAPI_SendCback(SAPICB_START_CNF, logicalType, 0); } else { logicalType = ZB_SUCCESS; ZDOInitDevice(zgStartDelay); } return; }
/****************************************************************************** * @fn zb_HandleOsalEvent * * @brief The zb_HandleOsalEvent function is called by the operating * system when a task event is set * * @param event - Bitmask containing the events that have been set * * @return none */ void zb_HandleOsalEvent( uint16 event ) { uint8 logicalType; if(event & SYS_EVENT_MSG) { } if( event & ZB_ENTRY_EVENT ) { // Initialise UART initUart(uartRxCB); // blind LED 1 to indicate starting/joining a network #ifndef SYS_DEBUG_SH HalLedBlink ( HAL_LED_1, 0, 50, 500 ); #endif HalLedSet( HAL_LED_2, HAL_LED_MODE_OFF ); // Read logical device type from NV zb_ReadConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType); // Start the device zb_StartRequest(); #ifdef SYS_DEBUG_SH // Turn ON Allow Bind mode infinitly zb_AllowBind( 0xFF ); HalLedSet( HAL_LED_2, HAL_LED_MODE_ON ); #endif } if ( event & MY_START_EVT ) { zb_StartRequest(); } if ( event & MY_REPORT_EVT ) { if (isGateWay) { osal_start_timerEx( sapi_TaskID, MY_REPORT_EVT, myReportPeriod ); } else if (appState == APP_BINDED) { sendDummyReport(); osal_start_timerEx( sapi_TaskID, MY_REPORT_EVT, myReportPeriod ); } } if ( event & MY_FIND_COLLECTOR_EVT ) { // Find and bind to a gateway device (if this node is not gateway) if (!isGateWay) { zb_BindDevice( TRUE, DUMMY_REPORT_CMD_ID, (uint8 *)NULL ); } } }
/** * @brief Esta función es llamada por el SO cuando se debe atender un * evento de la tarea. * @param event Mascara de bits conteniendo los eventos a atender */ void zb_HandleOsalEvent(uint16 event) { uint8 logicalType; if (event & SYS_EVENT_MSG) { } if (event & ZB_ENTRY_EVENT) { // inicializa UART initUart(uartRxCB); // blick LED 1 para indicar que se está uniendo a la red HalLedBlink(HAL_LED_1, 0, 50, 500 ); HalLedSet(HAL_LED_2, HAL_LED_MODE_OFF); // lee tipo de logical device desde la memoria NV zb_ReadConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType); // inicia la red zb_StartRequest(); } if (event & MY_START_EVT) { // inicia la red zb_StartRequest(); } if (event & SEND_UART_MSG) { // envia mensaje por UART a la PC //HalLcdWriteString("UART_EVT", HAL_LCD_LINE_1); sendUartMessage(&msgReport, &alarmFlags); } if (event & MY_TEST_EVT) { // crea mensaje de prueba msgReport.msgType = MSG_TYPE_REPORT; msgReport.sequence++; msgReport.lenData = MSG_LEN_DATA_REPORT; for (uint8 i = 0; i < 8; i++) msgReport.mac[i] = i; // datos de prueba static double d[10] = {220.5, 0.354, 85.12, 88.33, 85.06, 0.98, 1.23, 3.25, 0.97, 4.55}; for (int i = 0; i < 10; i++) memcpy(&(msgReport.data[i*4]), &(d[i]), sizeof(double)); // flags de prueba uint16 flags = 0; // imprime info en LCD HalLcdWriteString("TEST_EVT", HAL_LCD_LINE_1); HalLcdWriteStringValue("#", msgReport.sequence, 10, HAL_LCD_LINE_2); // envia mensaje por UART sendUartMessage(&msgReport, &flags); // crea evento nuevamente osal_start_timerEx(sapi_TaskID, MY_TEST_EVT, 5000); } }
/*************************************************************************************************** * @fn MT_SapiReadCfg * * @brief Process SAPI Read Config Commands * * @param pBuf - pointer to received buffer * * @return none ***************************************************************************************************/ void MT_SapiReadCfg(uint8 *pBuf) { uint8 len, retStatus; uint8 cfgId, cmdId; uint8 *pRetBuf; /* Parse header */ cmdId = pBuf[MT_RPC_POS_CMD1]; cfgId = pBuf[MT_RPC_POS_DAT0]; /* Length of item in NV memory */ len = (uint8)osal_nv_item_len(cfgId); pRetBuf = osal_mem_alloc(len+3); if (pRetBuf != NULL) { if (len && ((cfgId != ZCD_NV_NIB) && (cfgId != ZCD_NV_DEVICE_LIST) && (cfgId != ZCD_NV_ADDRMGR) && (cfgId != ZCD_NV_NWKKEY))) { if ((zb_ReadConfiguration(cfgId, len, pRetBuf+3)) == ZSUCCESS) { retStatus = ZSuccess; } else { retStatus = ZFailure; } } else { retStatus = ZInvalidParameter; } if (retStatus != ZSuccess) { /* Don't return garbage with error */ len = 0; } /* Status */ pRetBuf[0] = retStatus; /* Config ID */ pRetBuf[1] = cfgId; /* NV item length */ pRetBuf[2] = len; /* Build and send back the response */ MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_SRSP | (uint8)MT_RPC_SYS_SAPI), cmdId, len+3, pRetBuf ); osal_mem_free(pRetBuf); } }
/****************************************************************************** * @fn zb_StartRequest * * @brief The zb_StartRequest function starts the ZigBee stack. When the * ZigBee stack starts, the device reads configuration parameters * from Nonvolatile memory and the device joins its network. The * ZigBee stack calls the zb_StartConrifm callback function when * the startup process completes. * * @param none * * @return none */ void zb_StartRequest() { uint8 logicalType; // Start the device // start delay = min(NWK_START_DELAY, zgStartDelay) + rand() - only for fresh start, not restore if ( zgStartDelay < NWK_START_DELAY ) zgStartDelay = 0; else zgStartDelay -= NWK_START_DELAY; // check that bad combinations of compile flag definitions and device type zb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType ); if ( ( logicalType > ZG_DEVICETYPE_ENDDEVICE ) || #if defined( RTR_NWK ) #if defined( ZDO_COORDINATOR ) // Only RTR or Coord possible ( logicalType == ZG_DEVICETYPE_ENDDEVICE ) || #else // Only RTR possible ( logicalType != ZG_DEVICETYPE_ROUTER ) || #endif #else #if defined( ZDO_COORDINATOR ) // Error ( 1 ) || #else // only ED possible ( logicalType != ZG_DEVICETYPE_ENDDEVICE ) || #endif #endif ( 0 ) ) { // error configuration SAPI_SendCback( SAPICB_START_CNF, ZInvalidParameter, 0 ); } else { ZDOInitDevice(zgStartDelay); } return; }
/********************************************************************* * @fn SAPI_ProcessEvent * * @brief Simple API Task event processor. This function * is called to process all events for the task. Events * include timers, messages and any other user defined events. * * @param task_id - The OSAL assigned task ID. * @param events - events to process. This is a bit map and can * contain more than one event. * * @return none */ UINT16 SAPI_ProcessEvent( byte task_id, UINT16 events ) { osal_event_hdr_t *pMsg; afIncomingMSGPacket_t *pMSGpkt; afDataConfirm_t *pDataConfirm; if ( events & SYS_EVENT_MSG ) { pMsg = (osal_event_hdr_t *) osal_msg_receive( task_id ); while ( pMsg ) { switch ( pMsg->event ) { case ZDO_CB_MSG: SAPI_ProcessZDOMsgs( (zdoIncomingMsg_t *)pMsg ); break; case AF_DATA_CONFIRM_CMD: // This message is received as a confirmation of a data packet sent. // The status is of ZStatus_t type [defined in ZComDef.h] // The message fields are defined in AF.h pDataConfirm = (afDataConfirm_t *) pMsg; SAPI_SendDataConfirm( pDataConfirm->transID, pDataConfirm->hdr.status ); break; case AF_INCOMING_MSG_CMD: pMSGpkt = (afIncomingMSGPacket_t *) pMsg; SAPI_ReceiveDataIndication( pMSGpkt->srcAddr.addr.shortAddr, pMSGpkt->clusterId, pMSGpkt->cmd.DataLength, pMSGpkt->cmd.Data); break; case ZDO_STATE_CHANGE: // If the device has started up, notify the application if (pMsg->status == DEV_END_DEVICE || pMsg->status == DEV_ROUTER || pMsg->status == DEV_ZB_COORD ) { SAPI_StartConfirm( ZB_SUCCESS ); } else if (pMsg->status == DEV_HOLD || pMsg->status == DEV_INIT) { SAPI_StartConfirm( ZB_INIT ); } break; case ZDO_MATCH_DESC_RSP_SENT: SAPI_AllowBindConfirm( ((ZDO_MatchDescRspSent_t *)pMsg)->nwkAddr ); break; case KEY_CHANGE: #if ( SAPI_CB_FUNC ) zb_HandleKeys( ((keyChange_t *)pMsg)->state, ((keyChange_t *)pMsg)->keys ); #endif break; case SAPICB_DATA_CNF: SAPI_SendDataConfirm( (uint8)((sapi_CbackEvent_t *)pMsg)->data, ((sapi_CbackEvent_t *)pMsg)->hdr.status ); break; case SAPICB_BIND_CNF: SAPI_BindConfirm( ((sapi_CbackEvent_t *)pMsg)->data, ((sapi_CbackEvent_t *)pMsg)->hdr.status ); break; case SAPICB_START_CNF: SAPI_StartConfirm( ((sapi_CbackEvent_t *)pMsg)->hdr.status ); break; default: // User messages should be handled by user or passed to the application if ( pMsg->event >= ZB_USER_MSG ) { } break; } // Release the memory osal_msg_deallocate( (uint8 *) pMsg ); // Next pMsg = (osal_event_hdr_t *) osal_msg_receive( task_id ); } // Return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & ZB_ALLOW_BIND_TIMER ) { afSetMatch(sapi_epDesc.simpleDesc->EndPoint, FALSE); return (events ^ ZB_ALLOW_BIND_TIMER); } if ( events & ZB_BIND_TIMER ) { // Send bind confirm callback to application SAPI_BindConfirm( sapi_bindInProgress, ZB_TIMEOUT ); sapi_bindInProgress = 0xffff; return (events ^ ZB_BIND_TIMER); } if ( events & ZB_ENTRY_EVENT ) { uint8 startOptions; // Give indication to application of device startup #if ( SAPI_CB_FUNC ) zb_HandleOsalEvent( ZB_ENTRY_EVENT ); #endif // LED off cancels HOLD_AUTO_START blink set in the stack HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF); zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions ); if ( startOptions & ZCD_STARTOPT_AUTO_START ) { zb_StartRequest(); } else { // blink leds and wait for external input to config and restart HalLedBlink(HAL_LED_2, 0, 50, 500); } return (events ^ ZB_ENTRY_EVENT ); } // This must be the last event to be processed if ( events & ( ZB_USER_EVENTS ) ) { // User events are passed to the application #if ( SAPI_CB_FUNC ) zb_HandleOsalEvent( events ); #endif // Do not return here, return 0 later } // Discard unknown events return 0; }
/********************************************************************* * @fn zb_HandleKeys * * @brief Handles all key events for this device. * * @param shift - true if in shift/alt. * @param keys - bit field for key events. Valid entries: * EVAL_SW4 * EVAL_SW3 * EVAL_SW2 * EVAL_SW1 * * @return none */ void zb_HandleKeys( uint8 shift, uint8 keys ) { uint8 startOptions; uint8 logicalType; // Shift is used to make each button/switch dual purpose. if ( shift ) { if ( keys & HAL_KEY_SW_1 ) { } if ( keys & HAL_KEY_SW_2 ) { } if ( keys & HAL_KEY_SW_3 ) { } if ( keys & HAL_KEY_SW_4 ) { } } else { if ( keys & HAL_KEY_SW_1 ) { if ( myAppState == APP_INIT ) { // In the init state, keys are used to indicate the logical mode. // Key 1 starts device as a coordinator zb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType ); if ( logicalType != ZG_DEVICETYPE_ENDDEVICE ) { logicalType = ZG_DEVICETYPE_COORDINATOR; zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType); } // Do more configuration if necessary and then restart device with auto-start bit set // write endpoint to simple desc...dont pass it in start req..then reset zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions ); startOptions = ZCD_STARTOPT_AUTO_START; zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions ); zb_SystemReset(); } else { // Turn ON Allow Bind mode indefinitely zb_AllowBind( 0xFF ); HalLedSet( HAL_LED_1, HAL_LED_MODE_ON ); } } if ( keys & HAL_KEY_SW_2 ) { if ( myAppState == APP_INIT ) { // In the init state, keys are used to indicate the logical mode. // Key 2 starts device as a router zb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType ); if ( logicalType != ZG_DEVICETYPE_ENDDEVICE ) { logicalType = ZG_DEVICETYPE_ROUTER; zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType); } zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions ); startOptions = ZCD_STARTOPT_AUTO_START; zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions ); zb_SystemReset(); } else { // Turn OFF Allow Bind mode indefinitely zb_AllowBind( 0x00 ); HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF ); } } if ( keys & HAL_KEY_SW_3 ) { } if ( keys & HAL_KEY_SW_4 ) { } } }