Help please - Newbie - Strings doing strange things - Ethernet -

Hi all,
I am having trouble with my Ether Ten from Freetronics. (built in ethernet without the shield)
using Arduino 1.0, developing on a mac

I have a Windows XP based executable that is a HTTP server, and have used this for many years collecting data from things like barcode readers.

I am attempting to take some analogue reading (maybe temerature) and send it to this server listening on 192.168.3.42
To do this I have modified the example HTTP Client code, sending the ip address of the Arduino sending data and some other value I have called “seed” here.

To make it simple there are no sensors attached, I am sending millis() - If I can get that to work then the sensor will be a snap.

THE TEST
Taking a fixed string, I send it to the server and it is accepted, as in the various fields parse out nicely - GREAT - server returns text and the serial port on the Arduino shows it.

client.println(“GET /?request=PING,from=D33,IP=123.234.444.555,seed=3 HTTP/1.1”); this yields on HTTP server

query field value
from D33
IP 123.234.444.555
seed 3

MY PROBLEM
if I cut the outgoing string into 2 pieces or more this line of code stops working
ie HttpString = “GET /?request=PING,from=D33,IP=123.234.444.555,seed=3”;
HttpString += " HTTP/1.1 " ;
client.println( HttpString );

On the server this results in varying parts of this being split onto one or many query entries with most of it missing as it has not been parsed properly. Although the serial println appears perfectly.

QUESTION
I have not used C in over fifteen years, am I not using the string properly ?
It looks ot me like I am taking a fixed string, cutting it in half and sending both halves v-s one single transmission.
I attach the code below

Thanks in advance

#include <SPI.h>
#include <Ethernet.h>
EthernetClient  client;

byte              mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; byte x=0;
IPAddress       IPserver(192,168,3,42); // A4200
IPAddress       myIP(0,0,0,0);
String            HttpString=""; 
unsigned long  time;

void setup() {  
  Serial.begin(9600);
  do {
    Serial.println("Connecting  ");       
    
    if (Ethernet.begin(mac) == 0) {   
       Serial.println("Failed to configure Ethernet");
    } else {   x=1;
      Serial.println(" ethernet card init.");      // no point in carrying on, so do nothing forevermore:      
      delay(1000);  // give the Ethernet shield a second to initialize:
  
      //  if (Ethernet.begin(mac) == 0) { for (byte x=1;x>0;){  Serial.println("Failed to configure Ethernet using DHCP");} }   // no point in carrying on, so do nothing forevermore:      
      myIP = Ethernet.localIP();          
    }
  } while (x==0); 

////////////////////////////////////////////////////////

    Serial.print("- - Connected to server @ ");
    Serial.println(" 192,168,3,42");
    Serial.print("My IP address: ");
    for (byte thisByte = 0; thisByte < 4; thisByte++) {    // print the value of each byte of the IP address:
       Serial.print( myIP[thisByte]) ;
       Serial.print( ".");
    }      
    Serial.println();
}

void loop()
{    
  Serial.println( "..." );                               // top of loop
  if (client.connect(IPserver, 80))
  { 
      client.flush();   
      Serial.println(".   .   .");                       // server connected

      HttpString  = "GET /?request=PING,from=D33,IP=123.234.444.555,seed=";
      HttpString += String(millis(),DEC); 
      HttpString += " HTTP/1.1 \r\n" ; 
      Serial.println( HttpString );

//---{ This does not work }---//
      client.println( HttpString ); 

//---{ This works evertime }---//       
    // client.println("GET /?request=PING,from=D33,IP=123.234.444.555,seed=3 HTTP/1.1");       
       
    time = millis() + 10000;       
    while (client.connected() && !client.available() && time>millis() ) {} // Wait for it....
    while (client.available()) {          // if there are incoming bytes available from the server, read them and print them:
      char c = client.read();
      Serial.print(c);                       // serial mon shows server text OK
    }    
  }  else {
  Serial.println("- - No server found, timeout...");
  delay(5000);
  }
  client.stop(); 
  while (client.status() != 0) {delay(10);}
 delay(2000);                                                      // delays to stop network flooding.
}

Unhappy fix

Reasoning it was to do with the string, and viewing past posts on how client.println() works in the Ethernet library on a byte by byte basis, I used an array of chars, ie

char moo[ 99 ];

HttpString = “blah,”;
for (byte i=0; i < HttpString.length(); i++)
{
moo = HttpString.chaAt(i);
}
client.println( moo ); // Works OK
///// But I would still appriciate someone commenting on the use of the string. (2 days of my life went on this…)
///// I guess that means I am getting better at it. ahem…

Have you gotten any example code to work?

The String class uses malloc under the hood to grab memory for the string and to grow the string. Given the limited amount of ram on the atmega328 you might be better off just using regular C style strings (i.e. character arrays). You can use the snprintf() function to build the C string with whatever fields you want.

For example:

    char str[128];
    int len;
    len = snprintf(str, sizeof(str), "GET /?request=PING,from=%s,IP=%s,seed=%d HTTP 1.1 \n\r", "D33", "123.234.444.555", millis());

Also, the ethernet library client.print() and client.println() functions may send several packets rather than the one packet you would expect (take a look at the library source code). You can use client.write() instead to send a single packet.

   client.write(str, len);

Hi Zoomkat, yes, the example works, its the string that makes the error.

Thanks dhunt, this looks interesting, I will try this out later tonight.

Also, I am not sure about the %s %d, they look like passed params (?)

The snprintf() function is a standard C function. You're right about the %s and %d characters, they tell the function to insert the next argument in the function into the output string and and format it specific way. The %s means the argument is a string, the %d means the argument is a signed integer.

I did a bit of googling for you and found this site: http://www.rohitab.com/discuss/topic/11505-sprintf-tutorial-in-c which talks about sprintf(). The sprintf() function is basically the same as snprintf() except it doesn't let you limit the number of characters written to the buffer, so its an unsafe function that you should avoid using.

The format codes used in snprintf() are the same ones used in printf(), and there's a tutorial on that here: http://www.codingunit.com/printf-format-specifiers-format-conversions-and-formatted-output, or plenty more that google can find for you.

Thanks again

We all trust in Google, and the goodness it brings....

The below might be of use in parsing your strings.

http://arduino.cc/en/Reference/StringObject