Sunday, November 1, 2015

How to Make A Simple Web Server with Tiva C and CC3000

http://yangweinian.blogspot.co.id/2015/11/wireless-communication-on-microchip-sub.html

Wireless communication has not only became major necessity today, rather it has been a "MUST" component in everyone's life. Start from radio, TV remote control, mobile phone, and now the hottest topic on earth "IoT Internet of Things".
IoT is essentially network of physical object embedded in any devices (starts from industry sensors to home's appliances) which enables these "things" to exchange data over Internet connection. In other words, one can monitor the status of these "things" and conversely control them remotely via Internet.

During my final year in engineering degree, I developed wireless light switch which collaborates Sub-GHz and Wi-Fi connectivity. That says, one can control light bulbs over both dedicated remote control and/or smart phone. In this post I'd like to share the part with most fun, how to create a simple web server with micro-controller, specifically I used EK-TM4C123GXL Tiva C Series Launchpad from Texas Instruments.

All of above can be achieved with micro-controller unit (MCU) and a little bit of programming in C language. By knowing how to make an embedded web server, anyone can build their own Wi-Fi light switch and it can be furthermore developed into any other applications to suit your needs such as Wi-Fi garage door, washing machine or even your toaster. It may seems a little bit complicated at first glance but once you get used to it, it's relatively simple!


1. Foundation of Wi-Fi
Let's start with basic foundation of Wi-Fi, the popular wireless connectivity with operating frequency 2.4 GHz and 5 GHz base on IEEE 802.11 standard. Founded in 1999 under Wi-Fi Alliance as the trademark holder, this wireless local area network technology is globally used as admission ticket into Internet. 

Below are several key elements which allow one device to connect to WLAN access point :
- SSID : Network name of desired wireless access point or hotspot.
- Encryption : Type of password encryption, eg. WEP/WPA/WPA2. 
- Password : If it's an open connection, password is not necessary.

WLAN Connect Scheme

Wi-Fi only initiates the delivery of message from one device to another via wireless median. While core communication itself relies on TCP/IP, the most commonly used communication protocol worldwide on computer network including LAN, WAN and Internet. It provides end-to-end connectivity specifying how data should be virtually packaged, addressed, transmitted, routed and received. This makes operation in TCP/IP mostly relates to addresses, most important are as below :
- IP Address : This is the main address of CC3000 in wireless local area network. It will be automatically assigned by access point/router. A 32-bit binary value that is represented in combination of 4 decimal value, separated by dot. Each decimal value represents 8-bit binary therefore. For instance, home router generally has IP address of 192.168.0.1. 
- Socket : It defines which type of packet data to be received. There are two types of packet data, UDP (User Datagram Protocol) and TCP (Transmission Control Protocol). Generally for PC application, UDP packet data contains network status while TCP packet contains data/information. Although both can be used in this project, TCP is chosen as it makes more sense that we're sending data instead of network status. 
- Port : This defines at which port number the data shall be received, a 16-bit binary value, therefore it ranges from 1-65535. All port number can be used, however port number 80 is chosen in this project, as it is most commonly heard in real life application (port number 80 is used for HTTP/webpage application in PC).  

TCP Server Setup Scheme


2. Hardware
We need only two things, a host MCU and a compatible Wi-Fi module. 
I used Texas Instruments for both of them, both are in form of development board which is perfect solution for beginner as below :
- Host MCU : Texas Instrument EK-TM4C123GXL Tiva C Launchpad 
- Wi-Fi Module : Texas Instrument CC3000 Boosterpack

TI EK-TM4C123GXL Tiva C Launchpad costs US$12.9, can buy it HERE.
Tiva C Launchpad EK-TM4C123GXL

Wi-Fi module CC3000 Boosterpack is explicitly made to comply with Tiva C Launchpad, you may buy it for US$40 HERE.
CC3000 Boosterpack


3. Software/Coding
Now we have our hardware in place, get ready for the next BIG thing which is programming. I used "Code Composer Studio" to write my code in C++ and burn it into my Tiva C Launchpad. On top of it, we need "Tivaware for C Series" library to efficiently write program code for Tiva C Launchpad. Function calls and API for CC3000 Wi-Fi module are also well defined in Tivaware package. 

Start to write program code by download and install CCS+Tivaware HERE

If you don't already know how to initiate CCS and Tivaware, get started by following free tutorial in Tiva C Series Workshop HERE.

Flowchart is extremely important when it comes to write program code, it visualizes the entire operation flow hence give clear image on how the code should be efficiently written in achieving most desirable outcomes. Below is my flowchart, you can have your very own flowchart to suit your need.

My Flowchart

The first piece of code is always started with hardware configuration and protocol stack initialization. There are abundant peripherals to be turned on in Tiva C in order to greatly integrate to system, among all are two SPI modules one to communicate to CC3000 and another one to dsPIC33F, UART for debugging purpose, and output pins for any other peripherals such as alphanumeric display and trigger relays. I used dsPIC33F from Microchip to control sub-GHz peripherals which won't be covered in this post, you can just assume this as PWM to dim LED.

After initialization completes, CC3000 is expected to gain access into WLAN access point. Then port and socket are required to be opened and bound on in order to establish a communication channel between CC3000 and wireless router/end-device. Therefore allowing any incoming packet to be routed by wireless router towards CC3000 under assigned IP address. When a valid HTTP request is received, Tiva C is programmed to load the HTML code in CC3000 buffer and transmit to destination client. This will be displayed as a web page on destination's web browser with virtual button to send command back to Tiva C+CC3000. For instance, when the user click certain button on webpage, it will transmit TCP packet to CC3000 and Tiva C will toggle output according to this command.

#include <stdint>
#include <stdbool>
#include <stdlib>
#include "inc/hw_types.h"
#include "inc/tm4c123gh6pm.h"
#include "inc/hw_ssi.h"
#include "inc/hw_memmap.h"
#include "driverlib/timer.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/systick.h"
#include "driverlib/fpu.h"
#include "driverlib/debug.h"
#include "driverlib/ssi.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "utils/ustdlib.h"
#include "utils/uartstdio.h"
#include "utils/cmdline.h"
#include "utils/lcd44780_LP.h"
#include "driverlib/uart.h"
#include "driverlib/ssi.h"
#include "wlan.h"
#include "evnt_handler.h"
#include "nvmem.h"
#include "socket.h"
#include "netapp.h"
#include "spi.h"
#include "hci.h"
#include "cc3000_common.h"
#include "dispatcher.h"
#include "spi_version.h"
#include "board.h"
#include "host_driver_version.h"
#include "security.h"

volatile unsigned int CC3000Connected,CC3000DHCP; 	//Variables used for identification
volatile unsigned int ServerSocket = 0xFFFFFFFF;  	//Socket status
unsigned int SocketType = 0;				//Socket type
long ClientSocket = -1;					//Client Socket Descriptor
int ClientConnected;					//Client Status
volatile fd_set ConnectedSockets;		        //Incoming Client Socket
char ip3[3],ip2[3],ip1[3],ip0[3];
sockaddr SocketAddress;				        //Socket address (Port number)
unsigned char CC3000_Rx_Buffer[10];			//Receive buffer in CC3000
int RequestPage = 0;					//Data received identification

char *sendWLFWPatch(unsigned long *Length)		//Patch, return 0 since it's taken from CC3000 internal memory
{
    *Length = 0;
    return(NULL);
}

char *sendBootLoaderPatch(unsigned long *Length)	//Patch, return 0 since it's taken from CC3000 internal memory
{
    *Length = 0;
    return(NULL);
}


char *sendDriverPatch(unsigned long *Length)		//Patch, return 0 since it's taken from CC3000 internal memory
{
    *Length = 0;
    return(NULL);
}


void CC3000_Interrupt(long EventType, char *ipaddress, unsigned char Length);	//Interrupt, unsolicited event from CC3000
int connecting(void);								//WLAN connecting function
void opensocket(void);								//Open socket function
void portbinding(void);								//Port binding function
int acceptclient();
int datareceive(void);								//Receiving data function
void datasend();
void closingsocket(void);							//Closing socket function
void itoa(long unsigned int value, char* result, int base);

int main(void)
{
    pio_init(); 				//Initialize device pin configuration and the system clock, defined in board.c

    init_spi(1000000, SysCtlClockGet());	//Initialize and configure the SPI 1MHz
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    GPIOPinConfigure(GPIO_PD0_SSI1CLK);
    GPIOPinConfigure(GPIO_PD1_SSI1FSS);
    GPIOPinConfigure(GPIO_PD2_SSI1RX);
    GPIOPinConfigure(GPIO_PD3_SSI1TX);
    GPIOPinTypeSSI(GPIO_PORTD_BASE,GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_1|GPIO_PIN_0);
    SSIConfigSetExpClk(SSI1_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 10000, 8);
    SSIEnable(SSI1_BASE);
    IntMasterEnable();				//Enable processor interrupts

    wlan_init(CC3000_Interrupt,sendWLFWPatch, sendDriverPatch,sendBootLoaderPatch,
    		ReadWlanInterruptPin, WlanInterruptEnable, WlanInterruptDisable, WriteWlanPin);
    //Initialize, patch and enable WiFi on the CC3000

    wlan_start(0);			//Start up the CC3000

    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 2);
    //Turn on the the red LED to indicate CC3000 operates, defined in board.c

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

    DispatcherUARTConfigure(SysCtlClockGet());	//Initialize UART
    SysCtlDelay(1000000);

    UARTprintf("Welcome to FYP! \n");		//Welcoming note on UART

    initLCD();				//Initialize alphanumeric LCD
    LCDWriteText("     Hello!    ",0,0);	//Welcoming note on LCD
    LCDWriteText("Wireless Switch",1,0);

    InitSysTick();			// Configure and enable the system tick for interrupt handler

    while(1)
    {
    	if(CC3000Connected == 0)	//If WiFi is not connected
    	{
    		connecting();		//Connect function
    		opensocket();		//Open socket
    		portbinding();		//Bind to port
    	}
    	int x = acceptclient();	        //Client Acceptance
    	if(x==1)			//If there is client
    	{
    		UARTprintf("New Client \n");
    		datareceive();		//Receive data
    		switch(RequestPage)	//Decode the received data accordingly
    		{
    		case 1 :	datasend();	break;
    		case 2 :
    		{
    			datasend();
    			while(SSIBusy(SSI1_BASE))
    			{}
    			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 2); SysCtlDelay(0.1*SysCtlClockGet()/3);
    			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 10);
    			//Blink red LED, this can be modified to desired output
    			SSIDataPut(SSI1_BASE,0x01);
    			LCDWriteText("   NODE 1   ",0,0);
    		}; break;
    		case 3 :
    		{
    			datasend();
    			while(SSIBusy(SSI1_BASE))
    			{}
    			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 4); SysCtlDelay(0.1*SysCtlClockGet()/3);
    			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 10);
    			//Blink blue LED
    			SSIDataPut(SSI1_BASE,0x02);
    			LCDWriteText("   NODE 2  ",0,0);
    		}; break;
    		case 4 :
    		{
    			datasend();
    			while(SSIBusy(SSI1_BASE))
    			{}
    			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 8); SysCtlDelay(0.1*SysCtlClockGet()/3);
    			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 10);
    			//Blink green LED
    			SSIDataPut(SSI1_BASE,0x03);
    			LCDWriteText("   NODE 3  ",0,0);
    		}; break;
    		case 5 :
    		{
    			datasend();
    			while(SSIBusy(SSI1_BASE))
    			{}
    			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 14); SysCtlDelay(0.1*SysCtlClockGet()/3);
    			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 10);
    			//Blink all LEDs
    			SSIDataPut(SSI1_BASE,'d');
    			LCDWriteText("   SERVER D  ",0,0);
    		}; break;
    		case 6 :
    		{
    			datasend();
    			while(SSIBusy(SSI1_BASE))
    			{}
    			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 14); SysCtlDelay(0.1*SysCtlClockGet()/3);
    			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 10);
    			//Blink all LEDs
    			SSIDataPut(SSI1_BASE,'b');
    			LCDWriteText("   SERVER B  ",0,0);
    		}; break;
    		}
    		closingsocket();	//Close the socket, to prevent socket address clash
    	}
    	SysCtlDelay(100000);
    }
}


