Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: Troy DОтветов: 3

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

resthttp-postarduinoesp8266

Ответы

Ответ 1 · рейтинг 2 · Troy D

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

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

Ответ 2 · рейтинг 1 · amardeep verma

Код, объясненный Троем Д., верен и работает. Я думаю, что ошибка при отправке данных на сервер связана с этой строкой 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

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

Ответ 3 · рейтинг 1 · Lennart Jansson

Проблема с "Ошибка отправки пакета данных (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-командах, которые отправляет библиотека, и о том, что библиотека получает взамен.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы