jpatrick62
Well-known member
I recently upgraded to Arduino 1.61 and TeensyDuino 1.22, and it seems my CC3000 web server has become slow and hangs on requests. On Arduino 1.5 and Teensy 1.8
the web server worked (after setting SPI_CLOCK_DIV2)except that it would need a reboot after about 15 mins as it would stop responding. I was hoping the new
libs would solve the need to reboot after 15 mins. I have a rotary bcd switch that listens for SmartConfig when set to 0, and then boots with the config on a switch setting other
than 0. This seems to work well, and I always connect/reconnect to my AP as expected. I have flashed the CC3000 to the latest firmware (1.14) successfully, and I can get the
hardware to run the buildtest and other examples successfully.
the web server worked (after setting SPI_CLOCK_DIV2)except that it would need a reboot after about 15 mins as it would stop responding. I was hoping the new
libs would solve the need to reboot after 15 mins. I have a rotary bcd switch that listens for SmartConfig when set to 0, and then boots with the config on a switch setting other
than 0. This seems to work well, and I always connect/reconnect to my AP as expected. I have flashed the CC3000 to the latest firmware (1.14) successfully, and I can get the
hardware to run the buildtest and other examples successfully.
Code:
/***************************************************
* HTTPServer5
*
* This code will be auto-configurable for the SSID and
* password (in deference to the AP). We use TI SmartConfig as
* a template for this. This code also serves as a web server.
****************************************************/
#include <Adafruit_CC3000.h>
#include <SPI.h>+
#include "utility/debug.h"
#include "utility/socket.h"
#define ADAFRUIT_CC3000_IRQ 3 // MUST be an interrupt pin!
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
// SCK = 13, MISO = 12, and MOSI = 11
#define WIFI_CONNECTED 6
#define WIFI_TX 7
#define DEVICE_NAME "TEST1"
//for the bcd rotary
#define BIT_1 14
#define BIT_2 15
#define BIT_4 16
int iRotaryPosition = 0;
// SPI_CLOCK_DIVIDER caused the server to crash as the SPI bus speed could keep up with fast requests
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIV2);
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY WLAN_SEC_WPA2
#define LISTEN_PORT 80
#define MAX_ACTION 10 // Maximum length of the HTTP action that can be parsed.
#define MAX_PATH 256 // Maximum length of the HTTP request szQuery that can be parsed.
#define BUFFER_SIZE MAX_ACTION + MAX_PATH + 20 // Size of buffer for incoming request data.
#define TIMEOUT_MS 500 // Amount of time in milliseconds to wait for an incoming request to finish.
#define AP_CONNECTION_CHECK_PERIOD 15*60*1000 //every 15 minutes...
Adafruit_CC3000_Server httpServer(LISTEN_PORT);
uint8_t buffer[BUFFER_SIZE+1]; // Incoming request buffer...
int bufindex = 0;
char action[MAX_ACTION+1];
char szQuery[MAX_PATH+1]; // Actual query string from the client...
char szRotary[10] = {0}; // The rotary char buffer...
char szCC3000FirmwareVersion[MAX_PATH+1] = {0};
unsigned long ulLastCheckPeriod = 0;
char szIpAddress[50] = {0};
void setup(void)
{
pinMode(WIFI_CONNECTED, OUTPUT);
pinMode(WIFI_TX, OUTPUT);
digitalWrite(WIFI_CONNECTED, LOW);
digitalWrite(WIFI_TX, LOW);
Serial.begin(115200);
delay(1000);
Serial.print("Free RAM: ");
Serial.println(getFreeRam(), DEC);
RotaryInit();
//Read the rotary position, if Listen mode (rotary position 0) has been selected,
//then listen, otherwise reconnect using exising credentials stored in NVRAM on the CC3000
if(readRotary()==0)
{
Serial.println("Listening...");
listen4Config();
}
else
{
connect2AP();
}
Serial.println("Request DHCP");
while (!cc3000.checkDHCP())
{
delay(100); // Do: Insert a DHCP timeout!
}
// Display the IP address DNS, Gateway, etc.
while (! displayConnectionDetails())
{
delay(500);
}
// Start the http server and listen for connections
httpServer.begin();
Serial.println("Listening for connections...");
}
/*============================================================================
loop()
main processing loop
===========================================================================*/
void loop(void)
{
//get the current rotary value
getRotaryStringVal(szRotary);
// Try to get a client which is connected.
Adafruit_CC3000_ClientRef client = httpServer.available();
if (client)
{
Serial.println("Client connected.");
// Process this request until it completes or times out.
// Note that this is explicitly limited to handling one request at a time!
// Clear the incoming data buffer and point to the beginning of it.
bufindex = 0;
memset(&buffer, 0, sizeof(buffer));
// Clear action and szQuery strings.
memset(&action, 0, sizeof(action));
memset(&szQuery, 0, sizeof(szQuery));
// Set a timeout for reading all the incoming data.
unsigned long endtime = millis() + TIMEOUT_MS;
// Read all the incoming data until it can be parsed or the timeout expires.
bool parsed = false;
while (!parsed && (millis() < endtime) && (bufindex < BUFFER_SIZE))
{
if (client.available())
{
buffer[bufindex++] = client.read();
}
parsed = parseRequest(buffer, bufindex, action, szQuery);
}
Serial.println("---PARSED---");
// Handle the request if it was parsed.
if (parsed)
{
Serial.print("Action: ");
Serial.println(action);
Serial.print("Query: ");
Serial.println(szQuery);
// Check the action to see if it was a GET request.
digitalWrite(WIFI_TX, HIGH);
if (strcmp(action, "GET") == 0)
{
// Respond with the szQuery that was accessed.
// First send the success response code.
client.fastrprintln("HTTP/1.1 200 OK");
// Then send a few headers to identify the type of data returned and that
// the connection will not be held open.
client.fastrprintln("Content-Type: text/plain");
client.fastrprintln("Connection: close");
client.fastrprintln("Server: Adafruit CC3000");
// Send an empty line to signal start of body.
client.fastrprintln("");
// Now send the response data.
client.fastrprint("Your query: ");
client.fastrprintln(szQuery);
client.fastrprint("The rotary value: ");
client.fastrprintln(szRotary);
if(!strcmp(szQuery, "/version"))
{
checkFirmwareVersion();
client.fastrprint("CC3000 firmware version is: ");
client.fastrprintln(szCC3000FirmwareVersion);
}
}
else
{
// Unsupported action, respond with an HTTP 405 method not allowed error.
client.fastrprintln("HTTP/1.1 405 Method Not Allowed");
client.fastrprintln("");
}
digitalWrite(WIFI_TX, LOW);
}
// Wait a short period to make sure the response had time to send before
// the connection is closed (the CC3000 sends data asyncronously).
delay(200);
// Close the connection when done.
Serial.println("Client disconnected");
client.close();
}
}
/**************************************************************************/
/*!
@brief Tries to read the 6-byte MAC address of the CC3000 module
*/
/**************************************************************************/
void displayMACAddress(void)
{
uint8_t macAddress[6];
if(!cc3000.getMacAddress(macAddress))
{
Serial.println("Unable to retrieve MAC Address!\r\n");
}
else
{
Serial.print("MAC Address : ");
cc3000.printHex((byte*)&macAddress, 6);
}
}
/*-------------------------------------------------------------------------------
parseRequest()
// Return true if the buffer contains an HTTP request. Also returns the request
// szQuery and action strings if the request was parsed. This does not attempt to
// parse any HTTP headers because there really isn't enough memory to process
// them all.
// HTTP request looks like:
// [method] [szQuery] [version] \r\n
// Header_key_1: Header_value_1 \r\n
// ...
// Header_key_n: Header_value_n \r\n
// \r\n
-------------------------------------------------------------------------------*/
bool parseRequest(uint8_t* buf, int bufSize, char* action, char* szQuery)
{
// Check if the request ends with \r\n to signal end of first line.
if (bufSize < 2)
return false;
if (buf[bufSize-2] == '\r' && buf[bufSize-1] == '\n')
{
parseFirstLine((char*)buf, action, szQuery);
return true;
}
return false;
}
/*-------------------------------------------------------------------------------
parseFirstLine()
-------------------------------------------------------------------------------*/
// Parse the action and szQuery from the first line of an HTTP request.
void parseFirstLine(char* line, char* action, char* szQuery)
{
// Parse first word up to whitespace as action.
char* lineaction = strtok(line, " ");
if (lineaction != NULL)
strncpy(action, lineaction, MAX_ACTION);
// Parse second word up to whitespace as szQuery.
char* linepath = strtok(NULL, " ");
if (linepath != NULL)
strncpy(szQuery, linepath, MAX_PATH);
}
/*-------------------------------------------------------------------------------
displayConnectionDetails()
------------------------------------------------------------------------------*/
// Tries to read the IP address and other connection details
bool displayConnectionDetails(void)
{
uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
{
Serial.println("Unable to retrieve the IP Address!\r\n");
return false;
}
else
{
Serial.print("\nIP Addr: ");
cc3000.printIPdotsRev(ipAddress);
Serial.print("\nNetmask: ");
cc3000.printIPdotsRev(netmask);
Serial.print("\nGateway: ");
cc3000.printIPdotsRev(gateway);
Serial.print("\nDHCPsrv: ");
cc3000.printIPdotsRev(dhcpserv);
Serial.print("\nDNSserv: ");
cc3000.printIPdotsRev(dnsserv);
Serial.println();
return true;
}
}
/*---------------------------------------------------------------------------
listen4Config
---------------------------------------------------------------------------*/
void listen4Config()
{
/* is the default behaviour) */
Serial.println("\nInitialising the CC3000 ...");
if (!cc3000.begin(false))
{
Serial.println("Unable to initialise the CC3000");
while(1);
}
uint16_t firmware = checkFirmwareVersion();
if (firmware < 0x113)
{
Serial.println("Wrong firmware version!");
for(;;);
}
displayMACAddress();
/* Try to use the smart config app (no AES encryption), saving */
/* the connection details if we succeed */
Serial.println("Waiting for a SmartConfig connection (~60s) ...");
if (!cc3000.startSmartConfig(DEVICE_NAME))
{
Serial.println("SmartConfig failed");
while(1);
}
digitalWrite(WIFI_CONNECTED, HIGH);
Serial.println("Saved connection details and connected to AP!");
}
/*---------------------------------------------------------------------------
connect2AP
This method initializes the CC3000 with existing connection info stored in NVRAM
on board the CC3000.
---------------------------------------------------------------------------*/
void connect2AP()
{
// Initialise the module
Serial.println("\nInitializing...");
// get the existing connection details from NVRAM
if (!cc3000.begin(false, true, DEVICE_NAME))
{
Serial.println("Unable to re-connect - try Listening mode for connection information");
while(1);
}
digitalWrite(WIFI_CONNECTED, HIGH);
Serial.println("Connected!");
}
/*--------------------------------------------------------------------------
checkFirmwareVersion()
Tries to read the CC3000's internal firmware patch ID
--------------------------------------------------------------------------*/
uint16_t checkFirmwareVersion(void)
{
uint8_t major, minor;
uint16_t version;
#ifndef CC3000_TINY_DRIVER
if(!cc3000.getFirmwareVersion(&major, &minor))
{
Serial.println("Unable to retrieve the firmware version!\r\n");
version = 0;
}
else
{
Serial.print("Firmware V. : ");
Serial.print(major);
Serial.print(".");
Serial.println(minor);
sprintf(szCC3000FirmwareVersion, "%d.%d", major, minor);
version = major;
version <<= 8;
version |= minor;
}
#endif
return version;
}
/////////////////////////////////////////////////////////////////////////////
void RotaryInit()
{
pinMode(BIT_1, INPUT_PULLUP); // 1
pinMode(BIT_2, INPUT_PULLUP); // 2
pinMode(BIT_4, INPUT_PULLUP); // 4
}
//////////////////////////////////////////////////////////////////////////////
int readRotary()
{
int iValue = 0;
if(digitalRead(BIT_1)==LOW)
iValue += 1;
if(digitalRead(BIT_2)==LOW)
iValue += 2;
if(digitalRead(BIT_4)==LOW)
iValue += 4;
return iValue;
}
/////////////////////////////////////////////////////////////////////////////////
void getRotaryStringVal(char* szBuffer)
{
iRotaryPosition = readRotary();
itoa(iRotaryPosition, szBuffer, 10);
}