Replacing String class .

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(); 
  } 
  ////////////////////////////////////////////////////////////////
}

I'm using char array strings for my server

#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

bool contains(char *inBuff, char *inString) {
    
    if(strstr(inBuff, inString) == NULL) {
        return false;
    } else {
        return true;
    }
}

I'll give it a try :slight_smile:
Do you get random hangs of ethernet shield ( after couple of days ) ? Is it runnig 24/7 ?

Thanks for ansfer :slight_smile:

BTW :

bool contains(char *inBuff, char *inString) {
    
    if(strstr(inBuff, inString) == NULL) {
        return false;
    } else {
        return true;
    }
}

pointer *inBuff is where you capture incoming chars, right ? *inString is what you're looking for ? In my case "ajax_switch" ?

[...]
        HTTP_req += c;                                         // replace with HTTP_req[i++]  =  c;
[...]

Don't forget to always terminate your strings so the code should really be:

        HTTP_req[i++] = c;
        HTTP_req[i]   = '\0';

Hope this helps,

Brad
KF7FER

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 .

Thank you !

if you have a lot of or big html file to load, use the sd card, printing and coding it on the arduino is a pain.

It's not that big :

void GetAjaxData(EthernetClient cl)
{
  cl.print("<center><p><font color=\"red\">Piec : </font>");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.temp_co);
  cl.print("°C");
  cl.print("<font color=\"red\">");
  cl.print("  -> ");
  cl.print("</font>");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.zadana_t_co);
  cl.print("°C");
  cl.println("</font></p></center>");

  cl.print("<center><p><font color=\"red\">Powrót obiegu : </font>");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.temp_co_powrot);
  cl.print("°C");
  cl.println("</font></p></center>");

  cl.print("<center><p><font color=\"red\">CWU : </font>");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.temp_cwu);
  cl.print("°C");
  cl.println("</font></p></center>");

  cl.print("<center><p><font color=\"red\">Pi?tro : </font> ");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.temp_pietro);
  cl.print("°C");
  cl.println("</font></p></center>");

  cl.print("<center><p><font color=\"red\">Zewn?trzna : </font>");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.temp_zewn);
  cl.print("°C");
  cl.println("</font></p></center>");
  
   cl.print(F("<center><p><font color=\"red\">Klapa : </font>"));
  cl.print(F("<font color=\"white\">"));
  cl.print(odbierane.pozycja_klapy);
  cl.print(F("<font color=\"red\">"));
  cl.print(F("  -> PID : "));
  cl.print(F("</font>"));
  cl.print(F("<font color=\"white\">"));
  cl.print(odbierane.pid_pozycja_klapy);
  cl.println(F("</font></p></center>"));
  
  cl.print("<center><p><font color=\"red\">Stan pieca : </font>");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.stan);
  cl.println("</font></p></center>");
  
  if ( toggle_wdt )
  {
    cl.print("<center><p><font color=\"red\">Po??czenie : </font>");
  cl.print("<font color=\"white\">");
  cl.print("OK");
  cl.println("</font></p></center>");
  }
  
  else
  {
   cl.print("<center><p><font color=\"red\">Po??czenie : </font>");
  cl.print("<font color=\"white\">");
  cl.print("----");
  cl.println("</font></p></center>");
  } 
}

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.

http://playground.arduino.cc/Code/WebServerST#.UyNvfynD_iw

@ zoomkat : Thanks a lot for pointing me new server egzample ! But I'm stuck at making it work the way I'd like it to, that is - using AJAX .

I've placed this part in index.htm file :

<!DOCTYPE html>
<html>
<head>
<title>Zet - Ster II</title>
<script>
function GetSwitchAnalogData() {
  
nocache = &nocache= + Math.random() * 1000000;
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (this.readyState == 4) {
if (this.status == 200) {
if (this.responseText != null) {
document.getElementById(sw_an_data)\
                                    .innerHTML = this.responseText;
}}}}
           
request.open(GET, ajax_switch + nocache, true);
request.send(null);
setTimeout('GetSwitchAnalogData()', 1000);
}
</script>
</head>
<body onload=GetSwitchAnalogData()>
<body bgcolor=black>
<center><h1><font color=gray>Temperatury </font></h1></center>
<div id=sw_an_data>
</div>
</body>
</html>

And it is working - I can see this page in my web browser. But I'm not sure where to place this piece from my previous server :

void GetAjaxData(EthernetClient cl)
{
  cl.print("<center><p><font color=\"red\">Piec : </font>");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.temp_co);
  cl.print("°C");
  cl.print("<font color=\"red\">");
  cl.print("  -> ");
  cl.print("</font>");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.zadana_t_co);
  cl.print("°C");
  cl.println("</font></p></center>");

  cl.print("<center><p><font color=\"red\">Powrót obiegu : </font>");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.temp_co_powrot);
  cl.print("°C");
  cl.println("</font></p></center>");

  cl.print("<center><p><font color=\"red\">CWU : </font>");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.temp_cwu);
  cl.print("°C");
  cl.println("</font></p></center>");

  cl.print("<center><p><font color=\"red\">Pi?tro : </font> ");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.temp_pietro);
  cl.print("°C");
  cl.println("</font></p></center>");

  cl.print("<center><p><font color=\"red\">Zewn?trzna : </font>");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.temp_zewn);
  cl.print("°C");
  cl.println("</font></p></center>");
  
   cl.print(F("<center><p><font color=\"red\">Klapa : </font>"));
  cl.print(F("<font color=\"white\">"));
  cl.print(odbierane.pozycja_klapy);
  cl.print(F("<font color=\"red\">"));
  cl.print(F("  -> PID : "));
  cl.print(F("</font>"));
  cl.print(F("<font color=\"white\">"));
  cl.print(odbierane.pid_pozycja_klapy);
  cl.println(F("</font></p></center>"));
  
  cl.print("<center><p><font color=\"red\">Stan pieca : </font>");
  cl.print("<font color=\"white\">");
  cl.print(odbierane.stan);
  cl.println("</font></p></center>");
  
  if ( toggle_wdt )
  {
    cl.print("<center><p><font color=\"red\">Po??czenie : </font>");
  cl.print("<font color=\"white\">");
  cl.print("OK");
  cl.println("</font></p></center>");
  }
  
  else
  {
   cl.print("<center><p><font color=\"red\">Po??czenie : </font>");
  cl.print("<font color=\"white\">");
  cl.print("----");
  cl.println("</font></p></center>");
  } 
}

In previous server ( see first post ) this function was called here :

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)
           {                          
            GetAjaxData(client);
            }
....
}

I've tried couple solutions but without luck - can't get AJAX to work... I'll really apreciate any sugestions ..