I would like to get rid of String class from my program which is running on Mega2560. It is simple program to display basic web page with couple of temperatures etc. As network interface I'm using Wiznet5100 ethernet shield. Everything is working ok but from time to time ethernet won't respond - sometimes after 2 days, sometimes after a week. Code is based on Server egzample from standard ethernet library. It uses String class - and I got bad experience using String before, so now I would like to replace the String class with string but I'm not sure how to do some parts ( details in comments ) :
#include "SPI.h"
#include "Ethernet.h"
#include <utility/w5100.h>
#include <HttpClient.h>
#include <EasyTransfer.h>
EasyTransfer ETin, ETout;
struct RECEIVE_DATA_STRUCTURE
{
};
////////////////////////////////////////////////////////////////////////////
struct SEND_DATA_STRUCTURE
{
};
///////////////////////////////////////////////////////////////////////////
RECEIVE_DATA_STRUCTURE odbierane;
SEND_DATA_STRUCTURE wysylane;
///////////////////////////////////////////////////////////////////////////
byte mac[] = {
0xDE, 0xA2, 0xDE, 0xEF, 0xFE, 0x67 };
IPAddress ip(192, 168, 1, 50);
IPAddress gateway( 192, 168, 1, 1 );
IPAddress subnet( 255, 255, 255, 0 );
EthernetServer server(8085);
String HTTP_req; // stores the HTTP request , replace it with static char HTTP_req[] but what goes to [] ?
void GetAjaxData(EthernetClient cl)
{
// here goes code for sipmle web page. This part works ok .
}
///////////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
delay(1000);
Serial1.begin(19200);
ETin.begin(details(odbierane), &Serial1);
ETout.begin(details(wysylane), &Serial1);
Ethernet.begin(mac, ip, gateway, gateway, subnet);
W5100.setRetransmissionTime(0x07D0);
W5100.setRetransmissionCount(2);
delay(2000);
server.begin();
lastMillis = millis();
}
void loop()
{
EthernetClient client = server.available();
if (client) {
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
HTTP_req += c; // replace with HTTP_req[i++] = c;
if (c == '\n' && currentLineIsBlank) {
client.println(F("HTTP/1.1 200 OK"));
client.println(F("Content-Type: text/html"));
client.println(F("Connection: keep-alive"));
client.println();
if (HTTP_req.indexOf("ajax_switch") > -1) { // this is where I'm lost - what to use instead of .indexOf ??
GetAjaxData(client);
}
else {
client.println(F("<!DOCTYPE html>"));
client.println(F("<html>"));
client.println(F("<head>"));
client.println(F("<title>Zet - Ster II</title>"));
client.println(F("<script>"));
client.println(F("function GetSwitchAnalogData() {"));
client.println(F(
"nocache = \"&nocache=\" + Math.random() * 1000000;"));
client.println(F("var request = new XMLHttpRequest();"));
client.println(F("request.onreadystatechange = function() {"));
client.println(F("if (this.readyState == 4) {"));
client.println(F("if (this.status == 200) {"));
client.println(F("if (this.responseText != null) {"));
client.println(F("document.getElementById(\"sw_an_data\")\
.innerHTML = this.responseText;"));
client.println(F("}}}}"));
client.println(F(
"request.open(\"GET\", \"ajax_switch\" + nocache, true);"));
client.println(F("request.send(null);"));
client.println(F("setTimeout('GetSwitchAnalogData()', 1000);"));
client.println(F("}"));
client.println(F("</script>"));
client.println(F("</head>"));
client.println(F("<body onload=\"GetSwitchAnalogData()\">"));
client.println(F("<body bgcolor=\"black\">"));
client.println(F("<center><h1><font color=\"gray\">Temperatury </font></h1></center>"));
client.println(F("<div id=\"sw_an_data\">"));
client.println(F("</div>"));
client.println(F("</body>"));
client.println(F("</html>"));
}
HTTP_req = "";
break;
}
if (c == '\n')
{
currentLineIsBlank = true;
}
else if (c != '\r')
{
currentLineIsBlank = false;
}
}
}
delay(2);
client.stop();
}
////////////////////////////////////////////////////////////////
}
#define bufferMax 128 // i know it won't be longer than this
char queryBuffer[bufferMax];
int bufferSize;
void loop()
{
// listen for incoming clients
WiFiClient client = server.available();
if (client) {
boolean currentLineIsBlank = true;
bufferSize = 0;
while (client.connected()) {
if (client.available()) { // client data available to read
char c = client.read(); // read 1 byte (character) from client
if (bufferSize < bufferMax) queryBuffer[bufferSize++] = c;
if (c == '\n' && currentLineIsBlank) {
parseReceivedRequest(client);
bufferSize = 0;
webParser.clearBuffer(queryBuffer, 128);
break;
}
if (c == '\n') {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != '\r') {
// a text character was received from client
currentLineIsBlank = false;
}
}//end if available
}//end while connected
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disonnected");
//
}//end client
}
I use this c function to check for strings instead of indexOf
inbuff is the HTTP_req and instring is the string you're looking for.
oops, left out another function to clear out the buffer.
it's where you see
webParser.clearBuffer(queryBuffer, 128);
void clearBuffer( char *inbuff , int inlength ) {
//clear out param for new param
memset(&inbuff[0], 0, inlength);
}
You need to clear out the http_req so you'd get a fresh string every time. I haven't run my server 24/7 yet but I have a feeling I'll run into your problem down the road.
I have used char arrays before but I just wasn't sure how should I approach searching for certain strings . I'm not sure if String is cosing ethernet hang but it is the last thing to try ... We'll se .
Ethernet shield is connected to my router. I'm displaying this web page on tablet - 24/7 , using LAN ( Wi-Fi ) and from time to time I'm allso checking it from internet , using dyndns.org . Also , every 3 minutes, few values are send to xively . The only problem is : ethernet shield is loosing connection randomly - sometimes aftes a day, sometimes more than a week . Arduino is still making it's job - just the ethernet shield needs to be reset. I've tried remowing xively part , changing the web page part, ports , timing etc... Some day I might try Wiz5200 shield...
I doubt the String Class is causing your Ethernet shield issue. More likely you may have suffered a broken internet connection and the connection did not close properly. The below code has a counter to close a connection when packets stop arriving.