Как я могу получить время, затраченное на http-запрос ESP32

#c #http #embedded #esp32

Вопрос:

В настоящее время я пытаюсь получить время, необходимое для выполнения HTTP-запроса(загрузка 1 файла) с помощью ESP32, но у API нет для этого возможности. Я могу установить тайм-аут, но у меня нет истинного времени, необходимого для его выполнения.

Я попытался получить разницу во времени после и до выполнения функции esp_err_t err = esp_http_client_perform(client); как таковой :

  struct timeval start, end;
 esp_http_client_config_t config = {
    .url = DOWNLOAD_FILE_URL,
    .event_handler = _http_event_handler,
 };
 esp_http_client_handle_t client = esp_http_client_init(amp;config);
 gettimeofday(amp;start, NULL);
 esp_err_t err = esp_http_client_perform(client);
 gettimeofday(amp;end, NULL);
 int64_t time_us = (((int64_t)end.tv_sec * 1000000L   (int64_t)end.tv_usec)-((int64_t)start.tv_sec * 1000000L   (int64_t)start.tv_usec));
 

Но возвращаемое значение кажется слишком большим для того, что я делаю по сравнению с тем, что я делаю (загрузка небольшого файла, и я сделал это с помощью завитка на моей машине Linux, это заняло всего 20 мс) :

 Time : 1305909 uS
 

Я предполагаю esp_http_client_perform(client) , что функция, вероятно, выполняет много других задач, кроме простой загрузки файла, и именно поэтому я получаю не только время, необходимое для загрузки файла.

Вы хоть представляете, что я могу сделать, чтобы получить только время, необходимое для загрузки файла?

Большое вам спасибо за вашу помощь.

Комментарии:

1. Может быть, просто запустите команду без ввода данных и верните это время. Затем вычтите время без полезной нагрузки из времени, которое вы получаете. Возможно, не очень точно, но лучше, чем то, что у вас есть в настоящее время.

2. Вы никогда не устанавливали end , так что у вас есть UB. Заменить download_end = clock(); на gettimeoday(amp;end,NULL);

3. @CraigEstey Говорит, что вы правы, но это просто пропущенная копипаста. У меня есть gettimeoday(amp;end,NULL); Я изменяю его сейчас. В любом случае, все еще не подходящее время…

4. @mechanical_meat Я действительно могу это попробовать. может быть, это даст что-то более точное.

Ответ №1:

Привет, приятель, я предлагаю использовать протокол сетевого времени. Это стандартный интернет-протокол (IP) для синхронизации компьютерных часов с некоторой ссылкой по сети. Протокол может использоваться для синхронизации всех сетевых устройств с Универсальным координированным временем (UTC). NTP устанавливает часы компьютеров в UTC, любое смещение местного часового пояса или смещение времени для экономии дневного света применяется клиентом. Таким образом, клиенты могут синхронизироваться с серверами независимо от местоположения и разницы во времени. Сервер использует протокол пользовательских дейтаграмм (UDP) на порту 123. Затем клиент передает пакет запроса на сервер NTP. В ответ на этот запрос сервер NTP отправляет пакет с отметкой времени.

Пожалуйста, попробуйте этот код:

 #include "NTPClient.h"
#include "ESP8266WiFi.h"
#include "WiFiUdp.h"

const char *ssid = "***********";
const char *password = "***********";

const long utcOffsetInSeconds = 0;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);

void setup(){
Serial.begin(115200);

WiFi.begin(ssid, password);

while ( WiFi.status() != WL_CONNECTED ) {
delay ( 500 );
Serial.print ( "." );
}

timeClient.begin();
}

void loop() {
timeClient.update();

Serial.print(daysOfTheWeek[timeClient.getDay()]);
Serial.print(", ");
Serial.print(timeClient.getHours());
Serial.print(":");
Serial.print(timeClient.getMinutes());
Serial.print(":");
Serial.println(timeClient.getSeconds());
//Serial.println(timeClient.getFormattedTime());

delay(1000);
}
 

Примечание: строка:

 const long utcOffsetInSeconds = 0;
 

устанавливает время в формате UTC (в основном гринвичское время без смещения времени для экономии света), если хотите, установите свое собственное смещение в секундах от гринвичского времени.
Отличная статья здесь: https://www.instructables.com/Getting-Time-From-Internet-Using-ESP8266-NTP-Clock/

Если вы получите два показания и определите разницу между ними, у вас будет продолжительность операции и (что очень важно, поскольку мы говорим о сетевых операциях) указание времени для последующего анализа.

Я надеюсь, что это поможет всем самым лучшим образом

Комментарии:

1. NTP предназначен для получения времени настенных часов и на самом деле не имеет отношения к измерению продолжительности операции.

2. Хороший момент, однако, если вы получите два показания и сделаете разницу между ними, у вас будет продолжительность операции и (что очень важно, поскольку мы говорим о сетевых операциях) временная привязка для последующего анализа. Всего наилучшего, Приятель.

3. Ответ был обновлен, спасибо за драгоценный комментарий. Всего наилучшего, Приятель.

Ответ №2:

Во-первых, вызов gettimeofday() и вычисление разницы-это, ИМХО, слишком много усилий для такой простой задачи. Проще позвонить esp_timer_get_time() , чтобы получить микросекунды с момента загрузки и рассчитать продолжительность на основе этого.

Во-вторых, пользовательский обработчик событий, который вы предоставили своему HTTP-клиенту ( _http_event_handler ), вызывается для каждого соответствующего события при загрузке HTTP, поэтому используйте его, чтобы узнать, сколько времени занимает каждый шаг. Я преобразовал в миллисекунды, потому что это кажется правильной шкалой единиц измерения для измерения событий загрузки.

 uint64_t start_time;
esp_http_client_config_t config = {
    .url = DOWNLOAD_FILE_URL,
    .event_handler = _http_event_handler,
    .user_data = amp;start_time,
};
esp_http_client_handle_t client = esp_http_client_init(amp;config);
start_time = esp_timer_get_time();
esp_err_t err = esp_http_client_perform(client);
ESP_LOGI(TAG, "Total time %u ms", (uint32_t)((esp_timer_get_time() - start_time) / 1000));
...

esp_err_t _http_event_handle(esp_http_client_event_t *evt) {
    uint32_t duration_ms = (uint32_t) ((esp_timer_get_time() - *(uint64_t*)(evt->user_data)) / 1000);
    switch(evt->event_id) {
        case HTTP_EVENT_ERROR:
            ESP_LOGI(TAG, "HTTP_EVENT_ERROR %u ms", duration_ms);
            break;
        case HTTP_EVENT_ON_CONNECTED:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED %u ms", duration_ms);
            break;
        case HTTP_EVENT_HEADER_SENT:
            ESP_LOGI(TAG, "HTTP_EVENT_HEADER_SENT %u ms", duration_ms);
            break;
        case HTTP_EVENT_ON_HEADER:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER %u ms", duration_ms);
            printf("%.*s", evt->data_len, (char*)evt->data);
            break;
        case HTTP_EVENT_ON_DATA:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d %u ms", evt->data_len, duration_ms);
            break;
        case HTTP_EVENT_ON_FINISH:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH %u ms", duration_ms);
            break;
        case HTTP_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED %u ms", duration_ms);
            break;
    }
    return ESP_OK;
}
 

Наконец, обратите внимание, что если вы загружаете HTTPS, то бедному маленькому ESP32 потребуется значительное время для выполнения криптографических вычислений TLS-квитирования.