Several sub-functions shall be defined in more detail such as connecting(), opensocket(), portbinding(), acceptclient(), datareceive(), datasend() and CC3000_Interrupt(). In obtaining initial access, CC3000 would require to connect to wireless access point by providing SSID network name and password. Tivaware library made most of crucial applications very simple by just calling necessary API function. CC3000 Wi-Fi module spends most time in waiting for incoming client and TCP packet. Once client request is received, TCP packet data is buffered into temporary memory array and processed accrodingly. Tiva C will process the TCP packet and respond accordingly. In general, HTTP request always starts with "HTTP / GET".

int connecting(void)
{
	unsigned int x;
	wlan_connect (WLAN_SEC_WPA2,"a7nightmare",11,0,"akutidaktahu",12);	//Connect to access point with no password
	LCDCommand(0x01);					//Clear LCD
    LCDWriteText("Connecting...",0,0);	//Display status on LCD
    LCDWriteText("8s timeout...",1,0);
	UARTprintf("Attempting to connect (8 second timeout)...\n");	//Display status on UART

	    for(x = 0; x < 8000; x++)	// Wait for 8 seconds, since the delay in loop is 1 ms
	    {
	        if(CC3000DHCP == 1)		// Check to see if CC3000 is connected to a network
	            return(0);			//Go back to main execution
 	        SysCtlDelay(SysCtlClockGet() / 3000);	//Delay 1 ms, one delay take 3 clock cycles
	    }
	    UARTprintf("Connection Failed. Please check the network name.\n");
	    LCDCommand(0x01);
	    LCDWriteText("Connection Fail!",0,0);
	    LCDWriteText("Try Again.....",1,0);
	    return(0);
}

