From 602509650ebd974f95a59f98ecaf173dc4c2abb3 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sat, 7 Dec 2019 16:50:09 +0100 Subject: [PATCH 01/14] wifi: ARP gratuitous API for wifi station mode --- libraries/ESP8266WiFi/keywords.txt | 3 ++ libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp | 56 +++++++++++++++++++- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h | 12 +++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266WiFi/keywords.txt b/libraries/ESP8266WiFi/keywords.txt index b24bfc598e..ca600820bb 100644 --- a/libraries/ESP8266WiFi/keywords.txt +++ b/libraries/ESP8266WiFi/keywords.txt @@ -108,6 +108,9 @@ psk KEYWORD2 BSSID KEYWORD2 BSSIDstr KEYWORD2 RSSI KEYWORD2 +stationKeepAliveSetupMs KEYWORD2 +stationKeepAliveStop KEYWORD2 +stationKeepAliveEnabled KEYWORD2 enableInsecureWEP KEYWORD2 getListenInterval KEYWORD2 isSleepLevelMax KEYWORD2 diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp index 8f52942b74..d765992f64 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp @@ -34,6 +34,7 @@ #include "mem.h" #include "user_interface.h" #include "smartconfig.h" +#include "Schedule.h" extern "C" { #include "lwip/err.h" @@ -43,6 +44,11 @@ extern "C" { #if LWIP_IPV6 #include "lwip/netif.h" // struct netif #endif +#if LWIP_VERSION_MAJOR == 1 +#include "netif/etharp.h" // gratuitous arp +#else +#include "lwip/etharp.h" // gratuitous arp +#endif } #include "debug.h" @@ -89,7 +95,7 @@ static bool sta_config_equal(const station_config& lhs, const station_config& rh return false; } } - + if(lhs.threshold.rssi != rhs.threshold.rssi) { return false; } @@ -704,7 +710,55 @@ int32_t ESP8266WiFiSTAClass::RSSI(void) { return wifi_station_get_rssi(); } +bool ESP8266WiFiSTAClass::stationKeepAliveEnabled () +{ + return _keepStationAliveUs != 0; +} +void ESP8266WiFiSTAClass::stationKeepAliveStop () +{ + _keepStationAliveUs = -1; + // will be set to 0 at recurrent call +} + +bool ESP8266WiFiSTAClass::stationKeepAliveSetupMs (int ms) +{ + if (_keepStationAliveUs != 0 || ms <= 0) + return false; + _keepStationAliveUs = ms * 1000; + + schedule_recurrent_function_us([&]() + { + for (netif* interface = netif_list; interface != nullptr; interface = interface->next) + + if ( + (interface->flags & NETIF_FLAG_LINK_UP) + && (interface->flags & NETIF_FLAG_UP) +#if LWIP_VERSION_MAJOR == 1 + && (!ip_addr_isany(&interface->ip_addr)) +#else + && interface->num == STATION_IF /* lwip1 does not set num properly */ + && (!ip4_addr_isany_val(*netif_ip4_addr(interface))) +#endif + ) + { + etharp_gratuitous(interface); + break; + } + + if (_keepStationAliveUs > 0) + // continue + return true; + + // stop on user request (value < 0) + _keepStationAliveUs = 0; // stop acknowledged + // stop recurrent function + return false; + + }, _keepStationAliveUs); + + return true; +} // ----------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------- STA remote configure ----------------------------------------------- diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h index 696ff1b390..27ca713b77 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h @@ -83,10 +83,22 @@ class ESP8266WiFiSTAClass { int32_t RSSI(); + // enable automatic sending of Gratuitous ARP packets + // based on a time interval in milliseconds + // returns true on success + bool stationKeepAliveSetupMs (int ms = 1000); + + // request for stopping arp gratuitous packets + void stationKeepAliveStop (); + + // allows to check whether the gratuitous ARP service is still running + bool stationKeepAliveEnabled (); + static void enableInsecureWEP (bool enable = true) { _useInsecureWEP = enable; } protected: + int _keepStationAliveUs = 0; static bool _useStaticIp; static bool _useInsecureWEP; From c087e08ca9c303d254a5f216bce7c57c32b19bb4 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sat, 7 Dec 2019 17:03:39 +0100 Subject: [PATCH 02/14] fix with lwip1 --- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp index d765992f64..e699ae2861 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp @@ -45,6 +45,7 @@ extern "C" { #include "lwip/netif.h" // struct netif #endif #if LWIP_VERSION_MAJOR == 1 +#include "netif/wlan_lwip_if.h" // eagle_lwip_getif() #include "netif/etharp.h" // gratuitous arp #else #include "lwip/etharp.h" // gratuitous arp @@ -730,11 +731,11 @@ bool ESP8266WiFiSTAClass::stationKeepAliveSetupMs (int ms) schedule_recurrent_function_us([&]() { for (netif* interface = netif_list; interface != nullptr; interface = interface->next) - if ( (interface->flags & NETIF_FLAG_LINK_UP) && (interface->flags & NETIF_FLAG_UP) #if LWIP_VERSION_MAJOR == 1 + && interface == eagle_lwip_getif(STATION_IF) && (!ip_addr_isany(&interface->ip_addr)) #else && interface->num == STATION_IF /* lwip1 does not set num properly */ From 93bc15e3726e1e7832e04f7f7edd88866ff0a509 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sat, 7 Dec 2019 17:05:03 +0100 Subject: [PATCH 03/14] update comment --- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp index e699ae2861..0c450027cb 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp @@ -735,10 +735,10 @@ bool ESP8266WiFiSTAClass::stationKeepAliveSetupMs (int ms) (interface->flags & NETIF_FLAG_LINK_UP) && (interface->flags & NETIF_FLAG_UP) #if LWIP_VERSION_MAJOR == 1 - && interface == eagle_lwip_getif(STATION_IF) + && interface == eagle_lwip_getif(STATION_IF) /* lwip1 does not set num properly */ && (!ip_addr_isany(&interface->ip_addr)) #else - && interface->num == STATION_IF /* lwip1 does not set num properly */ + && interface->num == STATION_IF && (!ip4_addr_isany_val(*netif_ip4_addr(interface))) #endif ) From cbd217faa1c6c964a1420ebd2dbc4307708e1d14 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 8 Dec 2019 01:39:05 +0100 Subject: [PATCH 04/14] update API to allow changing interval on the fly --- libraries/ESP8266WiFi/keywords.txt | 2 +- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp | 53 +++++++++----------- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h | 12 +++-- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/libraries/ESP8266WiFi/keywords.txt b/libraries/ESP8266WiFi/keywords.txt index ca600820bb..e1af1be675 100644 --- a/libraries/ESP8266WiFi/keywords.txt +++ b/libraries/ESP8266WiFi/keywords.txt @@ -108,7 +108,7 @@ psk KEYWORD2 BSSID KEYWORD2 BSSIDstr KEYWORD2 RSSI KEYWORD2 -stationKeepAliveSetupMs KEYWORD2 +stationKeepAliveSetIntervalMs KEYWORD2 stationKeepAliveStop KEYWORD2 stationKeepAliveEnabled KEYWORD2 enableInsecureWEP KEYWORD2 diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp index 0c450027cb..61d4a309cf 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp @@ -711,24 +711,9 @@ int32_t ESP8266WiFiSTAClass::RSSI(void) { return wifi_station_get_rssi(); } -bool ESP8266WiFiSTAClass::stationKeepAliveEnabled () +void ESP8266WiFiSTAClass::stationKeepAliveNow () { - return _keepStationAliveUs != 0; -} - -void ESP8266WiFiSTAClass::stationKeepAliveStop () -{ - _keepStationAliveUs = -1; - // will be set to 0 at recurrent call -} - -bool ESP8266WiFiSTAClass::stationKeepAliveSetupMs (int ms) -{ - if (_keepStationAliveUs != 0 || ms <= 0) - return false; - _keepStationAliveUs = ms * 1000; - - schedule_recurrent_function_us([&]() + if (_keepStationAliveUs > 0) { for (netif* interface = netif_list; interface != nullptr; interface = interface->next) if ( @@ -747,18 +732,30 @@ bool ESP8266WiFiSTAClass::stationKeepAliveSetupMs (int ms) break; } - if (_keepStationAliveUs > 0) - // continue - return true; - - // stop on user request (value < 0) - _keepStationAliveUs = 0; // stop acknowledged - // stop recurrent function - return false; - - }, _keepStationAliveUs); + // re/schedule with a possibly updated interval + schedule_recurrent_function_us([&]() + { + stationKeepAliveNow(); + return false; + }, _keepStationAliveUs); + } + else + // mark disabled (0) if user cancelled it (<0) + _keepStationAliveUs = 0; +} - return true; +void ESP8266WiFiSTAClass::stationKeepAliveSetIntervalMs (int ms) +{ + bool wasEnabled = (_keepStationAliveUs > 0); + int us = ms * 1000; + if (wasEnabled) + _keepStationAliveUs = ms <= 0? /*disable*/-1: /*update*/us; + else if (ms > 0) + { + _keepStationAliveUs = us; + // start + stationKeepAliveNow(); + } } // ----------------------------------------------------------------------------------------------------------------------- diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h index 27ca713b77..171bbf7511 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h @@ -83,16 +83,16 @@ class ESP8266WiFiSTAClass { int32_t RSSI(); - // enable automatic sending of Gratuitous ARP packets + // enable or update automatic sending of Gratuitous ARP packets // based on a time interval in milliseconds - // returns true on success - bool stationKeepAliveSetupMs (int ms = 1000); + void stationKeepAliveSetIntervalMs (int ms = 1000); // request for stopping arp gratuitous packets - void stationKeepAliveStop (); + void stationKeepAliveStop () { stationKeepAliveSetIntervalMs(0); } // allows to check whether the gratuitous ARP service is still running - bool stationKeepAliveEnabled (); + bool stationKeepAliveEnabled () const { return _keepStationAliveUs != 0; } + static void enableInsecureWEP (bool enable = true) { _useInsecureWEP = enable; } @@ -102,6 +102,8 @@ class ESP8266WiFiSTAClass { static bool _useStaticIp; static bool _useInsecureWEP; + void stationKeepAliveNow (); + // ---------------------------------------------------------------------------------------------- // ------------------------------------ STA remote configure ----------------------------------- // ---------------------------------------------------------------------------------------------- From 8d433ca6d5c51df17d2c315feeaf43c43755692b Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 8 Dec 2019 21:58:20 +0100 Subject: [PATCH 05/14] update API --- libraries/ESP8266WiFi/keywords.txt | 2 +- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp | 77 +++++++++++--------- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h | 17 ++--- 3 files changed, 53 insertions(+), 43 deletions(-) diff --git a/libraries/ESP8266WiFi/keywords.txt b/libraries/ESP8266WiFi/keywords.txt index e1af1be675..3db3541a23 100644 --- a/libraries/ESP8266WiFi/keywords.txt +++ b/libraries/ESP8266WiFi/keywords.txt @@ -110,7 +110,7 @@ BSSIDstr KEYWORD2 RSSI KEYWORD2 stationKeepAliveSetIntervalMs KEYWORD2 stationKeepAliveStop KEYWORD2 -stationKeepAliveEnabled KEYWORD2 +stationKeepAliveNow KEYWORD2 enableInsecureWEP KEYWORD2 getListenInterval KEYWORD2 isSleepLevelMax KEYWORD2 diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp index 61d4a309cf..7435848be7 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp @@ -713,48 +713,59 @@ int32_t ESP8266WiFiSTAClass::RSSI(void) { void ESP8266WiFiSTAClass::stationKeepAliveNow () { - if (_keepStationAliveUs > 0) - { - for (netif* interface = netif_list; interface != nullptr; interface = interface->next) - if ( - (interface->flags & NETIF_FLAG_LINK_UP) - && (interface->flags & NETIF_FLAG_UP) + for (netif* interface = netif_list; interface != nullptr; interface = interface->next) + if ( + (interface->flags & NETIF_FLAG_LINK_UP) + && (interface->flags & NETIF_FLAG_UP) #if LWIP_VERSION_MAJOR == 1 - && interface == eagle_lwip_getif(STATION_IF) /* lwip1 does not set num properly */ - && (!ip_addr_isany(&interface->ip_addr)) + && interface == eagle_lwip_getif(STATION_IF) /* lwip1 does not set if->num properly */ + && (!ip_addr_isany(&interface->ip_addr)) #else - && interface->num == STATION_IF - && (!ip4_addr_isany_val(*netif_ip4_addr(interface))) + && interface->num == STATION_IF + && (!ip4_addr_isany_val(*netif_ip4_addr(interface))) #endif - ) - { - etharp_gratuitous(interface); - break; - } - - // re/schedule with a possibly updated interval - schedule_recurrent_function_us([&]() - { - stationKeepAliveNow(); - return false; - }, _keepStationAliveUs); - } - else - // mark disabled (0) if user cancelled it (<0) - _keepStationAliveUs = 0; + ) + { + etharp_gratuitous(interface); + break; + } } void ESP8266WiFiSTAClass::stationKeepAliveSetIntervalMs (int ms) { - bool wasEnabled = (_keepStationAliveUs > 0); - int us = ms * 1000; - if (wasEnabled) - _keepStationAliveUs = ms <= 0? /*disable*/-1: /*update*/us; - else if (ms > 0) + int us; + if (ms > std::numeric_limits::max() / 1000) + // for sanity only, 24 days is not really meaningful + us = std::numeric_limits::max(); + else + us = ms * 1000; + + // cancel possibly already scheduled future events + _keepStationState++; + + if (us) { - _keepStationAliveUs = us; - // start + // send one now stationKeepAliveNow(); + + // schedule next ones + int checkState = _keepStationState; + schedule_recurrent_function_us([&, checkState]() + { +Serial.printf("--- %d %d\n", checkState, this->_keepStationState); + // this recurring scheduled function will be cancelled + // when this->_keepStationState != checkState + if (checkState != this->_keepStationState) + // cancel this recurring event + return false; + +Serial.printf("--- SEND\n"); + // send gratuitous ARP + this->stationKeepAliveNow(); + + // keep on with next event + return true; + }, us); } } diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h index 171bbf7511..024a391f0a 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h @@ -41,8 +41,8 @@ class ESP8266WiFiSTAClass { wl_status_t begin(const String& ssid, const String& passphrase = emptyString, int32_t channel = 0, const uint8_t* bssid = NULL, bool connect = true); wl_status_t begin(); - //The argument order for ESP is not the same as for Arduino. However, there is compatibility code under the hood - //to detect Arduino arg order, and handle it correctly. Be aware that the Arduino default value handling doesn't + //The argument order for ESP is not the same as for Arduino. However, there is compatibility code under the hood + //to detect Arduino arg order, and handle it correctly. Be aware that the Arduino default value handling doesn't //work here (see Arduino docs for gway/subnet defaults). In other words: at least 3 args must always be given. bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000); @@ -83,26 +83,25 @@ class ESP8266WiFiSTAClass { int32_t RSSI(); - // enable or update automatic sending of Gratuitous ARP packets - // based on a time interval in milliseconds + // disable(0) or enable/update automatic sending of Gratuitous ARP packets + // a gratuitous ARP packet is sent at start, then + // based on a time interval in milliseconds, default 1s void stationKeepAliveSetIntervalMs (int ms = 1000); // request for stopping arp gratuitous packets void stationKeepAliveStop () { stationKeepAliveSetIntervalMs(0); } - // allows to check whether the gratuitous ARP service is still running - bool stationKeepAliveEnabled () const { return _keepStationAliveUs != 0; } - + // immediately send one gratuitous ARP from STA + static void stationKeepAliveNow (); static void enableInsecureWEP (bool enable = true) { _useInsecureWEP = enable; } protected: - int _keepStationAliveUs = 0; static bool _useStaticIp; static bool _useInsecureWEP; - void stationKeepAliveNow (); + int _keepStationState = 0; // ---------------------------------------------------------------------------------------------- // ------------------------------------ STA remote configure ----------------------------------- From 716baecf2f281dde27755ab253bee6af425d62ca Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 8 Dec 2019 22:03:23 +0100 Subject: [PATCH 06/14] remove debug lines --- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp index 7435848be7..076fe23ffa 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp @@ -752,14 +752,12 @@ void ESP8266WiFiSTAClass::stationKeepAliveSetIntervalMs (int ms) int checkState = _keepStationState; schedule_recurrent_function_us([&, checkState]() { -Serial.printf("--- %d %d\n", checkState, this->_keepStationState); // this recurring scheduled function will be cancelled // when this->_keepStationState != checkState if (checkState != this->_keepStationState) // cancel this recurring event return false; -Serial.printf("--- SEND\n"); // send gratuitous ARP this->stationKeepAliveNow(); From 2885ac46dfb3c76b71a0a2a01035fd061051a36e Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 8 Dec 2019 22:31:34 +0100 Subject: [PATCH 07/14] mock lwIP's etharp_request() --- tests/host/common/MocklwIP.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/host/common/MocklwIP.cpp b/tests/host/common/MocklwIP.cpp index bc5ae6ebc4..f114572c14 100644 --- a/tests/host/common/MocklwIP.cpp +++ b/tests/host/common/MocklwIP.cpp @@ -26,4 +26,11 @@ const ip_addr_t* sntp_getserver(u8_t) return IP_ADDR_ANY; } +err_t etharp_request(struct netif *netif, const ip4_addr_t *ipaddr) +{ + (void)netif; + (void)ipaddr; + return ERR_OK; +} + } // extern "C" From 338c3df9c8d21cf706fed4b83eed713f9e99dbfe Mon Sep 17 00:00:00 2001 From: david gauchard Date: Mon, 9 Dec 2019 22:26:52 +0100 Subject: [PATCH 08/14] unsigned interval --- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp | 10 +++++----- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp index 076fe23ffa..7e1f2dd2f7 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp @@ -731,12 +731,12 @@ void ESP8266WiFiSTAClass::stationKeepAliveNow () } } -void ESP8266WiFiSTAClass::stationKeepAliveSetIntervalMs (int ms) +void ESP8266WiFiSTAClass::stationKeepAliveSetIntervalMs (uint32_t ms) { - int us; - if (ms > std::numeric_limits::max() / 1000) - // for sanity only, 24 days is not really meaningful - us = std::numeric_limits::max(); + uint32_t us; + if (ms > std::numeric_limits::max() / 1000) + // for sanity only, 49 days is not really meaningful + us = std::numeric_limits::max(); else us = ms * 1000; diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h index 024a391f0a..6d5f97513c 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h @@ -86,7 +86,7 @@ class ESP8266WiFiSTAClass { // disable(0) or enable/update automatic sending of Gratuitous ARP packets // a gratuitous ARP packet is sent at start, then // based on a time interval in milliseconds, default 1s - void stationKeepAliveSetIntervalMs (int ms = 1000); + void stationKeepAliveSetIntervalMs (uint32_t ms = 1000); // request for stopping arp gratuitous packets void stationKeepAliveStop () { stationKeepAliveSetIntervalMs(0); } From 55370eb1b94d57fbe89f3498e3ab6be6f80680b8 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Wed, 8 Apr 2020 19:11:59 +0200 Subject: [PATCH 09/14] use scheduled ticker --- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp | 40 +++++++------------- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h | 12 +++--- 2 files changed, 20 insertions(+), 32 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp index 7e1f2dd2f7..98c7e86ea2 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp @@ -731,40 +731,28 @@ void ESP8266WiFiSTAClass::stationKeepAliveNow () } } -void ESP8266WiFiSTAClass::stationKeepAliveSetIntervalMs (uint32_t ms) +bool ESP8266WiFiSTAClass::stationKeepAliveSetIntervalMs (uint32_t ms) { - uint32_t us; - if (ms > std::numeric_limits::max() / 1000) - // for sanity only, 49 days is not really meaningful - us = std::numeric_limits::max(); - else - us = ms * 1000; - - // cancel possibly already scheduled future events - _keepStationState++; + if (_keepalive) { + delete _keepalive; + _keepalive = nullptr; + } - if (us) - { + if (ms) { // send one now stationKeepAliveNow(); - // schedule next ones - int checkState = _keepStationState; - schedule_recurrent_function_us([&, checkState]() - { - // this recurring scheduled function will be cancelled - // when this->_keepStationState != checkState - if (checkState != this->_keepStationState) - // cancel this recurring event - return false; + _keepalive = new (std::nothrow) Ticker; + if (_keepalive == nullptr) + return false; - // send gratuitous ARP + _keepalive->attach_ms_scheduled(ms, [&]() + { this->stationKeepAliveNow(); - - // keep on with next event - return true; - }, us); + }); } + + return true; } // ----------------------------------------------------------------------------------------------------------------------- diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h index 6d5f97513c..ac21f50628 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h @@ -23,7 +23,7 @@ #ifndef ESP8266WIFISTA_H_ #define ESP8266WIFISTA_H_ - +#include #include "ESP8266WiFiType.h" #include "ESP8266WiFiGeneric.h" #include "user_interface.h" @@ -83,13 +83,13 @@ class ESP8266WiFiSTAClass { int32_t RSSI(); - // disable(0) or enable/update automatic sending of Gratuitous ARP packets - // a gratuitous ARP packet is sent at start, then + // disable(0) or enable/update automatic sending of Gratuitous ARP packets. + // A gratuitous ARP packet is immediately sent when calling this function, then // based on a time interval in milliseconds, default 1s - void stationKeepAliveSetIntervalMs (uint32_t ms = 1000); + bool stationKeepAliveSetIntervalMs (uint32_t ms = 1000); // request for stopping arp gratuitous packets - void stationKeepAliveStop () { stationKeepAliveSetIntervalMs(0); } + void stationKeepAliveStop () { (void)stationKeepAliveSetIntervalMs(0); } // immediately send one gratuitous ARP from STA static void stationKeepAliveNow (); @@ -101,7 +101,7 @@ class ESP8266WiFiSTAClass { static bool _useStaticIp; static bool _useInsecureWEP; - int _keepStationState = 0; + Ticker* _keepalive; // ---------------------------------------------------------------------------------------------- // ------------------------------------ STA remote configure ----------------------------------- From 817f3b78aa51a26d8efc24a419ffef15cb9eab4d Mon Sep 17 00:00:00 2001 From: david gauchard Date: Wed, 8 Apr 2020 22:54:00 +0200 Subject: [PATCH 10/14] ticker: +attach_ms_scheduled_accurate ticker: +comment gratuitous: use attach_ms_scheduled_accurate --- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp | 3 +-- libraries/Ticker/src/Ticker.h | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp index 98c7e86ea2..c88105d1f9 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp @@ -746,8 +746,7 @@ bool ESP8266WiFiSTAClass::stationKeepAliveSetIntervalMs (uint32_t ms) if (_keepalive == nullptr) return false; - _keepalive->attach_ms_scheduled(ms, [&]() - { + _keepalive->attach_ms_scheduled_accurate(ms, [&]() { this->stationKeepAliveNow(); }); } diff --git a/libraries/Ticker/src/Ticker.h b/libraries/Ticker/src/Ticker.h index 436a68ce8e..07ce33c623 100644 --- a/libraries/Ticker/src/Ticker.h +++ b/libraries/Ticker/src/Ticker.h @@ -35,30 +35,42 @@ class Ticker typedef void (*callback_with_arg_t)(void*); typedef std::function callback_function_t; + // callback will be called at following loop() after ticker fires void attach_scheduled(float seconds, callback_function_t callback) { _callback_function = [callback]() { schedule_function(callback); }; _attach_ms(1000UL * seconds, true); } + // callback will be called in SYS ctx when ticker fires void attach(float seconds, callback_function_t callback) { _callback_function = std::move(callback); _attach_ms(1000UL * seconds, true); } + // callback will be called at following loop() after ticker fires void attach_ms_scheduled(uint32_t milliseconds, callback_function_t callback) { _callback_function = [callback]() { schedule_function(callback); }; _attach_ms(milliseconds, true); } + // callback will be called at following yield() after ticker fires + void attach_ms_scheduled_accurate(uint32_t milliseconds, callback_function_t callback) + { + _callback_function = [callback]() { schedule_recurrent_function_us([callback]() { callback(); return false; }, 0); }; + _attach_ms(milliseconds, true); + } + + // callback will be called in SYS ctx when ticker fires void attach_ms(uint32_t milliseconds, callback_function_t callback) { _callback_function = std::move(callback); _attach_ms(milliseconds, true); } + // callback will be called in SYS ctx when ticker fires template void attach(float seconds, void (*callback)(TArg), TArg arg) { @@ -66,6 +78,7 @@ class Ticker _attach_ms(1000UL * seconds, true, reinterpret_cast(callback), reinterpret_cast(arg)); } + // callback will be called in SYS ctx when ticker fires template void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg) { @@ -73,30 +86,35 @@ class Ticker _attach_ms(milliseconds, true, reinterpret_cast(callback), reinterpret_cast(arg)); } + // callback will be called at following loop() after ticker fires void once_scheduled(float seconds, callback_function_t callback) { _callback_function = [callback]() { schedule_function(callback); }; _attach_ms(1000UL * seconds, false); } + // callback will be called in SYS ctx when ticker fires void once(float seconds, callback_function_t callback) { _callback_function = std::move(callback); _attach_ms(1000UL * seconds, false); } + // callback will be called at following loop() after ticker fires void once_ms_scheduled(uint32_t milliseconds, callback_function_t callback) { _callback_function = [callback]() { schedule_function(callback); }; _attach_ms(milliseconds, false); } + // callback will be called in SYS ctx when ticker fires void once_ms(uint32_t milliseconds, callback_function_t callback) { _callback_function = std::move(callback); _attach_ms(milliseconds, false); } + // callback will be called in SYS ctx when ticker fires template void once(float seconds, void (*callback)(TArg), TArg arg) { @@ -104,6 +122,7 @@ class Ticker _attach_ms(1000UL * seconds, false, reinterpret_cast(callback), reinterpret_cast(arg)); } + // callback will be called in SYS ctx when ticker fires template void once_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg) { From 8f04314abc9246ff2e5437528c33717ae2b1cfe5 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Wed, 8 Apr 2020 23:23:08 +0200 Subject: [PATCH 11/14] move to experimental namespace --- libraries/ESP8266WiFi/keywords.txt | 1 + .../ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp | 82 +++++++++++++++++++ .../ESP8266WiFi/src/ESP8266WiFiGratuitous.h | 53 ++++++++++++ libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp | 48 ----------- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h | 15 +--- 5 files changed, 137 insertions(+), 62 deletions(-) create mode 100644 libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp create mode 100644 libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h diff --git a/libraries/ESP8266WiFi/keywords.txt b/libraries/ESP8266WiFi/keywords.txt index 3db3541a23..16eea24227 100644 --- a/libraries/ESP8266WiFi/keywords.txt +++ b/libraries/ESP8266WiFi/keywords.txt @@ -26,6 +26,7 @@ PublicKey KEYWORD1 CertStoreSPIFFSBearSSL KEYWORD1 CertStoreSDBearSSL KEYWORD1 Session KEYWORD1 +ESP8266WiFiGratuitous KEYWORD1 ####################################### diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp new file mode 100644 index 0000000000..a2108a4b09 --- /dev/null +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp @@ -0,0 +1,82 @@ +/* + ESP8266WiFiGratuitous.cpp - esp8266 Wifi support + copyright esp8266/arduino + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +#include "lwip/init.h" // LWIP_VERSION_* +#if LWIP_VERSION_MAJOR == 1 +#include "netif/wlan_lwip_if.h" // eagle_lwip_getif() +#include "netif/etharp.h" // gratuitous arp +#else +#include "lwip/etharp.h" // gratuitous arp +#endif + +#include "ESP8266WiFiGratuitous.h" + +namespace experimental +{ + +Ticker* ESP8266WiFiGratuitous::_keepalive = nullptr; + +void ESP8266WiFiGratuitous::stationKeepAliveNow () +{ + for (netif* interface = netif_list; interface != nullptr; interface = interface->next) + if ( + (interface->flags & NETIF_FLAG_LINK_UP) + && (interface->flags & NETIF_FLAG_UP) +#if LWIP_VERSION_MAJOR == 1 + && interface == eagle_lwip_getif(STATION_IF) /* lwip1 does not set if->num properly */ + && (!ip_addr_isany(&interface->ip_addr)) +#else + && interface->num == STATION_IF + && (!ip4_addr_isany_val(*netif_ip4_addr(interface))) +#endif + ) + { + etharp_gratuitous(interface); + break; + } +} + +bool ESP8266WiFiGratuitous::stationKeepAliveSetIntervalMs (uint32_t ms) +{ + if (_keepalive) + { + delete _keepalive; + _keepalive = nullptr; + } + + if (ms) { + // send one now + stationKeepAliveNow(); + + _keepalive = new (std::nothrow) Ticker; + if (_keepalive != nullptr) + { + _keepalive->attach_ms_scheduled_accurate(ms, []() + { + stationKeepAliveNow(); + }); + } + } + + return true; +} + +}; // experimental:: diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h new file mode 100644 index 0000000000..a0640d35b2 --- /dev/null +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h @@ -0,0 +1,53 @@ +/* + ESP8266WiFiGratuitous.h - esp8266 Wifi support + copyright esp8266/arduino + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef ESP8266WIFIGRATUITOUS_H_ +#define ESP8266WIFIGRATUITOUS_H_ + +#include // uint32_t + +class Ticker; + +namespace experimental +{ + +class ESP8266WiFiGratuitous +{ +public: + + // disable(0) or enable/update automatic sending of Gratuitous ARP packets. + // A gratuitous ARP packet is immediately sent when calling this function, then + // based on a time interval in milliseconds, default = 1s + // return value: true when started, false otherwise + static bool stationKeepAliveSetIntervalMs (uint32_t ms = 1000); + + // request for stopping arp gratuitous packets + static void stationKeepAliveStop () { (void)stationKeepAliveSetIntervalMs(0); } + + // immediately send one gratuitous ARP from STA + static void stationKeepAliveNow (); + +protected: + + static Ticker* _keepalive; +}; + +}; // experimental:: + +#endif // ESP8266WIFIGRATUITOUS_H_ diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp index c88105d1f9..26fb4b9d37 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp @@ -34,7 +34,6 @@ #include "mem.h" #include "user_interface.h" #include "smartconfig.h" -#include "Schedule.h" extern "C" { #include "lwip/err.h" @@ -44,12 +43,6 @@ extern "C" { #if LWIP_IPV6 #include "lwip/netif.h" // struct netif #endif -#if LWIP_VERSION_MAJOR == 1 -#include "netif/wlan_lwip_if.h" // eagle_lwip_getif() -#include "netif/etharp.h" // gratuitous arp -#else -#include "lwip/etharp.h" // gratuitous arp -#endif } #include "debug.h" @@ -711,48 +704,7 @@ int32_t ESP8266WiFiSTAClass::RSSI(void) { return wifi_station_get_rssi(); } -void ESP8266WiFiSTAClass::stationKeepAliveNow () -{ - for (netif* interface = netif_list; interface != nullptr; interface = interface->next) - if ( - (interface->flags & NETIF_FLAG_LINK_UP) - && (interface->flags & NETIF_FLAG_UP) -#if LWIP_VERSION_MAJOR == 1 - && interface == eagle_lwip_getif(STATION_IF) /* lwip1 does not set if->num properly */ - && (!ip_addr_isany(&interface->ip_addr)) -#else - && interface->num == STATION_IF - && (!ip4_addr_isany_val(*netif_ip4_addr(interface))) -#endif - ) - { - etharp_gratuitous(interface); - break; - } -} -bool ESP8266WiFiSTAClass::stationKeepAliveSetIntervalMs (uint32_t ms) -{ - if (_keepalive) { - delete _keepalive; - _keepalive = nullptr; - } - - if (ms) { - // send one now - stationKeepAliveNow(); - - _keepalive = new (std::nothrow) Ticker; - if (_keepalive == nullptr) - return false; - - _keepalive->attach_ms_scheduled_accurate(ms, [&]() { - this->stationKeepAliveNow(); - }); - } - - return true; -} // ----------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------- STA remote configure ----------------------------------------------- diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h index ac21f50628..cf38e1254e 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h @@ -23,7 +23,7 @@ #ifndef ESP8266WIFISTA_H_ #define ESP8266WIFISTA_H_ -#include + #include "ESP8266WiFiType.h" #include "ESP8266WiFiGeneric.h" #include "user_interface.h" @@ -83,17 +83,6 @@ class ESP8266WiFiSTAClass { int32_t RSSI(); - // disable(0) or enable/update automatic sending of Gratuitous ARP packets. - // A gratuitous ARP packet is immediately sent when calling this function, then - // based on a time interval in milliseconds, default 1s - bool stationKeepAliveSetIntervalMs (uint32_t ms = 1000); - - // request for stopping arp gratuitous packets - void stationKeepAliveStop () { (void)stationKeepAliveSetIntervalMs(0); } - - // immediately send one gratuitous ARP from STA - static void stationKeepAliveNow (); - static void enableInsecureWEP (bool enable = true) { _useInsecureWEP = enable; } protected: @@ -101,8 +90,6 @@ class ESP8266WiFiSTAClass { static bool _useStaticIp; static bool _useInsecureWEP; - Ticker* _keepalive; - // ---------------------------------------------------------------------------------------------- // ------------------------------------ STA remote configure ----------------------------------- // ---------------------------------------------------------------------------------------------- From 2ce8df5f6cd548e59f14fff4e897ecd017df1d6b Mon Sep 17 00:00:00 2001 From: david gauchard Date: Wed, 8 Apr 2020 23:48:55 +0200 Subject: [PATCH 12/14] fix for lwIP-v1.4 --- libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp index a2108a4b09..31db896ba4 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp @@ -19,13 +19,17 @@ #include +extern "C" +{ #include "lwip/init.h" // LWIP_VERSION_* #if LWIP_VERSION_MAJOR == 1 #include "netif/wlan_lwip_if.h" // eagle_lwip_getif() #include "netif/etharp.h" // gratuitous arp +#include "user_interface.h" #else #include "lwip/etharp.h" // gratuitous arp #endif +} // extern "C" #include "ESP8266WiFiGratuitous.h" From 4c5cc0227a2bdbf4aece823ee445f68314710e81 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Thu, 9 Apr 2020 09:54:47 +0200 Subject: [PATCH 13/14] attempt to make pio happy --- libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp | 2 -- libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp index 31db896ba4..3c157f6e01 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp @@ -17,8 +17,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include - extern "C" { #include "lwip/init.h" // LWIP_VERSION_* diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h index a0640d35b2..228ed0cb1b 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h @@ -22,7 +22,7 @@ #include // uint32_t -class Ticker; +#include namespace experimental { From 6801b3c5c0d5963a5910180a0cdb69bd2dfa442c Mon Sep 17 00:00:00 2001 From: david gauchard Date: Thu, 9 Apr 2020 15:38:23 +0200 Subject: [PATCH 14/14] use directly ETSTimer instead of Ticker --- .../ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp | 36 ++++++++++++------- .../ESP8266WiFi/src/ESP8266WiFiGratuitous.h | 9 ++--- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp index 3c157f6e01..0465fbc4f8 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp @@ -29,12 +29,14 @@ extern "C" #endif } // extern "C" +#include + #include "ESP8266WiFiGratuitous.h" namespace experimental { -Ticker* ESP8266WiFiGratuitous::_keepalive = nullptr; +ETSTimer* ESP8266WiFiGratuitous::_timer = nullptr; void ESP8266WiFiGratuitous::stationKeepAliveNow () { @@ -56,26 +58,34 @@ void ESP8266WiFiGratuitous::stationKeepAliveNow () } } +void ESP8266WiFiGratuitous::scheduleItForNextYieldOnce (void*) +{ + schedule_recurrent_function_us([]() + { + ESP8266WiFiGratuitous::stationKeepAliveNow(); + return false; + }, 0); +} + bool ESP8266WiFiGratuitous::stationKeepAliveSetIntervalMs (uint32_t ms) { - if (_keepalive) + if (_timer) { - delete _keepalive; - _keepalive = nullptr; + os_timer_disarm(_timer); + _timer = nullptr; } - if (ms) { + if (ms) + { // send one now stationKeepAliveNow(); - _keepalive = new (std::nothrow) Ticker; - if (_keepalive != nullptr) - { - _keepalive->attach_ms_scheduled_accurate(ms, []() - { - stationKeepAliveNow(); - }); - } + _timer = (ETSTimer*)malloc(sizeof(ETSTimer)); + if (_timer == nullptr) + return false; + + os_timer_setfn(_timer, ESP8266WiFiGratuitous::scheduleItForNextYieldOnce, nullptr); + os_timer_arm(_timer, ms, true); } return true; diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h index 228ed0cb1b..d86426cd87 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h @@ -20,9 +20,8 @@ #ifndef ESP8266WIFIGRATUITOUS_H_ #define ESP8266WIFIGRATUITOUS_H_ -#include // uint32_t - -#include +#include // uint32_t +#include // ETSTimer namespace experimental { @@ -45,7 +44,9 @@ class ESP8266WiFiGratuitous protected: - static Ticker* _keepalive; + static void scheduleItForNextYieldOnce (void*); + + static ETSTimer* _timer; }; }; // experimental::