|
| 1 | +/**************************************************************************************************************************** |
| 2 | + * ConfigOnDoubleReset.ino |
| 3 | + * For ESP8266 / ESP32 boards |
| 4 | + * |
| 5 | + * ESP_WiFiManager is a library for the ESP8266/ESP32 platform (https://github.com/esp8266/Arduino) to enable easy |
| 6 | + * configuration and reconfiguration of WiFi credentials using a Captive Portal. Inspired by: |
| 7 | + * http://www.esp8266.com/viewtopic.php?f=29&t=2520 |
| 8 | + * https://github.com/chriscook8/esp-arduino-apboot |
| 9 | + * https://github.com/esp8266/Arduino/blob/master/libraries/DNSServer/examples/CaptivePortalAdvanced/ |
| 10 | + * |
| 11 | + * Forked from Tzapu https://github.com/tzapu/WiFiManager |
| 12 | + * and from Ken Taylor https://github.com/kentaylor |
| 13 | + * |
| 14 | + * Built by Khoi Hoang https://github.com/khoih-prog/ESP_WiFiManager |
| 15 | + * Licensed under MIT license |
| 16 | + * Version: 1.0.1 |
| 17 | + * |
| 18 | + * Version Modified By Date Comments |
| 19 | + * ------- ----------- ---------- ----------- |
| 20 | + * 1.0.0 K Hoang 07/10/2019 Initial coding |
| 21 | + * 1.0.1 K Hoang 13/12/2019 Fix bug. Add features. Add support for ESP32 |
| 22 | + *****************************************************************************************************************************/ |
| 23 | +/**************************************************************************************************************************** |
| 24 | + * This example will open a configuration portal when the reset button is pressed twice. |
| 25 | + * This method works well on Wemos boards which have a single reset button on board. It avoids using a pin for launching the configuration portal. |
| 26 | + * |
| 27 | + * How It Works |
| 28 | + * 1) ESP8266 |
| 29 | + * Save data in RTC memory |
| 30 | + * 2) ESP32 |
| 31 | + * Save data in EEPROM from address 256, size 512 bytes (both configurable) |
| 32 | + * |
| 33 | + * So when the device starts up it checks this region of ram for a flag to see if it has been recently reset. |
| 34 | + * If so it launches a configuration portal, if not it sets the reset flag. After running for a while this flag is cleared so that |
| 35 | + * it will only launch the configuration portal in response to closely spaced resets. |
| 36 | + * |
| 37 | + * Settings |
| 38 | + * There are two values to be set in the sketch. |
| 39 | + * |
| 40 | + * DRD_TIMEOUT - Number of seconds to wait for the second reset. Set to 10 in the example. |
| 41 | + * DRD_ADDRESS - The address in ESP8266 RTC RAM to store the flag. This memory must not be used for other purposes in the same sketch. Set to 0 in the example. |
| 42 | + * |
| 43 | + * This example, originally relied on the Double Reset Detector library from https://github.com/datacute/DoubleResetDetector |
| 44 | + * To support ESP32, use ESP_DoubleResetDetector library from //https://github.com/khoih-prog/ESP_DoubleResetDetector |
| 45 | + *****************************************************************************************************************************/ |
| 46 | + |
| 47 | +//Ported to ESP32 |
| 48 | +#ifdef ESP32 |
| 49 | + #include <esp_wifi.h> |
| 50 | + #include <WiFi.h> |
| 51 | + #include <WiFiClient.h> |
| 52 | + |
| 53 | + #define ESP_getChipId() ((uint32_t)ESP.getEfuseMac()) |
| 54 | + |
| 55 | + #define LED_ON HIGH |
| 56 | + #define LED_OFF LOW |
| 57 | +#else |
| 58 | + #include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino |
| 59 | + //needed for library |
| 60 | + #include <DNSServer.h> |
| 61 | + #include <ESP8266WebServer.h> |
| 62 | + |
| 63 | + #define ESP_getChipId() (ESP.getChipId()) |
| 64 | + |
| 65 | + #define LED_ON LOW |
| 66 | + #define LED_OFF HIGH |
| 67 | +#endif |
| 68 | + |
| 69 | +// SSID and PW for Config Portal |
| 70 | +String ssid = "ESP_" + String(ESP_getChipId(), HEX); |
| 71 | +const char* password = "your_password"; |
| 72 | + |
| 73 | +// SSID and PW for your Router |
| 74 | +String Router_SSID; |
| 75 | +String Router_Pass; |
| 76 | + |
| 77 | +#include <ESP_WiFiManager.h> //https://github.com/khoih-prog/ESP_WiFiManager |
| 78 | + |
| 79 | +#include <ESP_DoubleResetDetector.h> //https://github.com/khoih-prog/ESP_DoubleResetDetector |
| 80 | + |
| 81 | +// Number of seconds after reset during which a |
| 82 | +// subseqent reset will be considered a double reset. |
| 83 | +#define DRD_TIMEOUT 10 |
| 84 | + |
| 85 | +// RTC Memory Address for the DoubleResetDetector to use |
| 86 | +#define DRD_ADDRESS 0 |
| 87 | + |
| 88 | +//DoubleResetDetector drd(DRD_TIMEOUT, DRD_ADDRESS); |
| 89 | +DoubleResetDetector* drd; |
| 90 | + |
| 91 | +// Onboard LED I/O pin on NodeMCU board |
| 92 | +const int PIN_LED = 2; // D4 on NodeMCU and WeMos. GPIO2/ADC12 of ESP32. Controls the onboard LED. |
| 93 | + |
| 94 | +// Indicates whether ESP has WiFi credentials saved from previous session, or double reset detected |
| 95 | +bool initialConfig = false; |
| 96 | + |
| 97 | +void heartBeatPrint(void) |
| 98 | +{ |
| 99 | + static int num = 1; |
| 100 | + |
| 101 | + if (WiFi.status() == WL_CONNECTED) |
| 102 | + Serial.print("H"); // H means connected to WiFi |
| 103 | + else |
| 104 | + Serial.print("F"); // F means not connected to WiFi |
| 105 | + |
| 106 | + if (num == 80) |
| 107 | + { |
| 108 | + Serial.println(); |
| 109 | + num = 1; |
| 110 | + } |
| 111 | + else if (num++ % 10 == 0) |
| 112 | + { |
| 113 | + Serial.print(" "); |
| 114 | + } |
| 115 | +} |
| 116 | + |
| 117 | +void check_status() |
| 118 | +{ |
| 119 | + static ulong checkstatus_timeout = 0; |
| 120 | + |
| 121 | + #define HEARTBEAT_INTERVAL 10000L |
| 122 | + // Print hearbeat every HEARTBEAT_INTERVAL (10) seconds. |
| 123 | + if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0)) |
| 124 | + { |
| 125 | + heartBeatPrint(); |
| 126 | + checkstatus_timeout = millis() + HEARTBEAT_INTERVAL; |
| 127 | + } |
| 128 | +} |
| 129 | + |
| 130 | +void setup() |
| 131 | +{ |
| 132 | + // put your setup code here, to run once: |
| 133 | + // initialize the LED digital pin as an output. |
| 134 | + pinMode(PIN_LED, OUTPUT); |
| 135 | + Serial.begin(115200); |
| 136 | + Serial.println("\nStarting"); |
| 137 | + |
| 138 | + drd = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS); |
| 139 | + |
| 140 | + //Local intialization. Once its business is done, there is no need to keep it around |
| 141 | + ESP_WiFiManager ESP_wifiManager; |
| 142 | + |
| 143 | + // We can't use WiFi.SSID() in ESP32 as it's only valid after connected. |
| 144 | + // SSID and Password stored in ESP32 wifi_ap_record_t and wifi_config_t are also cleared in reboot |
| 145 | + // Have to create a new function to store in EEPROM/SPIFFS for this purpose |
| 146 | + Router_SSID = ESP_wifiManager.WiFi_SSID(); |
| 147 | + Router_Pass = ESP_wifiManager.WiFi_Pass(); |
| 148 | + |
| 149 | + //Remove this line if you do not want to see WiFi password printed |
| 150 | + Serial.println("Stored: SSID = " + Router_SSID + ", Pass = " + Router_Pass); |
| 151 | + |
| 152 | + // SSID to uppercase |
| 153 | + ssid.toUpperCase(); |
| 154 | + |
| 155 | + if (Router_SSID != "") |
| 156 | + { |
| 157 | + ESP_wifiManager.setConfigPortalTimeout(60); //If no access point name has been previously entered disable timeout. |
| 158 | + Serial.println("Got stored Credentials. Timeout 60s"); |
| 159 | + } |
| 160 | + else |
| 161 | + { |
| 162 | + Serial.println("No stored Credentials. No timeout"); |
| 163 | + initialConfig = true; |
| 164 | + } |
| 165 | + |
| 166 | + if (drd->detectDoubleReset()) |
| 167 | + { |
| 168 | + Serial.println("Double Reset Detected"); |
| 169 | + initialConfig = true; |
| 170 | + } |
| 171 | + |
| 172 | + if (initialConfig) |
| 173 | + { |
| 174 | + Serial.println("Starting configuration portal."); |
| 175 | + digitalWrite(PIN_LED, LED_ON); // turn the LED on by making the voltage LOW to tell us we are in configuration mode. |
| 176 | + |
| 177 | + //sets timeout in seconds until configuration portal gets turned off. |
| 178 | + //If not specified device will remain in configuration mode until |
| 179 | + //switched off via webserver or device is restarted. |
| 180 | + //ESP_wifiManager.setConfigPortalTimeout(600); |
| 181 | + |
| 182 | + //it starts an access point |
| 183 | + //and goes into a blocking loop awaiting configuration |
| 184 | + if (!ESP_wifiManager.startConfigPortal((const char *) ssid.c_str(), password)) |
| 185 | + Serial.println("Not connected to WiFi but continuing anyway."); |
| 186 | + else |
| 187 | + Serial.println("WiFi connected...yeey :)"); |
| 188 | + } |
| 189 | + |
| 190 | + digitalWrite(PIN_LED, LED_OFF); // Turn led off as we are not in configuration mode. |
| 191 | + |
| 192 | + #define WIFI_CONNECT_TIMEOUT 30000L |
| 193 | + #define WHILE_LOOP_DELAY 200L |
| 194 | + #define WHILE_LOOP_STEPS (WIFI_CONNECT_TIMEOUT / ( 3 * WHILE_LOOP_DELAY )) |
| 195 | + |
| 196 | + unsigned long startedAt = millis(); |
| 197 | + |
| 198 | + while ( (WiFi.status() != WL_CONNECTED) && (millis() - startedAt < WIFI_CONNECT_TIMEOUT ) ) |
| 199 | + { |
| 200 | + WiFi.mode(WIFI_STA); |
| 201 | + WiFi.persistent (true); |
| 202 | + // We start by connecting to a WiFi network |
| 203 | + |
| 204 | + Serial.print("Connecting to "); |
| 205 | + Serial.println(Router_SSID); |
| 206 | + |
| 207 | + WiFi.begin(Router_SSID.c_str(), Router_Pass.c_str()); |
| 208 | + |
| 209 | + int i = 0; |
| 210 | + while((!WiFi.status() || WiFi.status() >= WL_DISCONNECTED) && i++ < WHILE_LOOP_STEPS) |
| 211 | + { |
| 212 | + delay(WHILE_LOOP_DELAY); |
| 213 | + } |
| 214 | + } |
| 215 | + |
| 216 | + Serial.print("After waiting "); |
| 217 | + Serial.print((millis()- startedAt) / 1000); |
| 218 | + Serial.print(" secs more in setup(), connection result is "); |
| 219 | + |
| 220 | + if (WiFi.status() == WL_CONNECTED) |
| 221 | + { |
| 222 | + Serial.print("connected. Local IP: "); |
| 223 | + Serial.println(WiFi.localIP()); |
| 224 | + } |
| 225 | + else |
| 226 | + Serial.println(ESP_wifiManager.getStatus(WiFi.status())); |
| 227 | +} |
| 228 | + |
| 229 | +void loop() |
| 230 | +{ |
| 231 | + // Call the double reset detector loop method every so often, |
| 232 | + // so that it can recognise when the timeout expires. |
| 233 | + // You can also call drd.stop() when you wish to no longer |
| 234 | + // consider the next reset as a double reset. |
| 235 | + drd->loop(); |
| 236 | + |
| 237 | + // put your main code here, to run repeatedly |
| 238 | + check_status(); |
| 239 | + |
| 240 | +} |
0 commit comments