Skip to content

Commit 67cf3cd

Browse files
authored
Merge pull request #65 from andreagilardoni/ping
Add ping feature
2 parents e80ed99 + 94fcd9c commit 67cf3cd

File tree

4 files changed

+162
-1
lines changed

4 files changed

+162
-1
lines changed

UNOR4USBBridge/cmds_esp_generic.h

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define CMDS_ESP_GENERIC_H
33

44
#include "at_handler.h"
5+
#include "ping.h"
56

67
extern "C" {
78
#include "esp32-hal-tinyusb.h"
@@ -360,7 +361,7 @@ void CAtHandler::add_cmds_esp_generic() {
360361
return chAT::CommandStatus::ERROR;
361362
}
362363
};
363-
364+
364365
/* ....................................................................... */
365366
command_table[_GETTIME] = [this](auto & srv, auto & parser) {
366367
/* ....................................................................... */
@@ -386,6 +387,52 @@ void CAtHandler::add_cmds_esp_generic() {
386387
return chAT::CommandStatus::ERROR;
387388
}
388389
};
390+
391+
/* ....................................................................... */
392+
command_table[_PING] = [this](auto & srv, auto & parser) {
393+
/* ....................................................................... */
394+
switch (parser.cmd_mode) {
395+
case chAT::CommandMode::Write: {
396+
if (parser.args.size() != 4) {
397+
return chAT::CommandStatus::ERROR;
398+
}
399+
400+
// get IP
401+
auto &target = parser.args[1];
402+
if (target.empty()) {
403+
return chAT::CommandStatus::ERROR;
404+
}
405+
406+
// get ttl
407+
auto &ttl = parser.args[2];
408+
if (ttl.empty()) {
409+
return chAT::CommandStatus::ERROR;
410+
}
411+
412+
// get count
413+
auto &cnt = parser.args[3];
414+
if (cnt.empty()) {
415+
return chAT::CommandStatus::ERROR;
416+
}
417+
418+
auto ping_res = execute_ping(target.c_str(), atoi(ttl.c_str()), atoi(cnt.c_str()));
419+
char rsl[8];
420+
if (ping_res.status == ping_status::SUCCESS) {
421+
sprintf(rsl,"%.0f", ping_res.averagertt);
422+
} else {
423+
sprintf(rsl,"%d", ping_res.status);
424+
}
425+
426+
srv.write_response_prompt();
427+
srv.write_str((const char *) rsl);
428+
srv.write_line_end();
429+
return chAT::CommandStatus::OK;
430+
431+
}
432+
default:
433+
return chAT::CommandStatus::ERROR;
434+
}
435+
};
389436
}
390437

391438
#endif

UNOR4USBBridge/commands.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ enum file_op {
105105
#define _UDPREMOTEPORT "+UDPREMOTEPORT"
106106
#define _UDPSTOP "+UDPSTOP"
107107

108+
#define _PING "+PING"
109+
108110
#define _FWVERSION "+FWVERSION"
109111
#define _FWVERSION_U32 "+FWVERSION_U32"
110112

UNOR4USBBridge/ping.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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+
}

UNOR4USBBridge/ping.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
5+
enum class ping_status: int {
6+
ERROR = -4,
7+
DNS_RESOLUTION_ERROR = -3,
8+
TIMEOUT = -2,
9+
RUNNING = 0,
10+
SUCCESS = 1
11+
};
12+
13+
struct ping_statistics {
14+
uint8_t success_count;
15+
uint8_t timedout_count;
16+
float averagertt; // measured in ms
17+
volatile ping_status status;
18+
};
19+
20+
ping_statistics execute_ping(const char* address, uint8_t ttl, uint8_t count);

0 commit comments

Comments
 (0)