HTTP-запрос на Arduino не удается на каждой второй итерации

Вопрос или проблема

Я как-то теряю терпение. У меня есть довольно простой 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) указывает на то, что произошла проблема при отправке заголовков запроса.

Вот несколько возможных причин и решений вашей проблемы:

  1. Проблемы с подключением к Wi-Fi:
    Поскольку ваш код проверяет статус подключения к Wi-Fi в каждом цикле, убедитесь, что соединение стабильно. Проверьте, не обрывается ли соединение между отправкой запросов. Убедитесь, что функция initWiFi() правильно инициирует подключение и обрабатывает возможные повторные попытки подключения.

  2. Управление объектом HTTPClient:
    Вы объявили HTTPClient http; как глобальную переменную, что является правильным подходом, но убедитесь, что вы закрываете соединение с сервером после каждого запроса, используя http.end();. Возможно, вам следует вставить дополнительную паузу между запросами (например, используйте delay(1000);), чтобы дать время для завершения всех процессов.

  3. Правильное формирование строки запроса:
    Вы используете snprintf для формирования строки, но необходимо убедиться, что строка корректно заканчивается. Однако, поскольку вы уже упомянули, что это не решило проблему, это, вероятно, не основная причина.

  4. Параметры времени ожидания:
    Возможно, сервер отбрасывает запросы, если они приходят слишком быстро или слишком медленно. Проверьте настройки таймаута на серверной стороне и убедитесь, что они соответствуют вашим ожиданиям. Возможно, вам стоит увеличить время ожидания на стороне клиента (используя http.setTimeout()).

  5. Логи на сервере:
    Если у вас есть доступ к логам сервера, посмотрите, что там происходит, когда запросы от вашего устройства не проходят. Это может дать полезную информацию о том, что именно происходит на серверной стороне.

  6. Регулярные перезагрузки:
    Если у вас возникли проблемы с переполнением памяти или ресурсами, возможно, стоит добавить регулярные перезагрузки вашего устройства, чтобы сбросить состояние. Это можно сделать с помощью 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 секунду перед следующим запросом
    } 
}

Используйте этот улучшенный подход и следите за выходными данными для дальнейшей диагностики. Если проблема сохранится, рекомендуется углубиться в логирование на сервере и настройки сети.

Оцените материал
Добавить комментарий

Капча загружается...