void main(void) { CLRWDT(); ENABLE_WDT(); currentPrimitive = NO_PRIMITIVE; NetworkDescriptor = NULL; orphanTries = 3; // If you are going to send data to a terminal, initialize the UART. ConsoleInit(); ConsolePutROMString( (ROM char *)"Universidade Paulista - UNIP\r\n" ); ConsolePutROMString( (ROM char *)"Daniel Gonçalves\r\n" ); ConsolePutROMString( (ROM char *)"Projeto: Baba Eletronica\r\n\r\n" ); ConsolePutROMString( (ROM char *)"\r\n\r\n\r\n*************************************\r\n" ); ConsolePutROMString( (ROM char *)"Microchip ZigBee(TM) Stack - v1.0-3.8\r\n\r\n" ); ConsolePutROMString( (ROM char *)"ZigBee RFD\r\n\r\n" ); ConsolePutROMString( (ROM char *)"Transceiver-MRF24J40\r\n\r\n" ); // Inicializa o Hardware HardwareInit(); // Inicializa a pilha ZigBee ZigBeeInit(); // ************************************************************************* // Outras Inicializações // ************************************************************************* myStatusFlags.Val = STATUS_FLAGS_INIT; // Endereço padrão do Coordenador destinationAddress.Val = 0x0000; // Inicializa os LEDS MOVE_SENSOR_LED = ON; LEVEL_SENSOR_LED = ON; // Habilita as interrupções RCONbits.IPEN = 1; INTCONbits.GIEH = 1; while (1) { CLRWDT(); ZigBeeTasks( ¤tPrimitive ); switch (currentPrimitive) { case NLME_NETWORK_DISCOVERY_confirm: currentPrimitive = NO_PRIMITIVE; if (!params.NLME_NETWORK_DISCOVERY_confirm.Status) { if (!params.NLME_NETWORK_DISCOVERY_confirm.NetworkCount) { ConsolePutROMString( (ROM char *)"No networks found. Trying again...\r\n" ); } else { // Save the descriptor list pointer so we can destroy it later. NetworkDescriptor = params.NLME_NETWORK_DISCOVERY_confirm.NetworkDescriptor; // Select a network to try to join. We're not going to be picky right now... currentNetworkDescriptor = NetworkDescriptor; SubmitJoinRequest: // not needed for new join params.NLME_JOIN_request.ScanDuration = ; // not needed for new join params.NLME_JOIN_request.ScanChannels = ; params.NLME_JOIN_request.PANId = currentNetworkDescriptor->PanID; ConsolePutROMString( (ROM char *)"Network(s) found. Trying to join " ); PrintChar( params.NLME_JOIN_request.PANId.byte.MSB ); PrintChar( params.NLME_JOIN_request.PANId.byte.LSB ); ConsolePutROMString( (ROM char *)".\r\n" ); params.NLME_JOIN_request.JoinAsRouter = FALSE; params.NLME_JOIN_request.RejoinNetwork = FALSE; params.NLME_JOIN_request.PowerSource = NOT_MAINS_POWERED; params.NLME_JOIN_request.RxOnWhenIdle = FALSE; params.NLME_JOIN_request.MACSecurity = FALSE; currentPrimitive = NLME_JOIN_request; } } else { PrintChar( params.NLME_NETWORK_DISCOVERY_confirm.Status ); ConsolePutROMString( (ROM char *)" Error finding network. Trying again...\r\n" ); } break; case NLME_JOIN_confirm: currentPrimitive = NO_PRIMITIVE; if (!params.NLME_JOIN_confirm.Status) { ConsolePutROMString( (ROM char *)"Join successful!\r\n" ); // Free the network descriptor list, if it exists. If we joined as an orphan, it will be NULL. while (NetworkDescriptor) { currentNetworkDescriptor = NetworkDescriptor->next; free( NetworkDescriptor ); NetworkDescriptor = currentNetworkDescriptor; } } else { PrintChar( params.NLME_JOIN_confirm.Status ); // If we were trying as an orphan, see if we have some more orphan attempts. if (ZigBeeStatus.flags.bits.bTryOrphanJoin) { // If we tried to join as an orphan, we do not have NetworkDescriptor, so we do // not have to free it. ConsolePutROMString( (ROM char *)" Could not join as orphan. " ); orphanTries--; if (orphanTries == 0) { ConsolePutROMString( (ROM char *)"Must try as new node...\r\n" ); ZigBeeStatus.flags.bits.bTryOrphanJoin = 0; } else { ConsolePutROMString( (ROM char *)"Trying again...\r\n" ); } } else { ConsolePutROMString( (ROM char *)" Could not join selected network. " ); currentNetworkDescriptor = currentNetworkDescriptor->next; if (currentNetworkDescriptor) { ConsolePutROMString( (ROM char *)"Trying next discovered network...\r\n" ); goto SubmitJoinRequest; } else { // We ran out of descriptors. Free the network descriptor list, and fall // through to try discovery again. ConsolePutROMString( (ROM char *)"Cleaning up and retrying discovery...\r\n" ); while (NetworkDescriptor) { currentNetworkDescriptor = NetworkDescriptor->next; free( NetworkDescriptor ); NetworkDescriptor = currentNetworkDescriptor; } } } } break; case NLME_LEAVE_indication: if (!memcmppgm2ram( ¶ms.NLME_LEAVE_indication.DeviceAddress, (ROM void *)&macLongAddr, 8 )) { ConsolePutROMString( (ROM char *)"We have left the network.\r\n" ); } else { ConsolePutROMString( (ROM char *)"Another node has left the network.\r\n" ); } currentPrimitive = NO_PRIMITIVE; break; case NLME_RESET_confirm: ConsolePutROMString( (ROM char *)"ZigBee Stack has been reset.\r\n" ); currentPrimitive = NO_PRIMITIVE; break; case NLME_SYNC_confirm: switch (params.NLME_SYNC_confirm.Status) { case SUCCESS: // I have heard from my parent, but it has no data for me. Note that // if my parent has data for me, I will get an APSDE_DATA_indication. ConsolePutROMString( (ROM char *)"No data available.\r\n" ); break; case NWK_SYNC_FAILURE: // I cannot communicate with my parent. ConsolePutROMString( (ROM char *)"I cannot communicate with my parent.\r\n" ); break; case NWK_INVALID_PARAMETER: // If we call NLME_SYNC_request correctly, this doesn't occur. ConsolePutROMString( (ROM char *)"Invalid sync parameter.\r\n" ); break; } currentPrimitive = NO_PRIMITIVE; break; case APSDE_DATA_indication: { WORD_VAL attributeId; BYTE command; BYTE data; BYTE dataLength; //BYTE dataType; BYTE frameHeader; BYTE sequenceNumber; BYTE transaction; BYTE transByte; currentPrimitive = NO_PRIMITIVE; frameHeader = APLGet(); switch (params.APSDE_DATA_indication.DstEndpoint) { case EP_ZDO: ConsolePutROMString( (ROM char *)" Receiving ZDO cluster " ); PrintChar( params.APSDE_DATA_indication.ClusterId ); ConsolePutROMString( (ROM char *)"\r\n" ); // Put code here to handle any ZDO responses that we requested if ((frameHeader & APL_FRAME_TYPE_MASK) == APL_FRAME_TYPE_MSG) { frameHeader &= APL_FRAME_COUNT_MASK; for (transaction=0; transaction<frameHeader; transaction++) { sequenceNumber = APLGet(); dataLength = APLGet(); transByte = 1; // Account for status byte switch( params.APSDE_DATA_indication.ClusterId ) { // ******************************************************** // Put a case here to handle each ZDO response that we requested. // ******************************************************** case NWK_ADDR_rsp: if (APLGet() == SUCCESS) { ConsolePutROMString( (ROM char *)" Receiving NWK_ADDR_rsp.\r\n" ); // Skip over the IEEE address of the responder. for (data=0; data<8; data++) { APLGet(); transByte++; } destinationAddress.byte.LSB = APLGet(); destinationAddress.byte.MSB = APLGet(); transByte += 2; myStatusFlags.bits.bDestinationAddressKnown = 1; } break; default: break; } // Read out the rest of the MSG in case there is another transaction. for (; transByte<dataLength; transByte++) { APLGet(); } } } break; // ************************************************************************ // Place a case for each user defined endpoint. // ************************************************************************ case EP_LIGHT: if ((frameHeader & APL_FRAME_TYPE_MASK) == APL_FRAME_TYPE_KVP) { frameHeader &= APL_FRAME_COUNT_MASK; for (transaction=0; transaction<frameHeader; transaction++) { sequenceNumber = APLGet(); command = APLGet(); attributeId.byte.LSB = APLGet(); attributeId.byte.MSB = APLGet(); //dataType = command & APL_FRAME_DATA_TYPE_MASK; command &= APL_FRAME_COMMAND_MASK; if ((params.APSDE_DATA_indication.ClusterId == OnOffSRC_CLUSTER) && (attributeId.Val == OnOffSRC_OnOff)) { if ((command == APL_FRAME_COMMAND_SET) || (command == APL_FRAME_COMMAND_SETACK)) { // Prepare a response in case it is needed. TxBuffer[TxData++] = APL_FRAME_TYPE_KVP | 1; // KVP, 1 transaction TxBuffer[TxData++] = sequenceNumber; TxBuffer[TxData++] = APL_FRAME_COMMAND_SET_RES | (APL_FRAME_DATA_TYPE_UINT8 << 4); TxBuffer[TxData++] = attributeId.byte.LSB; TxBuffer[TxData++] = attributeId.byte.MSB; // Data type for this attibute must be APL_FRAME_DATA_TYPE_UINT8 data = APLGet(); switch (data) { case LIGHT_OFF: ConsolePutROMString( (ROM char *)" Turning light off.\r\n" ); LEVEL_SENSOR_LED = 0; TxBuffer[TxData++] = SUCCESS; break; case LIGHT_ON: ConsolePutROMString( (ROM char *)" Turning light on.\r\n" ); LEVEL_SENSOR_LED = 1; TxBuffer[TxData++] = SUCCESS; break; case LIGHT_TOGGLE: ConsolePutROMString( (ROM char *)" Toggling light.\r\n" ); LEVEL_SENSOR_LED ^= 1; TxBuffer[TxData++] = SUCCESS; break; default: PrintChar( data ); ConsolePutROMString( (ROM char *)" Invalid light message.\r\n" ); TxBuffer[TxData++] = KVP_INVALID_ATTRIBUTE_DATA; break; } } if (command == APL_FRAME_COMMAND_SETACK) { // Send back an application level acknowledge. ZigBeeBlockTx(); // Take care here that parameters are not overwritten before they are used. // We can use the data byte as a temporary variable. params.APSDE_DATA_request.DstAddrMode = params.APSDE_DATA_indication.SrcAddrMode; params.APSDE_DATA_request.DstEndpoint = params.APSDE_DATA_indication.SrcEndpoint; params.APSDE_DATA_request.DstAddress.ShortAddr = params.APSDE_DATA_indication.SrcAddress.ShortAddr; //params.APSDE_DATA_request.asduLength; TxData //params.APSDE_DATA_request.ProfileId; unchanged params.APSDE_DATA_request.RadiusCounter = DEFAULT_RADIUS; params.APSDE_DATA_request.DiscoverRoute = ROUTE_DISCOVERY_ENABLE; #ifdef I_SUPPORT_SECURITY params.APSDE_DATA_request.TxOptions.Val = 1; #else params.APSDE_DATA_request.TxOptions.Val = 0; #endif params.APSDE_DATA_request.SrcEndpoint = EP_LIGHT; //params.APSDE_DATA_request.ClusterId; unchanged currentPrimitive = APSDE_DATA_request; } else { // We are not sending an acknowledge, so reset the transmit message pointer. TxData = TX_DATA_START; } } // TODO read to the end of the transaction. } // each transaction } // frame type break; default: break; } APLDiscardRx(); } break; case APSDE_DATA_confirm: if (params.APSDE_DATA_confirm.Status) { ConsolePutROMString( (ROM char *)"Error " ); PrintChar( params.APSDE_DATA_confirm.Status ); ConsolePutROMString( (ROM char *)" sending message.\r\n" ); } else { ConsolePutROMString( (ROM char *)" Message sent successfully.\r\n" ); } currentPrimitive = NO_PRIMITIVE; break; case NO_PRIMITIVE: if (!ZigBeeStatus.flags.bits.bNetworkJoined) { if (!ZigBeeStatus.flags.bits.bTryingToJoinNetwork) { if (ZigBeeStatus.flags.bits.bTryOrphanJoin) { ConsolePutROMString( (ROM char *)"Trying to join network as an orphan...\r\n" ); params.NLME_JOIN_request.JoinAsRouter = FALSE; params.NLME_JOIN_request.RejoinNetwork = TRUE; params.NLME_JOIN_request.PowerSource = NOT_MAINS_POWERED; params.NLME_JOIN_request.RxOnWhenIdle = FALSE; params.NLME_JOIN_request.MACSecurity = FALSE; params.NLME_JOIN_request.ScanDuration = 8; params.NLME_JOIN_request.ScanChannels.Val = ALLOWED_CHANNELS; currentPrimitive = NLME_JOIN_request; } else { ConsolePutROMString( (ROM char *)"Trying to join network as a new device...\r\n" ); params.NLME_NETWORK_DISCOVERY_request.ScanDuration = 6; params.NLME_NETWORK_DISCOVERY_request.ScanChannels.Val = ALLOWED_CHANNELS; currentPrimitive = NLME_NETWORK_DISCOVERY_request; } } } else { // See if I can do my own internal tasks. We don't want to try to send a message // if we just asked for one. if (ZigBeeStatus.flags.bits.bDataRequestComplete && ZigBeeReady()) { // ************************************************************************ // Place all processes that can send messages here. Be sure to call // ZigBeeBlockTx() when currentPrimitive is set to APSDE_DATA_request. // ************************************************************************ if ( myStatusFlags.bits.bMoveSensorButtonPressed) { // Send a light toggle message to the other node. myStatusFlags.bits.bMoveSensorButtonPressed = FALSE; BLINK_LED(MOVE_SENSOR_LED); // envia a mensagem para ligar/desligar o led RFDSendMessage(MoveSensor_Activated, 0x00); } else if (myStatusFlags.bits.bLevelSensorButtonPressed) { // Envia mensagem indicando que o sensor de nível foi acionado myStatusFlags.bits.bLevelSensorButtonPressed = FALSE; BLINK_LED(LEVEL_SENSOR_LED); RFDSendMessage(LevelSensor_Activated, 0x00); } // We've processed any key press, so re-enable interrupts. INTCONbits.RBIE = 1; } // If we don't have to execute a primitive, see if we need to request data from // our parent, or if we can go to sleep. if (currentPrimitive == NO_PRIMITIVE) { if (!ZigBeeStatus.flags.bits.bDataRequestComplete) { // We have not received all data from our parent. If we are not waiting // for an answer from a data request, send a data request. if (!ZigBeeStatus.flags.bits.bRequestingData) { if (ZigBeeReady()) { // Our parent still may have data for us. params.NLME_SYNC_request.Track = FALSE; currentPrimitive = NLME_SYNC_request; ConsolePutROMString( (ROM char *)"Requesting data...\r\n" ); } } } else { if (!ZigBeeStatus.flags.bits.bHasBackgroundTasks && myProcessesAreDone()) { // We do not have a primitive to execute, we've extracted all messages // that our parent has for us, the stack has no background tasks, // and all application-specific processes are complete. Now we can // go to sleep. Make sure that the UART is finished, turn off the transceiver, // and make sure that we wakeup from key press. if(APLDisable() == TRUE) { ConsolePutROMString( (ROM char *)"Going to sleep...\r\n" ); while (!ConsoleIsPutReady()); APLDisable(); INTCONbits.RBIE = 1; SLEEP(); NOP(); // We just woke up from sleep. Turn on the transceiver and // request data from our parent. APLEnable(); params.NLME_SYNC_request.Track = FALSE; currentPrimitive = NLME_SYNC_request; ConsolePutROMString( (ROM char *)"Requesting data...\r\n" ); } } } } } break; default: PrintChar( currentPrimitive ); ConsolePutROMString( (ROM char *)" Unhandled primitive.\r\n" ); currentPrimitive = NO_PRIMITIVE; } // ********************************************************************* // Place any non-ZigBee related processing here. Be sure that the code // will loop back and execute ZigBeeTasks() in a timely manner. // ********************************************************************* } }
void main(void) { CLRWDT(); ENABLE_WDT(); currentPrimitive = NO_PRIMITIVE; NetworkDescriptor = NULL; // If you are going to send data to a terminal, initialize the UART. ConsoleInit(); // Initialize the hardware - must be done before initializing ZigBee. HardwareInit(); // Initialize the ZigBee Stack. ZigBeeInit(); // ************************************************************************* // Perform any other initialization here // ************************************************************************* // Enable interrupts to get everything going. IPEN = 1; GIEH = 1; while (1) { CLRWDT(); ZigBeeTasks( ¤tPrimitive ); switch (currentPrimitive) { case NLME_NETWORK_DISCOVERY_confirm: currentPrimitive = NO_PRIMITIVE; if (!params.NLME_NETWORK_DISCOVERY_confirm.Status) { if (!params.NLME_NETWORK_DISCOVERY_confirm.NetworkCount) { ConsolePutROMString( (ROM char *)"No networks found. Trying again...\r\n" ); } else { // Save the descriptor list pointer so we can destroy it later. NetworkDescriptor = params.NLME_NETWORK_DISCOVERY_confirm.NetworkDescriptor; // Select a network to try to join. We're not going to be picky right now... currentNetworkDescriptor = NetworkDescriptor; // not needed for new join params.NLME_JOIN_request.ScanDuration = ; // not needed for new join params.NLME_JOIN_request.ScanChannels = ; params.NLME_JOIN_request.PANId = currentNetworkDescriptor->PanID; params.NLME_JOIN_request.JoinAsRouter = FALSE; params.NLME_JOIN_request.RejoinNetwork = FALSE; params.NLME_JOIN_request.PowerSource = NOT_MAINS_POWERED; params.NLME_JOIN_request.RxOnWhenIdle = FALSE; params.NLME_JOIN_request.MACSecurity = FALSE; currentPrimitive = NLME_JOIN_request; ConsolePutROMString( (ROM char *)"Network(s) found. Trying to join " ); PrintChar( params.NLME_JOIN_request.PANId.byte.MSB ); PrintChar( params.NLME_JOIN_request.PANId.byte.LSB ); ConsolePutROMString( (ROM char *)".\r\n" ); } } else { PrintChar( params.NLME_NETWORK_DISCOVERY_confirm.Status ); ConsolePutROMString( (ROM char *)" Error finding network. Trying again...\r\n" ); } break; case NLME_JOIN_confirm: currentPrimitive = NO_PRIMITIVE; if (!params.NLME_JOIN_confirm.Status) { ConsolePutROMString( (ROM char *)"Join successful!\r\n" ); if (NetworkDescriptor) { // If we joined as an orphan, this will be NULL. free( NetworkDescriptor ); } // We are now on the network. Enable routing. params.NLME_START_ROUTER_request.BeaconOrder = MAC_PIB_macBeaconOrder; params.NLME_START_ROUTER_request.SuperframeOrder = MAC_PIB_macSuperframeOrder; params.NLME_START_ROUTER_request.BatteryLifeExtension = FALSE; currentPrimitive = NLME_START_ROUTER_request; } else { PrintChar( params.NLME_JOIN_confirm.Status ); ConsolePutROMString( (ROM char *)" Could not join. Trying again as new device..." ); } break; case NLME_LEAVE_indication: if (!memcmppgm2ram( ¶ms.NLME_LEAVE_indication.DeviceAddress, (ROM void *)&macLongAddr, 8 )) { ConsolePutROMString( (ROM char *)"We have left the network.\r\n" ); } else { ConsolePutROMString( (ROM char *)"Another node has left the network.\r\n" ); } currentPrimitive = NO_PRIMITIVE; break; case NLME_RESET_confirm: ConsolePutROMString( (ROM char *)"ZigBee Stack has been reset.\r\n" ); currentPrimitive = NO_PRIMITIVE; break; case NLME_START_ROUTER_confirm: if (!params.NLME_START_ROUTER_confirm.Status) { ConsolePutROMString( (ROM char *)"Router Started!\r\n" ); } else { PrintChar( params.NLME_JOIN_confirm.Status ); ConsolePutROMString( (ROM char *)" Router start unsuccessful. We cannot route frames.\r\n" ); } // We are now ready to do ZigBee related tasks. currentPrimitive = NO_PRIMITIVE; break; case APSDE_DATA_indication: { WORD_VAL attributeId; BYTE command; BYTE data; BYTE dataLength; //BYTE dataType; BYTE frameHeader; BYTE sequenceNumber; BYTE transaction; BYTE transByte; currentPrimitive = NO_PRIMITIVE; frameHeader = APLGet(); switch (params.APSDE_DATA_indication.DstEndpoint) { case EP_ZDO: if ((frameHeader & APL_FRAME_TYPE_MASK) == APL_FRAME_TYPE_MSG) { frameHeader &= APL_FRAME_COUNT_MASK; for (transaction=0; transaction<frameHeader; transaction++) { sequenceNumber = APLGet(); dataLength = APLGet(); transByte = 0; switch( params.APSDE_DATA_indication.ClusterId ) { // ******************************************************** // Put a case here to handle each ZDO response that we requested. // Be sure to increment transByte for each APLGet(). // ******************************************************** default: break; } // Read out the rest of the MSG in case there is another transaction. for (; transByte<dataLength; transByte++) { APLGet(); } } } break; // ************************************************************************ // Place a case for each user defined endpoint. // ************************************************************************ default: // If the command type was something that requested an acknowledge, we could send back // KVP_INVALID_ENDPOINT here. break; } APLDiscardRx(); } break; case APSDE_DATA_confirm: if (params.APSDE_DATA_confirm.Status) { ConsolePutROMString( (ROM char *)"Error " ); PrintChar( params.APSDE_DATA_confirm.Status ); ConsolePutROMString( (ROM char *)" sending message.\r\n" ); } else { ConsolePutROMString( (ROM char *)" Message sent successfully.\r\n" ); } currentPrimitive = NO_PRIMITIVE; break; case NO_PRIMITIVE: if (!ZigBeeStatus.flags.bits.bNetworkJoined) { if (!ZigBeeStatus.flags.bits.bTryingToJoinNetwork) { if (ZigBeeStatus.flags.bits.bTryOrphanJoin) { ConsolePutROMString( (ROM char *)"Trying to join network as an orphan...\r\n" ); params.NLME_JOIN_request.ScanDuration = 8; params.NLME_JOIN_request.ScanChannels.Val = ALLOWED_CHANNELS; // not needed for orphan join - params.NLME_JOIN_request.PANId params.NLME_JOIN_request.JoinAsRouter = FALSE; params.NLME_JOIN_request.RejoinNetwork = TRUE; params.NLME_JOIN_request.PowerSource = NOT_MAINS_POWERED; params.NLME_JOIN_request.RxOnWhenIdle = FALSE; params.NLME_JOIN_request.MACSecurity = FALSE; currentPrimitive = NLME_JOIN_request; } else { ConsolePutROMString( (ROM char *)"Trying to join network as a new device...\r\n" ); params.NLME_NETWORK_DISCOVERY_request.ScanDuration = 8; params.NLME_NETWORK_DISCOVERY_request.ScanChannels.Val = ALLOWED_CHANNELS; currentPrimitive = NLME_NETWORK_DISCOVERY_request; } } } else { // See if we can do our own internal tasks. if (ZigBeeReady()) { // ************************************************************************ // Place all processes that can send messages here. Be sure to call // ZigBeeBlockTx() when currentPrimitive is set to APSDE_DATA_request. // ************************************************************************ } } break; default: PrintChar( currentPrimitive ); ConsolePutROMString( (ROM char *)" Unhandled primitive.\r\n" ); currentPrimitive = NO_PRIMITIVE; break; } // ********************************************************************* // Place any non-ZigBee related processing here. Be sure that the code // will loop back and execute ZigBeeTasks() in a timely manner. // ********************************************************************* } }