void opensocket(void)
{
	ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);	//Open TCP socket
	if(ServerSocket >= 0)		//If socket is successfully opened
	{
		UARTprintf("Server socket is handled by '%d'.\n",ServerSocket);
		return;					//Jump to main function
	}
	else
	UARTprintf("Fail to open socket. \n");
}

void portbinding()
{
	unsigned char x = 0;
	SocketAddress.sa_family = AF_INET;	//Port family is always AF_INET
	SocketAddress.sa_data[0] = (80 & 0xFF00) >> 8;	//Set the number of port to be bound
	SocketAddress.sa_data[1] = (80 & 0x00FF) >> 0;
	memset (&SocketAddress.sa_data[2], 0, 4);		//Set dynamic IP address
	x = bind(ServerSocket, &SocketAddress, sizeof(sockaddr));	//Bind the port
	if(x == 0)	//Check if port is successfully bound
	{
		UARTprintf("Bind Successful to port 80.\n");
	}
	else
	{
		UARTprintf("Bind Failed. Bind returned code '%d'\n",x);
		CC3000Connected = 0;	//Set variable to 0, reconnect needed
	}
	if (listen (ServerSocket, 1) != 0)				//Listen to incoming connection
	{
		return ;
	}
}

int acceptclient()
{
	sockaddr clientaddr;		//Client socket address
	socklen_t addrlen;			//Length of address
	addrlen = sizeof(addrlen);	//Function to calculate length
	ClientSocket = accept(ServerSocket, (sockaddr *)&clientaddr, &addrlen);	//Accepting client
	FD_CLR(ClientSocket, &ConnectedSockets);	//Binding the connected client if any
	if(ClientSocket<0) return 0;	//If no client, return value 0
	else return 1;						//If there is client, return 1
}

