Troubleshooting a 400 response, ethernet + php

This problem seems complex to me and I'll outline it as best I can below, but the short of it is that I am trying to troubleshoot a 400 server response. I've looked at the data string (the POST request) that the Arduino sends, and it looks ok, but I need to see what the server is receiving. I suspect the POST data is not sending as it should, but I don't know how to read this from my php page. Is there a PHP command to echo something other than 400 if the POST string is not correct?

I have an ethernet connection POSTing data to a PHP page. It is working fine on a Pro Mini with Optiboot, but now I am porting it to a self-made board with a 328 (which I've been told the standard bootloader is Optiboot, but watchdog, itself, is not the problem).

The system posts to 4 different tables: 1)Startup report; 2)"heartbeat"; 3)Pump runtime and amps; and 4)Switch changes.

Though they all use similar code, the Runtime and change tables return a 400 message (below). Also, if I have the watchdog enabled, this causes a reset bc it takes 15 seconds (which is probably normal since it is waiting for the server).

I suspect that the problem with the code has to do with the conversion of the raw data into the String, but I do not know how to go about troubleshooting this as I can't find it with a simple Serial.print.

Here is the code I am sending the server (the server address is changed for privacy):

  Serial.print("Out of delay"); // -------------
  Serial.println(millis());
  byte runtime = analogRead(A3);
  float amps = analogRead(A2) / 100; // changed for simplicity
  char cruntime[4]; // create character array for runtime
  char camps[5]; // create character array for amps
  dtostrf(runtime, 4, 0, cruntime); // convert to string
  dtostrf(amps, 2, 1, camps);
  String sruntime = String(cruntime);
  sruntime.trim(); // NOT SURE IF THIS IS NEEDED
  String samps = String(camps);
  samps.trim();
  int memory = freeMemory();
  Serial.print("Free Memory: ");
  Serial.println(memory);
  String strmem = String(memory);
  String cwpdata = "serial=test&runtime=" + sruntime + "&amps=" + samps;
  Serial.println(cwpdata);
  wdt_reset();
  Serial.print("Sending: ");
  Serial.println(millis());
  
  if (client.connect(server, 80)) {
    postData(cwpdata, "addcwp");
  } 

  Serial.print("Sent: ");
  Serial.println(millis());

With the postData function:

void postData(String inputData, String filename) {
  Serial.println("connected");
      // Make a HTTP request:
      client.println("POST /dev/telemetry/test/" + filename + ".php HTTP/1.1");
      client.println("Host: www.SERVER.com");
      client.println("Content-Type: application/x-www-form-urlencoded");
      client.print("Content-Length: "); 
      client.println(inputData.length()); 
      Serial.println(inputData);
      Serial.print("Data Length: ");
      Serial.println(inputData.length());
      client.println("Connection: close");
      client.println(); 
      client.println(inputData);
      client.println();
      
      wdt_reset();
      unsigned long startMillis = millis();
      unsigned long endMillis = startMillis + timeout;
      while(client.connected() && (millis() < endMillis)) {
      while(client.available()) {
        char ch = client.read();
        Serial.write(ch);
      }
      wdt_reset();
      }
      // if the server's disconnected, stop the client:
      Serial.println();
      client.stop();
      int memory = freeMemory();
      if (memory < 275) {   // if memory is low, reset uC
        delay(15000);
      }
}

Here is the response. The numbers 48000 to 64000 are the millis() readings at each point.

Starting Loop: 43794
Out of delay48794 // millis
Free Memory: 308
serial=test&runtime=15.0&amps=5.0
Sending: 48796  // millis
connected
serial=test&runtime=15.0&amps=5.0
Data Length: 33
HTTP/1.1 400 Bad Request
Server: nginx
Date: Wed, 02 Dec 2015 16:17:55 GMT
Content-Type: text/html
Content-Length: 166
Connection: close

<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx</center>
</body>
</html>

Sent: 64086  // millis

And my PHP code is simply:

<?php
   	include("connect.php");

   	$link=Connection();

	$serial=$_POST["serial"];
	$runtime=$_POST["runtime"];
	$amps = $_POST["amps"];


	$query = "INSERT INTO `test_cwp` (`serial`, `runtime`, `amps`)
		VALUES ('".$serial."','".$runtime."','".$amps."')";

   	mysql_query($query,$link);
	mysql_close($link);

	echo "Pump Add Success!!!";
