Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BREAKING] wifi: remove pseudo-modes for shutdown, expose ::[resumeFrom]shutdown() #7956

Merged
merged 10 commits into from
May 15, 2021
58 changes: 34 additions & 24 deletions doc/esp8266wifi/generic-class.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ Once ``WiFi.persistent(false)`` is called, ``WiFi.begin``, ``WiFi.disconnect``,
mode
~~~~

Regular WiFi modes
__________________

.. code:: cpp

bool mode(WiFiMode_t m)
Expand All @@ -65,25 +62,6 @@ Switches to one of the regular WiFi modes, where ``m`` is one of:
- ``WIFI_AP``: switch to `Access Point (AP) <readme.rst#soft-access-point>`__ mode.
- ``WIFI_AP_STA``: enable both Station (STA) and Access Point (AP) mode.

Pseudo-modes
____________

.. code:: cpp

bool mode(WiFiMode_t m, WiFiState* state)

Used with the following pseudo-modes, where ``m`` is one of:

- ``WIFI_SHUTDOWN``: Fills in the provided ``WiFiState`` structure, switches to ``WIFI_OFF`` mode and puts WiFi into forced sleep, preserving energy.
- ``WIFI_RESUME``: Turns WiFi on and tries to re-establish the WiFi connection stored in the ``WiFiState`` structure.

These modes are 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 ``WIFI_SHUTDOWN`` and ``WIFI_RESUME``, e.g. by storing it
in RTC user data and/or flash memory.

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.

getMode
~~~~~~~

Expand Down Expand Up @@ -170,6 +148,40 @@ getPhyMode

Gets the WiFi radio phy mode that is currently set.

forceSleepBegin
~~~~~~~~~~~~~~~

.. code:: cpp

bool forceSleepBegin (uint32_t sleepUs=0)
bool forceSleepWake ()

Saves the currently set WiFi mode and starts forced modem sleep for the specified time (us)

forceSleepWake
~~~~~~~~~~~~~~

.. code:: cpp

bool forceSleepWake ()

Called after `forceSleepBegin()`. Restores the previous WiFi mode. Attemtps reconnection when STA was active.

shutdown and resumeFromShutdown
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code:: cpp

bool shutdown (uint32_t sleepUs, WiFiState* state)
bool resumeFromShutdown (WiFiState* state)

Stores the STA interface IP configuration in the specified state struct and calls ``forceSleepBegin(sleepUs)``.
Restores STA interface configuration from the ``state`` and calls ``forceSleepWake()``.

These method is 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.

See `WiFiShutdown.ino <https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiShutdown/WiFiShutdown.ino>`__ for an example of usage.

Other Function Calls
~~~~~~~~~~~~~~~~~~~~

Expand All @@ -179,8 +191,6 @@ Other Function Calls
WiFiSleepType_t getSleepMode ()
bool enableSTA (bool enable)
bool enableAP (bool enable)
bool forceSleepBegin (uint32 sleepUs=0)
bool forceSleepWake ()
int hostByName (const char *aHostname, IPAddress &aResult)

appeared with SDK pre-V3:
Expand Down
8 changes: 4 additions & 4 deletions libraries/ESP8266WiFi/examples/WiFiShutdown/WiFiShutdown.ino
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

// Demonstrate the use of WiFi.mode(WIFI_SHUTDOWN)/WiFi.mode(WIFI_RESUME)
// Demonstrate the use of WiFi.shutdown() and WiFi.resumeFromShutdown()
// Released to public domain

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

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

WiFi.mode(WIFI_SHUTDOWN, &state);
WiFi.shutdown(0, &state);
ESP.rtcUserMemoryWrite(RTC_USER_DATA_SLOT_WIFI_STATE, reinterpret_cast<uint32_t *>(&state), sizeof(state));

// ---
Expand All @@ -82,4 +82,4 @@ void setup() {

void loop() {
// Nothing to do here.
}
}
2 changes: 2 additions & 0 deletions libraries/ESP8266WiFi/keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ enableSTA KEYWORD2
enableAP KEYWORD2
forceSleepBegin KEYWORD2
forceSleepWake KEYWORD2
shutdown KEYWORD2
resumeFromShutdown KEYWORD2