int datareceive(void)
{
	RequestPage = 0;
	int ByteReceived = 0;
	int ret;
	int i;
	int home =0;
	int client1 = 0;
	int client2 = 0;
	int client3 = 0;
	int serverd = 0;
	int serverb = 0;
	char data[10] = "";
	char home_addr[10] = "GET / HTTP";   //Content References
	char Client_1[10] = "GET /node1";   //Content References
	char Client_2[10] = "GET /node2";
	char Client_3[10] = "GET /node3";
	char Server_d[10] = "GET /servd";
	char Server_b[10] = "GET /servb";
	timeval timeout;
	memset(&timeout, 0, sizeof(timeval));	//Timeout function
	timeout.tv_sec = 0;						//Timeout value
	timeout.tv_usec = 500000;
	fd_set readsds, errorsds;				//Read and error variable
	FD_ZERO(&readsds);						//Clear read
	FD_ZERO(&errorsds);						//Clear error
	FD_SET(ClientSocket, &readsds);			//Apply function
	FD_SET(ClientSocket, &errorsds);

		ret = select(ClientSocket + 1, &readsds, NULL, NULL, &timeout);	//Select port
		if(!FD_ISSET(ClientSocket, &readsds)) return 0;		//If no data, return 0
		ByteReceived = recv(ClientSocket, CC3000_Rx_Buffer, 10, 0);	//Receiving incoming data
		UARTprintf("Data received with size of %d bytes. \n",ByteReceived);

		for (i=0; i<ByteReceived; i++)			//Checking data content
		{
			data[i] = CC3000_Rx_Buffer[i];
			if(data[i] == home_addr[i])
				home++;
			if(data[i] == Client_1[i])
				client1++;
			if(data[i] == Client_2[i])
				client2++;
			if(data[i] == Client_3[i])
				client3++;
			if(data[i] == Server_d[i])
				serverd++;
			if(data[i] == Server_b[i])
				serverb++;
		}
		UARTprintf(data);

		if(home == ByteReceived)
		{
			RequestPage = 1;
			UARTprintf("User ask for welcoming home page. \n");
		}
		if(client1 == ByteReceived)
		{
			RequestPage = 2;
			UARTprintf("Client 1. \n");
		}
		if(client2 == ByteReceived)
		{
			RequestPage = 3;
			UARTprintf("Client 2. \n");
		}
		if(client3 == ByteReceived)
		{
			RequestPage = 4;
			UARTprintf("Client 3. \n");
		}
		if(serverd == ByteReceived)
		{
			RequestPage = 5;
			UARTprintf("Server D. \n");
		}
		if(serverb == ByteReceived)
		{
			RequestPage = 6;
			UARTprintf("Server B. \n");
		}
}

