POST-запрос на Arduino с ESP8266 с использованием библиотеки WifiESP

Я пытаюсь выполнить запрос RESTful POST, используя библиотеку WifiESP (https://github.com/bportaluri/WiFiEsp). Я могу успешно выполнить запрос с помощью curl, но постоянно получаю сообщение об ошибке с помощью Arduino и ESP. Я подозреваю, что проблема связана с ручным форматированием POST-запроса, который требует библиотека, но я не вижу ничего плохого. Вот мой продезинфицированный код:

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

Ошибка, которую я получаю (через последовательный монитор), такова:

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

Мои успешные запросы на скручивание выглядят так:

curl -X POST -H "Content-Type: application/json" -d 'Some JSON' http://things.ubidots.com/some/uri

person Troy D    schedule 28.12.2016    source источник
comment
Пара вещей. Я заметил, что библиотека добавляет как \r, так и \n, а не только \n, когда вы используете функцию println. Попробуйте выполнить \ns вручную и использовать функцию print. если это не сработает, распечатайте все это в Serial и сравните его с трассировкой wireshark вашего поста curl.   -  person leetibbett    schedule 28.12.2016
comment
@leetibbett Спасибо за ответ. \r\n оказалось, что это не проблема, но это заставило меня посмотреть документацию по протоколу HTTP, которая помогла мне найти несколько других проблем.   -  person Troy D    schedule 29.12.2016


Ответы (3)


После некоторых экспериментов вот решение нескольких проблем.

  1. Объект JSON был неправильно отформатирован. Одинарные кавычки не принимались, поэтому мне нужно было избежать двойных кавычек.
  2. Хост не нуждается в "http://" в запросе POST; POST — это HTTP-метод.
  3. Метод sizeof() возвращает размер переменной в памяти в байтах, а не длину строки. Его нужно заменить на .length().
  4. Добавление целого числа к строке требует приведения.

Это исправленный код:

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);
}
person Troy D    schedule 28.12.2016

Код, объясненный Троем Д., верен и работает. Я думаю, что ошибка при отправке данных на сервер связана с этой строкой client.println("Content-Length: " + sizeof(content)) ; и правильный способ:
client.println("Content-Length: " + String(content.length()));

Теперь приходит к этой ошибке Подключено к серверу

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

Это ошибка библиотеки, которую вы можете игнорировать.

person amardeep verma    schedule 06.11.2017

Проблема с «Ошибка отправки пакета данных (2)», «Не удалось записать в сокет 3» и «Отключение 3» не является проблемой в библиотеке WifiEsp, насколько я вижу, скорее всего, в AT прошивка. По умолчанию заголовки http содержат параметр «Соединение: закрыть», который в обычных случаях должен быть правильным. Однако из-за этой ошибки сервер будет отключен до того, как ответ будет получен на стороне клиента, и любой ответ от сервера будет идентифицирован как мусорные данные. Использование значения «Connection: keep-alive» в качестве обходного пути позволит получить подтверждение от сервера должным образом.

Я запускаю свой Arduino + ESP8266-07 против веб-API на основе MVC, который я создал на одном из своих серверов, и в методе пост-контроллеров я использую одну строку в качестве возвращаемого значения, значение, которое я возвращаю, если все в порядке, просто одна из строк, которые отслеживает WifiEsp (он по-прежнему будет включать код состояния http в заголовок ответа, который он возвращает)

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";
}

Поэтому в коде Arduino попробуйте следующее:

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

В файле debug.h, расположенном в исходном коде библиотеки, вы можете изменить определение и получить больше вывода на вашу последовательную консоль. Откройте файл и измените

#define _ESPLOGLEVEL_ 3

to

#define _ESPLOGLEVEL_ 4

Сохраните файл и перекомпилируйте/разверните исходный код на Arduino, и вы получите исчерпывающую информацию обо всех AT-командах, которые отправляет библиотека, и о том, что библиотека получает взамен.

person Lennart Jansson    schedule 18.07.2018