3

I am attempting to make RESTful POST request using the WifiESP library (https://github.com/bportaluri/WiFiEsp). I'm able to successfully make the request with curl, but consistently get an error using the Arduino and ESP. I suspect the problem is related to the manual formatting of the POST request the library requires, but I don't see anything wrong. Here my sanitized code:

if (client.connect(server, 80)) {
Serial.println("Connected to server");
// Make a HTTP request
String content = "{'JSON_key': 2.5}";   // some arbitrary JSON
client.println("POST /some/uri HTTP/1.1");
client.println("Host: http://things.ubidots.com");
client.println("Accept: */*");
client.println("Content-Length: " + sizeof(content));
client.println("Content-Type: application/json");
client.println();
client.println(content);
}

The error I get (via serial monitor) is this:

Connected to server
[WiFiEsp] Data packet send error (2)
[WiFiEsp] Failed to write to socket 3
[WiFiEsp] Disconnecting 3

My successful curl requests looks like this:

curl -X POST -H "Content-Type: application/json" -d 'Some JSON' http://things.ubidots.com/some/uri
2
  • Couple things. I noticed that the library appends both \r and \n instead of just \n when you use the println function. Try doing the \ns manually and use print function. if that doesn't do it, print the whole thing to Serial and compare it with a wireshark trace of your curl post. Commented Dec 28, 2016 at 13:40
  • @leetibbett Thanks for the response. \r\n ended up not being a problem, but it did get me looking at the HTTP protocol documentation which helped me find several other problems. Commented Dec 29, 2016 at 5:54

3 Answers 3

3

After some experimentation, here is the solution to the multiple problems.

  1. The JSON object was not correctly formatted. Single quotes were not accepted, so I needed to escape the double quotes.
  2. The host does not need "http://" in a POST request; POST is a HTTP method.
  3. The sizeof() method returns the size, in bytes, of the variable in memory rather than the length of the string. It needs to be replaced by .length().
  4. Appending an integer to a string requires a cast.

This is the corrected code:

if (client.connect(server, 80)) {
  Serial.println("Connected to server");
  // Make the HTTP request
  int value = 2.5;  // an arbitrary value for testing
  String content = "{\"JSON_key\": " + String(value) + "}";
  client.println("POST /some/uri HTTP/1.1");
  client.println("Host: things.ubidots.com");
  client.println("Accept: */*");
  client.println("Content-Length: " + String(content.length()));
  client.println("Content-Type: application/json");
  client.println();
  client.println(content);
}
Sign up to request clarification or add additional context in comments.

Comments

1

The code explained by Troy D is right and it's working .I think the error in posting the data to the server is due to this line client.println("Content-Length: " + sizeof(content)); and the correct way is
client.println("Content-Length: " + String(content.length()));

Now coming to this error Connected to server

 [WiFiEsp] Data packet send error (2)
 [WiFiEsp] Failed to write to socket 3
 [WiFiEsp] Disconnecting 3

This is the error of library you can ignore it.

Comments

1

The problem with "Data packet send error (2)", "Failed to write to socket 3" and "Disconnecting 3" is not a problem within the WifiEsp library as far as I can see, believe it's more likely to be within the AT firmware. By default the http headers contain a "Connection: close" parameter which in normal cases should be correct. However with this bug the server will get disconnected before the reply is received on the client side and any response from the server will be identified as garbage data. Using the value "Connection: keep-alive" as a workaround will make it possible to receive the acceptance from the server in a proper way.

I'm running my Arduino + ESP8266-07 against a MVC based Web Api that I created on one of my servers and in the controllers Post-method I use a single string as return value, the value I return if everything is ok is simply one of the strings that WifiEsp keeps track of (It will still include the http status code in the response header that it returns)

public async Task<string> Post([FromBody]JObject payload)
{
  //Code to handle the data received, in my case I log unit ip, macaddress, datetime and sensordata into a db with entity framework
  return "SEND OK";
}

So in your Arduino code try following instead:

String PostHeader = "POST http://" + server + ":" + String(port) + "/api/values HTTP/1.1\r\n";
PostHeader += "Connection: keep-alive\r\n";
PostHeader += "Content-Type: application/json; charset=utf-8\r\n";
PostHeader += "Host: " + server + ":" + String(port) + "\r\n";
PostHeader += "Content-Length: " + String(jsonString.length()) + "\r\n\r\n";
PostHeader += jsonString;

client.connect(server.c_str(), port);
client.println(PostHeader);
client.stop();

In the file debug.h located in the library source code you could alter a define and get more output to your serial console. Open the file and change

#define _ESPLOGLEVEL_ 3

to

#define _ESPLOGLEVEL_ 4

Save the file and recompile/deploy your source code to your Arduino and you will get extensive information about all AT commands the library sends and what the library receives in return.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.