Ошибка HTTP-запроса Arduino, медленное сотовое соединение
Настройка:
Arduino Mega 2560 с Ethernet-щитом Wiznet W5500
Использование маршрутизатора TP-Link TL-MR6400 LTE для подключения к Интернету по сотовой связи в Уганде.
Используя публикацию HTTP со следующим:
client.println("POST /hook HTTP/1.1");
client.print("Host: "); client.println(server);
client.println("Accept: */*");
client.print("Content-Type: text/html;");
client.println("User-Agent: Arduino/1.0");
client.println("Connection: close");
client.print("Content-Length: ");
client.println(PostData.length());
client.println();
client.println(PostData);
где PostData — это String
, а Ethernet2 — используемая библиотека.
Это прекрасно работает из США на тот же сервер AWS или экземпляр https://requestbin.com/.
При тестировании из Уганды с использованием Raspberry Pi и curl все работает нормально.
$ curl -vs -d 'ABCDEFG' -H "User-Agent: Arduino/1.0" -H "Content-Type: text/html" -H "Connection: close" http://<server here>/hook
* Trying <ip here>...
* TCP_NODELAY set
* Connected to <server here> (<ip here>) port 80 (#0)
> POST /tg HTTP/1.1
> Host: <server here>
> Accept: */*
> User-Agent: Arduino/1.0
> Content-Type: text/html
> Connection: close
> Content-Length: 7
>
* upload completely sent off: 7 out of 7 bytes
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: *
< Content-Type: application/json; charset=utf-8
< Date: Tue, 06 Aug 2019 21:06:49 GMT
< x-pd-status: sent to primary
< X-Powered-By: Express
< Content-Length: 16
< Connection: Close
<
* Curl_http_done: called premature == 0
* Closing connection 0
{"success":true}
Я даже попробовал пример HTTP GET из библиотеки Ethernet2,
https://www.arduino.cc/en/Tutorial/WebClientRepeating
В США это работало нормально, но в Уганде я получаю
My IP address: 192.168.1.177
connecting...
connecting...
connecting...
Я увеличил время между запросами здесь до 100 секунд, при этом он прослушивается все время между ними.
Похоже, что client.connect(server, 80)
выполнено успешно, и сообщения client.print
проходят, но сообщение никогда не достигает сервера, поэтому ответа нет. . Мой сервер AWS не получает запрос, и это то же самое для экземпляра requestbin. Это поведение отражено во всех моих тестах Arduino.
Я думал, что интернет-провайдер может блокировать, но RPi может отправить почти такое же сообщение. Думал может таймаут где-то но не могу найти где своими тестами. Я думал, что мое сообщение было слишком длинным, но я уменьшил его размер до 10 символов с теми же результатами.
Пытаемся выяснить, почему HTTP-запрос Arduino не может получить веб-перехватчики из Уганды, и как это исправить, если это возможно. Другой провайдер, более медленное соединение, сотовая связь?
Любая помощь будет оценена по достоинству.
@jmb2341, 👍1
Обсуждение1 ответ
Лучший ответ:
Буферизация и сброс()
Многие библиотеки Arduino страдают от медленной связи, потому что авторы не использовали буферизацию. Чтобы не отправлять каждый небольшой фрагмент данных по соединению с накладными расходами байтов протокола, используйте буферизацию. Данные собираются до тех пор, пока буфер не заполнится, а затем собранные данные отправляются, и буфер готов для следующих байтов. Функции flush() отправляют буфер, даже если он не заполнен, но у вас нет больше данных. («Дилемма» flush() была решена, и в основных классах Arduino метод flush() объявлен в классе Print, который является стандартным интерфейсом Arduino для выходных потоков.)
Моя библиотека StreamLib предлагает класс BufferedPrint, который упаковывает целевой поток и буферизует данные для отправки по целевому потоку. Конечно, не забудьте использовать flush() после печати последних данных.
Длина данных HTTP
В скетчах Arduino принято не отправлять заголовок Content-length с запросами POST. В большинстве случаев это связано с тем, что при отправке заголовков HTTP размер данных неизвестен. Затем веб-сервер не знает, получил ли он все данные, и ждет, пока соединение не будет закрыто или не будет достигнут тайм-аут. Это приводит к долгому времени, пока веб-сервер не отправит ответ на запрос скетча Arduino.
Если данные можно преобразовать в строку в памяти, заполните HTTP-заголовок Content-length.
Если данные, которые должны быть отправлены в ответ или в запросе POST, не помещаются в доступную память, ChunkedPrint из моей StreamLib можно использовать с HTTP-кодированием Transfer-Encoding. А ChunkedPrint является расширением BufferedPrint, поэтому веб-сервер без промедления обрабатывает ваш запрос.
- Отправка HTTP-запроса с Arduino Ethernet на сервер на ПК
- Разбор HTTP с аутентификацией в Arduino + Ethernet Shield
- MQTT на nano с Ethernet Shield не работает
- связь между двумя arduino с помощью ENC28J60?
- Ethernet Shield не работает с TFT-экраном
- Простой запрос GET молча терпит неудачу
- Ограничения подключения ко многим ардуино через Ethernet?
- Modbus TCP вместе с MQTT по тому же ethernet
@jsotola да, я могу подключиться к любому серверу с помощью Raspberry Pi в той же сети, что и Arduino в Уганде (подключенной к тому же маршрутизатору). Я также могу подключиться к обоим серверам с обеими попытками скетчей Arduino из США. Я здесь рассматриваю Raspberry Pi как компьютер., @jmb2341
мои извинения, я не внимательно прочитал ваш пост ... вы уже объяснили, что Pi подключается правильно, @jsotola
попробуйте библиотеку Ethernet, @Juraj
Единственное, что я могу придумать, это попробовать HTTP/1.0 вместо HTTP/1.1. Или, может быть, объединить все
client.print
, чтобы все отправлялось в одном пакете, а не в нескольких (я не мог понять, так ли это)., @Gerbenда, используйте буферизацию https://github.com/jandrassy/StreamLib/blob/master/README.md, @Juraj
@Juraj Ваше решение сработало для меня, если вы опубликуете ответ, я его приму. В качестве фона я пробовал Ethernet lib по сравнению с Ethernet2, я пробовал
HTTP/1.0
противHTTP/1.1
, а также добавлял только операторclient.flush()
после моих запросов. Я попытался использовать только IP-адрес, чтобы избежать DNS-запросов и ускорить процесс, используя другой, более быстрый DNS, например 1.1.1.1 или 8.8.8.8. Наконец, две вещи, которые помогли, заключались в том, чтобы поддерживать соединение открытым, когда это возможно, с помощьюConnection: Keep-Alive
и примера библиотеки [StreamLib](https://github.com/jandrassy/StreamLib) ChunkedPrint., @jmb2341