diff --git a/doc/esp8266wifi/generic-class.rst b/doc/esp8266wifi/generic-class.rst
index 44b8e6e73b..36a0180c2b 100644
--- a/doc/esp8266wifi/generic-class.rst
+++ b/doc/esp8266wifi/generic-class.rst
@@ -80,9 +80,6 @@ Once ``WiFi.persistent(false)`` is called, ``WiFi.begin``, ``WiFi.disconnect``,
 mode
 ~~~~
 
-Regular WiFi modes
-__________________
-
 .. code:: cpp
 
     bool mode(WiFiMode_t m)
@@ -94,25 +91,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
 ~~~~~~~
 
@@ -199,6 +177,41 @@ getPhyMode
 
 Gets the WiFi radio phy mode that is currently set.
 
+forceSleepBegin
+~~~~~~~~~~~~~~~
+
+.. code:: cpp
+
+    bool  forceSleepBegin (uint32 sleepUs=0)
+
+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 and attempts reconnection when STA was active.
+
+shutdown and resumeFromShutdown
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code:: cpp
+
+    bool  shutdown (WiFiState& state)
+    bool  shutdown (WiFiState& state, uint32 sleepUs)
+    bool  resumeFromShutdown (WiFiState& state)
+    bool  shutdownValidCRC (const 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 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.
+
+See `WiFiShutdown.ino <https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiShutdown/WiFiShutdown.ino>`__ for an example of usage.
+
 Other Function Calls
 ~~~~~~~~~~~~~~~~~~~~
 
@@ -208,8 +221,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:
diff --git a/libraries/ESP8266WiFi/examples/WiFiShutdown/WiFiShutdown.ino b/libraries/ESP8266WiFi/examples/WiFiShutdown/WiFiShutdown.ino
index 7fac16b45d..b03357c143 100644
--- a/libraries/ESP8266WiFi/examples/WiFiShutdown/WiFiShutdown.ino
+++ b/libraries/ESP8266WiFi/examples/WiFiShutdown/WiFiShutdown.ino
@@ -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):
@@ -39,7 +39,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);
@@ -63,7 +63,7 @@ void setup() {
   // Here you can do whatever you need to do that needs a WiFi connection.
   // ---
 
-  WiFi.mode(WIFI_SHUTDOWN, &state);
+  WiFi.shutdown(state);
   ESP.rtcUserMemoryWrite(RTC_USER_DATA_SLOT_WIFI_STATE, reinterpret_cast<uint32_t *>(&state), sizeof(state));
 
   // ---
@@ -77,4 +77,4 @@ void setup() {
 
 void loop() {
   // Nothing to do here.
-}
\ No newline at end of file
+}
diff --git a/libraries/ESP8266WiFi/keywords.txt b/libraries/ESP8266WiFi/keywords.txt
index ccdef76809..e5c11a1d94 100644
--- a/libraries/ESP8266WiFi/keywords.txt
+++ b/libraries/ESP8266WiFi/keywords.txt
@@ -56,6 +56,8 @@ enableSTA	KEYWORD2
 enableAP	KEYWORD2
 forceSleepBegin	KEYWORD2
 forceSleepWake	KEYWORD2
+shutdown	KEYWORD2
+resumeFromShutdown	KEYWORD2
 
 #ESP8266WiFi
 printDiag	KEYWORD2
diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp
index 7518f3c598..19da592c76 100644
--- a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp
+++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp
@@ -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(_persistent){
@@ -719,37 +708,37 @@ void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *ca
     esp_schedule(); // break delay in hostByName
 }
 
-uint32_t ESP8266WiFiGenericClass::shutdownCRC (const WiFiState* state)
+uint32_t ESP8266WiFiGenericClass::shutdownCRC (const WiFiState& state)
 {
-    return state? crc32(&state->state, sizeof(state->state)): 0;
+    return crc32(&state.state, sizeof(state.state));
 }
 
-bool ESP8266WiFiGenericClass::shutdownValidCRC (const WiFiState* state)
+bool ESP8266WiFiGenericClass::shutdownValidCRC (const WiFiState& state)
 {
-    return state && (crc32(&state->state, sizeof(state->state)) == state->crc);
+    return crc32(&state.state, sizeof(state.state)) == state.crc;
 }
 
-bool ESP8266WiFiGenericClass::shutdown (uint32 sleepUs, WiFiState* state)
+bool ESP8266WiFiGenericClass::shutdown (WiFiState& state, uint32 sleepUs)
 {
     bool persistent = _persistent;
     WiFiMode_t before_off_mode = getMode();
 
-    if ((before_off_mode & WIFI_STA) && state)
+    if (before_off_mode & WIFI_STA)
     {
-        bool ret = wifi_get_ip_info(STATION_IF, &state->state.ip);
+        bool ret = wifi_get_ip_info(STATION_IF, &state.state.ip);
         if (!ret)
         {
             DEBUG_WIFI("core: error with wifi_get_ip_info(STATION_IF)\n");
             return false;
         }
-        memset(state->state.fwconfig.bssid, 0xff, 6);
-        ret = wifi_station_get_config(&state->state.fwconfig);
+        memset(state.state.fwconfig.bssid, 0xff, 6);
+        ret = wifi_station_get_config(&state.state.fwconfig);
         if (!ret)
         {
             DEBUG_WIFI("core: error with wifi_station_get_config\n");
             return false;
         }
-        state->state.channel = wifi_get_channel();
+        state.state.channel = wifi_get_channel();
     }
 
     // disable persistence in FW so in case of power failure
@@ -766,57 +755,63 @@ bool ESP8266WiFiGenericClass::shutdown (uint32 sleepUs, WiFiState* state)
     }
 
     // WiFi is now in force-sleep mode
+    // finish filling state and process crc
+
+    state.state.persistent = persistent;
+    state.state.mode = before_off_mode;
 
-    if (state)
+    uint8_t i = 0;
+    for (auto& ntp: state.state.ntp)
     {
-        // finish filling state and process crc
+        ntp = *sntp_getserver(i++);
+    }
+    i = 0;
 
-        state->state.persistent = persistent;
-        state->state.mode = before_off_mode;
-        uint8_t i = 0;
-        for (auto& ntp: state->state.ntp)
-        {
-            ntp = *sntp_getserver(i++);
-        }
-        i = 0;
-        for (auto& dns: state->state.dns)
-            dns = WiFi.dnsIP(i++);
-        state->crc = shutdownCRC(state);
-        DEBUG_WIFI("core: state is saved\n");
+    for (auto& dns: state.state.dns)
+    {
+        dns = WiFi.dnsIP(i++);
     }
+
+    state.crc = shutdownCRC(state);
+    DEBUG_WIFI("core: state is saved\n");
+
     return true;
 }
 
