void main(void)
{
    WDTCTL = WDTPW + WDTHOLD;				// Stop WDT
    resetCC3000StateMachine();				// Start CC3000 State Machine
    initDriver();							// Initialize Board and CC3000
    unsolicicted_events_timer_init();		// Initialize CC3000 Unsolicited Events Timer
    __enable_interrupt();					// Enable interrupts for UART
    DefaultWifiConnection();				// Do a default connection

    while (1)
    {

        hci_unsolicited_event_handler();	// Handle any un-solicited event if required - the function shall be triggered few times in a second
        unsolicicted_events_timer_init();

        if(currentCC3000State() & CC3000_IP_ALLOC)
        {
            turnLedOn(CC3000_IP_ALLOC_IND);
            unsolicicted_events_timer_disable();
            
            // Attempt to start data server
            initServer();
            if(currentCC3000State() & CC3000_SERVER_INIT)
            {
                waitForConnection();
            }
            else//Wait for a bit, and try again.
            {
                __delay_cycles(100000);
            }
            unsolicicted_events_timer_init();
        }
    }
}
//*****************************************************************************
//
//! initDriver
//!
//!  \param  None
//!
//!  \return none
//!
//!  \brief  The function initializes a CC3000 device and triggers it to start operation
//
//*****************************************************************************
int
initDriver(void)
{



    pio_init(); // Init GPIO's
    init_spi();
    wlan_init( CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch, ReadWlanInterruptPin, WlanInterruptEnable, WlanInterruptDisable, WriteWlanPin);
    wlan_start(0);

	if (IP_ALLOC_METHOD == USE_STATIC_IP){// The DHCP setting shave been removed.

		pucSubnetMask[0] = 0xFF;// Subnet mask is assumed to be 255.255.255.0
		pucSubnetMask[1] = 0xFF;
		pucSubnetMask[2] = 0xFF;
		pucSubnetMask[3] = 0x0;


		pucIP_Addr[0] = STATIC_IP_OCT1;    // CC3000's IP
		pucIP_Addr[1] = STATIC_IP_OCT2;
		pucIP_Addr[2] = STATIC_IP_OCT3;
		pucIP_Addr[3] = STATIC_IP_OCT4;

		pucIP_DefaultGWAddr[0] = STATIC_IP_OCT1;// Default Gateway/Router IP
		pucIP_DefaultGWAddr[1] = STATIC_IP_OCT2;
		pucIP_DefaultGWAddr[2] = STATIC_IP_OCT3;
		pucIP_DefaultGWAddr[3] = 1;

		pucDNS[0] = STATIC_IP_OCT1;// We assume the router is also a DNS server
		pucDNS[1] = STATIC_IP_OCT2;
		pucDNS[2] = STATIC_IP_OCT3;
		pucDNS[3] = 1;

		netapp_dhcp((unsigned long *)pucIP_Addr, (unsigned long *)pucSubnetMask,
					(unsigned long *)pucIP_DefaultGWAddr, (unsigned long *)pucDNS);

		// reset the CC3000 to apply Static Setting
		wlan_stop();
		__delay_cycles(6000000);
		wlan_start(0);
	}
    
    // Mask out all non-required events from CC3000
    wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE|HCI_EVNT_WLAN_ASYNC_PING_REPORT);
    
    unsolicicted_events_timer_init();
    
    // CC3000 has been initialized
    setCC3000MachineState(CC3000_INIT);
    
    return(0);
}
//*****************************************************************************
//
//! board_init
//!
//! \param  none
//!
//! \return none
//!
//! \brief  Initialize the board's interfaces
//
//*****************************************************************************
void board_init()
{
  // Stop WDT
  WDTCTL = WDTPW + WDTHOLD;

  // Init GPIO's
  pio_init();

  // Setup sensors hooked up to the board (if any)
  setupSensors();

  // Start CC3000 State Machine
  resetCC3000StateMachine();
  // Initialize Board and CC3000
  initDriver();

  // Initialize CC3000 Unsolicited Events Timer
  unsolicicted_events_timer_init();
  // Enable interrupts
  __enable_interrupt();

}
//*****************************************************************************
//
//! initDriver
//!
//!  \param[in] cRequestPatch 0 to load with EEPROM patches and 1 to load with no patches
//!
//!  \return none
//!
//!  \brief  The function initializes a CC3000 device and triggers it to start operation
//
//*****************************************************************************
int
initDriver(unsigned short cRequestPatch)
{
	

    //
	// Init GPIO's
	//
	pio_init();
	//
    //init all layers
    //
    init_spi();


	//
	// WLAN On API Implementation
	//
	wlan_init( CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch, ReadWlanInterruptPin, WlanInterruptEnable, WlanInterruptDisable, WriteWlanPin);
	//
	// Trigger a WLAN device
	//
	wlan_start(cRequestPatch);
  wlan_smart_config_set_prefix(aucCC3000_prefix);
	
	// Turn on the LED 5 to indicate that we are active and initiated WLAN successfully
     turnLedOn(5);

	//
	// Mask out all non-required events from CC3000
	//
	wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE|HCI_EVNT_WLAN_UNSOL_INIT|HCI_EVNT_WLAN_ASYNC_PING_REPORT);

        unsolicicted_events_timer_init();
    return(0);
}
//*****************************************************************************
//
//!  checkWiFiConnected
//!
//!  \param  None
//!
//!  \return TRUE if connected, FALSE if not
//!
//!  \brief  Checks to see that WiFi is still connected.  If not associated
//!          with an AP for 5 consecutive retries, it will reset the board.
//
//*****************************************************************************
unsigned char
checkWiFiConnected(void)
{
  unsigned char ipInfoFlagSet = 0;

  if(!(currentCC3000State() & CC3000_ASSOC)) //try to associate with an Access Point
  {
    //
    // Check whether Smart Config was run previously. If it was, we
    // use it to connect to an access point. Otherwise, we connect to the
    // default.
    //

    if((isFTCSet() == 0)&&(ConnectUsingSmartConfig==0)&&(*SmartConfigProfilestored != SMART_CONFIG_SET))
    {
      // Smart Config not set, check whether we have an SSID
      // from the assoc terminal command. If not, use fixed SSID.
        //sendString("== ConnectUsingSSID==\r\n");
        ConnectUsingSSID(SSID);
    }
    unsolicicted_events_timer_init();
    // Wait until connection is finished
    //sendString("== Wait until connection is finished==\r\n");
    while (!(currentCC3000State() & CC3000_ASSOC))
    {
      WDTCTL = WDT_ARST_1000;
      __delay_cycles(100);

      // Handle any un-solicited event if required - the function will get triggered
      // few times in a second
      hci_unsolicited_event_handler();

      // Check if user pressed button to do Smart Config
      if(runSmartConfig == 1)
          break;
    }
  }

  // Handle un-solicited events - will be triggered few times per second
  hci_unsolicited_event_handler();
  WDTCTL = WDTPW + WDTHOLD;
  // Check if we are in a connected state.  If so, set flags and LED
  if(currentCC3000State() & CC3000_IP_ALLOC)
  {
    unsolicicted_events_timer_disable(); // Turn our timer off since isr-driven routines set LEDs too...

    if (obtainIpInfoFlag == FALSE)
    {
      //sendString("== CC3000_IP_ALLOC_IND==\r\n");
      obtainIpInfoFlag = TRUE;             // Set flag so we don't constantly turn the LED on
      turnLedOn(CC3000_IP_ALLOC_IND);
      ipInfoFlagSet = 1;
      unsolicicted_events_timer_init();
    }

    if (obtainIpInfoFlag == TRUE)
    {
    	WDTCTL = WDT_ARST_1000;
      //If Smart Config was performed, we need to send complete notification to the configure (Smart Phone App)
      if (ConnectUsingSmartConfig==1)
      {
        mdnsAdvertiser(1,DevServname, sizeof(DevServname));
        ConnectUsingSmartConfig = 0;
        *SmartConfigProfilestored = SMART_CONFIG_SET;
      }
      //Start mDNS timer in order to send mDNS Advertisement every 30 seconds
      mDNS_packet_trigger_timer_enable();

      unsolicicted_events_timer_init();
    }
    WDTCTL = WDTPW + WDTHOLD;
    if( ipInfoFlagSet == 1)
    {
      // Initialize an Exosite connection
      //sendString("== Exosite Activate ==\r\n");
      cloud_status = Exosite_Activate();
      ipInfoFlagSet = 0;
    }

    return TRUE;
  }

  return FALSE;

}
//*****************************************************************************
//
//!  main
//!
//!  \param  None
//!
//!  \return none
//!
//!  \brief   The main loop is executed here
//
//*****************************************************************************
void main(void)
{
  unsigned char loopCount = 0;
  int loop_time = 2000;

  ulCC3000Connected = 0;
  SendmDNSAdvertisment = 0;

  // Initialize hardware and interfaces
  board_init();
  initUart();
  sendString("System init : \r\n");

  // Must initialize one time for MAC address prepare..
  if (!Exosite_Init("exosite", "cc3000wifismartconfig", IF_WIFI, 0))
  {
    show_status();
    while(1);
  }

  // Main Loop
  while (1)
  {
    // Perform Smart Config if button pressed in current run or if flag set in FRAM
    // from previous MSP430 Run.
    if(runSmartConfig == 1 || *ptrFtcAtStartup == SMART_CONFIG_SET)
    {
      // Clear flag
      ClearFTCflag();
      unsetCC3000MachineState(CC3000_ASSOC);

      // Start the Smart Config Process
      StartSmartConfig();
      runSmartConfig = 0;
    }

    WDTCTL = WDTPW + WDTHOLD;
    // If connectivity is good, run the primary functionality
    if(checkWiFiConnected())
    {
      char * pbuf = exo_buffer;

      //unsolicicted_events_timer_disable();

      if (0 == cloud_status)
      { //check to see if we have a valid connection
        loop_time = 2000;

        loopCount = 1;

        while (loopCount++ <= (WRITE_INTERVAL+1))
        {
//          WDTCTL = WDT_ARST_1000;
          if (Exosite_Read("led7_ctrl", pbuf, EXO_BUFFER_SIZE))
          {
        	// Read success
        	turnLedOn(CC3000_CLIENT_CONNECTED_IND);

            if (!strncmp(pbuf, "0", 1))
              turnLedOff(LED7);
            else if (!strncmp(pbuf, "1", 1))
              turnLedOn(LED7);
          }
          else
          {
        	if (EXO_STATUS_NOAUTH == Exosite_StatusCode())
        	{
        		turnLedOff(CC3000_CLIENT_CONNECTED_IND);
        		// Activate device again
        		cloud_status = Exosite_Activate();
        	}
          }

          hci_unsolicited_event_handler();
          unsolicicted_events_timer_init();
          //sendString("== Exosite Read==\r\n");
          WDTCTL = WDTPW + WDTHOLD;
          busyWait(loop_time);        //delay before looping again
        }

        unsolicicted_events_timer_init();
    	if (EXO_STATUS_NOAUTH != Exosite_StatusCode())
    	{
          unsigned char sensorCount = 0;
          int value;
          char strRead[6]; //largest value of an int in ascii is 5 + null terminate
          WDTCTL = WDT_ARST_1000;
          for (sensorCount = 0; sensorCount < SENSOR_END; sensorCount++)
          {
            value = getSensorResult(sensorCount);                                       //get the sensor reading
            itoa(value, strRead, 10);                           //convert to a string
            unsolicicted_events_timer_init();
            //for each reading / data source (alias), we need to build the string "alias=value" (must be URL encoded)
            //this is all just an iteration of, for example, Exosite_Write("mydata=hello_world",18);
            memcpy(pbuf,&sensorNames[sensorCount][0],strlen(&sensorNames[sensorCount][0]));  //copy alias name into buffer
            pbuf += strlen(&sensorNames[sensorCount][0]);
            *pbuf++ = 0x3d;                                             //put an '=' into buffer
            memcpy(pbuf,strRead, strlen(strRead));                      //copy value into buffer
            pbuf += strlen(strRead);
            *pbuf++ = 0x26;                                             //put an '&' into buffer, the '&' ties successive alias=val pairs together
          }
          pbuf--;                                                                       //back out the last '&'
          WDTCTL = WDT_ARST_1000;
          Exosite_Write(exo_buffer,(pbuf - exo_buffer - 1));    //write all sensor values to the cloud

          if (EXO_STATUS_OK == Exosite_StatusCode())
          { // Write success
    	    turnLedOn(CC3000_CLIENT_CONNECTED_IND);
          }
    	}
      } else {
          //we don't have a good connection yet - we keep retrying to authenticate
    	  WDTCTL = WDTPW + WDTHOLD;
          //sendString("== Exosite Activate==\r\n");
          cloud_status = Exosite_Activate();
          if (0 != cloud_status) loop_time = 30000; //delay 30 seconds before retrying...
      }

        unsolicicted_events_timer_init();
      }
      WDTCTL = WDTPW + WDTHOLD;
      // TODO - make this a sleep instead of busy wait
      busyWait(loop_time);        //delay before looping again
    }
}