|
| 1 | +#include "ping.h" |
| 2 | +#include <string.h> |
| 3 | +#include <Arduino.h> |
| 4 | +#include <lwip/inet.h> |
| 5 | +#include <lwip/ip_addr.h> |
| 6 | +#include <lwip/netdb.h> |
| 7 | +#include "ping/ping_sock.h" |
| 8 | + |
| 9 | +// we are assuming that ping is a blocking call that returns the results of a ping session |
| 10 | +// async operations are not taken into account as of now |
| 11 | +// one ping session can be performed |
| 12 | + |
| 13 | +static ping_statistics _stats; |
| 14 | +static esp_ping_handle_t esp_ping_handle = nullptr; |
| 15 | + |
| 16 | +static void ping_success(esp_ping_handle_t hdl, void *args) { |
| 17 | + uint32_t elapsed_time; |
| 18 | + esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time)); |
| 19 | + // streaming average on rtt |
| 20 | + _stats.averagertt = _stats.averagertt + ((elapsed_time-_stats.averagertt)/++_stats.success_count); |
| 21 | +} |
| 22 | + |
| 23 | +static void ping_timeout(esp_ping_handle_t hdl, void *args) { |
| 24 | + _stats.timedout_count++; |
| 25 | +} |
| 26 | + |
| 27 | +static void ping_end(esp_ping_handle_t hdl, void *args) { |
| 28 | + esp_ping_stop(hdl); |
| 29 | + esp_ping_delete_session(hdl); |
| 30 | + if(_stats.success_count == 0) { |
| 31 | + // all ping request have timed out |
| 32 | + _stats.status = ping_status::TIMEOUT; |
| 33 | + } else { |
| 34 | + // at least one ping as succeded and we can return rtt value |
| 35 | + _stats.status = ping_status::SUCCESS; |
| 36 | + } |
| 37 | +} |
| 38 | + |
| 39 | +ping_statistics execute_ping(const char* address, uint8_t ttl, uint8_t count) { |
| 40 | + |
| 41 | + ip_addr_t target_addr; |
| 42 | + struct addrinfo hint; |
| 43 | + struct addrinfo *res = NULL; |
| 44 | + memset(&hint, 0, sizeof(hint)); |
| 45 | + memset(&target_addr, 0, sizeof(target_addr)); |
| 46 | + memset(&_stats, 0, sizeof(_stats)); |
| 47 | + |
| 48 | + if(getaddrinfo(address, NULL, &hint, &res) != 0) { |
| 49 | + _stats.status = ping_status::DNS_RESOLUTION_ERROR; |
| 50 | + return _stats; |
| 51 | + } |
| 52 | + |
| 53 | + struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr; |
| 54 | + inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4); |
| 55 | + freeaddrinfo(res); |
| 56 | + |
| 57 | + esp_ping_config_t ping_config = ESP_PING_DEFAULT_CONFIG(); |
| 58 | + ping_config.target_addr = target_addr; // target IP address |
| 59 | + ping_config.ttl = ttl; |
| 60 | + |
| 61 | + // for simplification we are not pinging indefinetly |
| 62 | + ping_config.count = count > 0 ? count : 1; |
| 63 | + |
| 64 | + /* set callback functions */ |
| 65 | + esp_ping_callbacks_t cbs; |
| 66 | + cbs.on_ping_success = ping_success; |
| 67 | + cbs.on_ping_timeout = ping_timeout; |
| 68 | + cbs.on_ping_end = ping_end; |
| 69 | + cbs.cb_args = NULL; |
| 70 | + |
| 71 | + if(esp_ping_new_session(&ping_config, &cbs, &esp_ping_handle) != ESP_OK) { |
| 72 | + _stats.status = ping_status::ERROR; |
| 73 | + return _stats; |
| 74 | + } |
| 75 | + |
| 76 | + if(esp_ping_start(esp_ping_handle) != ESP_OK) { |
| 77 | + _stats.status = ping_status::ERROR; |
| 78 | + esp_ping_delete_session(esp_ping_handle); |
| 79 | + return _stats; |
| 80 | + } |
| 81 | + |
| 82 | + _stats.status = ping_status::RUNNING; |
| 83 | + |
| 84 | + // wait for the end of ping session |
| 85 | + while(_stats.status == ping_status::RUNNING) { |
| 86 | + delay(10); |
| 87 | + } |
| 88 | + |
| 89 | + // session is deleted inside ping_end() callback |
| 90 | + |
| 91 | + return _stats; |
| 92 | +} |
0 commit comments