From 34471df4df81c9f65384a486d3f1eae499aa7a41 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Wed, 8 Jan 2025 16:07:55 +0100 Subject: [PATCH] add ping command --- libraries/GSM/src/GSM.h | 3 - libraries/SocketWrapper/src/SocketHelpers.cpp | 85 +++++++++++++ libraries/SocketWrapper/src/SocketHelpers.h | 10 ++ libraries/WiFi/examples/WiFiPing/WiFiPing.ino | 116 ++++++++++++++++++ .../WiFi/examples/WiFiPing/arduino_secrets.h | 2 + mbed-os-to-arduino | 2 +- variants/EDGE_CONTROL/conf/mbed_app.json | 5 +- .../GENERIC_STM32H747_M4/conf/mbed_app.json | 1 + variants/GIGA/conf/mbed_app.json | 1 + .../NANO_RP2040_CONNECT/conf/mbed_app.json | 3 +- variants/NICLA_VISION/conf/mbed_app.json | 1 + variants/OPTA/conf/mbed_app.json | 1 + variants/PORTENTA_H7_M7/conf/mbed_app.json | 1 + 13 files changed, 224 insertions(+), 7 deletions(-) create mode 100644 libraries/WiFi/examples/WiFiPing/WiFiPing.ino create mode 100644 libraries/WiFi/examples/WiFiPing/arduino_secrets.h diff --git a/libraries/GSM/src/GSM.h b/libraries/GSM/src/GSM.h index cf3652c26..0b724f284 100644 --- a/libraries/GSM/src/GSM.h +++ b/libraries/GSM/src/GSM.h @@ -108,9 +108,6 @@ class GSMClass : public MbedSocketClass { void trace(Stream& stream); void setTraceLevel(int trace_level, bool timestamp = false, bool at_trace = false); #endif - int ping(const char* hostname, uint8_t ttl = 128); - int ping(const String& hostname, uint8_t ttl = 128); - int ping(IPAddress host, uint8_t ttl = 128); bool isConnected(); friend class GSMClient; diff --git a/libraries/SocketWrapper/src/SocketHelpers.cpp b/libraries/SocketWrapper/src/SocketHelpers.cpp index ada31434f..a4f92167a 100644 --- a/libraries/SocketWrapper/src/SocketHelpers.cpp +++ b/libraries/SocketWrapper/src/SocketHelpers.cpp @@ -1,4 +1,8 @@ #include "SocketHelpers.h" +#include "lwip/prot/icmp.h" +#include "lwip/inet_chksum.h" +#include "lwip/prot/ip4.h" +#include uint8_t* arduino::MbedSocketClass::macAddress(uint8_t* mac) { const char* mac_str = getNetwork()->get_mac_address(); @@ -65,6 +69,24 @@ arduino::IPAddress arduino::MbedSocketClass::dnsIP(int n) { return ipAddressFromSocketAddress(ip); } +int arduino::MbedSocketClass::ping(const char *hostname, uint8_t ttl) +{ + SocketAddress socketAddress; + gethostbyname(getNetwork(),hostname, &socketAddress); + return ping(socketAddress, ttl); +} + +int arduino::MbedSocketClass::ping(const String &hostname, uint8_t ttl) +{ + return ping(hostname.c_str(), ttl); +} + +int arduino::MbedSocketClass::ping(IPAddress host, uint8_t ttl) +{ + SocketAddress socketAddress = socketAddressFromIpAddress(host, 0); + return ping(socketAddress, ttl); +} + void arduino::MbedSocketClass::config(arduino::IPAddress local_ip) { IPAddress dns = local_ip; dns[3] = 1; @@ -110,6 +132,69 @@ void arduino::MbedSocketClass::setDNS(IPAddress dns_server1, IPAddress dns_serve _dnsServer2 = SocketAddress(convertedDNSServer2); } +int arduino::MbedSocketClass::ping(SocketAddress &socketAddress, uint8_t ttl) +{ + uint32_t timeout = 5000; + ICMPSocket s; + s.set_timeout(timeout); + s.open(getNetwork()); + + struct __attribute__((__packed__)) { + struct icmp_echo_hdr header; + uint8_t data[32]; + } request; + + ICMPH_TYPE_SET(&request.header, ICMP_ECHO); + ICMPH_CODE_SET(&request.header, 0); + request.header.chksum = 0; + request.header.id = 0xAFAF; + request.header.seqno = random(0xffff); + + for (size_t i = 0; i < sizeof(request.data); i++) { + request.data[i] = i; + } + + request.header.chksum = inet_chksum(&request, sizeof(request)); + unsigned long recvTime = 0; + unsigned long sendTime = millis(); + + int res = s.sendto(socketAddress,&request, sizeof(request)); + if(res <= 0){ + return -1; + } + + uint32_t startRec = millis(); + do { + struct __attribute__((__packed__)) { + struct ip_hdr ipHeader; + struct icmp_echo_hdr header; + } response; + + int rxSize = s.recvfrom(&socketAddress, &response, sizeof(response)); + if (rxSize < 0) { + // time out + break; + } + + if (rxSize < sizeof(response)) { + // too short + continue; + } + + if ((response.header.id == request.header.id) && (response.header.seqno == request.header.seqno)) { + recvTime = millis(); + } + } while (recvTime == 0 && (millis() - startRec) < timeout); + + s.close(); + + if (recvTime == 0) { + return -1; + } else { + return (recvTime - sendTime); + } +} + arduino::IPAddress arduino::MbedSocketClass::ipAddressFromSocketAddress(SocketAddress socketAddress) { nsapi_addr_t address = socketAddress.get_addr(); return IPAddress(address.bytes[0], address.bytes[1], address.bytes[2], address.bytes[3]); diff --git a/libraries/SocketWrapper/src/SocketHelpers.h b/libraries/SocketWrapper/src/SocketHelpers.h index c31988fde..e3778fea7 100644 --- a/libraries/SocketWrapper/src/SocketHelpers.h +++ b/libraries/SocketWrapper/src/SocketHelpers.h @@ -108,6 +108,15 @@ class MbedSocketClass { virtual NetworkInterface* getNetwork() = 0; + /* + * Ping the specified target. + * + * return: RTT in milliseconds or -1 on error + */ + int ping(const char* hostname, uint8_t ttl = 128); + int ping(const String &hostname, uint8_t ttl = 128); + int ping(IPAddress host, uint8_t ttl = 128); + /* * Download a file from an HTTP endpoint and save it in the provided `target` location on the fs * The parameter cbk can be used to perform actions on the buffer before saving on the fs @@ -152,6 +161,7 @@ class MbedSocketClass { void body_callback(const char* data, uint32_t data_len); + int ping(SocketAddress &socketAddress, uint8_t ttl); static arduino::IPAddress ipAddressFromSocketAddress(SocketAddress socketAddress); static SocketAddress socketAddressFromIpAddress(arduino::IPAddress ip, uint16_t port); static nsapi_error_t gethostbyname(NetworkInterface* interface, const char* aHostname, SocketAddress* socketAddress); diff --git a/libraries/WiFi/examples/WiFiPing/WiFiPing.ino b/libraries/WiFi/examples/WiFiPing/WiFiPing.ino new file mode 100644 index 000000000..66cb4acdc --- /dev/null +++ b/libraries/WiFi/examples/WiFiPing/WiFiPing.ino @@ -0,0 +1,116 @@ +/* + Web ICMP Ping + + This sketch pings a device based on the IP address or the hostname + using the WiFi module. + + This example is written for a network using WPA encryption. For + WEP or WPA, change the WiFi.begin() call accordingly. + + created 14 February 2024 + by paulvha + modified 8 Jenuary 2025 + by fabik111 + + */ + +#include +#include "arduino_secrets.h" + +///////please enter your sensitive data in the Secret tab/arduino_secrets.h +char ssid[] = SECRET_SSID; // your network SSID (name) +char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) + +int status = WL_IDLE_STATUS; + +/* -------------------------------------------------------------------------- */ +void setup() { +/* -------------------------------------------------------------------------- */ + //Initialize serial and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // check for the WiFi module: + if (WiFi.status() == WL_NO_MODULE) { + Serial.println("Communication with WiFi module failed."); + // don't continue + while (true); + } + + // attempt to connect to WiFi network: + while (status != WL_CONNECTED) { + Serial.print("Attempting to connect to SSID: "); + Serial.println(ssid); + // Connect to WPA/WPA2 network. Change this line if using open or WEP network: + status = WiFi.begin(ssid, pass); + + // wait 3 seconds for connection: + delay(3000); + } + + printWifiStatus(); +} + +/* -------------------------------------------------------------------------- */ +void loop() { +/* -------------------------------------------------------------------------- */ + + // Ping IP + const IPAddress remote_ip(140,82,121,4); + Serial.print("Trying to ping github.com on IP: "); + Serial.println(remote_ip); + + // using default ping count of 1 + int res = WiFi.ping(remote_ip); + + if (res > 0) { + Serial.print("Ping response time: "); + Serial.print(res); + Serial.println(" ms"); + } + else { + Serial.println("Timeout on IP!"); + Serial.println("Make sure your WiFi firmware version is at least 0.5.0"); + } + + // Ping Host + const char* remote_host = "www.google.com"; + Serial.print("Trying to ping host: "); + Serial.println(remote_host); + + int res1 = WiFi.ping(remote_host); + + if (res1 > 0) { + Serial.print("Ping average response time: "); + Serial.print(res1); + Serial.println(" ms"); + } + else { + Serial.println("Timeout on host!"); + Serial.println("Make sure your WiFi firmware version is at least 0.5.0"); + } + + Serial.println(); + delay(5000); +} + +/* -------------------------------------------------------------------------- */ +void printWifiStatus() { +/* -------------------------------------------------------------------------- */ + // print the SSID of the network you're attached to: + Serial.print("SSID: "); + Serial.println(WiFi.SSID()); + + // print your board's IP address: + IPAddress ip = WiFi.localIP(); + Serial.print("IP Address: "); + Serial.println(ip); + + // print the received signal strength: + long rssi = WiFi.RSSI(); + Serial.print("signal strength (RSSI):"); + Serial.print(rssi); + Serial.println(" dBm"); +} diff --git a/libraries/WiFi/examples/WiFiPing/arduino_secrets.h b/libraries/WiFi/examples/WiFiPing/arduino_secrets.h new file mode 100644 index 000000000..0c9fdd556 --- /dev/null +++ b/libraries/WiFi/examples/WiFiPing/arduino_secrets.h @@ -0,0 +1,2 @@ +#define SECRET_SSID "" +#define SECRET_PASS "" diff --git a/mbed-os-to-arduino b/mbed-os-to-arduino index d919715ee..97141957a 100755 --- a/mbed-os-to-arduino +++ b/mbed-os-to-arduino @@ -164,7 +164,7 @@ generate_includes () { find ./BUILD/"$BOARDNAME"/GCC_ARM${PROFILE}/ -type f -name '.include*' -print0 | xargs -0 cat \ | tr ' ' '\n' | tr -d '"' | sed -e 's#-I./mbed-os#-iwithprefixbefore/mbed#g' \ - | sed '/^-I./d' | sed '/lwipstack/d' | cat \ + | sed '/^-I./d' | cat \ > "$ARDUINOVARIANT"/includes.txt echo -n " copying to destination... " diff --git a/variants/EDGE_CONTROL/conf/mbed_app.json b/variants/EDGE_CONTROL/conf/mbed_app.json index 572df7428..0de8bdce9 100644 --- a/variants/EDGE_CONTROL/conf/mbed_app.json +++ b/variants/EDGE_CONTROL/conf/mbed_app.json @@ -1,4 +1,4 @@ -{ +{ "macros": [ "MBED_HEAP_STATS_ENABLED=1", "MBED_STACK_STATS_ENABLED=1", @@ -19,7 +19,8 @@ "cellular.offload-dns-queries": true, "cellular.at-handler-buffer-size": 1024, "mbed-trace.enable": true, - "target.mbed_app_start": "0x10000" + "target.mbed_app_start": "0x10000", + "lwip.raw-socket-enabled": true }, "EDGE_CONTROL": { "sd.SPI_MOSI": "P0_20", diff --git a/variants/GENERIC_STM32H747_M4/conf/mbed_app.json b/variants/GENERIC_STM32H747_M4/conf/mbed_app.json index f93a5464a..405373d55 100644 --- a/variants/GENERIC_STM32H747_M4/conf/mbed_app.json +++ b/variants/GENERIC_STM32H747_M4/conf/mbed_app.json @@ -11,6 +11,7 @@ "rtos.main-thread-stack-size": 32768, "cordio.max-connections": 5, "target.lse_available": 0, + "lwip.raw-socket-enabled": true, "target.device_has_remove": [ "USBDEVICE", "EMAC" diff --git a/variants/GIGA/conf/mbed_app.json b/variants/GIGA/conf/mbed_app.json index 0fb7e9221..73b1e40b4 100644 --- a/variants/GIGA/conf/mbed_app.json +++ b/variants/GIGA/conf/mbed_app.json @@ -11,6 +11,7 @@ "rtos.main-thread-stack-size": 32768, "cordio.max-connections": 5, "target.mbed_app_start": "0x8040000", + "lwip.raw-socket-enabled": true, "target.macros_add": [ "METAL_INTERNAL", "VIRTIO_DRIVER_ONLY", diff --git a/variants/NANO_RP2040_CONNECT/conf/mbed_app.json b/variants/NANO_RP2040_CONNECT/conf/mbed_app.json index 8cd4676b8..42c3d6c49 100644 --- a/variants/NANO_RP2040_CONNECT/conf/mbed_app.json +++ b/variants/NANO_RP2040_CONNECT/conf/mbed_app.json @@ -9,7 +9,8 @@ "platform.callback-nontrivial": true, "platform.all-stats-enabled": true, "platform.memory-tracing-enabled": true, - "rtos.main-thread-stack-size": 32768 + "rtos.main-thread-stack-size": 32768, + "lwip.raw-socket-enabled": true } } } diff --git a/variants/NICLA_VISION/conf/mbed_app.json b/variants/NICLA_VISION/conf/mbed_app.json index 6d743d296..0e37c33c4 100644 --- a/variants/NICLA_VISION/conf/mbed_app.json +++ b/variants/NICLA_VISION/conf/mbed_app.json @@ -12,6 +12,7 @@ "rtos.main-thread-stack-size": 32768, "cordio.max-connections": 5, "target.mbed_app_start": "0x8040000", + "lwip.raw-socket-enabled": true, "target.macros_add": [ "METAL_INTERNAL", "VIRTIO_DRIVER_ONLY", diff --git a/variants/OPTA/conf/mbed_app.json b/variants/OPTA/conf/mbed_app.json index 0fb7e9221..73b1e40b4 100644 --- a/variants/OPTA/conf/mbed_app.json +++ b/variants/OPTA/conf/mbed_app.json @@ -11,6 +11,7 @@ "rtos.main-thread-stack-size": 32768, "cordio.max-connections": 5, "target.mbed_app_start": "0x8040000", + "lwip.raw-socket-enabled": true, "target.macros_add": [ "METAL_INTERNAL", "VIRTIO_DRIVER_ONLY", diff --git a/variants/PORTENTA_H7_M7/conf/mbed_app.json b/variants/PORTENTA_H7_M7/conf/mbed_app.json index 2ab0fddc5..89554855e 100644 --- a/variants/PORTENTA_H7_M7/conf/mbed_app.json +++ b/variants/PORTENTA_H7_M7/conf/mbed_app.json @@ -15,6 +15,7 @@ "cellular.at-handler-buffer-size": 512, "mbed-trace.enable": true, "target.mbed_app_start": "0x8040000", + "lwip.raw-socket-enabled": true, "target.macros_add": [ "BT_UART_NO_3M_SUPPORT", "USB_DYNAMIC_CONFIGURATION",