-bool ESP8266WiFiGenericClass::resumeFromShutdown (WiFiState* state)
+bool ESP8266WiFiGenericClass::shutdown (WiFiState& state) {
+    return shutdown(state, 0);
+}
+
+bool ESP8266WiFiGenericClass::resumeFromShutdown (WiFiState& state)
 {
     if (wifi_fpm_get_sleep_type() != NONE_SLEEP_T) {
         wifi_fpm_do_wakeup();
         wifi_fpm_close();
     }
 
-    if (!state || shutdownCRC(state) != state->crc)
+    if (shutdownCRC(state) != state.crc)
     {
-        DEBUG_WIFI("core: resume: no state or bad crc\n");
+        DEBUG_WIFI("core: resume: bad crc\n");
         return false;
     }
 
-    persistent(state->state.persistent);
+    persistent(state.state.persistent);
 
-    if (!mode(state->state.mode))
+    if (!mode(state.state.mode))
     {
-        DEBUG_WIFI("core: resume: can't set wifi mode to %d\n", state->state.mode);
+        DEBUG_WIFI("core: resume: can't set wifi mode to %d\n", state.state.mode);
         return false;
     }
 
-    if (state->state.mode & WIFI_STA)
+    if (state.state.mode & WIFI_STA)
     {
-        IPAddress local(state->state.ip.ip);
+        IPAddress local(state.state.ip.ip);
         if (local)
         {
             DEBUG_WIFI("core: resume: static address '%s'\n", local.toString().c_str());
-            WiFi.config(state->state.ip.ip, state->state.ip.gw, state->state.ip.netmask, state->state.dns[0], state->state.dns[1]);
+            WiFi.config(state.state.ip.ip, state.state.ip.gw, state.state.ip.netmask, state.state.dns[0], state.state.dns[1]);
             uint8_t i = 0;
-            for (const auto& ntp: state->state.ntp)
+            for (const auto& ntp: state.state.ntp)
             {
                 IPAddress ip(ntp);
                 if (ip.isSet())
@@ -826,10 +821,23 @@ bool ESP8266WiFiGenericClass::resumeFromShutdown (WiFiState* state)
                 }
             }
         }
-        auto beginResult = WiFi.begin((const char*)state->state.fwconfig.ssid,
-                       (const char*)state->state.fwconfig.password,
-                       state->state.channel,
-                       state->state.fwconfig.bssid,
+
+        String ssid;
+        {
+            const char* ptr = reinterpret_cast<const char*>(state.state.fwconfig.ssid);
+            ssid.concat(ptr, strnlen(ptr, sizeof(station_config::ssid)));
+        }
+
+        String pass;
+        {
+            const char* ptr = reinterpret_cast<const char*>(state.state.fwconfig.password);
+            pass.concat(ptr, strnlen(ptr, sizeof(station_config::password)));
+        }
+
+        auto beginResult = WiFi.begin(ssid.c_str(),
+                       pass.c_str(),
+                       state.state.channel,
+                       state.state.fwconfig.bssid,
                        true);
         if (beginResult == WL_CONNECT_FAILED)
         {
@@ -843,14 +851,14 @@ bool ESP8266WiFiGenericClass::resumeFromShutdown (WiFiState* state)
         }
     }
 
-    if (state->state.mode & WIFI_AP)
+    if (state.state.mode & WIFI_AP)
     {
         DEBUG_WIFI("core: resume AP mode TODO\n");
         return false;
     }
 
     // success, invalidate saved state
-    state->crc++;
+    state.crc++;
 
     return true;
 }
diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h
index 0e6a11e39b..3d3ceb3262 100644
--- a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h
+++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h
@@ -122,7 +122,7 @@ class ESP8266WiFiGenericClass {
 
         static void persistent(bool persistent);
 
-        bool mode(WiFiMode_t, WiFiState* state = nullptr);
+        bool mode(WiFiMode_t);
         WiFiMode_t getMode();
 
         bool enableSTA(bool enable);
@@ -131,21 +131,23 @@ class ESP8266WiFiGenericClass {
         bool forceSleepBegin(uint32 sleepUs = 0);
         bool forceSleepWake();
 
-        static uint32_t shutdownCRC (const WiFiState* state);
-        static bool shutdownValidCRC (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(WiFiState& stateSave);
+        bool shutdown(WiFiState& stateSave, uint32 sleepUs);
+        bool resumeFromShutdown(WiFiState& savedState);
+
+        static bool shutdownValidCRC (const WiFiState& state);
         static void preinitWiFiOff () __attribute__((deprecated("WiFi is off by default at boot, use enableWiFiAtBoot() for legacy behavior")));
 
     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 --------------------------------
diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiType.h b/libraries/ESP8266WiFi/src/ESP8266WiFiType.h
index 7e5e1dc7e1..9538b132c2 100644
--- a/libraries/ESP8266WiFi/src/ESP8266WiFiType.h
+++ b/libraries/ESP8266WiFi/src/ESP8266WiFiType.h
@@ -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
diff --git a/libraries/esp8266/examples/LowPowerDemo/LowPowerDemo.ino b/libraries/esp8266/examples/LowPowerDemo/LowPowerDemo.ino
index 7556c58820..2c22416e0d 100644
--- a/libraries/esp8266/examples/LowPowerDemo/LowPowerDemo.ino
+++ b/libraries/esp8266/examples/LowPowerDemo/LowPowerDemo.ino
@@ -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(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
@@ -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(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
@@ -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(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
@@ -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(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()
@@ -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.forceSleepBegin();  // 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()
@@ -397,15 +397,15 @@ void updateRTCcrc() {  // updates the reset count CRC
 void initWiFi() {
   digitalWrite(LED, LOW);  // give a visual indication that we're alive but busy with WiFi
   uint32_t wifiBegin = millis();  // how long does it take to connect
-  if ((crc32((uint8_t*) &nv->rtcData.rstCount + 1, sizeof(nv->wss)) && !WiFi.shutdownValidCRC(&nv->wss))) {
+  if ((crc32((uint8_t*) &nv->rtcData.rstCount + 1, sizeof(nv->wss)) && !WiFi.shutdownValidCRC(nv->wss))) {
     // if good copy of wss, overwrite invalid (primary) copy
     memcpy((uint32_t*) &nv->wss, (uint32_t*) &nv->rtcData.rstCount + 1, sizeof(nv->wss));
   }
-  if (WiFi.shutdownValidCRC(&nv->wss)) {  // if we have a valid WiFi saved state
+  if (WiFi.shutdownValidCRC(nv->wss)) {  // if we have a valid WiFi saved state
     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. */