void datasend()
{
	int ByteTransmitted;
	char newline[] = {'\n'};			//HTML content
	char *html = ("HTTP/1.1 200 OKContent-type:text/html\n");
	char *html1 = ("<html><head><title>SubGHz Wireless Switch</title></head>\n");
	char *html2 = ("<body align=center><h1 align=center><font color=\"blue\">Welcome to William Young's SubGHz-WiFi Light Switch</font></h1>\n");
	char *humid = ("<button onclick=\"location.href='/node1.html'\">Node 1</button><button onclick=\"location.href='/node2.html'\">Node 2</button><button onclick=\"location.href='/node3.html'\">Node 3</button> \n");
	char *temp = ("Welcome, click on one of buttons below to switch on and off the power socket. Have fun! :) <br><button onclick=\"location.href='/servb.html'\">Server B</button><button onclick=\"location.href='/servd.html'\">Server D</button>");
	char *html3 = ("<br><br><br><img src = \"http://www.gifs.net/Animation11/Jobs_and_People/Scientists/Inventor_3.gif\"></img> <br> \n");
	char *html4 = ("</body></html>");
	ByteTransmitted = send(ClientSocket, html, ustrlen(html), 0);		//Sending HTML code line per line
	ByteTransmitted = send(ClientSocket, newline, ustrlen(newline), 0);
	ByteTransmitted = send(ClientSocket, newline, ustrlen(newline), 0);
	ByteTransmitted = send(ClientSocket, html1, ustrlen(html1), 0);
	ByteTransmitted = send(ClientSocket, html2, ustrlen(html2), 0);
	ByteTransmitted = send(ClientSocket, temp, ustrlen(temp), 0);
	ByteTransmitted = send(ClientSocket, humid, ustrlen(humid), 0);
	ByteTransmitted = send(ClientSocket, html3, ustrlen(html3), 0);
	ByteTransmitted = send(ClientSocket, newline, ustrlen(newline), 0);
	ByteTransmitted = send(ClientSocket, html4, ustrlen(html4), 0);
	ByteTransmitted = send(ClientSocket, newline, ustrlen(newline), 0);
	ByteTransmitted = send(ClientSocket, newline, ustrlen(newline), 0);
}

