Skip to content

Commit b0ece8c

Browse files
authored
[BREAKING] wifi: remove pseudo-modes for shutdown, expose ::[resumeFrom]shutdown() (#7956)
* wifi: remove pseudo-modes for shutdown make shutdown and resumeFromShutdown public removes extra code from the mode handler and include method description in the docs * typo * dup * typos * reference only shutdown() & resumeFromShutdown() prefer to have some specific function, don't simply chain into sleep update examples and docs * safeguard raw sdk config usage
1 parent e9820c1 commit b0ece8c

File tree

7 files changed

+122
-100
lines changed

7 files changed

+122
-100
lines changed

doc/esp8266wifi/generic-class.rst

+35-24
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,6 @@ Once ``WiFi.persistent(false)`` is called, ``WiFi.begin``, ``WiFi.disconnect``,
8080
mode
8181
~~~~
8282

83-
Regular WiFi modes
84-
__________________
85-
8683
.. code:: cpp
8784
8885
bool mode(WiFiMode_t m)
@@ -94,25 +91,6 @@ Switches to one of the regular WiFi modes, where ``m`` is one of:
9491
- ``WIFI_AP``: switch to `Access Point (AP) <readme.rst#soft-access-point>`__ mode.
9592
- ``WIFI_AP_STA``: enable both Station (STA) and Access Point (AP) mode.
9693

97-
Pseudo-modes
98-
____________
99-
100-
.. code:: cpp
101-
102-
bool mode(WiFiMode_t m, WiFiState* state)
103-
104-
Used with the following pseudo-modes, where ``m`` is one of:
105-
106-
- ``WIFI_SHUTDOWN``: Fills in the provided ``WiFiState`` structure, switches to ``WIFI_OFF`` mode and puts WiFi into forced sleep, preserving energy.
107-
- ``WIFI_RESUME``: Turns WiFi on and tries to re-establish the WiFi connection stored in the ``WiFiState`` structure.
108-
109-
These modes are used in low-power scenarios, e.g. where ESP.deepSleep is used between actions to preserve battery power.
110-
111-
It is the user's responsibility to preserve the WiFiState between ``WIFI_SHUTDOWN`` and ``WIFI_RESUME``, e.g. by storing it
112-
in RTC user data and/or flash memory.
113-
114-
There is an example sketch `WiFiShutdown.ino <https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiShutdown/WiFiShutdown.ino>`__ available in the examples folder of the ESP8266WiFi library.
115-
11694
getMode
11795
~~~~~~~
11896

@@ -199,6 +177,41 @@ getPhyMode
199177
200178
Gets the WiFi radio phy mode that is currently set.
201179

180+
forceSleepBegin
181+
~~~~~~~~~~~~~~~
182+
183+
.. code:: cpp
184+
185+
bool forceSleepBegin (uint32 sleepUs=0)
186+
187+
Saves the currently set WiFi mode and starts forced modem sleep for the specified time (us)
188+
189+
forceSleepWake
190+
~~~~~~~~~~~~~~
191+
192+
.. code:: cpp
193+
194+
bool forceSleepWake ()
195+
196+
Called after `forceSleepBegin()`. Restores the previous WiFi mode and attempts reconnection when STA was active.
197+
198+
shutdown and resumeFromShutdown
199+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
200+
201+
.. code:: cpp
202+
203+
bool shutdown (WiFiState& state)
204+
bool shutdown (WiFiState& state, uint32 sleepUs)
205+
bool resumeFromShutdown (WiFiState& state)
206+
bool shutdownValidCRC (const WiFiState& state)
207+
208+
Stores the STA interface IP configuration in the specified ``state`` struct and calls ``forceSleepBegin(sleepUs)``.
209+
Restores STA interface configuration from the ``state`` and calls ``forceSleepWake()``.
210+
211+
These methods are intended to be used in low-power scenarios, e.g. where ESP.deepSleep is used between actions to preserve battery power. It is the user's responsibility to preserve the WiFiState between ``shutdown()`` and ``resumeFromShutdown()`` by storing it in the RTC user data and/or flash memory.
212+
213+
See `WiFiShutdown.ino <https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiShutdown/WiFiShutdown.ino>`__ for an example of usage.
214+
202215
Other Function Calls
203216
~~~~~~~~~~~~~~~~~~~~
204217

@@ -208,8 +221,6 @@ Other Function Calls
208221
WiFiSleepType_t getSleepMode ()
209222
bool enableSTA (bool enable)
210223
bool enableAP (bool enable)
211-
bool forceSleepBegin (uint32 sleepUs=0)
212-
bool forceSleepWake ()
213224
int hostByName (const char *aHostname, IPAddress &aResult)
214225
215226
appeared with SDK pre-V3:

libraries/ESP8266WiFi/examples/WiFiShutdown/WiFiShutdown.ino

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
// Demonstrate the use of WiFi.mode(WIFI_SHUTDOWN)/WiFi.mode(WIFI_RESUME)
2+
// Demonstrate the use of WiFi.shutdown() and WiFi.resumeFromShutdown()
33
// Released to public domain
44

55
// Current on WEMOS D1 mini (including: LDO, usbserial chip):
@@ -39,7 +39,7 @@ void setup() {
3939
ESP.rtcUserMemoryRead(RTC_USER_DATA_SLOT_WIFI_STATE, reinterpret_cast<uint32_t *>(&state), sizeof(state));
4040
unsigned long start = millis();
4141

42-
if (!WiFi.mode(WIFI_RESUME, &state)
42+
if (!WiFi.resumeFromShutdown(state)
4343
|| (WiFi.waitForConnectResult(10000) != WL_CONNECTED)) {
4444
Serial.println("Cannot resume WiFi connection, connecting via begin...");
4545
WiFi.persistent(false);
@@ -63,7 +63,7 @@ void setup() {
6363
// Here you can do whatever you need to do that needs a WiFi connection.
6464
// ---
6565

66-
WiFi.mode(WIFI_SHUTDOWN, &state);
66+
WiFi.shutdown(state);
6767
ESP.rtcUserMemoryWrite(RTC_USER_DATA_SLOT_WIFI_STATE, reinterpret_cast<uint32_t *>(&state), sizeof(state));
6868

6969
// ---
@@ -77,4 +77,4 @@ void setup() {
7777

7878
void loop() {
7979
// Nothing to do here.
80-
}
80+
}

libraries/ESP8266WiFi/keywords.txt

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ enableSTA KEYWORD2
5656
enableAP KEYWORD2
5757
forceSleepBegin KEYWORD2
5858
forceSleepWake KEYWORD2
59+
shutdown KEYWORD2
60+
resumeFromShutdown KEYWORD2
5961

6062
#ESP8266WiFi
6163
printDiag KEYWORD2

libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp

+61-53
Original file line numberDiff line numberDiff line change
@@ -401,21 +401,10 @@ bool ESP8266WiFiGenericClass::getPersistent(){
401401
* set new mode
402402
* @param m WiFiMode_t
403403
*/
404-
bool ESP8266WiFiGenericClass::mode(WiFiMode_t m, WiFiState* state) {
405-
if (m == WIFI_SHUTDOWN) {
406-
return shutdown(0, state);
407-
}
408-
else if (m == WIFI_RESUME) {
409-
return resumeFromShutdown(state);
410-
}
411-
else if (m & ~(WIFI_STA | WIFI_AP))
404+
bool ESP8266WiFiGenericClass::mode(WiFiMode_t m) {
405+
if (m & ~(WIFI_STA | WIFI_AP)) {
412406
// any other bits than legacy disallowed
413407
return false;
414-
415-
// m is now WIFI_STA, WIFI_AP or WIFI_AP_STA
416-
if (state)
417-
{
418-
DEBUG_WIFI("core: state is useless without SHUTDOWN or RESUME\n");
419408
}
420409

421410
if(_persistent){
@@ -719,37 +708,37 @@ void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *ca
719708
esp_schedule(); // break delay in hostByName
720709
}
721710

722-
uint32_t ESP8266WiFiGenericClass::shutdownCRC (const WiFiState* state)
711+
uint32_t ESP8266WiFiGenericClass::shutdownCRC (const WiFiState& state)
723712
{
724-
return state? crc32(&state->state, sizeof(state->state)): 0;
713+
return crc32(&state.state, sizeof(state.state));
725714
}
726715

727-
bool ESP8266WiFiGenericClass::shutdownValidCRC (const WiFiState* state)
716+
bool ESP8266WiFiGenericClass::shutdownValidCRC (const WiFiState& state)
728717
{
729-
return state && (crc32(&state->state, sizeof(state->state)) == state->crc);
718+
return crc32(&state.state, sizeof(state.state)) == state.crc;
730719
}
731720

732-
bool ESP8266WiFiGenericClass::shutdown (uint32 sleepUs, WiFiState* state)
721+
bool ESP8266WiFiGenericClass::shutdown (WiFiState& state, uint32 sleepUs)
733722
{
734723
bool persistent = _persistent;
735724
WiFiMode_t before_off_mode = getMode();
736725

737-
if ((before_off_mode & WIFI_STA) && state)
726+
if (before_off_mode & WIFI_STA)
738727
{
739-
bool ret = wifi_get_ip_info(STATION_IF, &state->state.ip);
728+
bool ret = wifi_get_ip_info(STATION_IF, &state.state.ip);
740729
if (!ret)
741730
{
742731
DEBUG_WIFI("core: error with wifi_get_ip_info(STATION_IF)\n");
743732
return false;
744733
}
745-
memset(state->state.fwconfig.bssid, 0xff, 6);
746-
ret = wifi_station_get_config(&state->state.fwconfig);
734+
memset(state.state.fwconfig.bssid, 0xff, 6);
735+
ret = wifi_station_get_config(&state.state.fwconfig);
747736
if (!ret)
748737
{
749738
DEBUG_WIFI("core: error with wifi_station_get_config\n");
750739
return false;
751740
}
752-
state->state.channel = wifi_get_channel();
741+
state.state.channel = wifi_get_channel();
753742
}
754743

755744
// disable persistence in FW so in case of power failure
@@ -766,57 +755,63 @@ bool ESP8266WiFiGenericClass::shutdown (uint32 sleepUs, WiFiState* state)
766755
}
767756

768757
// WiFi is now in force-sleep mode
758+
// finish filling state and process crc
759+
760+
state.state.persistent = persistent;
761+
state.state.mode = before_off_mode;
769762

770-
if (state)
763+
uint8_t i = 0;
764+
for (auto& ntp: state.state.ntp)
771765
{
772-
// finish filling state and process crc
766+
ntp = *sntp_getserver(i++);
767+
}
768+
i = 0;
773769

774-
state->state.persistent = persistent;
775-
state->state.mode = before_off_mode;
776-
uint8_t i = 0;
777-
for (auto& ntp: state->state.ntp)
778-
{
779-
ntp = *sntp_getserver(i++);
780-
}
781-
i = 0;
782-
for (auto& dns: state->state.dns)
783-
dns = WiFi.dnsIP(i++);
784-
state->crc = shutdownCRC(state);
785-
DEBUG_WIFI("core: state is saved\n");
770+
for (auto& dns: state.state.dns)
771+
{
772+
dns = WiFi.dnsIP(i++);
786773
}
774+
775+
state.crc = shutdownCRC(state);
776+
DEBUG_WIFI("core: state is saved\n");
777+
787778
return true;
788779
}
789780

790-
bool ESP8266WiFiGenericClass::resumeFromShutdown (WiFiState* state)
781+
bool ESP8266WiFiGenericClass::shutdown (WiFiState& state) {
782+
return shutdown(state, 0);
783+
}
784+
785+
bool ESP8266WiFiGenericClass::resumeFromShutdown (WiFiState& state)
791786
{
792787
if (wifi_fpm_get_sleep_type() != NONE_SLEEP_T) {
793788
wifi_fpm_do_wakeup();
794789
wifi_fpm_close();
795790
}
796791

797-
if (!state || shutdownCRC(state) != state->crc)
792+
if (shutdownCRC(state) != state.crc)
798793
{
799-
DEBUG_WIFI("core: resume: no state or bad crc\n");
794+
DEBUG_WIFI("core: resume: bad crc\n");
800795
return false;
801796
}
802797

803-
persistent(state->state.persistent);
798+
persistent(state.state.persistent);
804799

805-
if (!mode(state->state.mode))
800+
if (!mode(state.state.mode))
806801
{
807-
DEBUG_WIFI("core: resume: can't set wifi mode to %d\n", state->state.mode);
802+
DEBUG_WIFI("core: resume: can't set wifi mode to %d\n", state.state.mode);
808803
return false;
809804
}
810805

811-
if (state->state.mode & WIFI_STA)
806+
if (state.state.mode & WIFI_STA)
812807
{
813-
IPAddress local(state->state.ip.ip);
808+
IPAddress local(state.state.ip.ip);
814809
if (local)
815810
{
816811
DEBUG_WIFI("core: resume: static address '%s'\n", local.toString().c_str());
817-
WiFi.config(state->state.ip.ip, state->state.ip.gw, state->state.ip.netmask, state->state.dns[0], state->state.dns[1]);
812+
WiFi.config(state.state.ip.ip, state.state.ip.gw, state.state.ip.netmask, state.state.dns[0], state.state.dns[1]);
818813
uint8_t i = 0;
819-
for (const auto& ntp: state->state.ntp)
814+
for (const auto& ntp: state.state.ntp)
820815
{
821816
IPAddress ip(ntp);
822817
if (ip.isSet())
@@ -826,10 +821,23 @@ bool ESP8266WiFiGenericClass::resumeFromShutdown (WiFiState* state)
826821
}
827822
}
828823
}
829-
auto beginResult = WiFi.begin((const char*)state->state.fwconfig.ssid,
830-
(const char*)state->state.fwconfig.password,
831-
state->state.channel,
832-
state->state.fwconfig.bssid,
824+
825+
String ssid;
826+
{
827+
const char* ptr = reinterpret_cast<const char*>(state.state.fwconfig.ssid);
828+
ssid.concat(ptr, strnlen(ptr, sizeof(station_config::ssid)));
829+
}
830+
831+
String pass;
832+
{
833+
const char* ptr = reinterpret_cast<const char*>(state.state.fwconfig.password);
834+
pass.concat(ptr, strnlen(ptr, sizeof(station_config::password)));
835+
}
836+
837+
auto beginResult = WiFi.begin(ssid.c_str(),
838+
pass.c_str(),
839+
state.state.channel,
840+
state.state.fwconfig.bssid,
833841
true);
834842
if (beginResult == WL_CONNECT_FAILED)
835843
{
@@ -843,14 +851,14 @@ bool ESP8266WiFiGenericClass::resumeFromShutdown (WiFiState* state)
843851
}
844852
}
845853

846-
if (state->state.mode & WIFI_AP)
854+
if (state.state.mode & WIFI_AP)
847855
{
848856
DEBUG_WIFI("core: resume AP mode TODO\n");
849857
return false;
850858
}
851859

852860
// success, invalidate saved state
853-
state->crc++;
861+
state.crc++;
854862

855863
return true;
856864
}

libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h

+11-9
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ class ESP8266WiFiGenericClass {
122122

123123
static void persistent(bool persistent);
124124

125-
bool mode(WiFiMode_t, WiFiState* state = nullptr);
125+
bool mode(WiFiMode_t);
126126
WiFiMode_t getMode();
127127

128128
bool enableSTA(bool enable);
@@ -131,21 +131,23 @@ class ESP8266WiFiGenericClass {
131131
bool forceSleepBegin(uint32 sleepUs = 0);
132132
bool forceSleepWake();
133133

134-
static uint32_t shutdownCRC (const WiFiState* state);
135-
static bool shutdownValidCRC (const WiFiState* state);
134+
// wrappers around mode() and forceSleepBegin/Wake
135+
// - sleepUs is WiFi.forceSleepBegin() parameter, 0 means forever
136+
// - saveState is the user's state to hold configuration on restore
137+
bool shutdown(WiFiState& stateSave);
138+
bool shutdown(WiFiState& stateSave, uint32 sleepUs);
139+
bool resumeFromShutdown(WiFiState& savedState);
140+
141+
static bool shutdownValidCRC (const WiFiState& state);
136142
static void preinitWiFiOff () __attribute__((deprecated("WiFi is off by default at boot, use enableWiFiAtBoot() for legacy behavior")));
137143

138144
protected:
139145
static bool _persistent;
140146
static WiFiMode_t _forceSleepLastMode;
141147

142-
static void _eventCallback(void *event);
148+
static uint32_t shutdownCRC (const WiFiState& state);
143149

144-
// called by WiFi.mode(SHUTDOWN/RESTORE, state)
145-
// - sleepUs is WiFi.forceSleepBegin() parameter, 0 = forever
146-
// - saveState is the user's state to hold configuration on restore
147-
bool shutdown (uint32 sleepUs = 0, WiFiState* stateSave = nullptr);
148-
bool resumeFromShutdown (WiFiState* savedState = nullptr);
150+
static void _eventCallback(void *event);
149151

150152
// ----------------------------------------------------------------------------------------------
151153
// ------------------------------------ Generic Network function --------------------------------

libraries/ESP8266WiFi/src/ESP8266WiFiType.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@
3434

3535
typedef enum WiFiMode
3636
{
37-
WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3,
38-
/* these two pseudo modes are experimental: */ WIFI_SHUTDOWN = 4, WIFI_RESUME = 8
37+
WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3
3938
} WiFiMode_t;
4039

4140
typedef enum WiFiPhyMode

0 commit comments

Comments
 (0)