Skip to content

Commit bc170e6

Browse files
authored
WiFi: ARP gratuitous API for wifi station mode (#6889)
* wifi: ARP gratuitous API for wifi station mode * fix with lwip1 * update comment * update API to allow changing interval on the fly * update API * remove debug lines * mock lwIP's etharp_request() * unsigned interval * use scheduled ticker * ticker: +attach_ms_scheduled_accurate ticker: +comment gratuitous: use attach_ms_scheduled_accurate * move to experimental namespace * fix for lwIP-v1.4 * attempt to make pio happy * use directly ETSTimer instead of Ticker
1 parent d600cc7 commit bc170e6

File tree

7 files changed

+181
-3
lines changed

7 files changed

+181
-3
lines changed

libraries/ESP8266WiFi/keywords.txt

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ PublicKey KEYWORD1
2626
CertStoreSPIFFSBearSSL KEYWORD1
2727
CertStoreSDBearSSL KEYWORD1
2828
Session KEYWORD1
29+
ESP8266WiFiGratuitous KEYWORD1
2930

3031

3132
#######################################
@@ -108,6 +109,9 @@ psk KEYWORD2
108109
BSSID KEYWORD2
109110
BSSIDstr KEYWORD2
110111
RSSI KEYWORD2
112+
stationKeepAliveSetIntervalMs KEYWORD2
113+
stationKeepAliveStop KEYWORD2
114+
stationKeepAliveNow KEYWORD2
111115
enableInsecureWEP KEYWORD2
112116
getListenInterval KEYWORD2
113117
isSleepLevelMax KEYWORD2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
ESP8266WiFiGratuitous.cpp - esp8266 Wifi support
3+
copyright esp8266/arduino
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
extern "C"
21+
{
22+
#include "lwip/init.h" // LWIP_VERSION_*
23+
#if LWIP_VERSION_MAJOR == 1
24+
#include "netif/wlan_lwip_if.h" // eagle_lwip_getif()
25+
#include "netif/etharp.h" // gratuitous arp
26+
#include "user_interface.h"
27+
#else
28+
#include "lwip/etharp.h" // gratuitous arp
29+
#endif
30+
} // extern "C"
31+
32+
#include <Schedule.h>
33+
34+
#include "ESP8266WiFiGratuitous.h"
35+
36+
namespace experimental
37+
{
38+
39+
ETSTimer* ESP8266WiFiGratuitous::_timer = nullptr;
40+
41+
void ESP8266WiFiGratuitous::stationKeepAliveNow ()
42+
{
43+
for (netif* interface = netif_list; interface != nullptr; interface = interface->next)
44+
if (
45+
(interface->flags & NETIF_FLAG_LINK_UP)
46+
&& (interface->flags & NETIF_FLAG_UP)
47+
#if LWIP_VERSION_MAJOR == 1
48+
&& interface == eagle_lwip_getif(STATION_IF) /* lwip1 does not set if->num properly */
49+
&& (!ip_addr_isany(&interface->ip_addr))
50+
#else
51+
&& interface->num == STATION_IF
52+
&& (!ip4_addr_isany_val(*netif_ip4_addr(interface)))
53+
#endif
54+
)
55+
{
56+
etharp_gratuitous(interface);
57+
break;
58+
}
59+
}
60+
61+
void ESP8266WiFiGratuitous::scheduleItForNextYieldOnce (void*)
62+
{
63+
schedule_recurrent_function_us([]()
64+
{
65+
ESP8266WiFiGratuitous::stationKeepAliveNow();
66+
return false;
67+
}, 0);
68+
}
69+
70+
bool ESP8266WiFiGratuitous::stationKeepAliveSetIntervalMs (uint32_t ms)
71+
{
72+
if (_timer)
73+
{
74+
os_timer_disarm(_timer);
75+
_timer = nullptr;
76+
}
77+
78+
if (ms)
79+
{
80+
// send one now
81+
stationKeepAliveNow();
82+
83+
_timer = (ETSTimer*)malloc(sizeof(ETSTimer));
84+
if (_timer == nullptr)
85+
return false;
86+
87+
os_timer_setfn(_timer, ESP8266WiFiGratuitous::scheduleItForNextYieldOnce, nullptr);
88+
os_timer_arm(_timer, ms, true);
89+
}
90+
91+
return true;
92+
}
93+
94+
}; // experimental::
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
ESP8266WiFiGratuitous.h - esp8266 Wifi support
3+
copyright esp8266/arduino
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#ifndef ESP8266WIFIGRATUITOUS_H_
21+
#define ESP8266WIFIGRATUITOUS_H_
22+
23+
#include <stdint.h> // uint32_t
24+
#include <ets_sys.h> // ETSTimer
25+
26+
namespace experimental
27+
{
28+
29+
class ESP8266WiFiGratuitous
30+
{
31+
public:
32+
33+
// disable(0) or enable/update automatic sending of Gratuitous ARP packets.
34+
// A gratuitous ARP packet is immediately sent when calling this function, then
35+
// based on a time interval in milliseconds, default = 1s
36+
// return value: true when started, false otherwise
37+
static bool stationKeepAliveSetIntervalMs (uint32_t ms = 1000);
38+
39+
// request for stopping arp gratuitous packets
40+
static void stationKeepAliveStop () { (void)stationKeepAliveSetIntervalMs(0); }
41+
42+
// immediately send one gratuitous ARP from STA
43+
static void stationKeepAliveNow ();
44+
45+
protected:
46+
47+
static void scheduleItForNextYieldOnce (void*);
48+
49+
static ETSTimer* _timer;
50+
};
51+
52+
}; // experimental::
53+
54+
#endif // ESP8266WIFIGRATUITOUS_H_

libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ static bool sta_config_equal(const station_config& lhs, const station_config& rh
8989
return false;
9090
}
9191
}
92-
92+
9393
if(lhs.threshold.rssi != rhs.threshold.rssi) {
9494
return false;
9595
}

libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ class ESP8266WiFiSTAClass {
4141
wl_status_t begin(const String& ssid, const String& passphrase = emptyString, int32_t channel = 0, const uint8_t* bssid = NULL, bool connect = true);
4242
wl_status_t begin();
4343

44-
//The argument order for ESP is not the same as for Arduino. However, there is compatibility code under the hood
45-
//to detect Arduino arg order, and handle it correctly. Be aware that the Arduino default value handling doesn't
44+
//The argument order for ESP is not the same as for Arduino. However, there is compatibility code under the hood
45+
//to detect Arduino arg order, and handle it correctly. Be aware that the Arduino default value handling doesn't
4646
//work here (see Arduino docs for gway/subnet defaults). In other words: at least 3 args must always be given.
4747
bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000);
4848

libraries/Ticker/src/Ticker.h

+19
Original file line numberDiff line numberDiff line change
@@ -35,75 +35,94 @@ class Ticker
3535
typedef void (*callback_with_arg_t)(void*);
3636
typedef std::function<void(void)> callback_function_t;
3737

38+
// callback will be called at following loop() after ticker fires
3839
void attach_scheduled(float seconds, callback_function_t callback)
3940
{
4041
_callback_function = [callback]() { schedule_function(callback); };
4142
_attach_ms(1000UL * seconds, true);
4243
}
4344

45+
// callback will be called in SYS ctx when ticker fires
4446
void attach(float seconds, callback_function_t callback)
4547
{
4648
_callback_function = std::move(callback);
4749
_attach_ms(1000UL * seconds, true);
4850
}
4951

52+
// callback will be called at following loop() after ticker fires
5053
void attach_ms_scheduled(uint32_t milliseconds, callback_function_t callback)
5154
{
5255
_callback_function = [callback]() { schedule_function(callback); };
5356
_attach_ms(milliseconds, true);
5457
}
5558

59+
// callback will be called at following yield() after ticker fires
60+
void attach_ms_scheduled_accurate(uint32_t milliseconds, callback_function_t callback)
61+
{
62+
_callback_function = [callback]() { schedule_recurrent_function_us([callback]() { callback(); return false; }, 0); };
63+
_attach_ms(milliseconds, true);
64+
}
65+
66+
// callback will be called in SYS ctx when ticker fires
5667
void attach_ms(uint32_t milliseconds, callback_function_t callback)
5768
{
5869
_callback_function = std::move(callback);
5970
_attach_ms(milliseconds, true);
6071
}
6172

73+
// callback will be called in SYS ctx when ticker fires
6274
template<typename TArg>
6375
void attach(float seconds, void (*callback)(TArg), TArg arg)
6476
{
6577
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
6678
_attach_ms(1000UL * seconds, true, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
6779
}
6880

81+
// callback will be called in SYS ctx when ticker fires
6982
template<typename TArg>
7083
void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)
7184
{
7285
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
7386
_attach_ms(milliseconds, true, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
7487
}
7588

89+
// callback will be called at following loop() after ticker fires
7690
void once_scheduled(float seconds, callback_function_t callback)
7791
{
7892
_callback_function = [callback]() { schedule_function(callback); };
7993
_attach_ms(1000UL * seconds, false);
8094
}
8195

96+
// callback will be called in SYS ctx when ticker fires
8297
void once(float seconds, callback_function_t callback)
8398
{
8499
_callback_function = std::move(callback);
85100
_attach_ms(1000UL * seconds, false);
86101
}
87102

103+
// callback will be called at following loop() after ticker fires
88104
void once_ms_scheduled(uint32_t milliseconds, callback_function_t callback)
89105
{
90106
_callback_function = [callback]() { schedule_function(callback); };
91107
_attach_ms(milliseconds, false);
92108
}
93109

110+
// callback will be called in SYS ctx when ticker fires
94111
void once_ms(uint32_t milliseconds, callback_function_t callback)
95112
{
96113
_callback_function = std::move(callback);
97114
_attach_ms(milliseconds, false);
98115
}
99116

117+
// callback will be called in SYS ctx when ticker fires
100118
template<typename TArg>
101119
void once(float seconds, void (*callback)(TArg), TArg arg)
102120
{
103121
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
104122
_attach_ms(1000UL * seconds, false, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
105123
}
106124

125+
// callback will be called in SYS ctx when ticker fires
107126
template<typename TArg>
108127
void once_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)
109128
{

tests/host/common/MocklwIP.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,11 @@ const ip_addr_t* sntp_getserver(u8_t)
2626
return IP_ADDR_ANY;
2727
}
2828

29+
err_t etharp_request(struct netif *netif, const ip4_addr_t *ipaddr)
30+
{
31+
(void)netif;
32+
(void)ipaddr;
33+
return ERR_OK;
34+
}
35+
2936
} // extern "C"

0 commit comments

Comments
 (0)