void closingsocket(void)
{
	unsigned int x;
	x = closesocket(ClientSocket);	//Close client socket
	FD_CLR(ClientSocket, &ConnectedSockets);
	if(x == 0)					//If socket closed successfully
	{
		UARTprintf("Socket is closed.\n");
		ClientSocket = -1;		//Set client descriptor back to its initial value
	}
	else
		UARTprintf("Socket close Failed.\n");
}

void CC3000_Interrupt(long EventType, char *ipaddress, unsigned char Length)
{
	if(EventType == HCI_EVNT_WLAN_UNSOL_CONNECT)		//Interrupt from CC3000-WLAN is connected
	{
		CC3000Connected = 1;			//Set variable to indicate connection
	}
	if(EventType == HCI_EVNT_WLAN_UNSOL_DISCONNECT)		//Interrupt from CC3000-WLAN is disconnected
	{
		UARTprintf("CC3000 is disconnected from WLAN\n");
		CC3000Connected = 0;		//Set the variable to indicate the status
		CC3000DHCP = 0;
		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 2);	//Only Red LED is ON
		LCDCommand(0x01);
		LCDWriteText("WiFi Network",0,0);
		LCDWriteText("Disconnected!",1,0);
	}
	if(EventType == HCI_EVNT_WLAN_UNSOL_DHCP)  //Interrupt from CC3000-DHCP WLAN is connected
	{
		if( *(ipaddress + 20) == 0)		//Check if connection is valid
		{
			UARTprintf("DHCP Connected. IP: %d.%d.%d.%d\n",
					ipaddress[3],ipaddress[2],ipaddress[1],ipaddress[0]);	//Print IP address on UART
			itoa(ipaddress[3],ip3,10);
			itoa(ipaddress[2],ip2,10);
			itoa(ipaddress[1],ip1,10);
			itoa(ipaddress[0],ip0,10);
			LCDCommand(0x01);
		    LCDWriteText("IP Address :",0,0);
		    LCDWriteText(ip3,1,0);
		    LCDWriteText(".",1,3);
		    LCDWriteText(ip2,1,4);
		    LCDWriteText(".",1,7);
		    LCDWriteText(ip1,1,8);
		    LCDWriteText(".",1,11);
		    LCDWriteText(ip0,1,12);
			CC3000DHCP = 1;		//Set indication variable
			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 10);	//Turn on red and green LED
		}
		else
			CC3000DHCP = 0;		//If connection is not valid, set variable to 0
	}
}


With this, you can basically make anything in your house an IoT. All you need is small tweak to the code to produce desired output. You can also make the website interface more interesting by modifying HTML content or even make an Android app to communicate with this simple web server. I'd love to hear from you if you succeed in making your own mini web server and/or simple IoT.