#ESP8266WiFi
printDiag KEYWORD2
Expand Down
17 changes: 3 additions & 14 deletions libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,21 +401,10 @@ bool ESP8266WiFiGenericClass::getPersistent(){
* set new mode
* @param m WiFiMode_t
*/
bool ESP8266WiFiGenericClass::mode(WiFiMode_t m, WiFiState* state) {
if (m == WIFI_SHUTDOWN) {
return shutdown(0, state);
}
else if (m == WIFI_RESUME) {
return resumeFromShutdown(state);
}
else if (m & ~(WIFI_STA | WIFI_AP))
bool ESP8266WiFiGenericClass::mode(WiFiMode_t m) {
if (m & ~(WIFI_STA | WIFI_AP)) {
// any other bits than legacy disallowed
return false;

// m is now WIFI_STA, WIFI_AP or WIFI_AP_STA
if (state)
{
DEBUG_WIFI("core: state is useless without SHUTDOWN or RESUME\n");
}

if (wifi_fpm_get_sleep_type() != NONE_SLEEP_T) {
Expand Down Expand Up @@ -729,7 +718,7 @@ bool ESP8266WiFiGenericClass::shutdownValidCRC (const WiFiState* state)
return state && (crc32(&state->state, sizeof(state->state)) == state->crc);
}

bool ESP8266WiFiGenericClass::shutdown (uint32 sleepUs, WiFiState* state)
bool ESP8266WiFiGenericClass::shutdown (uint32_t sleepUs, WiFiState* state)
{
bool persistent = _persistent;
WiFiMode_t before_off_mode = getMode();
Expand Down
20 changes: 11 additions & 9 deletions libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,30 +122,32 @@ class ESP8266WiFiGenericClass {

void persistent(bool persistent);

bool mode(WiFiMode_t, WiFiState* state = nullptr);
bool mode(WiFiMode_t);
WiFiMode_t getMode();

bool enableSTA(bool enable);
bool enableAP(bool enable);

bool forceSleepBegin(uint32 sleepUs = 0);
bool forceSleepBegin(uint32_t sleepUs = 0);
bool forceSleepWake();

static uint32_t shutdownCRC (const WiFiState* state);
// wrappers around mode() and forceSleepBegin/Wake
// - sleepUs is WiFi.forceSleepBegin() parameter, 0 means forever
// - saveState is the user's state to hold configuration on restore
bool shutdown(uint32_t sleepUs = 0, WiFiState* stateSave = nullptr);
bool resumeFromShutdown(WiFiState* savedState = nullptr);

static bool shutdownValidCRC (const WiFiState* state);

static void preinitWiFiOff (); //meant to be called in user-defined preinit()

protected:
static bool _persistent;
static WiFiMode_t _forceSleepLastMode;

static void _eventCallback(void *event);
static uint32_t shutdownCRC (const WiFiState* state);

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

// ----------------------------------------------------------------------------------------------
// ------------------------------------ Generic Network function --------------------------------
Expand Down
3 changes: 1 addition & 2 deletions libraries/ESP8266WiFi/src/ESP8266WiFiType.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@

typedef enum WiFiMode
{
WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3,
/* these two pseudo modes are experimental: */ WIFI_SHUTDOWN = 4, WIFI_RESUME = 8
WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3
} WiFiMode_t;

typedef enum WiFiPhyMode
Expand Down
12 changes: 6 additions & 6 deletions libraries/esp8266/examples/LowPowerDemo/LowPowerDemo.ino
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ void runTest2() {

void runTest3() {
Serial.println(F("\n3rd test - Forced Modem Sleep"));
WiFi.mode(WIFI_SHUTDOWN, &nv->wss); // shut the modem down and save the WiFi state for faster reconnection
WiFi.shutdown(0, &nv->wss); // shut the modem down and save the WiFi state for faster reconnection
// WiFi.forceSleepBegin(delay_in_uS); // alternate method of Forced Modem Sleep for an optional timed shutdown,
// with WiFi.forceSleepBegin(0xFFFFFFF); the modem sleeps until you wake it, with values <= 0xFFFFFFE it's timed
// delay(10); // it doesn't always go to sleep unless you delay(10); yield() wasn't reliable
Expand Down Expand Up @@ -290,7 +290,7 @@ void runTest7() {
delay(50); // debounce time for the switch, pushbutton released
waitPushbutton(false, blinkDelay); // set true if you want to see Automatic Modem Sleep
digitalWrite(LED, LOW); // turn the LED on, at least briefly
//WiFi.mode(WIFI_SHUTDOWN, &nv->wss); // Forced Modem Sleep for a more Instant Deep Sleep,
//WiFi.shutdown(0, &nv->wss); // Forced Modem Sleep for a more Instant Deep Sleep,
// and no extended RFCAL as it goes into Deep Sleep
Serial.println(F("going into Deep Sleep now..."));
printMillis(); // show time difference across sleep
Expand All @@ -308,7 +308,7 @@ void runTest8() {
readVoltage(); // read internal VCC
Serial.println(F("press the switch to continue"));
waitPushbutton(false, blinkDelay); // set true if you want to see Automatic Modem Sleep
//WiFi.mode(WIFI_SHUTDOWN, &nv->wss); // Forced Modem Sleep for a more Instant Deep Sleep,
//WiFi.shutdown(0, &nv->wss); // Forced Modem Sleep for a more Instant Deep Sleep,
// and no extended RFCAL as it goes into Deep Sleep
Serial.println(F("going into Deep Sleep now..."));
Serial.flush(); // needs a delay(10) or Serial.flush() else it doesn't print the whole message
Expand All @@ -322,7 +322,7 @@ void runTest9() {
readVoltage(); // read internal VCC
Serial.println(F("press the switch to continue"));
waitPushbutton(false, blinkDelay); // set true if you want to see Automatic Modem Sleep
WiFi.mode(WIFI_SHUTDOWN, &nv->wss); // Forced Modem Sleep for a more Instant Deep Sleep
WiFi.shutdown(0, &nv->wss); // Forced Modem Sleep for a more Instant Deep Sleep
Serial.println(F("going into Deep Sleep now..."));
Serial.flush(); // needs a delay(10) or Serial.flush() else it doesn't print the whole message
testPoint_HIGH; // testPoint set HIGH to track Deep Sleep period, cleared at startup()
Expand All @@ -335,7 +335,7 @@ void runTest10() {
readVoltage(); // read internal VCC
Serial.println(F("press the switch to continue"));
waitPushbutton(false, blinkDelay); // set true if you want to see Automatic Modem Sleep
//WiFi.mode(WIFI_SHUTDOWN); // Forced Modem Sleep for a more Instant Deep Sleep
//WiFi.shutdown(); // Forced Modem Sleep for a more Instant Deep Sleep
Serial.println(F("going into Deep Sleep now..."));
Serial.flush(); // needs a delay(10) or Serial.flush() else it doesn't print the whole message
testPoint_HIGH; // testPoint set HIGH to track Deep Sleep period, cleared at startup()
Expand Down Expand Up @@ -405,7 +405,7 @@ void initWiFi() {
memcpy((uint32_t*) &nv->rtcData.rstCount + 1, (uint32_t*) &nv->wss, sizeof(nv->wss)); // save a copy of it
Serial.println(F("resuming WiFi"));
}
if (!(WiFi.mode(WIFI_RESUME, &nv->wss))) { // couldn't resume, or no valid saved WiFi state yet
if (!(WiFi.resumeFromShutdown(&nv->wss))) { // couldn't resume, or no valid saved WiFi state yet
/* Explicitly set the ESP8266 as a WiFi-client (STAtion mode), otherwise by default it
would try to act as both a client and an access-point and could cause network issues
with other WiFi devices on your network. */
Expand Down