Вопрос или проблема
Я как-то теряю терпение. У меня есть довольно простой http POST запрос в моем коде, который вроде как работает, но и не совсем. Это полностью зависит от времени (таймаута). Пожалуйста, посмотрите на это:
void sendUpdateToServer(int l_rotations) {
http.begin(server);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
char postQuery[100];
snprintf(postQuery, sizeof(postQuery), "speed=%d&username=DasSaffe", l_rotations);
Serial.println(postQuery);
String httpRequestData = postQuery;
int httpResponseCode = http.POST(httpRequestData);
if (httpResponseCode > 0) {
String response = http.getString(); //Получить ответ на запрос
Serial.println(response); //Напечатать ответ на запрос
} else {
Serial.print("Ошибка при отправке POST: ");
Serial.println(httpResponseCode);
}
http.end();
}
currentMillis = millis();
if (currentMillis - startMillis >= period) {
if(WiFi.status() != WL_CONNECTED) {
initWiFi();
}
Serial.println();
sendUpdateToServer(rotations);
startMillis = currentMillis;
rotations = 1;
}
По сути, мой код выполняется каждые секунду / 5 секунд / 10 секунд. Я регулирую это в глобальной переменной, которую здесь не указал. Но в любом случае.
Если я запускаю этот код каждую секунду, мой вывод выглядит следующим образом:
вызвано с 1 км/ч от DasSaffe
Обновление отправлено на сервер
post-query-string: speed=1&username=DasSaffe
вызвано с 1 км/ч от DasSaffe
Обновление отправлено на сервер
post-query-string: speed=1&username=DasSaffe
вызвано с 1 км/ч от DasSaffe
Обновление отправлено на сервер
post-query-string: speed=1&username=DasSaffe
Это код успешного ответа, так что он работает все время.
Однако, если я запускаю его каждые 5 или 10 секунд, каждая вторая итерация терпит неудачу. Таким образом, полная противоположность того, что я думал произойдет, если я “заполню” сервер.
Обновление отправлено на сервер
post-query-string: speed=1&username=DasSaffe
вызвано с 1 км/ч от DasSaffe (успех)
Обновление отправлено на сервер
post-query-string: speed=1&username=DasSaffe
Ошибка при отправке POST: -2 (неудача)
Обновление отправлено на сервер
post-query-string: speed=1&username=DasSaffe
вызвано с 1 км/ч от DasSaffe (успех)
Обновление отправлено на сервер
post-query-string: speed=1&username=DasSaffe
Ошибка при отправке POST: -2 (неудача)
Это продолжается бесконечно: успех, неудача, успех, неудача, успех, неудача, успех, неудача,…..
К слову:
У меня есть
HTTPClient http;
в качестве глобальной переменной.
Я упускаю что-то очевидное? Почему это работает на более коротких интервалах, но не на более длинных? Согласно документации, ошибка -2
— это HTTPC_ERROR_SEND_HEADER_FAILED
. Я попробовал отправить несколько запросов с помощью POSTMAN на более коротких интервалах, и там это работает. Это также работает, если я запускаю это каждые 5 секунд из POSTMAN. Строка запроса также всегда одинаковая. Я пытался добавлять нуль-терминатор к строке, но это тоже не помогло. Может быть, было бы неплохо держать соединение открытым все время, возможно?
Любая помощь будет приветствоваться
Ответ или решение
Ваш вопрос касается проблемы с HTTP POST-запросами в Arduino, где запросы проходят успешно при коротких интервалах, но каждый второй запрос терпит неудачу при длительных интервалах. Обычно ошибка -2 (HTTPC_ERROR_SEND_HEADER_FAILED) указывает на то, что произошла проблема при отправке заголовков запроса.
Вот несколько возможных причин и решений вашей проблемы:
-
Проблемы с подключением к Wi-Fi:
Поскольку ваш код проверяет статус подключения к Wi-Fi в каждом цикле, убедитесь, что соединение стабильно. Проверьте, не обрывается ли соединение между отправкой запросов. Убедитесь, что функцияinitWiFi()
правильно инициирует подключение и обрабатывает возможные повторные попытки подключения. -
Управление объектом HTTPClient:
Вы объявилиHTTPClient http;
как глобальную переменную, что является правильным подходом, но убедитесь, что вы закрываете соединение с сервером после каждого запроса, используяhttp.end();
. Возможно, вам следует вставить дополнительную паузу между запросами (например, используйтеdelay(1000);
), чтобы дать время для завершения всех процессов. -
Правильное формирование строки запроса:
Вы используетеsnprintf
для формирования строки, но необходимо убедиться, что строка корректно заканчивается. Однако, поскольку вы уже упомянули, что это не решило проблему, это, вероятно, не основная причина. -
Параметры времени ожидания:
Возможно, сервер отбрасывает запросы, если они приходят слишком быстро или слишком медленно. Проверьте настройки таймаута на серверной стороне и убедитесь, что они соответствуют вашим ожиданиям. Возможно, вам стоит увеличить время ожидания на стороне клиента (используяhttp.setTimeout()
). -
Логи на сервере:
Если у вас есть доступ к логам сервера, посмотрите, что там происходит, когда запросы от вашего устройства не проходят. Это может дать полезную информацию о том, что именно происходит на серверной стороне. -
Регулярные перезагрузки:
Если у вас возникли проблемы с переполнением памяти или ресурсами, возможно, стоит добавить регулярные перезагрузки вашего устройства, чтобы сбросить состояние. Это можно сделать с помощьюESP.restart();
в определённой части вашего кода.
Пример улучшенного кода
Вот пример небольших изменений, которые могут помочь решить вашу проблему:
void sendUpdateToServer(int l_rotations) {
http.begin(server);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
char postQuery[100];
snprintf(postQuery, sizeof(postQuery), "speed=%d&username=DasSaffe", l_rotations);
Serial.println(postQuery);
String httpRequestData = postQuery;
int httpResponseCode = http.POST(httpRequestData);
if (httpResponseCode > 0) {
String response = http.getString(); // Получите ответ на запрос
Serial.println(response); // Печать ответа
} else {
Serial.print("Ошибка отправки POST: ");
Serial.println(httpResponseCode);
}
http.end();
}
void loop() {
currentMillis = millis();
if (currentMillis - startMillis >= period) {
if (WiFi.status() != WL_CONNECTED) {
initWiFi();
// Попробуйте перезагрузить через несколько секунд,
// если не удастся подключиться
}
Serial.println();
sendUpdateToServer(rotations);
startMillis = currentMillis;
rotations = 1;
// Имейте небольшую паузу
delay(1000); // например, подождите 1 секунду перед следующим запросом
}
}
Используйте этот улучшенный подход и следите за выходными данными для дальнейшей диагностики. Если проблема сохранится, рекомендуется углубиться в логирование на сервере и настройки сети.