?>

Is there some reason to POST instead of GET?

The main reason is for security. I will eventually add identifiers to these and I don't want them included in the url.

I don't want them included in the url.

What kind of identifiers? Who is going to see the URL?

I'm prototyping a product that I want to sell at a later date. This would use a userID and pw to authenticate the unit.

Chances are it is in this line. The requested page may not be correctly formatted.

      client.println("POST /dev/telemetry/test/" + filename + ".php HTTP/1.1");

I found a space in the 'client.println' before and corrected that.

I got it working for this function, but I don't know how.

Now it stopped working on another similar function where I POST binary data. This is really frustrating. Could it have to do with encoding?

pekasus:
Now it stopped working on another similar function where I POST binary data. This is really frustrating. Could it have to do with encoding?

Maybe.

OK. So I isolated where the problem is in the other section. Here is the code:

void heartbeat(unsigned long hblength) {
  if (millis() - hbstart > hblength) {
/*    ss = digitalRead(ssPin);
    char css[2];
    dtostrf(ss, 1, 0, css);
    String sss = String(css);
    hw = digitalRead(hwPin);
    char chw[2];
    dtostrf(hw, 1, 0, chw);
    String shw = String(chw);
    al = digitalRead(alPin);
    char cal[2];
    dtostrf(al, 1, 0, cal);
    String sal = String(cal);
    ex = digitalRead(exPin);
    char cex[2];
    dtostrf(ex, 1, 0, cex);
    String sex = String(cex);
*/    String strmem = String(freeMemory());
    wdt_reset();
//    String hbdata = "serial=test&ss=" + sss + "&hw=" + shw + "&al=" + sal + "&ex=" + sex + "&mem=" + strmem;
    String hbdata = "serial=test&ss=0&hw=1&al=0&ex=1&mem=007";
    postData(hbdata, "heartbeat"); 
    wdt_reset();
    hbstart = millis();
  }
} // close heartbeat

It reads the state of 4 switches and reports them to a .php page.

I first commented out the first "String hbdata" and wrote out the data. That didn't work.

Then I commented out the large section of code above it (still commented out), and it works like a charm.

This is strange bc it doesn't have to do with using the string, but rather with the string being formed.

Do you have your code printing out your final String to the serial monitor to see what it looks like? Note that compounding strings together may run into memory problems as you may have all the string components still in memory along with the new big string.

I do print out the final string. It is: "serial=test&ss=0&hw=1&al=0&ex=1&mem=385"

For this troubleshooting, I am writing out a string.

I just reduced the section that I comment out to:

    hw = digitalRead(hwPin);
    char chw[2];
    dtostrf(hw, 1, 0, chw);
    String shw = String(chw);

Then it only works sporadically. It works fine if all but the first chunk is commented out.

I just changed the char section to:

   String strmem = String(freeMemory());
    wdt_reset();
   
    String sss = 0;
    String shw = 0;
    String sal = 0;
    String sex = 0;
    if(digitalRead(ssPin)) {
      sss = "1";
    }
    if(digitalRead(hwPin)) {
      shw = "1";
    }
    if(digitalRead(alPin)) {
      sal = "1";
    }
    if(digitalRead(exPin)) {
      sex = "1";
    }

And it works fine. Something about working with those character arrays must be causing this.

This thing is driving me nuts. Now it works the first time, but it fails each time after that, even when I write the string out by hand. It's the same function each time, but for some reason, it fails the second time it runs.

EDIT: I finally figured it out. Monitoring the amperage on 4 analog pins is consuming too much RAM. I removed one pin and it now functions. When the function is called to post data, it consumes 250 bytes of RAM.

Monitoring the amperage on 4 analog pins is consuming too much RAM.

Nonsense. Abusing the String class the way you are is what is consuming too much SRAM.

Ditch the String class completely.

    char chw[2];
    dtostrf(hw, 1, 0, chw);
    String shw = String(chw);

This is just plain stupid. dtostrf() is designed to convert a float to a string. hw is NOT a float. Wrapping the resulting string in a String is just plain wasteful.

I did convert that to if statements as well. I was using dtostrf for a float, but I only have one, so I changed the rest.

As for the analog reads, it's not just a simple read. I am using emonLib and have to create an instance for each pin.