Explorar o código

Merge pull request #11 from judge2005/master

Add critical and safe loop methods
Alan Steremberg %!s(int64=7) %!d(string=hai) anos
pai
achega
8edbf510de

+ 69 - 39
ESPAsyncWiFiManager.cpp

@@ -113,6 +113,8 @@ void AsyncWiFiManager::setupConfigPortal() {
   dnsServer->setErrorReplyCode(DNSReplyCode::NoError);
   dnsServer->start(DNS_PORT, "*", WiFi.softAPIP());
 
+  setInfo();
+
   /* Setup web pages: root, wifi config pages, SO captive portal detectors and not found. */
   server->on("/", std::bind(&AsyncWiFiManager::handleRoot, this,std::placeholders::_1)).setFilter(ON_AP_FILTER);
   server->on("/wifi", std::bind(&AsyncWiFiManager::handleWifi, this, std::placeholders::_1,true)).setFilter(ON_AP_FILTER);
@@ -151,6 +153,7 @@ static String byteToHexString(uint8_t* buf, uint8_t length, String strSeperator=
   return dataString;
 } // byteToHexString
 
+#if !defined(ESP8266)
 String getESP32ChipID() {
   uint64_t chipid;
   chipid=ESP.getEfuseMac();//The chip ID is essentially its MAC address(length: 6 bytes).
@@ -161,6 +164,7 @@ String getESP32ChipID() {
   }
   return byteToHexString(chipid_arr, chipid_size, "");
 }
+#endif
 
 boolean AsyncWiFiManager::autoConnect() {
   String ssid = "ESP";
@@ -348,48 +352,71 @@ void AsyncWiFiManager::startConfigPortalModeless(char const *apName, char const
 }
 
 void AsyncWiFiManager::loop(){
-  dnsServer->processNextRequest();
-  if (_modeless)
-  {
-    if ( scannow==-1 || millis() > scannow + 60000)
-    {
+	safeLoop();
+	criticalLoop();
+}
 
-      scan();
-      scannow= millis() ;
-    }
-    if (connect) {
-      connect = false;
-      //delay(2000);
-      DEBUG_WM(F("Connecting to new AP"));
+void AsyncWiFiManager::setInfo() {
+	if (needInfo) {
+		pager = infoAsString();
+	    wifiStatus = WiFi.status();
+	    needInfo = false;
+	}
+}
 
-      // using user-provided  _ssid, _pass in place of system-stored ssid and pass
-      if (connectWifi(_ssid, _pass) != WL_CONNECTED) {
-        DEBUG_WM(F("Failed to connect."));
-      } else {
-        //connected
-        // alanswx - should we have a config to decide if we should shut down AP?
-        // WiFi.mode(WIFI_STA);
-        //notify that configuration has changed and any optional parameters should be saved
-        if ( _savecallback != NULL) {
-          //todo: check if any custom parameters actually exist, and check if they really changed maybe
-          _savecallback();
-        }
-        return;
-      }
+/**
+ * Anything that accesses WiFi, ESP or EEPROM goes here
+ */
+void AsyncWiFiManager::criticalLoop(){
+  if (_modeless)
+  {
 
-      if (_shouldBreakAfterConfig) {
-        //flag set to exit after config after trying to connect
-        //notify that configuration has changed and any optional parameters should be saved
-        if ( _savecallback != NULL) {
-          //todo: check if any custom parameters actually exist, and check if they really changed maybe
-          _savecallback();
-        }
-        return;
-      }
-    }
+	if ( scannow==-1 || millis() > scannow + 60000)
+	{
+
+	  scan();
+	  scannow= millis() ;
+	}
+	if (connect) {
+		connect = false;
+	  //delay(2000);
+	  DEBUG_WM(F("Connecting to new AP"));
+
+	  // using user-provided  _ssid, _pass in place of system-stored ssid and pass
+	  if (connectWifi(_ssid, _pass) != WL_CONNECTED) {
+		DEBUG_WM(F("Failed to connect."));
+	  } else {
+		//connected
+		// alanswx - should we have a config to decide if we should shut down AP?
+		// WiFi.mode(WIFI_STA);
+		//notify that configuration has changed and any optional parameters should be saved
+		if ( _savecallback != NULL) {
+		  //todo: check if any custom parameters actually exist, and check if they really changed maybe
+		  _savecallback();
+		}
+
+		return;
+	  }
+
+	  if (_shouldBreakAfterConfig) {
+		//flag set to exit after config after trying to connect
+		//notify that configuration has changed and any optional parameters should be saved
+		if ( _savecallback != NULL) {
+		  //todo: check if any custom parameters actually exist, and check if they really changed maybe
+		  _savecallback();
+		}
+	  }
+	}
   }
 }
 
+/*
+ * Anything that doesn't access WiFi, ESP or EEPROM can go here
+ */
+void AsyncWiFiManager::safeLoop(){
+  dnsServer->processNextRequest();
+}
+
 boolean  AsyncWiFiManager::startConfigPortal(char const *apName, char const *apPassword) {
   //setup AP
   WiFi.mode(WIFI_AP_STA);
@@ -488,7 +515,7 @@ int AsyncWiFiManager::connectWifi(String ssid, String pass) {
 
     WiFi.begin(ssid.c_str(), pass.c_str());
   } else {
-    if (WiFi.SSID()) {
+    if (WiFi.SSID().length() > 0) {
       DEBUG_WM("Using last saved values, should be faster");
 #if defined(ESP8266)
       //trying to fix connection in progress hanging
@@ -514,6 +541,9 @@ int AsyncWiFiManager::connectWifi(String ssid, String pass) {
     //should be connected at the end of WPS
     connRes = waitForConnectResult();
   }
+
+  needInfo = true;
+  setInfo();
   return connRes;
 }
 
@@ -756,6 +786,7 @@ void AsyncWiFiManager::handleWifiSave(AsyncWebServerRequest *request) {
   DEBUG_WM(F("WiFi save"));
 
   //SAVE/connect here
+  needInfo = true;
   _ssid = request->arg("s").c_str();
   _pass = request->arg("p").c_str();
 
@@ -872,11 +903,10 @@ void AsyncWiFiManager::handleInfo(AsyncWebServerRequest *request) {
   if (connect==true)
   {
     page += F("<dt>Trying to connect</dt><dd>");
-    page += WiFi.status();
+    page += wifiStatus;
     page += F("</dd>");
   }
 
-  String pager = infoAsString();
   page +=pager;
   page += FPSTR(HTTP_END);
 

+ 6 - 0
ESPAsyncWiFiManager.h

@@ -98,6 +98,8 @@ public:
   void          scan();
   String        scanModal();
   void          loop();
+  void          safeLoop();
+  void          criticalLoop();
   String        infoAsString();
 
   boolean       autoConnect();
@@ -152,6 +154,7 @@ private:
   boolean         _modeless;
   int             scannow;
   int             shouldscan;
+  boolean         needInfo = true;
 
   //const int     WM_DONE                 = 0;
   //const int     WM_WAIT                 = 10;
@@ -161,6 +164,8 @@ private:
   void          setupConfigPortal();
   void          startWPS();
 
+  String        pager;
+  wl_status_t   wifiStatus;
   const char*   _apName                 = "no-net";
   const char*   _apPassword             = NULL;
   String        _ssid                   = "";
@@ -190,6 +195,7 @@ private:
   int           status = WL_IDLE_STATUS;
   int           connectWifi(String ssid, String pass);
   uint8_t       waitForConnectResult();
+  void          setInfo();
 
   String networkListAsString();
 

+ 87 - 0
examples/ModelessWithInterrupts/ModelessWithInterrupts.ino

@@ -0,0 +1,87 @@
+#if defined(ESP8266)
+#include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino
+#else
+#include <WiFi.h>
+#endif
+
+//needed for library
+#include <DNSServer.h>
+#include <ESPAsyncWebServer.h>
+#include <ESPAsyncWiFiManager.h>         //https://github.com/tzapu/WiFiManager
+
+AsyncWebServer server(80);
+DNSServer dns;
+AsyncWiFiManager wifiManager(&server,&dns);
+
+volatile boolean guard = true;
+const uint32_t callCycleCount = ESP.getCpuFreqMHz() * 1024 / 8;
+
+/*
+ * If some other code was in the process of calling a method in
+ * WiFi, ESP or EEPROM, and we do too, there is a very good chance
+ * a reset will happen.
+ */
+void ICACHE_RAM_ATTR interruptFunction() {
+	/*
+	 * This is equivalent to:
+	 * timer0_write(ESP.getCycleCount() + ESP.getCpuFreqMHz() * 1024 / 8)
+	 * But that could clash with the main thread code.
+	 */
+    uint32_t ccount;
+    __asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
+
+	timer0_write(ccount + callCycleCount);
+
+	if (!guard) {
+		// An example call that would cause a reset if it happens
+		// to be called while AsyncWiFiManager is also calling
+		// methods that modify flash.
+		ESP.getChipId();
+	}
+}
+
+void setup() {
+    // put your setup code here, to run once:
+    Serial.begin(115200);
+
+    //WiFiManager
+    //Local intialization. Once its business is done, there is no need to keep it around
+    //reset saved settings
+    //wifiManager.resetSettings();
+
+    //set custom ip for portal
+    //wifiManager.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
+
+    //fetches ssid and pass from eeprom and tries to connect
+    //if it does not connect it starts an access point with the specified name
+    //here  "AutoConnectAP"
+    //and goes into a blocking loop awaiting configuration
+    //wifiManager.autoConnect("AutoConnectAP");
+    //or use this for auto generated name ESP + ChipID
+    //wifiManager.autoConnect();
+    wifiManager.startConfigPortalModeless("ModelessAP", "Password");
+
+
+ server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
+    request->send(200, "text/plain", "Hello World");
+  });
+
+    // Set up some code that could cause a reset.
+	guard = true;
+	timer0_isr_init();
+	timer0_attachInterrupt(interruptFunction);
+	timer0_write(ESP.getCycleCount() + ESP.getCpuFreqMHz() * 1024);	// Wait 2 seconds before displaying
+	updateDisplay = false;
+}
+
+void loop() {
+    // put your main code here, to run repeatedly:
+	// This can be called with guarding interrupt routines - so
+	// interrupt routines can interrupt it!
+    wifiManager.safeLoop();
+
+    guard = true;
+	// This call can not be interrupted without possibly causing a reset.
+	wifiManager.criticalLoop();
+    guard = false;
+}