espressif: fix returning ping time and pinging too often

This commit is contained in:
Dan Halbert 2024-06-18 14:13:27 -04:00
parent ecb399a958
commit 17c4e9c864
2 changed files with 42 additions and 14 deletions

View file

@ -532,32 +532,59 @@ void common_hal_wifi_radio_set_ipv4_address_ap(wifi_radio_obj_t *self, mp_obj_t
common_hal_wifi_radio_start_dhcp_server(self); // restart access point DHCP
}
static void ping_success_cb(esp_ping_handle_t hdl, void *args) {
wifi_radio_obj_t *self = (wifi_radio_obj_t *)args;
esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &self->ping_elapsed_time, sizeof(self->ping_elapsed_time));
}
mp_int_t common_hal_wifi_radio_ping(wifi_radio_obj_t *self, mp_obj_t ip_address, mp_float_t timeout) {
esp_ping_config_t ping_config = ESP_PING_DEFAULT_CONFIG();
ipaddress_ipaddress_to_esp_idf(ip_address, &ping_config.target_addr);
ping_config.count = 1;
// We must fetch ping information using the callback mechanism, because the session storage is freed when
// the ping session is done, even before esp_ping_delete_session().
esp_ping_callbacks_t ping_callbacks = {
.on_ping_success = ping_success_cb,
.cb_args = (void *)self,
};
size_t timeout_ms = timeout * 1000;
// ESP-IDF creates a task to do the ping session. It shuts down when done, but only after a one second delay.
// Calling common_hal_wifi_radio_ping() too fast will cause resource exhaustion.
esp_ping_handle_t ping;
CHECK_ESP_RESULT(esp_ping_new_session(&ping_config, NULL, &ping));
esp_err_t ret;
for (size_t tries = 1; tries <= 5; tries++) {
ret = esp_ping_new_session(&ping_config, &ping_callbacks, &ping);
if (ret == ESP_OK) {
break;
}
// Wait for old task to go away and then try again.
// Empirical testing shows we have to wait at least two seconds, despite the task
// having a one-second timeout.
common_hal_time_delay_ms(2000);
if (mp_hal_is_interrupted()) {
return -1;
}
}
CHECK_ESP_RESULT(ret);
esp_ping_start(ping);
uint32_t received = 0;
uint32_t total_time_ms = 0;
// Use all ones as a flag that the elapsed time was not set (ping failed or timed out).
self->ping_elapsed_time = (uint32_t)(-1);
uint32_t start_time = common_hal_time_monotonic_ms();
while (received == 0 && (common_hal_time_monotonic_ms() - start_time < timeout_ms) && !mp_hal_is_interrupted()) {
while ((self->ping_elapsed_time == (uint32_t)(-1)) &&
(common_hal_time_monotonic_ms() - start_time < timeout_ms) &&
!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
esp_ping_get_profile(ping, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms));
esp_ping_get_profile(ping, ESP_PING_PROF_REPLY, &received, sizeof(received));
}
uint32_t elapsed_time = 0xffffffff;
if (received > 0) {
esp_ping_get_profile(ping, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
}
esp_ping_stop(ping);
esp_ping_delete_session(ping);
return elapsed_time;
return (mp_int_t)self->ping_elapsed_time;
}
void common_hal_wifi_radio_gc_collect(wifi_radio_obj_t *self) {

View file

@ -32,15 +32,16 @@ typedef struct {
esp_netif_ip_info_t ip_info;
esp_netif_dns_info_t dns_info;
esp_netif_t *netif;
uint32_t ping_elapsed_time;
wifi_config_t ap_config;
esp_netif_ip_info_t ap_ip_info;
esp_netif_t *ap_netif;
bool started;
bool ap_mode;
bool sta_mode;
uint8_t retries_left;
uint8_t starting_retries;
uint8_t last_disconnect_reason;
wifi_config_t ap_config;
esp_netif_ip_info_t ap_ip_info;
esp_netif_t *ap_netif;
} wifi_radio_obj_t;
extern void common_hal_wifi_radio_gc_collect(wifi_radio_obj_t *self);