#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-квитирования.