/** Waits for SRDY to go low, indicating a message has arrived. Displays the msg to console. */
void displayReceivedMessages()
{
    while (1)
    {
        while (SRDY_IS_HIGH());         
        pollAndDisplay();
    }
}
/** Blocking wait until a message is received. Exits if received message is a ZDO_STATE_CHANGE_IND
and the state matches what we want. Else loops. 
@param expectedState the deviceState we are expecting - DEV_ZB_COORD etc.*/
void waitForDeviceState(unsigned char expectedState)
{
    unsigned char state = 0xFF;
    while (state != expectedState)
    {
        while (SRDY_IS_HIGH());         
        pollAndDisplay();
        if (CONVERT_TO_INT(znpBuf[2], znpBuf[1]) == ZDO_STATE_CHANGE_IND)
            state = znpBuf[SRSP_PAYLOAD_START];
    }
}
/** Waits for SRDY to go low, indicating a message has arrived. Displays the msg to console, 
and find the device's MAC address using ZDO_IEEE_ADDR_REQ.
Then, if FIND_NWK_ADDRESS was defined, uses the received MAC address to find the device's short address.
The two should match.
@pre callbacks have been enabled with enableCallbacks() - otherwise you will never receive the ZDO_IEEE_ADDR_RSP message.
*/
void displayReceivedMessagesAndFindDevice()
{
    znpBuf[0] = 0;  
    unsigned int shortAddress;
    while (1) 
    {
        while (SRDY_IS_HIGH());         
        pollAndDisplay();
        if (CONVERT_TO_INT(znpBuf[2], znpBuf[1]) == AF_INCOMING_MSG)
        {
            shortAddress = CONVERT_TO_INT(znpBuf[7], znpBuf[8]);     
            zdoRequestIeeeAddress(shortAddress, SINGLE_DEVICE_RESPONSE, 0); 
            if (znpResult == 0)
            {
                printf("MAC Address (LSB first) of sender is :");
                printHexBytes(znpBuf+4, 8);
            } else {
                printf("IEEE Request Failed (%d)\r\n", znpResult);
                continue;
            }

#ifdef FIND_NWK_ADDRESS
            /** Very simple example of zdoNetworkAddressRequest() */
            unsigned char* response = zdoNetworkAddressRequest(znpBuf+4, SINGLE_DEVICE_RESPONSE, 0);  //was SINGLE_DEVICE_RESPONSE

            if (znpResult == 0)
            {
                unsigned int sa = CONVERT_TO_INT(znpBuf[12], znpBuf[13]);
                printf("Short Address = %04X\r\n", sa);
            } else {
                printf("NWK Request Failed (%d)\r\n", znpResult);
                continue;
            } 
            printZdoNetworkAddressResponse(response);
#endif            
        }
    }
}
int main( void )
{
    halInit(); 
    printf("\r\n++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n");          
    printf("\r\nBasic Communications Example - ROUTER - using Simple API\r\n");
    HAL_ENABLE_INTERRUPTS();
    
    //Simple check to ensure that both security options weren't #defined.
#if defined(USE_SECURITY_MODE_PRECONFIGURED_KEYS) && defined(USE_SECURITY_MODE_COORD_DIST_KEYS)
    printf("ERROR - only select one security option!\r\n");
    while (1);
#endif 
    
    /* Initialize the ZNP */
    printf("Initializing the ZNP\r\n");
    znpInit(); 
    handleReturnValue();
    
    /* Set Startup Options (will restore the ZNP to default values on reset) */
    printf("Setting StartupOptions\r\n");    
    setStartupOptions(STARTOPT_CLEAR_CONFIG + STARTOPT_CLEAR_STATE);
    handleReturnValue();
    
    /* Reset the ZNP */
    printf("Reset the ZNP\r\n");    
    znpReset();
    handleReturnValue();
    
    /* Set Zigbee Device Type to be ROUTER */
    printf("Setting Zigbee Device Type\r\n"); 
    setZigbeeDeviceType(ROUTER);
    handleReturnValue();

    /* Configure security mode, if it is being used */
#ifdef USE_SECURITY_MODE_PRECONFIGURED_KEYS
    printf("SECURITY ON WITH PRECONFIGURED KEYS\r\n");
    
    /* Turn security ON with pre-configured keys */
    setSecurityMode(SECURITY_MODE_PRECONFIGURED_KEYS);
    handleReturnValue();
    
    /* All devices on the network must be loaded with the same key */    
    setSecurityKey(key);
    handleReturnValue();    
#endif
    
#ifdef USE_SECURITY_MODE_COORD_DIST_KEYS
    printf("SECURITY ON WITH COORDINATOR DISTRIBUTING KEYS\r\n");
    
    /* Turn security ON with the coordinator distributing keys. */
    setSecurityMode(SECURITY_MODE_COORD_DIST_KEYS);
    handleReturnValue();
    
    /* This is the key that will be distributed to other devices when they attempt to join */
    setSecurityKey(key);
    handleReturnValue();
#endif   
    
#if !defined(USE_SECURITY_MODE_PRECONFIGURED_KEYS) && !defined(USE_SECURITY_MODE_COORD_DIST_KEYS)
    printf("SECURITY OFF\r\n");
#endif 
    
    /* Configure the ZNP for our application */
    printf("Registering Application\r\n");  
    sapiRegisterGenericApplication();
    handleReturnValue();
    
    /* Now, start the application. We will receive a START_REQUEST_SRSP, and then if it is successful, a START_CONFIRM. */
    printf("Starting the Application\r\n");      
    sapiStartApplication();
    handleReturnValue();
    
    printf("On Network!\r\n");
    setLed(0);
    /* On network, display info about this network */
#ifdef DISPLAY_NETWORK_INFORMATION     
    getNetworkConfigurationParameters();                
    getDeviceInformation();
#endif    
    
    /* Now the network is running - send a message to the coordinator every few seconds.*/
    unsigned char counter = 0;
    unsigned char testMessage[] = {0xF0,0xF1,0xF2,0xF3,0xF4};
#define TEST_CLUSTER 0x77    

        pollAndDisplay();
    
    while (1)
    {
        printf("Sending Message %u\r\n", counter++);
        sendData(0, TEST_CLUSTER, testMessage, 5);        
        handleReturnValue();
        toggleLed(1);         
        delayMs(5000);          
    }   
}
int main( void )
{
    halInit();
    printf("\r\n****************************************************\r\n");
    printf("Secure Communications Example - COORDINATOR - using AFZDO\r\n");
    HAL_ENABLE_INTERRUPTS();
    setLed(0);
    
    //Simple idiot check to ensure that we didn't accidentally define both security options.
#if defined(USE_SECURITY_MODE_PRECONFIGURED_KEYS) && defined(USE_SECURITY_MODE_COORD_DIST_KEYS)
    printf("ERROR - only select one security option!\r\n");
    while (1);
#endif     
    
    /* Initialize the ZNP */
    printf("Initializing the ZNP\r\n");    
    znpInit(); 
    handleReturnValue();
    
    /* Set Startup Options (will restore the ZNP to default values on reset) */
    printf("Setting StartupOptions\r\n");
    setStartupOptions(STARTOPT_CLEAR_CONFIG + STARTOPT_CLEAR_STATE);
    handleReturnValue();
    
    /* Set Zigbee Device Type to be COORDINATOR */
    printf("Setting Zigbee Device Type\r\n"); 
    setZigbeeDeviceType(COORDINATOR);
    handleReturnValue();
    
    /* Enabling Callbacks (required to receive ZDO_IEEE_ADDR_RSP)  */
    printf("Enabling Callbacks\r\n"); 
    setCallbacks(CALLBACKS_ENABLED);
    handleReturnValue();    
    
    /* Reset the ZNP */
    printf("Reset the ZNP\r\n");    
    znpReset();
    handleReturnValue();
    
    /* Configure security mode, if it is being used */
#ifdef USE_SECURITY_MODE_PRECONFIGURED_KEYS
    printf("SECURITY ON WITH PRECONFIGURED KEYS\r\n");
    
    /* Turn security ON with pre-configured keys */
    setSecurityMode(SECURITY_MODE_PRECONFIGURED_KEYS);
    handleReturnValue();
    
    /* All devices on the network must be loaded with the same key */    
    setSecurityKey(key);
    handleReturnValue();    
#endif
    
#ifdef USE_SECURITY_MODE_COORD_DIST_KEYS
    printf("SECURITY ON WITH COORDINATOR DISTRIBUTING KEYS\r\n");
    
    /* Turn security ON with the coordinator distributing keys. */
    setSecurityMode(SECURITY_MODE_COORD_DIST_KEYS);
    handleReturnValue();
    
    /* This is the key that will be distributed to other devices when they attempt to join */
    setSecurityKey(key);
    handleReturnValue();
#endif   
    
    /** Note: if no security option is selected then this will behave like a normal coordinator
    and will accept join requests from any device. */
#if !defined(USE_SECURITY_MODE_PRECONFIGURED_KEYS) && !defined(USE_SECURITY_MODE_COORD_DIST_KEYS)
    printf("WARNING - NO SECURITY OPTION SELECTED; SECURITY OFF\r\n");
#endif 
    
    /* Configure the ZNP for our application */
    printf("Registering Application\r\n");     
    afRegisterGenericApplication();    
    handleReturnValue();
    
    /* Now, start the application. We will receive a START_REQUEST_SRSP, and then if it is successful, a START_CONFIRM. */
    printf("Starting the Application\r\n"); 
    zdoStartApplication();
    handleReturnValue();
    
    /** Wait until we get on the network. 
    We will receive a ZDO_STATE_CHANGE_IND message whenever the state changes. */
    waitForDeviceState(DEV_ZB_COORD);

    printf("On Network!\r\n");
    setLed(1);
    
    /* On network, display info about this network */
#ifdef DISPLAY_NETWORK_INFORMATION     
    getNetworkConfigurationParameters();                
    getDeviceInformation();
#endif  

    /* Now the network is running - continually poll for any received messages from the ZNP */
    if (SRDY_IS_HIGH())
        pollAndDisplay();
    
    displayReceivedMessages();
    
}