Floats and strings for http

I'm writing a program to monitor energy usage and report it to my server using http. For that, I need to know the length of the data that I am sending. I've read a lot about String, and that basically we shouldn't use them, but I can't find another way to concatenate all the data and then have the Arduino calculate the length.

The confusion is greater because I am using a float, so I can't predict how many digits the arduino will send. Also, the integer I am using can be 1, 2, 3, or 4 digits. This is why I was using the String function.

Is there another way to do this? I am concerned from what I read that the String function will cause the Arduino to run out of memory, and this will be at a remote location so I can't easily reset it.

Here's the code:

double Irms = emon1.calcIrms(1480);  // Calculate current only
  if (Irms > 0.1) {
    unsigned int counter = 0;
    float avgamp = 0.0; // hold amp value
    while (Irms > 0.1) {
      counter++;
      avgamp += Irms;
      delay(1000);
      Irms = emon1.calcIrms(1480);
    } 
    avgamp = avgamp / counter;
    char cruntime[7];
    char camps[7];
    dtostrf(counter, 4, 0, cruntime);
    dtostrf(avgamp, 2, 1, camps);
    String sruntime = String(cruntime);
    String samps = String(camps);
    String data = "serial=007&runtime=" + sruntime + "&s=" + samps;

Work out how long the longest output string could be. Add at least 1 to this number (you need space for the null character that terminates a C-string).

Define a C-string of that length that will hold your output string:

char outString[100];
outString[0] = '\0';  // Null character in first element gives you a zero length string to start with

Add the elements that you need:

strcat(outString, "serial=007&runtime=");
strcat(outString, cruntime);
strcat(outString, "&s=");
strcat(outString, camps);

Each time you call strcat, it concatenates the 2nd string to the 1st string and moves the null character along so that the new string is properly terminated.

Is the floating point precision a necessity, or simply the way you get the data? Why not use a comma-delimited list of the data where the data is converted to ASCII and then use a sentinel (i.e., a packet marker) to denote the end-of-data. The Arduino can then use a worst-case char array, pack the data into the array, comma-separated, add the sentinel (e.g., '\n'), send the data, and have the server pull it apart.

The other alternative is to pack the data and prepend a length byte to the front of the char array, much like the string descriptor blocks many languages use.

@Hackscribble - so I would still call

dtostrf(counter, 4, 0, cruntime);
    dtostrf(avgamp, 2, 1, camps);

to turn the values into strings first, right? This way, I would know the lengths of the values.

Then, for the length to send in the HTTP request, I would just do length(outString) , or would it be length(outString) - 1?

@econjack - I am only using 1 decimal place on the database, so I don't need the full float.

When string functions (e.g., strlen()) work on char arrays, the length does not include the null termination character.

I'm writing a program to monitor energy usage and report it to my server using http. For that, I need to know the length of the data that I am sending. I've read a lot about String, and that basically we shouldn't use them, but I can't find another way to concatenate all the data and then have the Arduino calculate the length.

Getting the length of a String is fairly easy. If you are using a POST http method to send your data, then the below code method should work.

    String data;
  data="entry.0.single=";
  data+=analogRead(A2);
  data+="&submit=Submit";

    client.print("POST /formResponse?formkey=");
    client.print(formkey);
    client.println("&ifq HTTP/1.1");
    client.println("Host: spreadsheets.google.com");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.print(data);
 client.print(F("POST /formResponse?formkey="));

Etc, is preferable

AWOL: client.print(F("POST /formResponse?formkey="));

Etc, is preferable

If you are trying to save memory, yes, otherwise no.

What about datalength = client.write(data); It works for Serial. I'll give it a try with client.

zoomkat: If you are trying to save memory, yes, otherwise no.

sp. "if you're trying to save precious RAM, yes"

This is how I'd do it.

Note that this will only work if the number of "amps" to be output is between 0.0 and 3276.7 (I did not write it to handle negative numbers or very large numbers).

 double Irms = emon1.calcIrms(1480);  // Calculate current only
  if (Irms > 0.1) {
    unsigned int counter = 0;
    float avgamp = 0.0; // hold amp value
    while (Irms > 0.1) {
      counter++;
      avgamp += Irms;
      delay(1000);
      Irms = emon1.calcIrms(1480);
    }
    avgamp = avgamp / counter;
    int aatenths = (int)(10.0 * avgamp); // I hope this is big enough
    char data[41];
    sprintf(data, "serial=007&runtime=%d&s=%d.%d",
            sruntime, aatenths/10, aatenths%10);

try this tutorial for sending stuff out to a webpage. Saves a lot of memory. Worked really well with my home automation project.

http://startingelectronics.org/tutorials/arduino/ethernet-shield-web-server-tutorial/web-server-read-switch-using-AJAX/

Thanks , @ACremers. I am using POST so that I don't have to set up the Arduino as a webserver bc then I would need to manage the IP of each unit. I want these to be plug and play so I can send them out to others and they can just plug them in and see data online.